24

Is there any way to swap network interfaces (eth1 <-> eth0) after system installation.

My brand new Debian 6.0 install assigned PCI network card as "eth0" and motherboards integrated network device as "eth1" by default. The problem is I want to use the integrated device as default (eth0) network interface.

I already edited :

/etc/udev/rules.d/70-persistent-net.rules

to swap the names and everything seems to be ok and network is working but programs are still trying to use the PCI network card (which is now "eth1") as the default interface. For example iftop now tries to use "eth1" as default device as it used "eth0" before the swap.

Is this purely a software problem as the applications are trying to use the first found device as a default device despite their interface naming or is there any way to fix this by configuring OS?


edit: I wrote a small app to print out iflist and the PCI device (eth1) came up before "eth0". Any ideas how to swap the device order.


edit: I found a thread about the same problem and I tried everything they suggested and none of the solutions are working except for swapping the names "virtually".

2
  • Just to note, editing /etc/udev/rules.d/70-persistent-net.rules and a reboot did the job for me
    – Xosofox
    Commented Jan 14, 2016 at 18:42
  • I somewhat remember renaming them in Debian. I dont remember how I did it though. Commented Nov 13, 2023 at 9:05

7 Answers 7

20

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:

1
  • I have a similar problem: I have an integrated NIC, then sometimes I run a VPN program which creates another interface. The VPN interface always seems to take precedence, but I don't know why. I only want it to be used in very rare circumstances (I want the application that uses it to have to specify the VPN interface). Any ideas? ^_^ I'll probably post a new question pretty soon anyway. Commented Jul 9, 2014 at 13:04
2

You can use the netdev= kernel command line parameter (you need to pass that to the kernel in grub) to instruct the kernel to link a given irq to a given interface, e.g.: netdev=irq=2,name=eth0

2
  • 1
    I booted my box with the grub config modifications and I am still getting eth1 as the default device in many apps. I checked the dmesg for network info and and it says that the integrated NIC has still 'eth1' as ifname: forcedeth 0000:00:04.0: ifname eth1, PHY OUI 0x57d @ 1, addr 40:40:00:40:40:40. This is not too serious problem but it really grinds my gears because the integrated is 1gb card and it should be the default device. Commented Mar 29, 2011 at 10:19
  • 1
    I have now tried to use nameif to change the network interface names but looks like it does the same that udev does. No change in "real" NIC order. I also tried to change the PCI NICs physical location but it didn't help either. Integrated NIC has IRQ 22 and PCI NIC has IRQ 17 so looks like kernel is ordering them by IRQ and user cannot change that fact in any way. Any fresh ideas? Commented Mar 29, 2011 at 12:15
2

You can't change which interface is used by default in applications like iftop. They call the C library function if_nameindex and use the first element in the returned array by default. GNU libc's if_nameindex on Linux is a thin wrapper around the SIOCGIFCONF ioctl. That returns interfaces in a fixed order, based on the order in which the network drivers were initialized and the order in which each driver detected each device.

If you really don't want to have to pass -i to iftop and similar programs, you can make a small wrapper around if_nameindex that reorders the elements in the returned list, with LD_PRELOAD. I would call that a lot more trouble than it's worth.

2
  • I managed pinpoint the "problem" into if_nameindex function too. Perhaps I just leave it for now. Luckily some apps really checks the interface name. On the other hand some apps doesnt even have default configuration options so I just have to use -i option. I was just wondering why kernel loading option netdev=irq=22,name=eth0 does not work? I thought it should be possible to change the NIC order at kernel startup. Commented Mar 29, 2011 at 21:16
  • From a quick look at the kernel source (the for_each_netdev macro), interfaces are enumerated in the order in which drivers are loaded (roughly). Your interfaces probably use different drivers, so you'd have to arrange for the drivers to be loaded in the order you want. I would expect this to be difficult, especially if you want your tweak to work across a kernel upgrade. Commented Mar 29, 2011 at 21:21
1

