"It Just Works" is more than just a slogan, it's a way of life!

Main menu

Post navigation

Consistent Network Device Naming coming to Fedora 15

One of my long-standing pet projects – Consistent Network Device Naming, is finally coming to Fedora (emphasizing the 2 of the Fedora F’s: Features and First), and thereafter, all Linux distributions. What is this, you ask?

Systems running Linux have long had ethernet network devices named ethX. Your desktop likely has one ethernet port, named eth0. This works fine if you have only one network port, but what if, like on Dell PowerEdge servers, you have four ethernet ports? They are named eth0, eth1, eth2, eth3, corresponding to the labels on the back of the chassis, 1, 2, 3, 4, respectively. Sometimes. Aside from the obvious confusion of names starting at 0 verses starting at 1, other race conditions can happen such that each port may not get the same name on every boot, and they may get named in an arbitrary order. If you add in a network card to a PCI slot, it gets even worse, as the ports on the motherboard and the ports on the add-in card may have their names intermixed.

While several solutions have been proposed over time (detailed at Linux Plumbers Conference last year), none were deemed acceptable, until now.

Enter biosdevname, the tool Dell has developed to bring sanity (and consistency!) to network device names. Biosdevname is a udev helper, which renames network interfaces based on information presented by system BIOS.

The new naming convention is as follows:

