Network bonding combines two or more physical interfaces into one logical interface, bond0. Depending on the mode, the bond gives you failover when a cable, NIC or switch port dies, extra aggregate bandwidth, or both. In this tutorial you will configure a bond on Ubuntu 24.04 with Netplan, first in active-backup mode and then in LACP (802.3ad) mode, check its state, and test failover. A short section covers the equivalent NetworkManager commands for Rocky Linux 9.
Prerequisites
To follow this tutorial you need:
- A server running Ubuntu 24.04 LTS with at least two physical network interfaces connected to the same network, such as a CubePath dedicated server. Virtual machines usually have a single virtual NIC, where bonding brings no benefit.
- A non-root user with
sudoprivileges. - Access to an out-of-band console (IPMI, iDRAC, iLO or KVM). You are about to reconfigure the interface that carries your SSH session, and a typo can cut you off.
- For LACP only: switch ports configured as an LACP port-channel (LAG). If you do not control the switch, use active-backup.
Throughout the guide the interfaces are called eno1 and eno2, and the example addressing is 203.0.113.10/24 with gateway 203.0.113.1. Replace them with your own values.
Choosing a bonding mode
The Linux bonding driver supports seven modes. These are the ones worth knowing:
| Mode | Netplan name | What it does | Switch configuration |
|---|---|---|---|
| 1 | active-backup | One interface carries traffic, the others wait and take over on failure | None |
| 4 | 802.3ad | LACP aggregation, flows are spread over all links | LACP port-channel |
| 6 | balance-alb | Load balancing in software, including receive traffic via ARP | None |
| 0 | balance-rr | Round-robin per packet, causes reordering in TCP | Static port-channel |
Active-backup is the safest choice and works on any switch. LACP is the standard for more bandwidth, but remember that a single TCP flow never exceeds the speed of one link: aggregation helps with many concurrent flows.
NoteThe older
teamdteaming daemon is deprecated in RHEL 9 and derivatives and removed in RHEL 10. Use the kernel bonding driver shown here on all current distributions.
Step 1 - Identifying interfaces and backing up the configuration
List the physical interfaces and their link state:
ip -br link
lo UNKNOWN 00:00:00:00:00:00 <LOOPBACK,UP,LOWER_UP>
eno1 UP 3c:ec:ef:12:34:56 <BROADCAST,MULTICAST,UP,LOWER_UP>
eno2 UP 3c:ec:ef:12:34:57 <BROADCAST,MULTICAST,UP,LOWER_UP>
Both interfaces should show LOWER_UP, which means there is carrier on the cable. Note the current address, gateway and DNS servers, because the bond will take them over:
ip -br addr show eno1
ip route show default
resolvectl dns
Then look at the existing Netplan files and copy them to a backup directory outside /etc/netplan:
ls /etc/netplan/
sudo mkdir -p /root/netplan-backup
sudo cp /etc/netplan/*.yaml /root/netplan-backup/
Step 2 - Configuring an active-backup bond
Netplan merges every YAML file in /etc/netplan/ in lexical order, so a leftover file that still assigns the address to eno1 would conflict with the bond. Move the old files out of the directory (they are already backed up) and create a single new configuration:
sudo mv /etc/netplan/*.yaml /root/netplan-backup/
sudo nano /etc/netplan/01-bond0.yaml
Add the following content, adjusting the interface names, addresses and DNS servers:
network:
version: 2
renderer: networkd
ethernets:
eno1:
dhcp4: false
eno2:
dhcp4: false
bonds:
bond0:
interfaces:
- eno1
- eno2
addresses:
- 203.0.113.10/24
routes:
- to: default
via: 203.0.113.1
nameservers:
addresses:
- 1.1.1.1
- 9.9.9.9
parameters:
mode: active-backup
primary: eno1
mii-monitor-interval: 100
The member interfaces carry no addresses of their own. mii-monitor-interval: 100 checks the link state every 100 ms, and primary: eno1 makes eno1 the preferred active interface whenever it is up.
Netplan warns about world-readable files, so restrict the permissions:
sudo chmod 600 /etc/netplan/01-bond0.yaml
Step 3 - Applying the configuration safely
Validate the syntax first. This generates the backend configuration without applying it:
sudo netplan generate
No output means the file is valid. Now apply it with netplan try, which rolls back automatically unless you confirm within 120 seconds. If your SSH session freezes, wait and the old configuration returns:
sudo netplan try
Do you want to keep these settings?
Press ENTER before the timeout to accept the new configuration
Changes will revert in 118 seconds
Open a new SSH connection to the server. If it works, go back to the first session and press ENTER to keep the configuration.
Step 4 - Verifying the bond
The bonding driver exposes its full state in /proc:
cat /proc/net/bonding/bond0
Ethernet Channel Bonding Driver: v6.8.0-45-generic
Bonding Mode: fault-tolerance (active-backup)
Primary Slave: eno1 (primary_reselect always)
Currently Active Slave: eno1
MII Status: up
MII Polling Interval (ms): 100
Up Delay (ms): 0
Down Delay (ms): 0
Slave Interface: eno1
MII Status: up
Speed: 10000 Mbps
Duplex: full
Link Failure Count: 0
Slave Interface: eno2
MII Status: up
Speed: 10000 Mbps
Duplex: full
Link Failure Count: 0
Confirm that bond0 holds the address and the default route:
ip -br addr show bond0
ip route show default
bond0 UP 203.0.113.10/24 fe80::3eec:efff:fe12:3456/64
default via 203.0.113.1 dev bond0 proto static
Step 5 - Testing failover
A bond that has never failed over is untested. From another machine, start a continuous ping to the server so you can measure any interruption:
ping 203.0.113.10
On the server, from the out-of-band console, disable the active interface:
sudo ip link set eno1 down
Check which interface is active now:
grep "Currently Active Slave" /proc/net/bonding/bond0
Currently Active Slave: eno2
The ping on the other machine should lose at most one or two replies. Bring eno1 back:
sudo ip link set eno1 up
Because eno1 is the primary interface, the bond switches back to it once its link is up again, and the Link Failure Count of eno1 increases by one. For a more realistic test, unplug the cable or shut down the switch port, which also exercises the switch side.
Step 6 - Switching to LACP (802.3ad)
Once the switch ports are configured as an LACP port-channel, edit the parameters block of bond0:
sudo nano /etc/netplan/01-bond0.yaml
parameters:
mode: 802.3ad
lacp-rate: fast
mii-monitor-interval: 100
transmit-hash-policy: layer3+4
lacp-rate: fast exchanges LACP packets every second instead of every 30 seconds, so a dead link is detected sooner; set the same rate on the switch. transmit-hash-policy: layer3+4 spreads flows across links using IP addresses and ports instead of MAC addresses only, which balances much better when most traffic goes through a single gateway. The primary key only applies to active-backup, so remove it.
Apply the change with the same safety net:
sudo netplan try
Check the LACP negotiation:
grep -E "Bonding Mode|Transmit Hash|Aggregator ID|Partner Mac" /proc/net/bonding/bond0
Bonding Mode: IEEE 802.3ad Dynamic link aggregation
Transmit Hash Policy: layer3+4 (1)
Aggregator ID: 1
Partner Mac Address: 44:4c:a8:9a:10:01
Aggregator ID: 1
Aggregator ID: 1
Both interfaces must show the same Aggregator ID, and the partner MAC must be non-zero. A partner address of 00:00:00:00:00:00 means the switch is not speaking LACP on that port.
Configuring a bond on Rocky Linux 9
Rocky Linux 9, AlmaLinux 9 and RHEL 9 manage the network with NetworkManager, and the legacy ifcfg files are deprecated there, so use nmcli. Create the bond with its options and addressing:
sudo nmcli connection add type bond con-name bond0 ifname bond0 \
bond.options "mode=active-backup,miimon=100,primary=eno1" \
ipv4.method manual ipv4.addresses 203.0.113.10/24 \
ipv4.gateway 203.0.113.1 ipv4.dns "1.1.1.1 9.9.9.9"
Add both interfaces as members:
sudo nmcli connection add type ethernet con-name bond0-eno1 ifname eno1 master bond0
sudo nmcli connection add type ethernet con-name bond0-eno2 ifname eno2 master bond0
List the connections, then deactivate the old profile of eno1 and activate the bond from the out-of-band console, since this interrupts SSH:
nmcli connection show
sudo nmcli connection down eno1
sudo nmcli connection up bond0
Verify it with cat /proc/net/bonding/bond0 as in Step 4. For LACP, change the options and reactivate the connection:
sudo nmcli connection modify bond0 bond.options "mode=802.3ad,miimon=100,lacp_rate=fast,xmit_hash_policy=layer3+4"
sudo nmcli connection up bond0
Troubleshooting
netplan tryreverts or SSH drops: an older file in/etc/netplan/still configureseno1oreno2. Runsudo netplan getto see the merged configuration and make sure only the bond carries addresses.Permissions for /etc/netplan/01-bond0.yaml are too open: runsudo chmod 600on the file.- Bond has no connectivity in 802.3ad mode: the switch ports are not in an LACP port-channel, or they are in a static (non-LACP) one. Check the partner MAC as shown in Step 6.
- One member shows
MII Status: down: check the cable and switch port withip -br linkandsudo ethtool eno2;Link detected: nopoints to a physical problem. - LACP works but traffic uses only one link: a single flow always uses one link. With many flows, confirm
Transmit Hash Policy: layer3+4.
Conclusion
You combined two interfaces into bond0 on Ubuntu 24.04, verified its state in /proc/net/bonding/bond0, proved that failover works and moved the bond to LACP. Test failover again after every switch or cabling change. As next steps, add VLAN interfaces on top of the bond with Netplan's vlans section, alert on bond member failures in your monitoring system, or bond a second NIC pair for a separate private network.