You are likely going to have to go into each affected programs configuration files and change 'eth1' to 'eth0.' Such programs defaults are setup when they are installed or first run with the currently detected NICs.

I use Linux as a router, and had this issue when using scripts. I now have a nice script fragment called netconf that I source in for any other script whenever i need to use NIC names, this file gives me a central location to specify them (i.e. LAN_IFACE=eth0, WAN_IFACE=eth1, etc.)

1
  • 2
    Looks like that lots of programs are just relying on if_nameindex() function from <net/if.h> header. They just use the first device they find and totally ignores the interface names. I can see why it is done like that, its much easier to use the first found device than sort the names. Commented Mar 29, 2011 at 14:22
1

If they have different drivers, at least back in the day you could put into one of the module configuration files:

alias eth0 driver1
alias eth1 driver2

That's some pretty old knowledge but it may help.

0

I also encountered the same need. My operating system is Ubuntu 18.04.

I tried the Second method in the answer by the question author: First, add a blacklist, and then specify the loading order through /etc/modules.

As a result, systemd-modules-load prompts that "Module 'driver_name' is blacklisted".

Finally, I found that there is no need to add the disable-nics.conf file in /etc/modprobe.d/. You can directly specify the network card loading order you need in the /etc/modules file.

Also note:

  1. You can get the driver_name through ethtool -i eth0 | grep driver,
  2. In the /etc/modules configuration file, there cannot be a # comment after driver_name, otherwise you will encounter "failed to find modules", because systemd-modules-load will use the entire line as driver_name.

Additional description:

The above operation does not take effect in some cases, and I don't know why.

Finally, I solved the problem by adding the following script to /etc/rc.local.

#!/bin/bash

# reload network interface cards when more than one
reload_nic(){
    nic_arr=(`lspci -k | grep -e 'Ethernet controller' | awk '{print $1}'`)
    if [ ${#nic_arr[@]} -gt 0 ];then
        # collect drivers        
        declare -a drivers=()
        for nic in "${nic_arr[@]}"
        do
            driver_name=`lspci -vs ${nic} | grep "Kernel modules" | cut -d : -f 2 | sed s/[[:space:]]//g`
            drivers+=($driver_name)
        done
        unique_drivers=($(printf "%s\n" "${drivers[@]}" | sort -u))
        
        # skip when less than two nic type
        if [ ${#unique_drivers[@]} -lt 2 ];then
            echo "less than two nic type, no need to reload"
            return
        fi

        # remove all nic module
        for dname in "${unique_drivers[@]}"
        do
            `/sbin/modprobe -r ${dname}`
            if [ $? -ne 0 ];then
                echo "failed to remove module ${dname}"
            else
                echo "remove module ${dname} success"
            fi
        done

        # install module in order
        for dname in "${unique_drivers[@]}"
        do
            `/sbin/modprobe ${dname}`
            if [ $? -ne 0 ];then
                echo "failed to install module ${dname}"
            else    
                echo "install module ${dname} success"
            fi
        done
    fi
}
reload_nic
-1

Take a look at the 'ifrename' package. This lets you rename interface names based on a variety of information such as MAC address of interface, driver, interrupt ..., configured in a /etc/iftab file.

Some examples from the man page:

   # This is a comment
   eth2      mac 08:00:09:DE:82:0E
   eth3      driver wavelan interrupt 15 baseaddress 0x390
   eth4      driver pcnet32 businfo 0000:02:05.0
   air*      mac 00:07:0E:* arp 1
   myvpn     SYSFS{address} 00:10:83:* SYSFS{type} 1
   bcm*      SYSFS{device} 0000:03:00.0 SYSFS{device/driver} bcm43xx
   bcm*      SYSFS{..} 0000:03:00.0 SYSFS{../driver} bcm43xx
1
  • Welcome to U&L, can you provide us with a complete answer, not mere hints ? You shouldn't post with someting like "there is a man page ...".
    – Archemar
    Commented Apr 3, 2015 at 11:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .