一、概述
大型计算机通常有多块网卡,有板载集成的,也有插在PCIe插槽的。Linux系统的命名原来是eth0、eth1这样的形式,但是这个编号往往不一定准确对应网卡接口的物理顺序,机器重启后,同一物理位置的网卡可能会获得不同的“eth”编号。
在openKylin系统上,我们可以在内核启动参数上加上“net.ifnames=0”选项,跳过udev的重命名过程,此时只是根据内核扫描到的网卡先后顺序进行命名。通过查看网络连接界面,我们可以看到此时网卡命名只是简单的eth0:
因此,为解决这一问题,systemd和udev引入了一种新的网络设备命名方式:一致网络设备命名(CONSISTENT NETWORK DEVICE NAMING)。根据固件、拓扑、位置信息来设置固定名字,带来的好处是命名自动化,名字完全可预测,这样可以让硬件的更换无缝化。此时,再次查看openKylin上的网络连接界面,可以看到网卡已经按照物理位置进行了命名,为enp4s0:
systemd的网络设备命名方案为systemd.net-naming-scheme,该方案根据设备的确定接口信息来给网络设备生成属性(udev property,可以通过“udevadm info --query property”命令查询)。这些属性由udev内建(buildin)程序“net_id”生成添加,udev的内建程序“net_setup_link”会根据“
/lib/systemd/network/99-default.link”文件中的“NamePolicy”和“AlternativeNamesPolicy”参数,选择一个可行的命名策略对网卡进行重命名。
二、命名第一步:net_id添加udev属性
查看udev rules文件“
/lib/udev/rules.d/75-net-description.rules”,内容如下:
当一个udev事件的“SUBSYSTEM”为“net”,且“ACTION”不为“remove”时,会触发内建程序“net_id”的运行。net_id程序会为网络设备添加“ID_NET_NAME_xxxx”类型的属性,这些属性就是“database、onboard、slot、path、mac”中某一命名策略的生成名字。这些属性可以用“udevadm info --query property”命令查询,例如:
通过命令“udevadm info --query property /sys/class/net/enp4s0”得到了网卡“enp4s0”的所有属性,其中由net_id添加的属性有:
- ID_NET_NAME_MAC=enx88a4c262c304
- ID_NET_NAME_PATH=enp4s0
2.1 网卡命名前缀及设备类型
网卡命名规范中,所有名字的前两个字母称为前缀,根据设备类型不同,包含以下五种前缀:
Prefix | Description |
en | 以太网(Ethernet) |
ib | 无限带宽(InfiniBand) |
sl | 串列线路互联网协议(Serial line IP (slip)) |
wl | 无线局域网(Wireless local area network (WLAN)) |
ww | 无限广域网(Wireless wide area network (WWAN)) |
其中,对于“en、ib、sl”三种设备的判断,通过设备路径下的“type”类型来区分,例如:
可见本机网卡enp3s0的type为1,type值与设备类型对应如下:
type值 | 设备类型 |
1 | en |
32 | ib |
256 | sl |
对于“wl、ww”两种类型,则判断设备属性中的devtype内容来区分,例如:
其中,DEVTYPE=wlan,因此设备类型为“wl”;同理,当DEVTYPE=wwan时,设备类型为“ww”。
2.2 udev命名属性类型
根据设备类型得到相应的前缀后,再根据不同的命名策略构造相应的网卡名,然后将此命名添加到设备属性,属性类型有如下5种:
属性名 | 来源 |
ID_NET_NAME_FROM_DATABASE | 来自于udev硬件数据库 |
ID_NET_NAME_ONBOARD | 来自于板载网卡固件 |
ID_NET_NAME_MAC | 来自于网卡的固定MAC地址 |
ID_NET_NAME_SLOT | 来自于可插拔网卡固件 |
ID_NET_NAME_PATH | 来自于网卡的总线位置 |
- ID_NET_NAME_FROM_DATABASE由hwdb中获得,不会由“net_id”产生。
- ID_NET_NAME_ONBOARD由固件提供的板载设备索引号信息合成,字母“o”后面接板载PCI的索引号,字母“d”后面接设备树别名索引号,如“eno1、end1”,板载设备才会有这项属性,比较少见。
- ID_NET_NAME_MAC由字母“x”后接设备的MAC地址组成,MAC地址记录在设备路径下的“address”文件中,例如:
- ID_NET_NAME_SLOT描述设备的插槽位置,根据不同的总线类型会使用不同的引导字母,如“s”后接slot编号,“f”接function编号,“u”接USB端口编号,这些编号都是通过设备路径解析获得的。
- ID_NET_NAME_PATH描述的是设备的安装位置,常见的格式形如“enp4s0”,这个命名信息也是从设备路径解析获得的。
下面提供一个生成命名的例子。
例1:查询网卡enp4s0属性:
可知设备路径:
/devices/pci0000:00/0000:00:1c.2/0000:04:00.0/net/enp4s0
父设备子系统为pci,通过names_pci函数解析对设备路径进行处理;
通过字符串处理截取其中的0000:04:00.0,将此字符串格式化输入:
sscanf(sysname, "%x:%x:%x.%u", &domain, &bus, &slot, &func)
得到domain=0、bus=4、slot=0、func=0的值,再将这几个值格式化打印:
strpcpyf(&s, l, "p%us%u", bus, slot)
得到一个字符串“p4s0”,加上前缀,得到“enp4s0”。
三、命名第二步:udev重命名
在2.1节的描述中,rules文件“
/lib/udev/rules.d/75-net-description.rules”首先被触发,内建“net_id”程序会向设备添加“ID_NET_NAME_XXXX”属性,在此规则处理完后,rules文件“/lib/udev/rules.d/80-net-setup-link.rules”会被触发,文件如下:
根据此rules文件可知,当设备类型为“net”且动作不为“remove”时会触发内建函数“net_setup_link”,此函数会根据udev命名策略选择2.2中“net_id”生成的属性名字添加为新的属性“ID_NET_NAME”,如果NAME为空且属性中的ID_NET_NAME非空,则会触发修改网卡名,NAME修改为ID_NET_NAME。
内建程序“net_setup_link”被触发时,读取命名策略配置文件“
/lib/systemd/network/99-default.link”,查看文件内容如下:
依据上述配置文件,先执行NamePolicy,再执行AlternativeNamesPolicy。执行时,从前往后开始执行策略,当前一策略执行成功,则后续策略不会再执行。可用命名策略如下:
- keep:如果网卡已经被用户空间命名(创建新设备时命名或对已有设备重命名), 那么就保留它(不进行重命名操作)。
- kernel:如果内核 已经为此网卡设置了固定的可预测名称, 那么不进行任何重命名操作。
- database:基于网卡的 ID_NET_NAME_FROM_DATABASE 属性值设置网卡的名称。
- onboard:基于网卡的 ID_NET_NAME_ONBOARD 属性值设置网卡的名称。
- slot:基于网卡的 ID_NET_NAME_SLOT 属性值设置网卡的名称。
- path:基于网卡的 ID_NET_NAME_PATH 属性值设置网卡的名称。
- mac:基于网卡的 ID_NET_NAME_MAC 属性值设置网卡的名称。
注:database、onboard、slot、path、mac五种策略只要设备的属性中有相应的ID_NET_NAME_XXXX属性(由第2节net_id生成),就会用这个属性的名字重命名,即可认为执行该策略成功。
MACAddressPolicy描述MAC地址的设置策略,可选的策略有:persistent、random、none。
- persistent:如果内核使用了网卡硬件固有的MAC地址(绝大多数网卡都有),那么啥也不做,直接使用内核的MAC地址。 否则, 将会随机新生成一个 确保在多次启动之间保持固定不变的MAC地址(针对给定的主板与网卡)。自动生成MAC地址的特性要求网卡必须存在 ID_NET_NAME_* 属性, 否则无法自动生成MAC地址。
- random:如果内核使用了随机生成的MAC地址(而不是网卡硬件固有的MAC地址), 那么啥也不做,直接使用内核的MAC地址。否则,将在网卡每次出现的时候(一般在启动过程中)随机新生成一个MAC地址。
- none:无条件的直接使用内核的MAC地址。
四、总结
网络设备事件上来时通常名字为传统命名“ethx”,udev识别到事件子系统为“net”且动作不为“remove”,触发内建程序“net_id”,为设备添加“ID_NET_NAME_XXXX”属性,随后触发内建程序“net_setup_link”,依据配置文件命名策略选择一个“ID_NET_NAME_XXXX”属性添加为新属性“ID_NET_NAME”,然后将这个“ID_NET_NAME”作为网络设备新名字进行重命名操作。至此,网卡重命名操作完成。
五、参考资料
- https://www.freedesktop.org/software/systemd/man/systemd.link.html#
- https://www.freedesktop.org/software/systemd/man/systemd.net-naming-scheme.html#
- https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/networking_guide/ch-consistent_network_device_naming