Linux Network Bonding (LACP and active-backup)
Configure Linux network bonding in LACP (802.3ad) and active-backup modes, including switch setup, systemd-networkd, NetworkManager, and fault-injection testing.
Before you start
- ▸Two or more physical Ethernet interfaces on the host
- ▸Root or sudo access
- ▸For LACP: access to switch CLI to configure a port-channel or LAG
- ▸NetworkManager or systemd-networkd installed and managing networking
Network bonding combines two or more physical interfaces into a single logical interface, giving you either increased throughput, link redundancy, or both. Linux implements bonding through the bonding kernel module and exposes it via NetworkManager, systemd-networkd, or manual ip commands. This guide covers the two most operationally useful modes: 802.3ad LACP (mode 4, requires a cooperating switch) and active-backup (mode 1, works with any switch or even a dumb hub). You will configure the bond, verify it, and deliberately break links to confirm failover behaves as expected.
Bonding Modes Reference
Linux supports seven bonding modes. Know at least these four before you touch production:
| Mode | Name | Use case | Switch requirement |
|---|---|---|---|
| 0 | balance-rr | Throughput, no fault tolerance guarantee | None, but can cause packet reordering |
| 1 | active-backup | Pure redundancy | None – works everywhere |
| 2 | balance-xor | Throughput + basic redundancy | Static LAG |
| 4 | 802.3ad (LACP) | Throughput + redundancy | LACP-enabled switch port |
| 6 | balance-alb | Adaptive load balancing | None, but ARP-dependent |
For most new deployments choose mode 4 (LACP) when you control the switch, or mode 1 (active-backup) when you do not. The rest of this guide configures both.
Switch-Side Configuration (LACP Only)
LACP (mode 4) requires both ends to speak IEEE 802.3ad. If your switch ports are not configured for LACP, use mode 1 instead; a misconfigured LACP bond will drop all traffic.
Cisco IOS / IOS-XE example
interface GigabitEthernet0/1
channel-group 1 mode active
interface GigabitEthernet0/2
channel-group 1 mode active
interface Port-channel1
description bond0-server
switchport mode access
switchport access vlan 100
Use mode active on the switch when the Linux side also sends LACP PDUs (it does by default). mode passive on one end is acceptable but mode on (static) will not negotiate and the bond will not come up in LACP mode.
Juniper EX example
set interfaces ae0 aggregated-ether-options lacp active
set interfaces ge-0/0/0 ether-options 802.3ad ae0
set interfaces ge-0/0/1 ether-options 802.3ad ae0
Install and Load the Bonding Module
The bonding module ships with every major distro kernel; you just need to load it and, on some distros, install the userspace tools.
Debian / Ubuntu
sudo apt install ifenslave
Fedora / RHEL / Rocky
sudo dnf install NetworkManager-team
Arch Linux
No extra package needed; the module is in linux. Load it now to verify:
sudo modprobe bonding
lsmod | grep bonding
Configure with NetworkManager (Recommended)
NetworkManager is the default on Fedora, RHEL, Rocky, Ubuntu Desktop, and most modern installs. It handles bonding cleanly without manual file editing.
Step 1 – Identify your physical interfaces
ip link show
Note the exact names—commonly enp3s0 and enp4s0 or similar. Substitute them in every command below.
Step 2 – Create the bond master (LACP)
sudo nmcli connection add type bond \
con-name bond0 \
ifname bond0 \
bond.options "mode=802.3ad,miimon=100,lacp_rate=fast,xmit_hash_policy=layer3+4"
For active-backup instead, change mode=802.3ad to mode=active-backup and drop the lacp_rate and xmit_hash_policy options; they are irrelevant for mode 1.
sudo nmcli connection add type bond \
con-name bond0 \
ifname bond0 \
bond.options "mode=active-backup,miimon=100,fail_over_mac=active"
fail_over_mac=active avoids MAC conflicts when connected to switches that track port MACs strictly.
Step 3 – Add slave interfaces
sudo nmcli connection add type ethernet \
con-name bond0-slave1 \
ifname enp3s0 \
master bond0
sudo nmcli connection add type ethernet \
con-name bond0-slave2 \
ifname enp4s0 \
master bond0
Step 4 – Assign an IP address to the bond
sudo nmcli connection modify bond0 \
ipv4.addresses 192.168.1.50/24 \
ipv4.gateway 192.168.1.1 \
ipv4.dns "1.1.1.1 8.8.8.8" \
ipv4.method manual
Step 5 – Bring it up
sudo nmcli connection up bond0
sudo nmcli connection up bond0-slave1
sudo nmcli connection up bond0-slave2
Configure with systemd-networkd (Servers / Headless)
On Ubuntu Server with systemd-networkd, or on Arch with networkd enabled, drop these files into /etc/systemd/network/.
Bond netdev
sudo tee /etc/systemd/network/10-bond0.netdev <<'EOF'
[NetDev]
Name=bond0
Kind=bond
[Bond]
Mode=802.3ad
TransmitHashPolicy=layer3+4
MIIMonitorSec=100ms
LACPTransmitRate=fast
EOF
Bond network (IP assignment)
sudo tee /etc/systemd/network/10-bond0.network <<'EOF'
[Match]
Name=bond0
[Network]
Address=192.168.1.50/24
Gateway=192.168.1.1
DNS=1.1.1.1
EOF
Enslave each interface
for iface in enp3s0 enp4s0; do
sudo tee /etc/systemd/network/20-${iface}.network <<EOF
[Match]
Name=${iface}
[Network]
Bond=bond0
EOF
done
sudo systemctl restart systemd-networkd
sudo systemctl enable systemd-networkd
Verifying the Bond
Always verify before relying on a bond in production.
Read the kernel bond status file
cat /proc/net/bonding/bond0
You should see MII Status: up for each slave, the active slave (mode 1) or aggregator ID (mode 4), and the bonding mode name. For LACP, confirm 802.3ad info is present and each port shows LACP Activity: Active.
Check link state with ip
ip link show bond0
ip -s link show bond0
Confirm connectivity
ping -I bond0 192.168.1.1 -c 4
Fault-Injection Testing
A bond you have never broken is a bond you cannot trust. Test failover deliberately.
Method 1 – Physically unplug a cable
Unplug one patch cable and watch /proc/net/bonding/bond0. For mode 1 you will see the active slave change within miimon milliseconds. For mode 4 the aggregator will drop one port but traffic continues on the remaining link.
Method 2 – Bring a slave down in software
# Disable slave 1
sudo ip link set enp3s0 down
# Watch bond status in real time
watch -n1 cat /proc/net/bonding/bond0
# Re-enable
sudo ip link set enp3s0 up
Method 3 – ethtool carrier injection
# Simulate carrier loss (requires ethtool and a driver that supports it)
sudo ethtool --set-priv-flags enp3s0 disable-fw-lldp on
sudo ip link set enp3s0 carrier off 2>/dev/null || echo "Driver does not support carrier injection"
Not all drivers support carrier injection; falling a slave down via ip link set down is the most portable approach.
Measure failover time with ping
ping -I bond0 192.168.1.1 -i 0.2 &
sudo ip link set enp3s0 down
# Count dropped pings, then restore
sudo ip link set enp3s0 up
With miimon=100 expect 1–3 dropped pings during failover. Tuning miimon lower (e.g. 50ms) reduces the window at the cost of more kernel polling overhead.
Monitoring in Production
systemd service to alert on slave state change
The kernel emits uevents when bond slave state changes. You can hook into them via a udev rule:
sudo tee /etc/udev/rules.d/90-bond-alert.rules <<'EOF'
SUBSYSTEM=="net", ACTION=="change", ENV{MASTER}=="bond0", \
RUN+="/usr/local/bin/bond-alert.sh %k"
EOF
Have bond-alert.sh send a notification via your preferred channel (email, Slack webhook, PagerDuty). Reload udev after saving:
sudo udevadm control --reload-rules
Check LACP PDU counters
cat /proc/net/bonding/bond0 | grep -A5 "Slave Interface"
Healthy LACP PDU exchange shows incrementing counters. Stalled counters indicate the switch stopped sending LACP PDUs—check your switch configuration first.
Troubleshooting
- Bond stays in mode 4 but traffic drops entirely: The switch ports are not configured for LACP. Switch to active-backup temporarily to restore connectivity, then fix the switch config.
- One slave never joins the aggregator (LACP): Run
cat /proc/net/bonding/bond0and check the aggregator ID. A slave with a different aggregator ID usually means a switch port speed/duplex mismatch or LACP PDU not reaching the switch. Checkethtool enp3s0for speed negotiation. - NetworkManager keeps disconnecting slaves: Ensure each slave connection has
connection.autoconnect-slaves 1set:sudo nmcli connection modify bond0 connection.autoconnect-slaves 1 - MAC address flapping on switch: In active-backup mode, set
fail_over_mac=activeto prevent both slaves from presenting the same MAC simultaneously during failover. - Bonding module options not persisting after reboot: With systemd-networkd, options live in the
.netdevfile. With NetworkManager they persist in the connection profile. Do not also write to/etc/modprobe.d/bonding.confor you may get conflicting parameters.
Frequently asked questions
- Can I bond interfaces from different network cards or different speeds?
- Technically yes, but for LACP (mode 4) the 802.3ad standard requires all ports in an aggregation group to run at the same speed and duplex. Mixing speeds will cause one port to be excluded from the aggregator by the switch. Active-backup (mode 1) has no such restriction.
- Does LACP actually double my bandwidth for a single connection?
- No. LACP distributes flows across links, not individual packets (to avoid reordering). A single TCP connection between two hosts will use exactly one link. You gain aggregate throughput only when there are multiple simultaneous flows.
- What is the difference between miimon and arp_interval for link detection?
- miimon polls the NIC's MII (hardware) register to detect carrier loss—it is fast, reliable, and does not depend on network reachability. arp_interval sends ARP probes and can detect layer-3 path failures that miimon misses, but is slower and requires a valid ARP target. Use miimon for most cases; combine both only if you need end-to-end path validation.
- My switch shows the port-channel as 'suspended'. What is wrong?
- A suspended port-channel almost always means an LACP parameter mismatch: check that both sides use the same port priority, system priority, and that the switch port is set to 'mode active' or 'mode passive'—never 'mode on' (static) when the Linux side is in 802.3ad mode.
- Can I add a third NIC to an existing bond without downtime?
- Yes. Just add a new slave connection pointing to the existing bond master. In LACP mode the switch must also add that port to the port-channel. Traffic continues on the existing slaves while the new one negotiates LACP and joins the aggregator.
Related guides
Build a Mesh VPN with Nebula
Build a fully self-hosted mesh VPN with Nebula: create a CA, sign node certs, configure lighthouses, enforce group-based firewall rules, and run as a systemd service.
Common Linux Network Ports Reference
Learn Linux port ranges, read /etc/services, find what's listening with ss and nmap, and apply solid firewall rules to expose or block the right ports.
How to Configure a Static IP on Linux
Configure a static IP on Linux using Netplan, NetworkManager (nmcli), or systemd-networkd across Ubuntu, Fedora, Debian, and Arch with verified steps.
Expose a Service with Cloudflare Tunnel
Expose local services to the internet without port-forwarding using Cloudflare Tunnel. Install cloudflared, create a named tunnel, configure ingress rules, and run as a systemd service.