skip to content

Why does a modern Linux server call its network card something like `enp3s0` or `eno1` rather than `eth0`, where do those names come from, and what problem was that change introduced to solve?

level: juniorimportance: should knowfreq 50%

answer

  1. names used to depend on boot timing
  2. two NICs, one race
  3. userspace renames, hardware does not
  4. firmware index, slot, or bus path
  5. the letters encode where it lives

basics

~20 s

Kernel names like eth0 were assigned in driver probe order, which could change between boots on multi-NIC machines. systemd-udevd instead derives a stable name from firmware index, PCI slot or bus path, giving eno1, ens3 or enp3s0.

solid answer

~40 s

The classic `eth0`/`eth1` names were handed out by the kernel in the order drivers finished probing. On a machine with two or more NICs that order is a race, so the card that was `eth0` yesterday could come up as `eth1` after a reboot or a kernel upgrade — and every firewall rule, bond definition and script that named `eth0` then pointed at the wrong hardware. systemd's udev now renames interfaces from something that does not move: the firmware/BIOS device index gives `eno1`, a PCI hotplug slot gives `ens3`, and the geographic PCI bus/slot path gives `enp3s0`. The two-letter prefix is the device type — `en` for Ethernet, `wl` for wireless, `ww` for WWAN. The names are ugly but deterministic for a given physical machine, which is the whole point.

go deeper

for a junior

Recall that eth0 came from boot probe order and that names like enp3s0 encode the card's location. Say plainly that you should not hardcode an interface name in a script.

for a middle

Explain that systemd-udevd performs the rename from a .link policy, decode the prefix and the o/s/p/x suffix forms, and name net.ifnames=0 as the way to opt out.

for a senior

Show judgment about fleets: know when pinning names with a MAC-matched .link file beats either scheme, and be able to explain why cloning a disk to new hardware can change the name.

for a principal

Own the naming convention as a platform decision — image strategy, configuration management keyed on stable identifiers rather than names, and the upgrade risk when a distribution moves to a newer naming scheme revision.

## The problem being solved Historically the kernel numbered network devices in the order their drivers registered them: the first Ethernet device became `eth0`, the next `eth1`, and so on. That order is not a property of the hardware — it is a property of how fast each driver's probe completed during that particular boot. With one NIC it never matters. With two NICs of different models, asynchronous driver initialisation means the assignment can differ between boots, after a kernel or firmware upgrade, or when a card is added. The consequence is not cosmetic. The interface name is the key that firewall rules, bond and bridge membership, static address configuration and monitoring all use. If `eth0` and `eth1` swap, a machine can boot with its public configuration applied to the interface plugged into the management network — a configuration error no file on disk records, because the files did not change. ## What replaced it On systemd-based distributions, `systemd-udevd` renames interfaces early in boot according to a naming policy. The default policy ships as a `.link` file (`/usr/lib/systemd/network/99-default.link`) and tries several sources of a stable identity, in order, stopping at the first that yields a name. In practice you meet these forms: - `eno1` — **o**nboard device, index taken from firmware (SMBIOS/ACPI). Typical for server motherboards whose BIOS reports which port is which. - `ens3` — PCI Express hotplug **s**lot number, again from firmware. Very common on virtual machines. - `enp3s0` — the geographic **p**CI path: bus 3, slot 0. Used when firmware supplies nothing usable. A function number appends as `f1`, and a VLAN or SR-IOV virtual function adds further components. - `enx001122334455` — derived from the MAC address; used for some USB adapters, where no slot exists. The leading two letters are the device type: `en` Ethernet, `wl` wireless LAN, `ww` wireless WAN, `sl` SLIP. So `wlp2s0` is a wireless card on PCI bus 2, slot 0. Note what "predictable" does and does not mean. The name is stable for a given physical machine across reboots and kernel upgrades. It is *not* stable if you move the card to a different PCI slot, clone a disk into different hardware, or change a VM's virtual topology — those genuinely change the identity the name is derived from, and that is by design. ## Controlling it Three levers come up in interviews: 1. **Turn the scheme off.** Adding `net.ifnames=0` to the kernel command line disables predictable naming and returns you to `eth0`-style kernel names. On some Dell hardware `biosdevname=0` is added alongside it. This is common on appliance images and cloud images that want a fixed `eth0`. 2. **Mask the default policy.** Symlinking `/etc/systemd/network/99-default.link` to `/dev/null` suppresses the shipped policy, since files in `/etc` override the same-named files in `/usr/lib`. 3. **Pin a name yourself.** Write your own `.link` file with a `[Match]` section keyed on `MACAddress=` and a `[Link]` section setting `Name=`. This is the clean way to get meaningful names — `Name=frontend`, `Name=storage` — rather than fighting the scheme. Avoid choosing names in the kernel's own `eth*` namespace when you do this, because a rename can collide with a name the kernel is still using. The naming scheme itself is versioned: systemd records which revision of the rules a release used, and a kernel-command-line option exists to pin an older revision so that a distribution upgrade does not rename interfaces underneath a machine. That option matters mostly to fleet operators upgrading in place. ## What an interviewer is really checking Three things. First, that you know the name is assigned by userspace udev, not baked into the hardware — which is why the name can differ between two distributions on the same box. Second, that you do not hardcode interface names in anything portable: a script that greps for `eth0` breaks on the first modern server it meets, and the robust patterns are to read the name from configuration, match on MAC, or ask for the interface associated with the route you care about. Third, judgment about when to disable the scheme — a golden image deployed to identical hardware may reasonably pin `eth0`, while a mixed fleet is far safer with the derived names. ## The short version `eth0` was a boot-order artefact. `enp3s0` is a statement about where the card physically is. The trade is readability for determinism, and determinism is what keeps a firewall rule pointed at the interface you meant.

  • How would you give an interface a meaningful name such as `storage` instead of accepting either scheme?
    Write your own `.link` file under `/etc/systemd/network/` with a `[Match]` section keyed on `MACAddress=` and a `[Link]` section setting `Name=storage`. Files in `/etc` override the shipped defaults of the same name, so the custom policy wins. Avoid names in the kernel's `eth*` namespace to prevent collisions during the rename, and remember the match is per-MAC, so replacing the card means updating the file.
  • Why can a disk image cloned from one server to another come up with a different interface name?
    Because the name is derived from where the card sits, not from the image. A different motherboard reports different firmware indexes, and a card in a different PCI slot yields a different bus/slot path, so `enp3s0` may become `enp5s0` or `eno2`. Nothing on disk changed, yet every rule naming the old interface is now wrong. Fleet images usually address this by pinning names or by keying configuration on MAC address.
  • What is the safest way for a script to refer to "the interface my traffic leaves by"?
    Don't hardcode a name at all — ask the kernel. Query the routing decision for the destination you care about and use the device it names, or read the name from the same configuration source that provisions the host. Matching on MAC address is the other durable option. Grepping for `eth0` breaks on modern servers, and even a predictable name changes if hardware moves, so deriving the name at runtime is the pattern that survives.

saying these in an interview costs you the question

  • Believes the interface name is a property of the card itself
  • Says predictable names never change under any circumstance
  • Hardcodes eth0 in scripts and firewall rules
  • Thinks the kernel, not udev, assigns enp3s0
  • Confuses the name with the MAC address as the stable identity

context