Logical Interface Names

From Exterior Memory
Jump to: navigation, search
This article was originally published at http://www.science.uva.nl/research/air/wiki/LogicalInterfaceNamesby me. The original page is no longer updated

How to reorder or rename logical interface names in Linux

One of the problems of Linux is that the order of the network interfaces is unpredictable. Between reboots the order stays the same, but after an upgrade to a new kernel or the addition or replacement of a network card (NIC) the order of all network interface may very well change. For example, what used to be eth0 now becomes eth1 or eth2 or vice versa.

Obviously there is some logic to which network interface gets which name, but Linux documentation states that this may change and no user or program should ever assume anything about this. This is annoying, in particular if your management interface is at eth1 at one node in a cluster and at eth2 in another node of the same cluster (which we have experienced). I personally like to have my (primary) management interface always to be at eth0.

Thankfully, there are ways to achieve this. They can be divided in four methods:

  1. Order the network interfaces based on the MAC address of the NIC.
  2. Order the network interfaces based on physical properties of the NIC.
  3. Order the network interfaces based on the driver of the NIC.
  4. Order the network interfaces based on the physical location of the NIC in the computer

Note: Linux kernels up to 2.4 did only probe for the first Ethernet card, ignoring other NICs. We assume you use a 2.6 or higher kernel or already fixed this, for example by specifying ether=0,0,eth1 as kernel parameter.

Based on the MAC address

Nowadays, the most common method to map a NIC to a name is to use the MAC address to identify a given NIC.

As a start, you must determine the MAC address of your interfaces. You can do this locally on a machine using

ifconfig -a

The MAC address is listed as "hwaddr" (hardware address). Alternatively, you can even determine MAC addresses remotely using ping and /sbin/arp.

There are three ways to do map the MAC address to the logical interface name. Either by using the udev device manager, get-mac-address.sh script, or by using the nameif program.

Using udev

udev renames interfaces based on their MAC address. It keeps a list of all MAC addresses it has seen in the past, and renames the interfaces to the interface name that it previously also had picked. If that interface already exists, it appends the string "_renamed".

The list of MAC addresses is stored in /etc/udev/rules.d/70-persistent-net.rules.

If your Linux distribution contains this file, this is the easiest solution.

The file looks something like this:

# wired interface
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:03:93:0d:d2:b7", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"

# wireless interface
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:30:65:38:64:fb", ATTR{type}=="1", KERNEL=="eth*", NAME="eth1"

Using the get-mac-address.sh script

If you still have a machine without udev (but use older device managers such as devfs and hotplug), you need another method. The get-mac-address.sh script relies on the the interface file present in Debian and Ubuntu. If you succeed in making it work for RedHat distributions (which files in the /etc/sysconfig/network-scripts/ directory), let us know.

On Debian, the get-mac-address.sh script is distributed as part of the ifupdown package (in /usr/share/doc/ifupdown/examples/get-mac-address.sh). With this script copied to some sane place (e.g. /usr/local/bin), you can then setup /etc/network/interfaces in this manner:

auto lo eth0 eth1

iface lo inet loopback

mapping eth0 eth1
	    script /usr/local/bin/get-mac-address.sh
	    map 00:37:E9:17:64:AF netA
	    map 00:21:E9:17:64:B5 netB

iface netA inet static
	    address etc...

iface netB inet static
	    address etc...%%

Source: https://www.gelato.unsw.edu.au/archives/gelato-technical/2004-February/000334.html

The disadvantage of this method is that defines a mapping, rather then changing the actual logical interface name.

Using the nameif program

Alternative to the get-mac-address.sh script, you can also use the slightly more convienant nameif program, which is distributed as part of the net-tools package on Debian.

The advantage of nameif is that you can specify the interface names in the /etc/mactab file:

ethmgnt 00:37:E9:17:64:AF
ethwireless 00:21:E9:17:64:B5

It is not possible to rename an interface to a name of an existing interface. So you can't rename eth1 to eth0 as long as eth0 still exists. It is possible to still swap the names eth0 and eth1 by using a temporary name (e.g. first rename eth1 to ethfoo, then eth0 to eth1 and finally ethfoo to eth0). It should be noted however, that this may lead to problems if you add another network cards or upgrade your kernel, and the interface names just before you call nameif are not as expected. Therefor, it is recommended to use other names like "ethmgmnt", "ethwired", "ethwireless" and "eth10ge", as shown in the example above.

Based on the physical properties

Perhaps the most elegant way to name the ethernet NIC is to do so based on their physical properties, like link speed and port type.

Using the ifrename tool

