Persistant enumeration of network interfaces across hardware addresses

If you’ve ever created a Linux virtual machine image for distribution, you have probably encountered this problem. The Virtualization is not really important – the problem exists on VirtualBox, VMWare, KVM, Xen and others supporting Linux guests.

So, what is the issue exactly?

The problem is that when you recreate a a virtual machine using an existing image, a new MAC address is generated. Udev sees this new address and creates a static name for it – e.g. eth1. Keeping the original – now removed – eth0 in the persistant naming file.

This interface typically does not exist in the /etc/network/interfaces file, and therefore is never “upped”. This leaves you with a machine that has no network connection out of the box.

Well, how do I fix it then?

The simple solution is to remove the /etc/udev/rules.d/70-persistent-net.rules file and reboot.
This means you have to remove the file as the last thing you do before shipping the image. I you make changes to the image, and reship it – you must do this every time. Plus it prevents easy redistribution of your image.

So, I’ve placed a small bash script at /usr/local/bin/reenumerate_interfaces and called it from /etc/rc.local.

This script also have the advantage, that you do not have to reboot the machine for the changes to take effect.

#! /bin/sh
echo Re-enumerating the network interfaces...
# Stop networking
/etc/init.d/networking stop
<pre lang="bash">
# Get the drivers and bounce the NICs
lspci -nnv | awk '{
if ($0 ~ /^$/) { getDriver = 0; }
if (getDriver == 0 && $0 ~ /.*Ethernet controller.*/) { getDriver=1; }
if (getDriver == 1 && $0 ~ /.*Kernel driver.*/) { printf ("%s\n", $5); }
}' | sort | uniq | while read a; do
echo Unloading network module $a from kernel space
rmmod $a
# Remove the static enumerations
rm /etc/udev/rules.d/70-persistent-net.rules
echo Reloading driver via udev
# Tickle udev
/sbin/udevadm trigger
# Start networking
/etc/init.d/networking start