Posted by 每特17劃 on 2019-02-21

systemd Network Interface Naming

近一兩年期間,一些 Linux 系統的網路卡命名,漸漸從 eth0, eth1, … 轉變成 eno1, enp5s0, … 這樣的格式。 一時間很不習慣,因為新命名方式較長也較複雜,輸入指令時不甚方便。

後來在網路上讀到這一篇文章的說明:

https://major.io/2015/08/21/understanding-systemds-predictable-network-device-names/

這個改變是來自 systemd 的 “Predictable Network Interface Names”,其在 Freedesktop 的說明如下:

https://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/

依上述的資訊,其版本變更是在 v197 版開始,時間是 2013-01-05 ,對應的 sourcce code 如下:

https://github.com/systemd/systemd/blob/v197/src/udev/udev-builtin-net_id.c

其開頭片段有註解文字如下:

/*
 * Predictable network interface device names based on:
 *  - firmware/bios-provided index numbers for on-board devices
 *  - firmware-provided pci-express hotplug slot index number
 *  - physical/geographical location of the hardware
 *  - the interface's MAC address
 *
 * Two character prefixes based on the type of interface:
 *   en -- ethernet
 *   wl -- wlan
 *   ww -- wwan
 *
 * Type of names:
 *   o<index>                              -- on-board device index number
 *   s<slot>[f<function>][d<dev_id>]       -- hotplug slot index number
 *   x<MAC>                                -- MAC address
 *   p<bus>s<slot>[f<function>][d<dev_id>] -- PCI geographical location
 *   p<bus>s<slot>[f<function>][u<port>][..][c<config>][i<interface>]
 *                                         -- USB port number chain
 *
 * All multi-function PCI devices will carry the [f<function>] number in the
 * device name, including the function 0 device.
 *
 * For USB devices the full chain of port numbers of hubs is composed. If the
 * name gets longer than the maximum number of 15 characters, the name is not
 * exported.
 * The usual USB configuration == 1 and interface == 0 values are suppressed.
 *
 * PCI ethernet card with firmware index "1":
 *   ID_NET_NAME_ONBOARD=eno1
 *   ID_NET_NAME_ONBOARD_LABEL=Ethernet Port 1
 *
 * PCI ethernet card in hotplug slot with firmware index number:
 *   /sys/devices/pci0000:00/0000:00:1c.3/0000:05:00.0/net/ens1
 *   ID_NET_NAME_MAC=enx000000000466
 *   ID_NET_NAME_PATH=enp5s0
 *   ID_NET_NAME_SLOT=ens1
 *
 * PCI ethernet multi-function card with 2 ports:
 *   /sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/enp2s0f0
 *   ID_NET_NAME_MAC=enx78e7d1ea46da
 *   ID_NET_NAME_PATH=enp2s0f0
 *   /sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.1/net/enp2s0f1
 *   ID_NET_NAME_MAC=enx78e7d1ea46dc
 *   ID_NET_NAME_PATH=enp2s0f1
 *
 * PCI wlan card:
 *   /sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlp3s0
 *   ID_NET_NAME_MAC=wlx0024d7e31130
 *   ID_NET_NAME_PATH=wlp3s0
 *
 * USB built-in 3G modem:
 *   /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.4/2-1.4:1.6/net/wwp0s29u1u4i6
 *   ID_NET_NAME_MAC=wwx028037ec0200
 *   ID_NET_NAME_PATH=wwp0s29u1u4i6
 *
 * USB Android phone:
 *   /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/net/enp0s29u1u2
 *   ID_NET_NAME_MAC=enxd626b3450fb5
 *   ID_NET_NAME_PATH=enp0s29u1u2
 */

wlp0s20f3 為例:

  • wl 開頭表示是 Wireless local area network (WLAN)
  • p0s20f3 則是 PCI geographical location
    • p0 => bus=0
    • s20 => slot=20
    • f3 => function=3

另一個例子是 enp0s20f0u4:

  • en => Ethernet
  • p0s20f0 => PCI geographical location
    • p0 => bus=0
    • s20 => slot=20
    • f0 => function=0
  • u4 => USB port number chain , port=4

那麼,這樣的命名的方式有什麼好處呢?

若依原先的命名方式,網路卡的 interface 名稱是看偵測到卡的順序。 假設電腦插了兩個網路裝置,今天 A 網卡比 B 網卡先偵測到,那兩張的名稱會是 A: eth0 跟 B: eth1。 但若重開機後,B 網卡先偵測到了,那就會反過來變成 A: eth1, B: eth0。 那麼,原先的網路設定,例如: 防卡牆、NetowrkManager Profile、… ,都會因此亂了套。 而驅動程式的載入時間,開機環境的不同,或其他不可預期的硬體異動,都有可能造成上述的狀況。 所以 systemd 所提出的這個可預測的命名方式,能讓網卡在相同的連接埠下,不論偵測順序先後,都得到相同的命名。

Q: 如何改回原本的 interface naming?

最簡單的方式是,在開機 kernel 參數加上:

net.ifnames=0

這個參數雖然是放在 kernel params 的設定,但實際上是由 systemd 去讀取判斷。 細節可參考 man systemd-udevd.service 指令的內容。

另外,有些地方提到也要加上這個 kernel 參數:

biosdevname=0

我爬了一下文,這個參數應該是在下列情況時才會用到:

  • 是 DELL 的硬體
  • 有安裝 biosdevname 套件

2022-10-15

目前 naming rules 的說明,已不放在 src/udev/udev-builtin-net_id.c 處,而是改放在 man/systemd.net-naming-scheme.xml 檔案。 其變更時間點如下:

在 Linux 系統內可直接執行下述指令查詢格式對照表

man systemd.net-naming-scheme

或是瀏覽網頁如下:

https://www.freedesktop.org/software/systemd/man/systemd.net-naming-scheme.html

2022-10-15

若遇到舊系統,想要切換至新的命名方式,但希望在 reboot 前,能先預測 interface 名稱預先 rename 的話。 可參考下述的討論:

https://github.com/systemd/systemd/issues/23661

內文提到可利用的工具指令如下:

udevadm info -q property /sys/class/net/eth0
udevadm test-builtin net_id /sys/class/net/eth0

References