Nuts and Bolts Admin Story: Device Names Lead image: © cbpix, 123RF.com
© cbpix, 123RF.com
 

Discovering device names

Find Nemo!

Ethernet devices in Linux have always been called eth0 and nothing else. All of a sudden, this universal truth has lost its validity, and Linux administrators need to understand why and how. By Thorsten Scherf

Recently, a customer asked me what was going on with his system. All of a sudden, he no longer had an eth0; instead, he was seeing strange names like em1 or p3p1 at the console. He wanted to know exactly what was happening.

The explanation is fairly simple. The rule-based udev subsystem is responsible for naming. If all criteria for a rule match a network device found at boot time, the device is typically given the defined name, such as eth<X>. Here's an example:

# grep eth0 /etc/udev/rules.d/70-persistent-net.rules
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="f0:de:f1:d5:c1:25", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"

The rule says that a network device with the stated MAC address should be given a device name of eth0 and thus be the first device visible on the system. The name in the file is arbitrary. If you like, you can call the card public or private. This principle works to a certain extent. The downside is that you don't know which card exactly this is on the system. The only thing that is clear is that it is the card with the stated MAC address; whether this is also the first network device on the system remains unclear. For system administrators, this situation has always been a big worry. If you've ever stood in front of a server with a dozen network ports looking for eth0, you will know exactly what I mean.

Danger of Confusion

The situation is aggravated in network installations where the TFTP boot request is sent on eth0, but the installer later sends the DHCPDISCOVER message via a different network card identified as eth0. This situation is really fun to troubleshoot.

I would like the name I see on the system to be identical to the chassis name so that I can see directly whether this is an onboard network port or a port on the external PCI card. You can get help from various tricks, such as, letting the LED on the card flash by issuing an

ethtool -p eth<X>

command, or telling the installer to use the network card via which the boot image was loaded for the installation by issuing ksdevice=bootif. However, this approach is not convenient.

Early in 2011, some Dell developers published a new tool called biosdevname under the GPL. Biosdevname ensures that the system BIOS detects the arrangement of the network devices and passes this information to the operating system. The operating system thus knows whether this is an onboard card or an external PCI adapter, and it detects the exact port on the mainboard or the PCI card.

The nomenclature, also known as Consistent Network Device Naming, then follows this pattern. The names of onboard NICs are:

emPort-number_instance_of_virtualFunction

(e.g., em1 for the first onboard card). The situation for external PCI cards is:

pSlot-NumberpPort-number_instance_of_virtual_function

(e.g., p2p1 for the first port on the external NIC in slot 2).

Virtual functions are used when the network card supports Single Root I/O Virtualization (SR-IOV). This functionality makes it possible to split a single PCI device across multiple virtual systems without sacrificing performance. A virtual system is then assigned a virtual function of the device. For example, a network card with a single port appears with multiple entries in the lspci output on the hypervisor (Listing 1).

Listing 1: Virtual Network Interfaces

# lspci | grep -i ether
07:00.0 Ethernet controller: Intel Corporation 82576 Gigabit Network Connection (rev 01)
# modprobe -r igb
# modprobe igb max_vfs=2
# lspci | grep -i ether
07:00.0 Ethernet controller: Intel Corporation 82576 Gigabit Network Connection (rev 01)
07:10.0 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
07:10.1 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)

The first entry relates to the physical function of the card, and the other two relate to the virtual functions, each of which can be passed on to a virtual system with a simple PCI assignment.

On a system with biosdevname enabled, the following device names thus exist for the network card mentioned above in PCI slot 3: p3p1, p3p1_0, p3p1_1. The designation for the network technology, such as VLAN or aliases, is kept. For example, p3p1:0 designates an alias for the network device p3p1 with more than one IPv4 address.

Info from the BIOS

What tells the operating system which slot a card is plugged into or which ports a card offers? The answer is fairly simple: The system BIOS (on current Dell and HP systems) stores this information in two tables: 9 (for external PCI cards) and 41 (for onboard cards).

The biosdevname simply accesses the tables and writes corresponding entries to a new udev rule. The rule is then responsible for the network cards being given their new names. If the system does not have a current version of SMBIOS, or if the information is missing from the corresponding tables, biosdevname can also access the data from the PCI IRQ routing table. The dmidecode and biosdecode tools provide this information on request. Alternatively, the script in Listing 2 can help.

Listing 2: Hardware Check

# curl -s https://fedoraproject.org/w/uploads/3/38/Biosdevname-support-check.sh | bash
Checking hardware requirements              [  OK  ]
Checking for SMBIOS type 41 support         [  OK  ]
Checking for SMBIOS type 9 support          [  OK  ]
Checking for PCI Interrupt Routing support  [  OK  ]

New Rules

Figure 1 shows the information path from the hardware to the application, which then sees the device names defined by biosdevname. The udev rule that implements the device names looks like this:

From the hardware via udev to the application.
Figure 1: From the hardware via udev to the application.
# grep PROGRAM /lib/udev/rules.d/71-biosdevname.rules
PROGRAM="/sbin/biosdevname --smbios 2.6 --policy physical -i %k", NAME="%c", OPTIONS+="string_escape=replace"

You can see that the biosdevname assigns a device a new name (%c) directly after the kernel driver has detected the device (%k).

If you want to use the new nomenclature on your system, you should first run the script above to see whether your hardware provides the desired information. Then, delete the /etc/udev/rules.d/70-persistent-net.rules file. You want the device names to come from biosdevname and not be set statically by udev. Finally, you must rename the configuration files for the network cards below /etc/sysconfig/network-scripts/ and change the DEVICE entry to a new name.

Red Hat Enterprise Linux as of 6.1, Fedora as of Version 15, and the current versions of openSUSE, SUSE Linux Enterprise Server, and Ubuntu already use the new naming approach, and the installer uses these new names during the installation. If you can't or don't want to change scripts that point to eth<X>, you can revert to the old way using the biosdevname=0 parameter at boot time.