Translation(s): English - italiano


Bonding

This article will show how to "bond" two Ethernet connections together to create an auto failover interface.

Installation

First install the ifenslave package, necessary to enable bonding:

# apt-get install ifenslave

Shutdown / Unconfigure Existing Interfaces

# ifdown eth0 (Repeat for all interfaces included in the bond)
# /etc/init.d/networking stop

{i} Sometimes, ifdown doesn't work, in that case use ifconfig eth0 down.

Configuration - Example 1

Modify the /etc/network/interfaces file:

auto bond0

iface bond0 inet static
    address 10.31.1.5
    netmask 255.255.255.0
    network 10.31.1.0
    gateway 10.31.1.254
    slaves eth0 eth1
    bond_mode active-backup
    bond_miimon 100
    bond_downdelay 200
    bond_updelay 200

For more detail, see /usr/share/doc/ifenslave/README.Debian and /usr/src/linux/Documentation/networking/bonding.txt.

Configuration - Example 2 ("Laptop-Mode")

Tie cable and wireless network interfaces (RJ45/WLAN) together to define a single, virtual (i.e. bonding) network interface (e.g. bond0).

As long as the network cable is connected, its interface (e.g. eth0) is used for the network traffic. If you pull the RJ45-plug, ifenslave switches over to the wireless interface (e.g. wlan0) transparently, without any loss of network packages.

After reconnecting the network cable, ifenslave switches back to eth0 ("failover mode").

From the outside (=network) view it doesn't matter which interface is active. The bonding device presents its own software-defined (i.e. virtual) MAC address, different from the hardware defined MACs of eth0 or wlan0.

The dhcp server will use this MAC to assign an ip address to the bond0 device. So the computer has one unique ip address under which it can be identified. Without bonding each interface would have its own ip address.

Modify the /etc/network/interfaces file:

# Define slaves   
auto eth0
iface eth0 inet manual
    bond-master bond0
    bond-primary eth0
    bond-mode active-backup
   
auto wlan0
iface wlan0 inet manual
    wpa-conf /etc/network/wpa.conf
    bond-master bond0
    bond-primary eth0
    bond-mode active-backup

# Define master
auto bond0
iface bond0 inet dhcp
    bond-slaves none
    bond-primary eth0
    bond-mode active-backup
    bond-miimon 100

Note: The configuration above has been found working on Debian 6 and 7.1. It is somewhat contrary to the documentation of interfaces, ifup and ifenslaveand the examples under /usr/share/doc/ifenslave/examples/.

Theoretically only the bond0 interface should have the auto attribute. ifup bond0 will bring up the slaves automatically (as documentation says). This is partially true but obviously the configuration options of the slaves are ignored. E.g. wlan0 is brought up without starting wpa_supplicant and the bond-primary setting of eth0 is ignored. (TODO: Is this a bug in ifenslave?)

It seems the slaves must be brought up before bond0 to include their configuration options. To do so via the /etc/init.d/networking script, their definitions must be before the bond0 definition and the auto attributes have to be set.

Of course, they must not be started again when bond0 starts. The option bond-slaves none disables this.

The options bond-master, bond-primary and bond-mode have to be repeated consistently for each slave.

There will be warnings "ifup: interface xyz already configured", but at least it works.

Tip

In order to get some insight what is happening behind the scenes while experimenting a small script to show some information about the bonding device may be helpful.

#! /bin/sh

echo "Slaves = $(cat /sys/class/net/bond0/bonding/slaves)"
echo "Primary = $(cat /sys/class/net/bond0/bonding/primary)"
echo "Active Slave = $(cat /sys/class/net/bond0/bonding/active_slave)"

r=$(pidof dhclient)
test -n "$r" && ps $r

r=$(pidof wpa_supplicant)
test -n "$r" && ps $r

Debugging ifenslave

The bonding mechanism is based on a kernel module named bonding which exposes its interface via the virtual /sys filesystem (e.g. /sys/class/net/bond0/*).

Setup and configuration is done in userland with shell-scripts:

These scripts are called on system initialization and shutdown (actually it is ifup which calls them). Their intention is to feed the kernel module with the appropriate parameters and settings.

If something with bonding fails at all (and the tip above doesn't help) you may have a look what the scripts do step by step.

To enable verbose output, invoke ifup -a -v directly (instead of invoking /etc/init.d/networking). The -v option enables a log of all commands the scripts are executing. This gives at least a trace what is happening when.

Unfortunately this will not show the reactions of the kernel module (like possible error messages), because kernel (module) messages are reported via the syslog utility.

To get a real insight what is going on you have to do what is called invasive debugging. This means to add lines to the scripts at critical points to send a message to syslog.

Example:

Function sysfs_change_down in file /etc/network/if-pre-up.d/ifenslave

        logger -t sysfs_change_down sysfs "$1" "$2"
                sysfs "$1" "$2"
        logger -t sysfs_change_down $(cat /sys/class/net/bond0/bonding/mode)

Additional Note For Debian Lenny On Sparc

(may be applicable on other architectures as well)

# cd /etc/modprobe.d

# cat > aliases-bond.conf
alias bond0 bonding
  options bonding mode=1 arp_interval=2000 arp_ip_target=192.168.3.1
<CTRL-D>

Without this file, you will get a warning when starting up the bonded interface similar to this:

bonding: Warning: either miimon or arp_interval and arp_ip_target module parameters must be specified, otherwise bonding will not detect link failures! see bonding.txt for details.

Startup / Configure New Interfaces

# ifup bond0
# /etc/init.d/networking start

And more, if you use a Lenny environment which has been upgraded from Etch, it is strongly recommended to check the result of the following command to check the bonding device mode, because configuration files for Etch and older versions do not work for Lenny and later releases.

cat /sys/class/net/bond0/bonding/mode

Testing

1. Ping to other system in a terminal

# ping X.X.X.X

2. Disconnect the active network cable and watch the ping result, the network should be resumed in few seconds

3. Reconnect the disconnected network cable, wait for 30 seconds to let the ARP table being updated

4. Disconnect another network cable and watch the ping result, the network should be resumed in few seconds

Change active slave

1. Use ifenslave to change the active slave. Below example will set eth0 as active slave

# ifenslave -c bond0 eth0 eth1

udev renaming issue

"udev" assign network adapter names as per

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

where rule typically looks like this:

# PCI device 0x10ec:0x8168 (r8169)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="xx:xx:xx:xx:xx:xx", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"

The problem with bonding is that two or more NICs may have the very same MAC address which confuses udev when it tries to (re)name adapters as per their MACs and fails because another card with this MAC already exists. When it happens NIC may be left named like "rename2" instead of "eth0" etc.

Possible solution is to change udev rule to assign network interface names as per NICs PCI IDs instead of MAC addresses. This can be done by replacing

ATTR{address}=="xx:xx:xx:xx:xx:xx"

with something like

KERNELS=="0000:04:00.0"

in the file "70-persistent-net.rules". Corresponding PCI IDs can be found in dmesg:

sudo dmesg | grep eth

Where one can look for line fragment like this:

r8169 0000:04:00.0 eth0: RTL8168e/8111e
#     ^^^^^^^^^^^^

Alternatively PCI IDs can be found using "lspci -D | grep Ether":

0000:04:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (rev 06)


CategoryNetwork