January 10, 2018
How to aggregate multiple network interfaces into a single logical interface?
If you haven’t heard about network bonding - it’s a network setup that allows you to use two or more network devices to act as one interface, giving you expanded bandwidth and some redundancy. Basically you can turn a 1 GiB link into a 2 GiB link for the one virtual interface.
Usually it’s used to bond ethernet devices, but let’s try to mix wifi and ethernet.
As long as the network cable is connected, its interface (e.g. eth0) is used for the network traffic.
The goal is to switch over to the wireless interface transparently, without any loss of network packages when you pull the RJ45-plug.
After reconnecting the network cable, it switches back to ethernet.
These steps were tested on Linux Mint 18.3 which is a Ubuntu based distribution.
I assume you have at least two network devices (one wifi, one eth), let’s list them:
ip -br addr show
The result on my laptop is:
lo UNKNOWN 127.0.0.1/8 ::1/128 enp3s0 DOWN wlp2s0 UP 192.168.1.19/24 ff70::957f:4ecd:d256:43c1/64 docker0 DOWN 172.17.0.1/16
As you can see I’m on my wifi at the moment as wlp2s0 is UP end I’m not using my ethernet ensp3s0 (it’s unplugged) connection right now.
If you don’t know which interface represents which device you can also use NetworkManager:
sudo nmcli device status DEVICE TYPE STATE CONNECTION docker0 bridge connected docker0 wlp2s0 wifi connected xxxxxxxxxxxx enp3s0 ethernet unavailable -- lo loopback unmanaged --
I replaced my real wifi name with “xxxxxxxxxxxx”, so you will see there a wifi network name you’re currently connected.
Tell the kernel to load the bonding module
If you want to check to see if your bonding module is already loaded in the kernel just run:
lsmod |grep bonding
and you should see something like this:
bonding 163840 0
If not, install neccecary packages:
sudo apt install ifenslave
And insert the module to the kernel:
sudo modprobe bonding
The magic happens in /etc/network/interfaces
A default content of this file should be similar to:
# interfaces(5) file used by ifup(8) and ifdown(8) auto lo iface lo inet loopback
This is a standard loopback interface configuration which informs the kernel to bring the adapter up automatically on start-up. iface lo inet loopback tells the system that this interface is the system’s loop-back interface or more commonly referenced as 127.0.0.1.
Let’s start by adding two existing interfaces to the list:
auto enp3s0 iface enp3s0 inet manual bond-master bond0 bond-primary enp3s0 wlp2s0 auto wlp2s0 iface wlp2s0 inet manual bond-master bond0 bond-primary enp3s0 wlp2s0 wpa-ssid xxxxxxxxxxxx wpa-bssid XX:XX:XX:XX:XX:XX wpa-psk xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
bond-master bond0 is fairly straightforward, it indicates which interface is master (we will create bond0 interface further)
bond-primary enp3s0 wlp2s0 is specifying which slave is the primary device. The specified device will always be the active slave while it is available. Only when the primary is off-line will alternate devices be used.
wpa-ssid is your wifi network broadcasted name, wpa-bssid is a mac of your wifi router, wpa-psk is your wifi password (don’t keep it as a plain text, use wpa_passphrase
New interface (bond0)
The goal is to bond wlp2s0 and enp3s0 together to appear as one interface, bond0.
The interface bond0 can be set a static one or as dhcp:
auto bond0 iface bond0 inet static address 192.168.1.10 netmask 255.255.255.0 network 192.168.1.0 gateway 192.168.1.1
These settings are down to individual congiguration settings of your network but very likely these will work for you as well but you may prefer dhcp, in this replace inet static with inet dhcp and remove everything below.
Time for bonding settings:
# Bonding bond-slaves none bond-mode active-backup bond-miimon 100 bond-downdelay 200 bond-updelay 200
bond-slaves none this one is very hard to find in any documentation but based on my understanding it instructs to not proceed with slaves interfaces before bond0 is started. Ping me if you find a better explaination.
bond-mode active-backup means that when the active interface fails, the other takes over. There are different options available here like broadcast which transmits everything to all slave devices, or balance-tld (adaptive load balancing), or balance-xor (selectable hashing algorithm) and a few more
bond-miimon 100 determines how often the link state of each slave is inspected for link failures. A value of zero disables MII link monitoring
bond-downdelay 200 means that the system will wait 200 ms before concluding that the currently active interface is indeed down.
bond-updelay 200 is used to tell the system to wait on using the new active interface until 200 ms after the link is brought up.
updelay and downdelay - both of these values must be multiples of the miimon value otherwise the system will round down
The completed setup should look like this:
auto enp3s0 iface enp3s0 inet manual bond-master bond0 bond-primary enp3s0 wlp2s0 auto wlp2s0 iface wlp2s0 inet manual bond-master bond0 bond-primary enp3s0 wlp2s0 wpa-scan-ssid 1 wpa-ssid xxxxxxxxxxxx wpa-bssid XX:XX:XX:XX:XX:XX wpa-psk xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx auto bond0 iface bond0 inet dhcp bond-slaves none bond-mode active-backup bond-miimon 100 bond-downdelay 200 bond-updelay 200
Testing the Bond Configuration
Enslave interfaces and restart network:
sudo ifenslave bond0 enp3s0 wlp2s0 sudo /etc/init.d/networking restart
Checkout the output:
Ethernet Channel Bonding Driver: v3.7.1 (April 27, 2011) Bonding Mode: fault-tolerance (active-backup) Primary Slave: enp3s0 (primary_reselect always) Currently Active Slave: enp3s0 MII Status: up MII Polling Interval (ms): 100 Up Delay (ms): 200 Down Delay (ms): 200 Slave Interface: enp3s0 MII Status: up Speed: 100 Mbps Duplex: full Link Failure Count: 0 Permanent HW addr: XX:XX:XX:XX:XX:XX Slave queue ID: 0 Slave Interface: wlp2s0 MII Status: up Speed: Unknown Duplex: Unknown Link Failure Count: 0 Permanent HW addr: XX:XX:XX:XX:XX:XX Slave queue ID: 0
You can also check:
dmesg | grep -i bond0 [ 1708.596284] IPv6: ADDRCONF(NETDEV_CHANGE): bond0: link becomes ready [ 1708.714483] bond0: Enslaving wlp2s0 as a backup interface with a down link [ 1712.352020] bond0: link status up for interface wlp2s0, enabling it in 200 ms [ 1712.560172] bond0: link status definitely up for interface wlp2s0, 0 Mbps full duplex [ 1823.200935] bond0: link status down for active interface enp3s0, disabling it in 200 ms [ 1823.409140] bond0: link status definitely down for interface enp3s0, disabling it [ 1823.409146] bond0: making interface wlp2s0 the new active one [ 1855.865317] bond0: link status up for interface enp3s0, enabling it in 200 ms [ 1856.073355] bond0: link status definitely up for interface enp3s0, 100 Mbps full duplex [ 1856.073358] bond0: making interface enp3s0 the new active one [ 3032.576211] bond0: link status down for active interface enp3s0, disabling it in 200 ms [ 3032.784299] bond0: link status definitely down for interface enp3s0, disabling it [ 3032.784304] bond0: making interface wlp2s0 the new active one
If you run sudo nmcli device status you probably notice that NetworkManager didn’t pick up bond0, you can safely disable it:
sudo systemctl stop NetworkManager.service sudo systemctl disable NetworkManager.service
Use ip -br addr show instead:
ip -br addr show lo UNKNOWN 127.0.0.1/8 ::1/128 enp3s0 UP wlp2s0 UP docker0 DOWN 172.17.0.1/16 bond0 UP 192.168.1.29/24 ff50::4fdd:6aff:fedc:fddc/64
Now you should enjoy packetless switching between network devices, which in practice means your video streaming or VPN connection won’t be frozen when unplugging RJ45 cable :)
 Kernel Docs