Home | Linux |     Share This Page
Consistent Network Device Naming

Another Linux kernel conceptual breakthrough (and how to repair it)

All content Copyright © 2011, P. LutusMessage Page

Introduction | What's In A Name? | Python To The Rescue
Conclusion | Reader Feedback | References

(double-click any word to see its definition)

Introduction

There's an old saying about the cure being worse than the disease, and I think this may be one of those times. In the present Fedora 15, and slated to be added to other Linux distributions as time passes, there's a new naming scheme for network interface cards (hereafter NICs) called "Consistent Network Device Naming" (hereafter CNDN).

CNDN is a pet project of Matt Domsch of Dell, Inc.. It's meant to avoid some of the pitfalls that arise from allowing kernel NIC names to percolate unchanged into the operating system and the outside world. Mr. Domsch and Dell have created a utility named "biosdevname" that uses a reasonably simple algorithm to consistently map the raw NIC hardware names to some new names that are meant to prevent the confusion that sometimes results from systems with multiple NICs. The confusion can result from moving NICs around in a chassis during upgrades and maintenance, or because of a race condition that may randomly assign NIC names based on the timing of events during boot-up.

The basic purpose of "biosdevname" and CNDN is to prevent a particular NIC from having different names at different times — that's all it does. For a rack-mounted server with multiple NICs, this is an important precaution. But on a system with only one NIC, a typical end-user system, CNDN serves no purpose.

To a typical end user, installing Fedora 15 means seeing your NIC's name change from "eth0" to "em1" if the NIC is embedded in the motherboard, or "p12p1" (or something similar) if your NIC is attached to the PCI bus (as on one of my systems).

What's In A Name?

Isn't this a tempest in a teacup? Does anyone really care what name a NIC has? Well, unfortunately, there are many applications and scripts that have the name "eth0" hard-coded into them. Many of these examples arise from laziness or shortsightedness, but some example have a purpose, a case where the NIC name must be hard-coded.

Can you think of an example where hard-coding "eth0" into an application might makes sense? Well, I can. Let's say an application has a high dollar value, such that end users might want to make and run copies. One classic strategy to prevent installation and use on multiple systems is to query the system's NIC, get its MAC address (a unique 48-bit address given to every NIC during manufacture), and use the MAC as an authorization key along with a password.

In the above security scenario, allowing users to specify a different NIC would undermine the scheme. Users could specify the name of a virtual NIC, circumvent the security system, and cheat the manufacturer. So, because low-level operating system calls that acquire MAC addresses require a NIC name to be submitted as a text string, the NIC name must be hard-wired into the program. This is not an accident or an example of programmer laziness — a hard-wired NIC name is essential.

How many programs use this security scheme? Well, many. There are some security vulnerabilities involved in using MAC authentication, but this hasn't prevented wide adoption. Some very expensive programs use MAC authentication — one example is Mathematica, which costs about US$2500.00 at the time of writing for an unrestricted license. (MATLAB uses the same basic authentication scheme.)

I happen to have Mathematica 5.0 on one of my systems, and when I installed Fedora 15, it ceased to function. It was while investigating what caused this expensive program to stop working that I became aware of the downside of CNDN. I realized I had certain options to make Mathematica operational again:

  1. Give Wolfram Research more money.
  2. Go back to Fedora 14.
  3. Figure out a way to return to the old NIC naming convention.

Option (1) fell right off the table — I've given Wolfram Research way too much money over the years, and because of the appearance of free programs like Sage (link to my Sage tutorial) and new tools like WolframAlpha, those days are past. But I wanted to keep my copy of Mathematica operational.

Option (2) wasn't realistic — I decided not upgrading Fedora was too much like the (possibly apocryphal) behavior of an ostrich, who, when faced with a scary new challenge, buries his head in the sand.

I did some online research and discovered there is a kernel argument that's supposed to prevent the biosdevname utility from being invoked — it's "biosdevname=0". That's the good news. The bad news is this kernel argument only works during installation, it has no effect afterwards.

It turns out the NIC naming activity is under the control of udev, and therefore can be modified by editing the udev rules scripts located in the /etc/udev/rules.d directory. In Fedora 15, a script located at /etc/udev/rules.d/70-persistent-net.rules contains the logic for the renaming. A typical rule looks like this (line-wrapped to fit on this page):

# PCI device 0x14e4:0x167a (tg3) (custom name provided by external tool)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="03:1a:a3:dc:98:8d",\
ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="em1"
            

In principle, one could simply change the NAME field from "em1" to "eth0", save the changed file and reboot, and for users with only one system to deal with, that's what I recommend. But for administrators of many systems, each of which has just one NIC, I've written a better, automated approach.

Python To The Rescue

Below is a Python script that automates the process of reverting to the old NIC naming convention, for use by network administrators. It should be automatically invoked on each target system (and it should only be used on systems with one NIC). Instead of editing an existing udev script, it creates a separate script (99-old-style-net.rules) that only changes the name of the primary NIC. If one later chooses to return to the new naming scheme, the special script can be deleted without any other changes required (apart from a reboot).

The Python script:

  • Checks to see if there is already a script present that renames the NIC, and exits if there is.
  • Acquires the MAC of the primary NIC (udev requires the MAC of the NIC to be renamed).
  • Creates the new script and places it in the /etc/udev/rules.d directory.
  • Prompts the user for a reboot.

Click here for a plain-text version of the Python script.

Here is a pretty-printed listing of the Python script:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Copyright 2011, P. Lutus
# Released under the GPL
# http://www.gnu.org/copyleft/gpl.html

import re,sys,os
    
def write_file(path,data):
  with open(path,'w') as f:
    f.write(data)

