前言:
udev可以在系统内核加载阶段对网卡进行重命名,区别与ifcfg命名的是,udev的命名优先级高于ifcfg。
如果用户定义了rules文件,放在/etc/udev/rules.d/目录下,同时也定义ifcfg,则启动后会按照udev进行匹配;但是如果在系统启动后启动NetworkManager或者network服务时,会依据ifcfg文件,所以用户不应该同时采用两种方式给同一个网卡命名不同的名字。
需求:
主机侧插拔网卡,device_name不会变化;拔网卡并重启主机网卡名不会变化
方案1:
通过网卡的pci地址固定device name,在systemd-udevd服务加载前执行生成弹性网卡固定的udev命名规则的脚本
方案2:
使用udev自带的ID_NET_NAME_PATH变量,比如下面的写法
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="virtio_net", IMPORT{builtin}=="net_id", NAME="$env{ID_NET_NAME_PATH}"
根据文档,https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/networking_guide/sec-understanding_the_predictable_network_interface_device_names
ID_NET_NAME_PATH也是基于PCI位置(PCI geographical location)的,其格式为[P]ps[f][d]。比如enp0s2
方案3:
根据udvadm test -a add /sys/class/net/ensX获取udev 属性
手动根据pci位置生成id
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="virtio_net", PROGRAM="/usr/local/sbin/generate-nic-name.sh $devpath", NAME="$result"
$devpath形如/devices/pci0000:00/0000:00:02.0/virtio0/net/eth0
generate-nic-name.sh可以简单一点直接取????:XX:??.?中的XX部分(方案1中的脚本网卡名主要取决于这部分)
#!/bin/bash
# /devices/pci0000:00/0000:00:02.0/virtio0/net/eth0
DEVPATH="$1"
PCI_ID=$(echo $DEVPATH | cut -d '/' -f4)
BUS_ID=$(echo $PCI_ID | cut -d ':' -f2)
echo "ens${BUS_ID}"
方案1实施步骤:
1、修改systemd-udev服务service文件中添加
ExecStartPre=/usr/bin/generate_virtio_net_udev.sh ExecReload=udevadm control --reload --timeout 0
2、在systemd-udevd服务启动前执行脚本/usr/bin/generate_virtio_net_udev.sh,并添加执行权限
chmod +x /usr/bin/generate_virtio_net_udev.sh
#!/bin/bash
rename_udev_path="/etc/udev/rules.d/40-virtio-net-rename.rules"
primary_port_pci=`lspci -n -v | grep 15b3:a2d | cut -d' ' -f1`
if [ -z "$primary_port_pci" ]; then
primary_port_pci=`lspci -v -n | grep 1af4:1041 -A 1 | grep 1bd4:f006 -B 1 | head -1 | cut -d' ' -f1`
fi
generate_virtio_net_udev()
{
if [ -f "$rename_udev_path" ] ; then
rm -f $rename_udev_path
fi
first_position=$((`echo 0x$primary_port_pci |cut -d':' -f1`))
temp_first_position=`printf "%.2x" $first_position`
echo "SUBSYSTEM==\"net\", ACTION==\"add\", KERNEL==\"*\", SUBSYSTEMS==\"pci\", KERNELS==\"0000:$temp_first_position:00.0\", NAME=\"ens0\"" >> $rename_udev_path
for((i=1;i<32;i++))
do
ten_first_position=`printf "%d" $first_position`
ten_first_position=$((ten_first_position+1))
first_position=`printf "%.2x" $ten_first_position`
echo "SUBSYSTEM==\"net\", ACTION==\"add\", KERNEL==\"*\", SUBSYSTEMS==\"pci\", KERNELS==\"0000:$first_position:00.0\", NAME=\"ens$i\"" >> $rename_udev_path
first_position=`echo 0x$first_position`
done
}
generate_virtio_net_udev
验证:
方案2实施步骤:
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="virtio_net", IMPORT{builtin}=="net_id", NAME="$env{ID_NET_NAME_PATH}"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="mlx5_core", IMPORT{builtin}=="net_id", NAME="$env{ID_NET_NAME_PATH}"
结论:
centos7.6 没有ID_NET_NAME_PATH参数,不支持此方案
方案3实施步骤:
- 创建udev脚本/etc/udev/rules.d/40-smart-nic-rename.rules
ENV{ID_PATH}=="", IMPORT{builtin}="path_id"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="virtio_net", PROGRAM="/usr/local/sbin/generate-nic-name.sh $env{ID_PATH}", NAME="$result"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="mlx5_core", ATTRS{vendor}=="0x15b3", ATTRS{device}=="0xa2d[69cf]", PROGRAM="/usr/local/sbin/generate-nic-name.sh $env{ID_PATH}", NAME="$result"
2. 添加 /usr/local/sbin/generate-nic-name.sh ,并添加执行权限
chmod +x /usr/local/sbin/generate-nic-name.sh
#!/bin/bash # pci-0000:a2:00.0 DEVPATH="$1" BUS_ID=$(echo $DEVPATH | cut -d ':' -f2) echo "ens${BUS_ID}"
验证: