How Linux Assigns Persistent Network Interface Names
Modern Linux operating systems assign persistent network interface
names primarily through systemd-udevd to guarantee that
network hardware retains the same identifier across reboots and hardware
changes. Historically, the kernel dynamically assigned names like
eth0 and eth1 based on the order devices were
detected during boot, which frequently caused interfaces to swap names
unpredictably. Today, systemd and udev query
hardware topology, firmware information, and bus paths to generate
deterministic, stable names such as eno1 or
enp3s0.
The Problem with Traditional Naming
In earlier Linux architectures, the kernel probed hardware
concurrently during boot. If two network cards were installed, whichever
card responded first was named eth0, and the second became
eth1. This race condition often reversed the names after a
reboot, breaking firewall rules, routing tables, and static IP network
configurations. Persistent network interface naming solves this by
binding the interface name to physical or electrical attributes of the
hardware.
The Naming Scheme Hierarchy
The systemd predictable network interface device naming
mechanism implements a five-step fallback policy to establish stable
names. It checks properties in the following order:
- Firmware/BIOS Provided Index Numbers: If the system
firmware or BIOS provides an index number for an onboard device, that
number is used (e.g.,
eno1). - Firmware/BIOS Provided Hotplug Slot Numbers: If the
PCI card slot architecture provides a physical slot number, it is
utilized (e.g.,
ens1). - Physical/Geographic Location: If bus topology is
available, the physical hardware connector location on the bus is
derived (e.g.,
enp2s0). - MAC Address: If explicitly requested or if other
methods fail, the hardware interface's MAC address is used to form the
name (e.g.,
enx78e7d1ea46da). - Traditional Kernel Naming: If all predictable
mechanisms are unavailable or disabled, the system falls back to the
traditional naming convention (e.g.,
eth0).
Decoding Interface Prefix and Types
The generated name combines a two-character interface type prefix with a location identifier:
en: Ethernetwl: Wireless Local Area Network (WLAN)ww: Wireless Wide Area Network (WWAN)ib: InfiniBand
Following the prefix, the naming scheme applies specific format characters:
o<index>: Onboard device (Example:eno1for onboard Ethernet port 1).s<slot>: Hotplug slot (Example:ens3for slot 3).p<bus>s<slot>: Bus location (Example:enp0s31f6represents PCI bus 0, slot 31, function 6).x<MAC>: MAC address (Example:enx002596123456).
Configuration and Implementation via systemd-udevd
During system initialization, the kernel detects the network card and
generates a sysfs tree containing the device's hardware
attributes. Next, systemd-udevd evaluates these attributes
using predefined rules located in
/usr/lib/systemd/network/99-default.link.
This default configuration instructs udev to attempt
naming via firmware index, slot, and physical path, in that
sequence:
[Match]
OriginalName=*
[Link]
NamePolicy=keep kernel database onboard slot path
AlternativeNamesPolicy=database onboard slot path mac
MACAddressPolicy=persistentAdministrators can override this behavior by creating higher-priority
files in /etc/systemd/network/. For instance, to assign a
custom name based on a MAC address, a file named
/etc/systemd/network/10-eth-local.link can be created:
[Match]
MACAddress=00:11:22:33:44:55
[Link]
Name=lan0Disabling Predictable Naming
If traditional names like eth0 are required for legacy
scripts or specific testing environments, persistent naming can be
disabled at boot time. Passing the kernel parameters
net.ifnames=0 and biosdevname=0 via the
bootloader (such as GRUB) instructs the system to ignore firmware and
topology rules, allowing the kernel to assign names sequentially as it
probes each device.