I am answering to my own question now because I finally found a workaround for this problem.
I found out that it is possible to reorder the devices by unloading the drivers and then loading them in correct order.
First method (bruteforce):
So the first method I came up with was simple to bruteforce the driver reload with init.d script.
Following init script is tailored for Debian 6.0, but the same principle should work on almost any distribution using proper init.d scripts.
#!/bin/sh -e
### BEGIN INIT INFO
# Provides: reorder-nics
# Required-Start:
# Required-Stop:
# Default-Start: S
# Default-Stop:
# Short-Description: Reloads the nics in correct order
### END INIT INFO
#
# This script should reload the nic drivers in corrected order.
# Basically it just unloads and then loads the drivers in different order.
#
echo "Reloading NICs!"
# unload the drivers
modprobe -r driver_0 # eth0 nic interface
modprobe -r driver_1 # eth1 nic interface
# load the drivers in corrected order
modprobe driver_1
modprobe driver_0
#EOF
Then the script must be added to proper runlevel directory. This can be done easily on Debian with "update-rc.d" command. For example: update-rc.d reorder-nics start S
Second method (Better I think):
I also found a bit more elegant way (at least for Debian & Ubuntu systems).
First Make sure that kernel doesn't automatically load the NIC drivers. This can be done by creating a blacklist file in /etc/modprobe.d/
. I created a file named "disable-nics.conf
". Note that files in /etc/modprobe.d/
must have .conf
suffix. Also naming modules in /etc/modprobe.d/blacklist.conf
do not affect autoloading of modules by the kernel, so you have to make your own file.
# Disable automatic loading of kernel driver modules
# Disable NIC drivers
blacklist driver_0 # eth0 by default
blacklist driver_1 # eth1 by default
Then run 'depmod -ae' as root
Recreate your initrd with 'update-initramfs -u'
And finally add the driver names in corrected order into /etc/modules file.
# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.
# Parameters can be specified after the module name.
# drivers in wanted order
driver_1 # this one should be loaded as eth0
driver_0 # this one should be loaded as eth1
Changes should come in effect after the next boot.
Reboot is not necessary though; it's easy to switch the devices with following command (as root, of course):
modprobe -r driver_0; modprobe -r driver_1; modprobe driver_1; modprobe driver_0
Some useful links I found while searching the solution:
I've run into this exact same problem under CentOS from time to time when I've cloned virtual machines (VM's). The problem stems from the original VM getting an entry put into this file to setup the Ethernet device eth0
.
Sample .rules file
# This file was automatically generated by the /lib/udev/write_net_rules
# program, run by the persistent-net-generator.rules rules file.
#
# You can modify it, as long as you keep each rule on a single
# line, and change only the value of the NAME= key.
# net device () (custom name provided by external tool)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="54:52:00:ff:ff:dd", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"
The problem rears its ugly head when you clone the first VM, this causes a new MAC address to be created, under some virtualization technologies such as KVM for one. This new MAC address is auto detected when the cloned VM is booted and viewed as a new Ethernet device by /lib/udev/write_net_rules
, and so a 2nd entry is added to the above file.
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="54:52:00:ff:ff:de", ATTR{type}=="1", KERNEL=="eth*", NAME="eth1"
I usually open this file, 70-persistent-net.rules
, in an editor and simply consolidate the lines so that the new MAC address is assigned to the eth0
device and reboot.
...
# net device () (custom name provided by external tool)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="54:52:00:ff:ff:de", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"
EDIT #1
The OP followed up the question with the following new information.
Item #1: Hmmm. That won't work in my case because I'm running software with a flex license that ties to the mac address. Constantly changing addresses render said software useless..
@Zobal - I'm familiar with Flex. Since it's a VM you can change the VM's MAC (in the VM software - VirtualBox, KVM, etc.).
NOTE: Flex is a licensing technology that's provided by Flexera. They used to be called GlobeTrotter Software. This technology allows software to be either tied to a physical host, or can have licenses managed from a central server as "tokens" where clients can check the tokens out for a period of time. The licenses are typically tied to a host, and this host is usually identified by a unique number that you can find using the command hostid
.
For example:
$ hostid
a8c0c801
Item #2: In my case it's not a VM. I've cloned one physical system onto another physical system.
To which I responded: Well then your only option is to change the new system's MAC address to the same as the other system's MAC. Realize that these 2 systems cannot exist on the same network, otherwise they will conflict with each other. Also Flex licensing typically does not use the MAC, they use the number that's identifiable using the command hostid
!
References
Best Answer
EDIT: After a small troubleshooting session with OP I'm modifying the answer to remove the quotes for "biosdevname"
Edit the following lines in
/etc/default/grub
:To:
Next, run
sudo update-grub
and then reboot.After this, you should have the
udev
rules persisted in/etc/udev/rules.d/70-persistent-net.rules
and you can edit them as necessary.Make sure you're changing the right interface by comparing MAC address information properly, e.g. via
ifconfig -a
.