Linux Bonding with VLANs

Every time I set up network bonding on a Linux box I end up digging through the same stack of man pages and blog posts from 2014. This is my attempt to write it down somewhere useful.

The Setup

The goal is straightforward: combine two physical NICs into a bonded interface for redundancy (or throughput), then layer VLAN-tagged sub-interfaces on top of the bond. This is bread-and-butter stuff for any server attached to a managed switch.

1
2
3
4
5
Physical: eth0, eth1
  └── bond0 (active-backup or 802.3ad)
        ├── bond0.10  (VLAN 10 — management)
        ├── bond0.20  (VLAN 20 — production)
        └── bond0.30  (VLAN 30 — storage)

Configuring the Bond

Load the bonding kernel module and create the bond interface:

1
2
3
4
5
modprobe bonding
ip link add bond0 type bond mode active-backup
ip link set eth0 master bond0
ip link set eth1 master bond0
ip link set bond0 up

For active-backup, one interface carries traffic and the other sits idle as a hot standby — the switch doesn’t need any special config. If you want 802.3ad (LACP) for active/active, your switch ports need to be configured with a port-channel on the other end.

To make the bond persist across reboots on a RHEL/Rocky system, drop a file in /etc/NetworkManager/system-connections/ or use nmcli:

1
2
3
nmcli con add type bond con-name bond0 ifname bond0 bond.options "mode=active-backup,miimon=100"
nmcli con add type ethernet ifname eth0 master bond0
nmcli con add type ethernet ifname eth1 master bond0

Adding VLANs

With the bond up, adding VLANs is just a matter of creating tagged sub-interfaces:

1
2
3
4
5
6
ip link add link bond0 name bond0.10 type vlan id 10
ip link add link bond0 name bond0.20 type vlan id 20
ip link set bond0.10 up
ip link set bond0.20 up
ip addr add 10.10.10.5/24 dev bond0.10
ip addr add 10.20.20.5/24 dev bond0.20

With nmcli:

1
2
nmcli con add type vlan con-name bond0.10 ifname bond0.10 dev bond0 id 10 ip4 10.10.10.5/24 gw4 10.10.10.1
nmcli con add type vlan con-name bond0.20 ifname bond0.20 dev bond0 id 20 ip4 10.20.20.5/24

Checking Your Work

A few commands worth bookmarking:

1
2
3
4
5
6
7
8
# Bond status — shows active slave, link state, MII status
cat /proc/net/bonding/bond0

# Verify VLAN sub-interfaces
ip -d link show bond0.10

# Check which slave is active
ip link show master bond0

The cat /proc/net/bonding/bond0 output is especially handy — it’ll tell you which interface is currently active, when the last failover happened, and the MII polling interval.

One Gotcha

If you’re running firewalld, new VLAN interfaces won’t automatically inherit a zone. Assign them explicitly or traffic will hit the default zone (usually public, which drops most things):

1
2
firewall-cmd --zone=trusted --add-interface=bond0.20 --permanent
firewall-cmd --reload

That one burned me for longer than I’d like to admit.


comments powered by Disqus