def capture_com_output(com):
  with os.popen(com) as p:
    return p.read()

if(os.geteuid() != 0):
  print "Must be root to run this script."
  sys.exit(0)
  
path='/etc/udev/rules.d/99-old-style-net.rules'

if os.path.exists(path):
  print 'Configuration file %s already exists, quitting.' % path
  sys.exit(0)

data = capture_com_output('ip link show')

search_str = '(em\\d+|p\\d+p\\d+)'

if not re.match('(?s).*%s.*' % search_str,data):
  print 'Interface name not found with %s, quitting.' % search_str
  sys.exit(0)

mac_address = re.sub('(?s).*?\n?%s:.*?link/ether\\s+(\\S+).*?\n.*' % search_str,'\\2',data)

data =  'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", KERNEL=="eth*", '
data += 'ATTR{address}=="%s", NAME="eth0"\n' % mac_address

write_file(path,data)

print 'Created %s.' % path

reply = raw_input('This change requires a system reboot. OK to reboot? (y/N): ')

reply.strip().lower()

if(reply == 'y'):
  os.system('init 6')
            
Conclusion

There are plenty of problems with Microsoft Windows — one scarcely knows where to begin. But one factor contributing to the disaster that is modern Windows, is the degree to which Microsoft software development takes place in a vacuum, so completely removed from the needs of users that they might as well live on a separate planet. It is this breathtaking distance between developers and the needs of users that led former Microsoft executive Jim Allchin to say:

"I am not sure how the company lost sight of what matters to our customers (both business and home) the most, but in my view we lost our way. I think our teams lost sight of what bug-free means, what resilience means, what full scenarios mean, what security means, what performance means, how important current applications are, and really understanding what the most important problems [our] customers face are. ..."

To me, a longstanding advocate of Linux adoption, the difference between Linux and Windows is obvious — Linux developers care about users' needs. One reason is that Linux is the underdog, with only a small slice of the total operating system market. Linux is small and nimble. Linux has to care about users — it's "the right thing to do" and we can't afford not to.

At risk of oversimplification, the key difference between Linux and Windows is that Linux asks you what you want, and Windows tells you what you want. It would be a shame if this distinction should evaporate over time. It would be a shame if Linux kernel developers fell into the habit of introducing new features that affect end users without first asking end users what effect those changes have.

As to the Consistent Network Device Naming scheme, can I ask something — what's consistent about it? Yesterday I had six networked systems and one NIC name (eth0), so I could write scripts and applications without worrying whether they would work on all the systems. Now I have six systems and three NIC names (eth0, em1 and p12p1 — the 'eth0' names come from systems whose BIOSes can't support the new naming convention) more or less randomly assigned, and dozens of programs written by myself and others that assume the primary NIC name is "eth0".

In my opinion, because of its far-reaching consequences, a feature like Consistent Network Device Naming should be a user-selectable option, and it shouldn't be the default on an end-user system with only one NIC. Barring that suggestion, there should be an alias name for a system's primary NIC that exists alongside the new, better naming scheme described above. The alias name should be consistent and reliable. I suggest "eth0".

Reader Feedback
What about the Kernel Argument? Paul,

A quick Google search brings the this entry in several places:

Add the following to /etc/grub.conf to get eth0 back

biosdevname=0
Doesn't work — I tried it. Does this work, if not, why not? Because udev is instructed about naming rules during installation. After that it's too late for kernel boot flags, instead one must change udev's own rules, which is what my method does. It sure seems easier than messing around with a script. So why don't you try it? Many people, including the author of biosdevname, seem to think it works — but it doesn't. There is plenty of confirmation that it doesn't work on the discussion boards, by those who actually do experiments.

My method creates an independent script that can be deleted later if the user changes his mind and wants the new naming convention after all. It's very easy. And it has the significant advantage that it actually works.
In this instance, is it possible that your solution is a little over the top. You need to actually do some experiments, as I have done. I'm not guessing that a kernel argument of biosdevname=0 doesn't work, it's the first thing I tried. It only works during installation, not later.

Also, as explained in the article above, the simplest solution for an end user with one computer and one NIC is to edit /etc/udev/rules.d/70-persistent-net.rules and change "em1" to "eth0", save the file, and reboot.
I agree that the modern Linux developers pay little to no regard for the end user. I feel that biosdevname=0 should be the default. Let those who need this modify the standard. Leave the average end user alone. It turns out that the reverse case would be a variation on the same problem — if installation is carried out with the biosdevname=0 flag, then the system administrator would later have to edit udev scripts to get the new naming convention.

I just think this change wasn't thought through by those who put it in place. They didn't appreciate how many apps and scripts depend on a consistent name for the primary NIC.
References

Some online reactions to CNDN:

  • Why can't I activate MATLAB or run the license manager on Fedora Core 15? — In this acticle, MATLAB technical people offer a number of seemingly learned suggestions, none of which can solve the user's problem.

  • Breaking a few eggs: Fedora 15 changes network device naming (NetworkWorld). A quote: "For desktop users with a single Ethernet port, it won't make much of a difference." Wrong — see above. Applications that use MAC authentication are almost certain to break.

  • Consistent Network Device Naming updates from Matt Domsch's blog. A quote: "... for everyone who still thinks renaming devices is a really bad idea, you get an out. A new kernel command line option, honored by udev, lets you disable biosdevname. biosdevname=0 will prevent biosdevname from being invoked, effectively disabling this feature, leaving you with the ethX names." Actually, Mr. Domsch, no — not for a running copy of Fedora 15. That remedy only works at install time.

 

Home | Linux |     Share This Page