While working on the Topology_Converter for work I came upon several lessons with Udev. The topology_converter project essentially takes input (from a graphiviz file) and builds a network topology with proper interface names. In order to make the interface names work there is a script which spits out udev rules.
Writing Udev Rules
With Udev you can rename interfaces using a number of parameters which are defined in rules. Rules should be stuck in the “/etc/udev/rules.d/70-persistent-net.rules” file to follow convention but you could technically stick them anywher in the rules.d directory.
To see all of the possible criteria that can be matched upon for a given network interface, use the command below replacing “eth0” with your interface of choice.
udevadm info -a -p /sys/class/net/eth0 Udevadm info starts with the device specified by the devpath and then walks up the chain of parent devices. It prints for every device found, all possible attributes in the udev rules key format. A rule to match, can be composed by the attributes of the device and the attributes from one single parent device. looking at device '/devices/pci0000:00/0000:00:19.0/net/eth0': KERNEL=="eth0" SUBSYSTEM=="net" DRIVER=="" ATTR{addr_assign_type}=="0" ATTR{addr_len}=="6" ATTR{address}=="54:ee:75:22:3d:70" ATTR{broadcast}=="ff:ff:ff:ff:ff:ff" ATTR{carrier}=="0" ATTR{carrier_changes}=="1" ATTR{dev_id}=="0x0" ATTR{dev_port}=="0" ATTR{dormant}=="0" ATTR{duplex}=="unknown" ATTR{flags}=="0x1003" ATTR{gro_flush_timeout}=="0" ATTR{ifalias}=="" ATTR{ifindex}=="2" ATTR{iflink}=="2" ATTR{link_mode}=="0" ATTR{mtu}=="1500" ATTR{netdev_group}=="0" ATTR{operstate}=="down" ATTR{proto_down}=="0" ATTR{speed}=="-1" ATTR{tx_queue_len}=="1000" ATTR{type}=="1" looking at parent device '/devices/pci0000:00/0000:00:19.0': KERNELS=="0000:00:19.0" SUBSYSTEMS=="pci" DRIVERS=="e1000e" ATTRS{broken_parity_status}=="0" ATTRS{class}=="0x020000" ATTRS{consistent_dma_mask_bits}=="64" ATTRS{d3cold_allowed}=="1" ATTRS{device}=="0x15a2" ATTRS{dma_mask_bits}=="64" ATTRS{driver_override}=="(null)" ATTRS{enable}=="1" ATTRS{irq}=="56" ATTRS{local_cpulist}=="0-3" ATTRS{local_cpus}=="0f" ATTRS{msi_bus}=="1" ATTRS{numa_node}=="-1" ATTRS{subsystem_device}=="0x2227" ATTRS{subsystem_vendor}=="0x17aa" ATTRS{vendor}=="0x8086" looking at parent device '/devices/pci0000:00': KERNELS=="pci0000:00" SUBSYSTEMS=="" DRIVERS==""
</code>
You can see there are quite a few options to match on. When remapping physical interfaces on Linux, I strongly recommend adding the match for PCI to make sure this interface is mapped to the PCI bus in some way. The concern when not using the PCI match (as shown below) is that if these physical interfaces are to take part in bridges or bonds with vlans or sub interfaces…. in that case your bridge or bond may inherit mac addresses from a physical interface and there will be a collision in the renaming process which means your interfaces may be left named “renameXX” or something like that.
Here are some sample Udev rules for a given series of interface renaming operations.
#### UDEV Rules (/etc/udev/rules.d/70-persistent-net.rules) #### ACTION=="add", SUBSYSTEM=="net", ATTR{address}=="44:38:39:00:00:1a", NAME="swp2", SUBSYSTEMS=="pci" ACTION=="add", SUBSYSTEM=="net", ATTR{address}=="44:38:39:00:00:12", NAME="swp1", SUBSYSTEMS=="pci" ACTION=="add", SUBSYSTEM=="net", ATTR{address}=="44:38:39:00:00:49", NAME="swp48", SUBSYSTEMS=="pci" ACTION=="add", SUBSYSTEM=="net", ATTR{address}=="44:38:39:00:00:42", NAME="eth0", SUBSYSTEMS=="pci" ACTION=="add", SUBSYSTEM=="net", ATTR{address}=="08:00:27:8a:39:05", NAME="vagrant", SUBSYSTEMS=="pci"
Applying the New Rules
Now that you’ve written the new rules it’d be nice to apply them without having to reboot.
EDIT: In Ubuntu 16.04 you have another option.
systemctl restart systemd-udev-trigger.service
That can be a little complicated and is totally disruptive to networking traffic likely on all interfaces but the procedure looks like this:
- Detect the driver used by each interface that requres a remap. The easiest way is to use
$ ethtool -i eth0 driver: e1000e version: 3.2.6-k firmware-version: 0.2-4 expansion-rom-version: bus-info: 0000:00:19.0 supports-statistics: yes supports-test: yes supports-eeprom-access: yes supports-register-dump: yes supports-priv-flags: no
You could potentially use this technique:
$ basename $(readlink /sys/class/net/eth0/device/driver/module)or this one:
$ basename $(readlink /sys/class/net/“+interface+“/device/driver)
YMMV depending on the driver in use. - Remove the driver that is shared/used by each interface that is to be remapped (other interfaces that are using that driver may get caught in the crossfire here).
$ modprobe -r e1000e
- Run the following command to detect the newly installed rules
$ udevadm control --reload-rules
- Apply the new rules with the last command
$ udevadm trigger
Applying the new rules with the trigger operation will also reinitialize the driver that you’ve previously removed.
Presto you’re done.
Man, really nice blog post. It helped me find a strange issue where a linux bridge (br1) would be rename to rename6 out of no reason.
It turns out that the bridge takes the MAC address of one of the interface and when udev was trying to set up the bridge, it would get assigned the same MAC address as the interface and udev would just decide to rename it.
The fix was to “strengthen” the matching rule for the net interface by adding the SUBSYSTEMS match, which is missing on the bridge interface.
SUBSYSTEMS==”pci”, SUBSYSTEM==”net”, ACTION==”add”, ATTR{address}==”00:xx:xx:xx:xx:xx”, NAME=”eth1″
SUBSYSTEMS==”pci”, SUBSYSTEM==”net”, ACTION==”add”, ATTR{address}==”00:xx:xx:xx:xx:xx”, NAME=”eth2″
SUBSYSTEMS==”pci”, SUBSYSTEM==”net”, ACTION==”add”, ATTR{address}==”00:xx:xx:xx:xx:xx”, NAME=”eth3″
LikeLiked by 1 person
Glad it was helpful I hit the same problems and wanted to make sure I remembered what to do not if but WHEN I saw it again!
LikeLike