Ifrename is a tool specifically desgined to (re)name network interfaces based on characteristics like MAC address (wildcards supported), bus information, and hardware settings. It uses a control file (/etc/iftab) to specify rules about how the interfaces will be named. (thanks to Matt Baron for this tip.)

# Example /etc/iftab file
eth2           mac 08:00:09:DE:82:0E
eth3           driver wavelan interrupt 15 baseaddress 0x390
eth4           driver pcnet32 businfo 0000:02:05.0
# wildcard name: pick the lowest available name of air0, air1, air2, etc.
air*           mac 00:07:0E:* arp 1

Using the ethtool and ip programs

It is possible to check the NIC properties using the ethtool program, and to change the name using the ip program (thanks to Jollynn Schmidt for this tip):

if ethtool eth0 | grep -q "Port: FIBRE"; then
	   ip link set dev eth0 name not_eth0
	   ip link set dev eth1 name eth0
	   ip link set dev not_eth0 name eth1
fi

The disadvantage of ethtool is that it can only be run by root, even when you're only using it to query for information. Though this is a minor annoyance of ethtool, it doesn't matter in this case, since you have to be root to set a device name anyway.

Based on the driver

Warning: This only works if the driver is available as a loadable module. Not if it is built into the kernel. Thankfully, most drivers are loadable modules.

This is a relative easy method, since it does not rely on external scripts. The idea is to just load the kernel module for your eth0 interface before the modules for other network cards.

First of all, you must determine which driver is used for each network card. Thankfully Linux does have a system to load the appropriate driver automatically, based on the PCI ID of the network card. Unfortunately, there is no single command to simply get the driver (and other information like the link speed) based on just the interface name in Linux. Your best bet is to look for kernel messages:

dmesg | grep eth

This should give you a good estimate of the driver name. You can verify if the name indeed does exist and is loaded:

lsmod

Note: lsmod gave:

e1000           84868  0
tg3             70816  0

However, the 0 indicates that these drivers are not controlling any device! That is strange, since modprobe -r tg3 and modprobe -r e1000 do disable the network cards. Apparently, this is a flaw in lsmod or -more likely- my understanding of lsmod.

Note that running modprobe tg3 en then modprobe e1000 does bring them up in the correct order, with the correct interface names. This is a good check if this approach (using the driver to decide the interface name) can work.

Red Hat

In Red Hat, if the driver is called "tg3" (the Tigon driver), you simply specify the network name by adding this enty in /etc/modules.conf:

alias eth0 tg3

Debian

On a Debian system, /etc/modules.conf is generated automatically and should not be edited directly. Instead, create a file in the subdirectory /etc/modutils/ (do not use /etc/modprobe.d/, that seems out-of-date). For example, create the file /etc/modutils/interfaces and add the appropriate modules. For example:

alias eth0 tg3
alias eth1 e1000

Next, update /etc/modules.conf by running:

update-modules

Alternative method: I have encountered scenario's where the kernel did already load the modules for the drivers, even before /etc/modules.conf was read. The result was that in effect, the specification in /etc/modules.conf was ignored, and this method did not work. As an alternative, it is possible to also list the drivers, in the appropriate order, in /etc/modules (thus not /etc/modules.conf):

tg3
e1000

The result will be that the tg3 driver is loaded before the e1000 kernel. Since /etc/modules only exists for Debian, this trick will most likely not work for other distributions.

Based on the physical location in the computer

Warning: This only works if the driver is built into the kernel, not as a loadable module.

Note: It is relatively hard to get this to work, and we encountered problems with it. The other methods are recommended.

It is possible to name the network interfaces based on the interrupt (IRQ) and memory address. This should work if you have network cards in PCI busses, and it involves appending the proper parameters to the "ether=" or "netdev=" kernel parameters.

First of all, you can detect the PCI slot of the devices using

lspci -v

This is reported to fail sometimes for certain cards. Now, write down the IRQ and IO (memory) address of each network card, and use this information to specify the interface name in your LILO or GRUB configuration file.

For LILO, you need to add an add line to the appropriate boot configuration. For example:

append="netdev=irq=21,io=0x2040,name=eth0 netdev=irq=20,io=0x3000,name=eth1 netdev=irq18,io=0x2000,name=eth2"

Under grub, it can just be listed as parameter. e.g.:

kernel /boot/vmlinuz netdev=irq=24,name=eth0

More Information

More information can be found at:

  1. http://www.tldp.org/HOWTO/Ethernet-HOWTO-8.html
  2. http://www.tldp.org/HOWTO/BootPrompt-HOWTO-11.html

Copyright Notice

Written by Freek Dijkstra. Licensed under public domain. (That is, feel free to re-use it, and there is no need to mention the source, even though you are of course welcome to do so.)