If you are running a recent ubuntu release ( > 15.XX ), you've probably noticed
that your net interfaces have been "rebranded". Maybe this noticing came in the
form of your sripts being broken....your
/etc/network/if-up.d/XXX script or
vagrant-libvirt deploy failed because you hard coded an interface name in your
scripts (bad practice which im guilty of). It worked previously on your
old-release, then you had to upgrade...but I digress.
In this post, I'll try talking about how net devices get their names, the schemes employed and the tech behind the schemes.
The classic naming scheme -
Not so long ago, without any devops intervention, interface names were decided solely by the Kernel based on the order in which they are enumerated which in turn is based on the order in which their modules/drivers are loaded and then, where multiple NICs catered for by the same driver are present, they'd be named in the order in which they were discovered which in turn is again affected by the order in which the PCI device list is enumerated.
When its all done, you'd have something like this :-
eth<index> = ethernet,
wlan<index> = wireless,
usb<index> = usbnet - prolly phone-tethered
While the scheme is good enough to tell about the type of connection, there's
not much in the way of name predictability and telling about the nature of
the hardware that provides a given interface i.e. are
by different ports on the same NIC? Is
eth2 provided by a USB adapter?
Another problem is that if you leave it all up to the powers behind the scheme, the device naming will probably not be the same after kernel, NIC or motherboard upgrades or sometimes even reboots.
It's possible to get around the above mentioned limitations using scripts and udev rules but we live in modern times and techies should not be bothered to jump through those hoops just to sort out something that should be automagic.
One of the efforts at bringing order out of chaos is dell's biosdevname
project which according to the project description is
a udev helper for naming
devices per BIOS names. This helper-utility determines device names based on
intended order of network devices as suggested by the BIOS.
With the default policy, the naming scheme of it goes like so:-
- On-board net devices get named
- Add-on NICs devices get named
<slot>= the respective PCI slot,
<port>the port number...for multi-port NICs.
<virtual instance>is the SRIOV and/or NPAR instance index
- The "p"s in the Add-on card scheme stand for pci slot and port respectively
The above scheme is implemented here:- naming_policy.c
If you have the utility installed, you can try it out by booting your kernel
biosdevname=1 option or just run
biosdevname -i eth0 #(swap eth0
with any interface you have) from the terminal. If conditions are right,
you should get something along the lines of
With this utility, names are stable, predictable and you can also tell what's embedded and what's slotted in...but it has it's limitations, one of them being that it doesn't cater for a wider range of interface types/devices. It refused to name my usb ethernet dongle.
systemd udev -
Starting version 197, shortly after udev was absorbed into systemd source tree, native predictable naming was added to the mix.
According to the systemd wiki on the topic, and the systemd-udev sources, the names are generated based on:-
- firmware/bios-provided for on-board devices -
- firmware/bios-provided for pci-express hotplug slot -
- physical/geographical location for PCI devices -
- the devices's MAC address -
<type>is a two character prefix that tells the nature of the device/connection:-
sl= Serial Line Internet Protocol,
wl= Wireless LAN/Wi-Fi and
wwfor Wireless WAN (LTE/3g device, probably even WiMAX)
<domain>is pci device domain.
<function>= SRIOV(or maybe also NPAR?) number for multi-function PCI devices.
u<port>is a usb port
Thus for example
eno1 is an onboard ethernet device,
enp8s0 should be an
ethernet interface provided by a device on bus #8 slot #0 with only 1 port and
wlp9s0 should be an wlan interface provided by device on bus #9 slot #0.
On trying out a usb ethernet dongle, I got
enp0s29f7u1 and going by the
location/path scheme we can tell that it's an ethernet interface provided by a
usb device connected to a usb controller on PCI bus #0, device #29, with function #7
plugged into usb port #1.
systemd-udev Naming Policy
Net devices may have more than one name generated for them which you can view by querying the udev database (filtering the results):-
udevadm info -q property -p /sys/class/net/ens33 | grep ID_NET_NAME ID_NET_NAME_MAC=enx112233445566 ID_NET_NAME_PATH=enp2s0 ID_NET_NAME_SLOT=ens33
In the above example, we have names by mac, location and bios provided index.
The choice of name is determined by a list if policies defined for
in the respective link config file (see
man systemd.link). To find out what
link file is in use, query udevadm like so:-
udevadm info -q property -p /sys/class/net/ens33 | grep LINK_FILE ID_NET_LINK_FILE=/lib/systemd/network/99-default.link
I get 99-default.link, contents of which are:-
cat /lib/systemd/network/99-default.link [Link] NamePolicy=kernel database onboard slot path MACAddressPolicy=persistent
Looking at the
NamePolicy entry, the precedence is defined by the order
in which they appear and the first successful one is used to set the device name.
In this case with ens33 being chosen,
slot passed and
path wasn't considered.
systemd-udev is now standard on most big name distros (ubuntu included) and has
naturally superseded biosdevname where it reigned. There is no need to sweat it out
with unpredictable interface names like the techies of yesterday but just in case
you want to, you can disable all manner of predictability by passing
biosdevname=0 to the kernel at boot time.