Seamless connection switching with Bonding
Configure seamless switchover between wifi and ethernet using bonding
Never again have hanging network shares or dead ssh connections when (un-)plugging your ethernet all while leaving Ubuntu’s settings UI intact.
Why you’d want this
I have a dock at home for my laptop that of course is plugged into ethernet for a faster and more stable connection. So whenever I decide to sit down at my desk my network connection changes. Most websites and browsers can deal with this, some just require a quick reload. However many other tools, most notably nfs and smb (for network file shares), ssh, rsync, … cannot. The connection just times out while the app or share is completely unresponsive, which is even worse than just crashing because you don’t notice immediatley.
The issue here is that your network connections have to switch to a new interface with new ip, gateway etc. And while these settings could very well all be identical, since you’re connecting to the same network on both devices, linux can’t be sure of that. However:
In linux there exists a feature called interface-bonding that (among other fancy things) enables you to combine multiple network interfaces into a single one. And any communication via this combined/bonded interface doesn’t even notice the switch (apart from maybe a hiccup in the packet routing of your Router).
Limitations
This solution assumes that all (bonded) interfaces are connected to the same network at all times. If you were to connect your wifi to network A and plug the ethernet into network B then you’d have no connection at all, as you’re now connected to network B (ethernet > wifi) but linux thinks you’re in network A (as the interface didn’t change).
If you want to network-hop with this config, make sure to fully disconnect from A before connecting to B.
What you need
- at least two active and working internet connections on your device both to the same Network
- NetworkManager and
nmcli
for configuration. There are other tools (see below fornetplan
) but NetworkManager is the one also used in the Ubuntu Settings leaving the UI intact and still able to configure your network. - knowledge of
sudo
,cat
andnano
(or some other text-editor)
NetworkManager in 30 seconds
NetworkManager is a daemon that does as its name suggests. For this guide all you need to know is that there are devices
and connections
. devices
, commonly known as interfaces, are both actual hardware (ethernet/wifi cards) aswell as virtual things like the loopback interface. A connection
is a configuration for a specific device (connection.interface-name
). For example for each wifi network you connect to, a connection (with the same name as the Wifi by default) is created for your network card storing the wifi’s name, password and other details.
nmcli
cheat sheet
# show all devices/connections
nmcli device
nmcli connection
# show the details of one specific one
nmcli device show eth0
nmcli connection show "Connection Name"
# edit some parameters
nmcli connection modify "Connection Name" parameter "Value" parameter.subparameter "Value"
# delete some parameter
nmcli connection modify "Connection Name" parameter ""
# delete devices (works for connections too)
nmcli device delete DeviceName
# bring down/up an interface
nmcli device down DeviceName
nmcli device up DeviceName
The actual guide
Make sure the interfaces are up and running. nmcli device
should give something like:
DEVICE TYPE STATE CONNECTION
wlp1s0 wifi connected NotYourWifi
enx000ec6300e6b ethenet connected Wired Connection 1
p2p-dev-wlp1s0 wifi-p2p disconnected --
lo loopback unmanaged --
Note the wifi (wlp1s0
) and ethernet (enx000ec6300e6b
) we will bond are both reporting as connected (disconnected would also be ok, everything else see troubleshooting).
Create the bonding connection MyBondConnection
. Configure it as follows
- type is bond
- name is
MyBondConnection
(or anything you like, this is never used) - device/interface name is
bond0
. Note that we don’t have to create this interface manually, it will be created automatically once we enable the connection. - bonding parameters:
- active failover mode, that is use any working connection
- check connection liveness every 100ms
- declare the “best” connection to be the ethernet one.
Check out the LinuxFoundation’s docs for a nice overview of all options.
- very low priority (large number) when choosing what interface to use, so that other interfaces take priority. This is needed because for some reason the bonding interface claims to be available all the time.
sudo nmcli connection add type bond con-name "MyBondConnection" ifname bond0 bond.options "mode=active-backup,miimon=100,primary=enx000ec6300e6b" ipv4.route-metric 2000 ipv6.route-metric 2000
Now all that’s left to do is configuring the (real) interfaces to act as slave
for the bonding interface. And since they are configured via connections we just have to change some parameters in them. I will just alter the existing connections for this, however you can run nmcli connection clone YourExistingConnection YourNewConnection
to create a copy of the existing connection and then modify
the copy instead.
Note that connection.id
just changes the name, you can omit it and the new name if you don’t want that.
nmcli connection modify NotYourWifi slave-type bond master bond0 connection.id "bond0 NotYourWifi"
nmcli connection modify "Wired Connection 1" slave-type bond master bond0 connection.id "bond0 Wired Connection 1"
Most devices don’t reload the applied config when it’s changed, so to do that you need to nmcli device down
and up
them again.
nmcli device down enx000ec6300e6b
nmcli device up enx000ec6300e6b
If you instead created copies of the connections, you can apply them manually by bringing them up
.
nmcli connection up "bond0 NotYourWifi"
nmcli connection up "bond0 Wired Connection 1"
This will probably ask you again for the password for some reason, no clue why, but it works afterwards.
Assuming you made it here, you now have bonding configured for the network you’re currently attached to. If you want this behaviour for other networks aswell, you have to edit the corresponding wifi connections aswell (the ethernet connection is usually reused regardless of the network you’re connected to).
If nmcli chooses other connections over the bonded one, try to increase the connection.autoconnect-priority
and connection.autoconnect-retries
of the bonded connection.
Troubleshooting
device is unavailable
Try to bring it up, either it works or it gives you the next error.
nmcli device up enx000ec6300e6b
device is “strictly unmanaged”
In /etc/NetworkManager/NetworkManager.conf
under [ifupdown]
set managed=true
, then restart the NetworkManager
nano /etc/NetworkManager/NetworkManager.conf
sudo systemctl restart NetworkManager
Performance is shit
Check /proc/net/bonding/bond0
to see what the bonding is currently doing and make sure mode
and miimon
are correct.
If the bonding settings aren’t as you expected, check the connection applied to the bond and restart the bond interface.
nmcli device down bond0
nmcli device up bond0
It’s not failing over
Check /proc/net/bonding/bond0
to see if the device you want it to fail over to is listed (when connected).
If not, make sure the connection applied to the interface is the one with the bonding changes.
No internet, but linux says it’s working
Try to curl google.com
(or any oher request to the router that gives a response), some routers are confused about where to send the traffic to after switching and figure it out when you send something.
If this doesn’t work try to force the bond to switch over to the other interface by enabling or disabling your primary interface
nmcli connection <down/up> "bond0 Wired Connection 1"
If this gets you back a connection (usually it works when using the wired connection), your wifi card’s firmware is pedantic:
According to some wifi spec, in order to reduce traffic, wifi cards are only allowed to send traffic they “know the origin of” which some manufacturers interpret as “only traffic with a matching MAC address”. You can verify you’re having this issue by watch ifconfig
-ing. You should see the TX-Packets
on the broken interface climb when you try to access the network but next to no change in the RX-Packets
. To fix this we can fool the card into thinking it is the ‘origin’ by changing the MAC address fo the bond-interface to the same as the broken interface.
# figure out the actual hw-addr of the broken interface
# all other sources will report the wrong one
cat /proc/net/bonding/bond0
# Ethernet Channel Bonding Driver: v6.2.0-33-generic
# ...
# Slave Interface: wlp1s0
# MII Status: up
# Speed: Unknown
# Duplex: Unknown
# Link Failure Count: 1
# Permanent HW addr: 98:fd:ef:34:96:ab < this one
# Slave queue ID: 0
# ...
# and change the address via nmcli
nmcli connection modify MyBondConnection ethernet.cloned-mac-address '98:fd:ef:34:96:ab'
# then bring the bond interface down and up
nmcli connection down MyBondConnection
nmcli connection up MyBondConnection
# and all slaves, because ubuntu automatically tries to reapply some default config
nmcli connection up "bond0 NotYourWifi"
nmcli connection up "bond0 Wired Connection 1"
It applied the wrong connection.
Either just open the settings and choose the one you want or bring down the current one and up the one you want.
nmcli device disconnect wlp1s0
nmcli connection up TheBondedConnection
Fuck, go Back
If it breaks or you mess up along the way, you can always delete the added bond connection and interface and revert the slave settings in the other connections.
nmcli connection delete MyBondConnection
nmcli device delete bond0
nmcli connection modify "bond0 NotYourWifi" slave-type "" master "" connection.id NotYourWifi
Further infos
doing it with netplan
and networkd
instead
Note that this completely breaks the UI and makes connecting to wifi a pain, as it works using networkd. This solution however seems more reliable from my testing and might be fine on headless machines (but why do you frequently plug and replug those?).
Replace /etc/netplan/01-network-manager-all.yaml
with the following and make sure there are no other files in that folder (and replace my interface names and connection configurations).
network:
version: 2
renderer: networkd
ethernets:
enx000ec6300e6b: # name of interface
dhcp4: false
dhcp6: false
optional: true
wifis:
wlp1s0: # name of interface
dhcp4: false
dhcp6: false
optional: true
access-points:
"NotYourWifi":
password: "NiceTry"
bonds:
bond0:
dhcp4: true
dhcp6: true
dhcp4-overrides: # for some reason DNS via DHCP didn't work
use-dns: false
dhcp6-overrides:
use-dns: false
nameservers: # best copy the settings from your current state
addresses:
- 1.1.1.1
- 8.8.8.8
interfaces:
- enx000ec6300e6b
- wlp1s0
parameters:
mode: active-backup
mii-monitor-interval: 100
primary: enx000ec6300e6b
then run
netplan generate
netplan apply
(you cannot try
this because that’s not supported with bonding and you can’t use NetworkManager as renderer because that’s also not supported with bond interfaces)
To undo this you can just generate and apply the stock config again.
network:
version: 2
renderer: NetworkManager
Comments
As stated on the homepage, still under construction. Send me an email if you have questions and maybe I'll add it here manually