em[1-N] for on-board (embedded) NICs (# matches chassis labels)

pci<slot>#<port> for cards in PCI slots, port 1..N

NPAR & SR-IOV devices add a suffix of _<vf>, from 0..N depending on the number of Partitions or Virtual Functions exposed on each port.

Other Linux conventions, such as .<vlan> and :<alias> suffixes remain unchanged and are still applicable.

Else fall back to using the legacy PCI IRQ Routing Table to figure out which slots devices are in, sort the PCI device list in breadth-first order, and assign index values.

How will this affect you?

If you have scripts that have hard-coded eth0 or have assumptions that ethX is a particular port, your scripts are already broken (you may just not know it yet). Begin planning on using the new interface names going forward, adjusting your scripts as necessary.

Fedora 15 will be the first distribution to use biosdevname by default. There will be a Test Day on Thursday, January 27. I encourage you to download the Live image, boot it on your system, and verify that your network interfaces are now named according to the above convention, and that all works as expected. You may also take the opportunity to review your custom scripts, looking for hard-coded ethX values, and prepare for the coming name change.

Once we get sufficient exposure and verification using Fedora, I expect to see this change roll into other Linux distributions, and other operating systems, over time. Consider yourself warned.

46 thoughts on “Consistent Network Device Naming coming to Fedora 15”

Great ideas — especially since we can still rename these devices once we’re sure what they actually are.

One question though, “bios” is right there in the name, is this somehow BIOS-specific? Would EFI work? Other architectures altogether? If we’re talking about this extending to other distributions and operating systems, it’s a bit strange to imply it’s somehow heavily tied to BIOS.

@Jonathan: nothing changes about USB ethernet adapters. biosdevname doesn’t know anything about the physical or logical USB bus topology to be able to provide any better name than ethX so it won’t suggest a different name.

@Dimitry: the information biosdevname uses is currently only exposed on x86 architecture systems, via ACPI, SMBIOS, or worst-case, the legacy PCI IRQ Routing Table. These tables are also exposed on UEFI, so that works. Other architectures could expose similar information, which biosdevname could then learn to use, but I’m not aware of any that do. ARM via DeviceTree might be the next obvious candidate.

@FACORAT_Fabrice: there are no symlinks to network interfaces. That was one of the ideas that was rejected upstream. You can continue to create /etc/udev/rules.d/70-persistent-net.rules files, just as is done today, which takes precedence over invoking biosdevname then. Or you can ‘yum remove biosdevname’ if you so wish to permanently disable this feature.

VMware (Workstation 7 and ESX 4.1) both expose the first NIC as being in PCI slot #3, so its NIC is renamed from eth0 to pci3#1.

Neither KVM nor Xen today expose virtual machine BIOS information in a manner that biosdevname can use, so they don’t change their naming. There is a request to enhance bochs to export SMBIOS 2.6 information, so this could change over time.

How well does this play with BIOSes that allow you to change the order that PCI buses are enumerated? If you flip from “Descending” to “Ascending” in the BIOS, are all your NICs going to be renumbered from pci0#0 (first PCI slot) to pci4#0 (last PCI slot)?

And, how does this this affect the order that kernels enumerate PCI buses? There’s nothing worse than doing a kernel update (2.6.x -> 2.6.x+1) and finding all your NICs have been renamed because the distro makes decided to flip a config option in the kernel.

At my old job we used the HWADDR fields in ifcfg-* to map from eth* to lan* namespaces – and found the physical location of the device via sysfs. These physical path names may be useful in some contexts, if only because they are susceptible to matching via regex, but when I set up a bunch of compute nodes, I’d often still like, e.g., lan0 to be the private network interface, lan1 to be the storage network, lan2 to be the network.

@Freddie: the only time biosdevname cares about PCI device ordering is if BIOS doesn’t provide an explicit naming indication via ACPI or SMBIOS. If BIOS does provide that info, that’s used. If not, it falls back to info in the PCI IRQ Routing Table plus assumes breadth-first ascending order for enumerating devices in the same slot (or embedded).

@Bill: nothing stops you from using additional udev rules to do so. I personally prefer “logical” names for devices, but you have to have some physical frame of reference that’s meaningful to you. With biosdevname, that’s the chassis labels. I couldn’t get the concept of “device aliases” pushed at this point, but that’s my longer-term hope.

@Mark: em* isn’t Dell-specific. Dell-specific would be if it used “Gb1″. I didn’t want to switch away from eth*, but given that the kernel owns that namespace and it’s completely arbitrary and non-deterministic, have no choice. You’re welcome to provide a “better” naming convention, but this is what has been hashed out on the Linux developer mailing lists (netdev in particular).

This new model is very bad if you’re automating things. It looks like if I’m not on a Dell or HP server, I have to figure out what my IRQ routing table looks like to determine my device name, then figure out how the system sorted them then address the card. This looks like the old days when I had to provide an address for my sound card in old DOS games… What a regression! I also wonder what happens if you move the operating system to another system? Oh god, my network interfaces have just been renamed! Why didn’t you guys use Debian’s model to keep consistancy? The MAC address is paired with a device name, and this won’t change on reboot or on kernel change. You can also easily manually change the order if you need something different.

To top it off, this new model doesn’t include a common prefix so I can’t hack something to list network devices.

I understand this is your pet project, but a little consideration for people automating different part of an operating system life (such as the installation…) would have been appreciated.

@not-a-fanboy: the idea is – you _don’t_ have to know all that stuff. Your BIOS knows already. You just need to know “I’m going to plug in my public network ethernet cable to the NIC on the motherboard” vs “I’m going to plug in my private network cable to the NIC in PCI slot 2″.

If you move the OS disks to another system – you get device names for the NICs in _that_ system, not a pile of ethX names that no longer match what you had before. So em1 on System A is still em1 on System B, even though the MAC address has changed. Without biosdevname, on system A if you have eth0 and eth1, when you move the disks to system B, you get eth2 and eth3, not eth0 and eth1 – their MAC addresses aren’t there, and thus don’t match.

@not-a-fanboy: also, at install time, there are several other methods you can use, including ksdevice=link (if you have only one cable plugged in), ksdevice=bootif (if you’re using PXE). If you’re using neither and have >1 NIC, then hard-coding eth0 may get you the “wrong” NIC.

Thank you. Thank you. Thank you. I’ve been waiting for this for a long time. Every new server build, I usually spend some time verifying and correcting NIC names to make sure the physical interfaces match up with the names in the OS. It would be nice to have this feature.

Regarding the use of # in the PCI names, I realize that you’ve worked around a few cases where this breaks, but have you considered just using another character instead? pci[slot]p[port] would work just as well (and even indicate “port” a bit more mnemonically), as would pci[slot]_[port].

Since you mentioned it in the blog post… Fedora still sitting on that awkward old “:alias” thing is horrible. Please, just get rid of this BSD hack. Other distros like openSUSE can already do this (setting an interface to have multiple addresses, without the alias thing). Speaking of which, I don’t remember Fedora supporting prefixlen notation either (“IPADDR=1.2.3.4/24″ that would be in suse’s sysconfig.)

eth0:0 aliasing format is not a “BSD hack”. BSDs have been able to add multiple IPs to an interface for many, many, many years (FreeBSD 3.1 had it, first BSD I used). Linux systems are the only ones I’ve seen with use eth0:0 format for adding IPs to an interface.

I have been looking forward to this for a long time too. No one would take a Cisco router seriously with non-deterministic device naming. It would be a administrative nightmare. Now Linux servers with multiple network interfaces can have the same stability, which is much appreciated.

What I want to know is why don’t onboard disk interfaces have similar deterministic naming rules. sata0..4 for example. Currently, if I have hda and hdb in a raid 1 pair on a simple two slot server, and one of them fails, the replacement drive becomes hdc and stays that way until the next reboot. Even c0t0d0s0 would be better than that.

It isn’t all that helpful for physical _disks_ to have _device_ names. That is what UUIDs and volume labels are for. For virtually any sort of direct attached server setup, what one needs are deterministic device names for disk _slots_ . How does someone with a large cardinality JBOD manage if the assignment of hda-hdz by slot is random from day to day?

I have used my own Python scripts for years that:
1. Delete udev files to re-probe Ethernet hardware for newly cloned Fedora systems.
2. Make adjustment to the udev files to get the eth names to match physical locations.
I hope biosdevname is as open ended as what I currently use.

“If you have scripts that have hard-coded eth0 or have assumptions that ethX is a particular port, your scripts are already broken (you may just not know it yet).”

that sounds not funny, like breaking well known and working scripts?
OS or OS Distribution Changes can be sad and many developers can’t or won’t keep changing what already works. i hope that there will be a fallback or alias device.

Anyone else expect an interface named pci0#0 to be a link made from PCI bus technologies, not a link from ethernet technologies? If this naming for ethernet interfaces gazumps “pci*” then what name would a network interface made using PCI technologies reasonably use?

The use of a special character doesn’t fit with current practice. The current use of non-alphabetic characters allows the base name of the interface to be determined by trimming from the special character onwards. For example, eth0.1, eth0:1, eth0.1:0 are subinterfaces of eth0 — if I drop eth0 then the subinterfaces drop too. It’s not true that pci0#0 is a subinterface of pci0 — pci0#0 and pci0#1 are in no way related, networking-wise.

Thanks Glen. First, there is no “pci0″ specifically. It’s a PCI slot number (as in, that black or white socket where an add-in PCI card goes), so pci1#1 is the card in PCI slot 1 (as the chassis labels say), port 1 (this could be a single-port or multi-port card). If in the future we have a different non-PCI technology but that has sockets/slots, I expect we would use a different set of letters to denote that technology.

Now, I get your point, but I hadn’t thought of it in those terms before, and don’t have a way to rationalize it with the above “it’s in a PCI socket, look at the chassis label” mindset I’m coming from.

Yes, lots of complaints about choosing ‘#’ as a delimiter. I get it. We even found out today through the Test Day that the anaconda kickstart parser is broken by this. Oops. In my tree I’ve changed it to ‘p’ (for “port”), but that may not stick.

The problem with special characters is there are so many of them already in use, either in this scheme, or elsewhere. ‘/’ is illegal (due to being exposed in sysfs), as are spaces (naturally). ‘.’ is used as a VLAN delimiter. ‘:’ is used as an alias delimiter. ‘_’ is used by this scheme to denote partitions (NPAR) or Virtual Functions (SR-IOV) of the same port. There’s no one single special character from which you can delimit to be the “drop from here on” part here, even if I use ‘p’ for port.

Some people have suggested replacing ‘#’ with ‘@’. pci2@1_3.1234:1 for a longish example (remember, it has to stay in 15 chars). pci2p1_3.1234:1 would be if we use ‘p’. I don’t find either that readable, IMHO ‘#” is more readable. But we need to paint this bikeshed soon and not look back.

@Patrick: the number for is based on the chassis labels. If you look at the picture at the top of the next blog post (https://domsch.com/blog/?p=470) you see a big bold “2” to the left of the PCI slot. That is PCI slot 2, and in this naming convention, its NICs would be pci2#1, pci2#2, …

As there is only a single name for a device, once it has been renamed from eth0 to pci2#1, there is no record of what the name was before. Besides, a different device may have been named eth0 by the kernel after the original eth0 was renamed to pci2#1.

Unfortunately (and I don’t know is it’s possible to work around this) “slot 2″ is not always “slot 2″.

A simple flip of a BIOS option can renumber the PCI slots. For example, on our Tyan motherboards (S2882) with 5 PCI/PCI-X slots, one version of the BIOS counted them the same was as the marks on the motherboard (ascending). Another version of the BIOS switched the numbering (descending). Thus, PCI slot 1 became PCI slot 5.

Same with the newer Tyan motherboards (S3992) we use with PCI, PCI-X, and PCIe slots.

With a co-operating BIOS/ACPI implementation, I can see this being useful. But how well does it work when the BIOS/ACPI implementation doesn’t co-operate?

Then you can report bugs to your motherboard manufacturer. Me, I walk down the hall to the “BIOS Corral” and corner the authors. You will be able to trivially disable biosdevname from running, reverting back to the traditional Linux behavior, should you need to.

Most embedded network cards are actually connected to pci-bus on motherboard as well including those wireless cards which are just mini-PCI cards on pci-bus. Also using pci is very PC’ish and linux is pretty much now everywhere especially embedded devices. Linux does indeed run on very different kinds of platforms today.

Thus for me it appears that most prevalent and providing future proof — no need to change again would be simple schema which idea can be well copied from HP-UX and Solaris disk naming schemas. There the idea is as follows:

/dev/c{controller-num}d{device-num}l{lun-num}s{slice-num}

That reflects 1:1 what is found on hardware and doesn’t change as long as
you don’t mess hardware with changing the slots where the controllers are or the controllers to different models etc.

That same naming schema did not have to change on a migration from SCSI to FC nor does it have to change when next generation DAS technology is being supported.

That schema has worked without any problems over 20 years there. Everybody from os-support to admins and users are very happy. No unpredictable changes is good thing.

OK, back to ethernet and/or network devices, I would suggest that you consider the above and then following

/dev/nc{controller-num}d{device-num}a{lun-num}v{vf-num}

Ofcourse some will think that it’s too cryptic and complicated, but AFAIK it would be quite easy to provide familiar aliases eth[0-x] at least for few first whatever found NIC’s for those who never need the complicated but exaclty hardware reflecting naming.

Oh, and whenever I have had problems with server with multiple nic’s and changing suddenly order of eth0 etc it has never been the case of having pci-slot card versus the embedded motherboard card. It’s always been the case of getting the motherboard nic’s changing after install or wrong order first place. Thus I think your proposal with naming does not solve this issue at all. The bios-order thing propably will, but that is different animal from the naming issue me thinks at least partly is.

The use of ‘pci’ in the naming scheme is not so much about the bus the device is connected to, but the slot name (e.g. “PCI slot/socket #1″) as labelled on the chassis.

I don’t know how HP-UX defines a permanent ordering for {controller-num}, {device-num}, {adapter-num}, and {vf-num} in your scheme. Without some additional information, if it’s merely discovery (enumeration) order, it would suffer the same problem as Linux kernel’s ethX convention.

The suggestion to use /dev/nc* names – using the file system to expose devices, was rejected by the upstream kernel maintainers. Likewise the idea of “aliases” – multiple names for the same device.

As for never having names change – I have, repeatedly, and on several vendors systems, had the names change due to configuration differences or changes, or simple device naming races completing differently. If the problem didn’t exist, I wouldn’t have spent a good portion of the last 5 years trying to solve it.

About /dev/ prefix, that was my bad. Sorry, I did write it quite quicly and as it was tl;dr; properly :/

So I did not actually try to propose adding /dev/ prefix. But about the rest of the issue how this numbering is done on HP-UX and SunOS would be certainly worth studying IMHO.

HP-UX was long time running EISA bus before transition to PCI, Sun had it’s SBUS then PCI. But the crux of the matter is that both have been using that PCI well over decade now and somehow they are able to enumerate devices there consistently and so that they are able to keep configuration from OS point of view very stable.

I do not unfortunately know that how that is done in detail, but having used that loooong time aside with linux servers (done that since -91 already) I must say that classic enumeration has been tremendous help on daily work and many many migrations over the years.

Don’t get me wrong. I’m not condeming what you do I just wanted to pop in and suggest first to study further and avoid reinventing the wheel if it’s anyhow possible

Oh, one way to find out was to do some type of clean-room one guy reads the OpenSolaris or if someone has access to HP-UX source code (having proprietary os-code is not that uncommon large enterprises, we did have SunOS & SYSV R4 code since -90) and describes in detail how it works. Then someone else writes and implements that same functionality.

That has been done many times to overcome copyright and it’s common practise where patents doesn’t prevent it.

If anyone thinks going that better seek legal advise before jumping in however, IANAL.

1. the order/mapping MUST be stable over reboot cycles
2. the order/mapping MUST be stable if I change a NIC (add, remove, switch off in BIOS)

All other things are IMHO subject to udev rules, the renaming etc. is better done there. So for compatibility reason you (or the distro) may use special crafted udev rules.
Please introduce this the sooner the better! No more discussion about this ‘#’ problem or naming schema <;-)