VyOSX · Bonding and Link AggregationBonding
Bond validation — /proc/net/bonding, show bonding, throughput testing
What you'll learn
- Run the canonical validation command set for a bond
- Read the kernel driver state from /proc/net/bonding
- Cross-check the host and switch counters
- Run a throughput test that proves the aggregate is working
- Build a validation script that runs the full set on demand
Prerequisites
- Ethernet, MAC and ARP — the Layer 2 the routing engineer must read
- LACP — the protocol that aggregates links
- Bond modes — balance-rr, active-backup, balance-xor, 802.3ad, balance-tlb, balance-alb
- Switch dependencies — LAG, port-channel, MLAG, and switch model specifics
- Bond failure modes — slave down, LACP flap, hash mismatch, MTU mismatch
- Bond + VLAN — trunk on a bond, sub-interfaces on bond members, native VLAN rule
Verified against VyOS 1.5.x LTS (circinus) · VyOS 1.4.x (sagitta) — legacy · FRRouting 10.x (VyOS 1.5) · Linux kernel 6.6 LTS (VyOS 1.5 base) · strongSwan 5.9.x (IPsec) · WireGuard 1.0.x (kernel module + userspace tooling) · 2026-08-15
Bond validation — /proc/net/bonding, show bonding, throughput testing
A bond that is “up” is not necessarily a bond that is working. The bond may be up but the aggregation may be broken, the slave may be silently degraded, or the switch-side may not match the host-side. The validation command set is what proves the bond is doing what the configuration says. This lesson walks through the canonical commands, the cross-check with the switch, and the throughput test that proves the aggregate.
The validation command set
flowchart TD
A[Bond validation] --> B[Host side]
A --> C[Switch side]
B --> B1[cat /proc/net/bonding/bond0]
B --> B2[show bonding]
B --> B3[ip -s link show bond0]
B --> B4[ip -s link show eth0]
B --> B5[ip -s link show eth1]
B --> B6[ethtool eth0]
B --> B7[ethtool eth1]
B --> B8[iperf3 to peer]
C --> C1[show etherchannel summary]
C --> C2[show etherchannel detail]
C --> C3[show interfaces counters]
C --> C4[show spanning-tree]
The host side has six commands. The switch side has four. The host-side set is the canonical truth; the switch-side is the cross-check.
Command 1 — cat /proc/net/bonding/bond0
This is the canonical source of truth. The kernel driver writes its state to this file on every state change.
vyos@vyos:~$ sudo cat /proc/net/bonding/bond0
Ethernet Channel Bonding Driver: v6.6
Bonding Mode: IEEE 802.3ad Dynamic Link Aggregation
LACP rate: fast
LACP active: on
...
Slave Interface: eth0
MII Status: up
Speed: 1000 Mbps
Duplex: full
Link Failure Count: 0
Slave Interface: eth1
MII Status: up
Speed: 1000 Mbps
Duplex: full
Link Failure Count: 0
What to check:
Bonding Mode:— must match the configuration.LACP active:— must beonfor 802.3ad.MII Status:on each slave — must beup.Speed:on each slave — must match.Link Failure Count:— should be 0 in steady state.Aggregator ID:on each slave — must be the same non-zero number.
Command 2 — show bonding
The VyOS-level wrapper around /proc/net/bonding:
vyos@vyos:~$ show bonding
Interface Mode Slaves Speed
bond0 802.3ad 2 2000
This is the summary. The full state is via show bonding detail:
vyos@vyos:~$ show bonding detail
What to check:
Mode:matches the configuration.Slaves:matches the number of configured members.Speed:is the aggregate of the slaves.
Command 3 — ip -s link show bond0
The kernel-level interface counters:
vyos@vyos:~$ ip -s link show bond0
3: bond0: <BROADCAST,MULTICAST,MASTER,UP,LOWER_UP> mtu 9000 ...
RX: bytes packets errors dropped missed mcast
123456 1234 0 0 0 0
TX: bytes packets errors dropped carrier collsns
234567 2345 0 0 0 0
What to check:
errorsanddroppedshould be 0 in steady state.carriershould be 0 — the bond is not losing carrier.- The
bytescounter should grow at the expected rate during a throughput test.
Command 4 — ip -s link show eth0 and eth1
The slave-level counters:
vyos@vyos:~$ ip -s link show eth0
4: eth0: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 9000 ...
RX: bytes packets errors dropped missed mcast
61728 617 0 0 0 0
TX: bytes packets errors dropped carrier collsns
117283 1172 0 0 0 0
The slave counters should be roughly half of the bond counters (for a 2-slave bond). The ratio is the proof that both slaves are carrying traffic.
Command 5 — ethtool eth0 and eth1
The physical link state:
vyos@vyos:~$ ethtool eth0
Settings for eth0:
Supported ports: [ TP ]
Supported link modes: 1000baseT/Full
Speed: 1000Mb/s
Duplex: Full
Port: Twisted Pair
PHYAD: 0
Link detected: yes
What to check:
Speed:— must match the configuration.Duplex:— must beFull.Link detected:— must beyes.
Command 6 — iperf3
The throughput test:
vyos@vyos:~$ iperf3 -c <peer> -t 30 -i 5
Connecting to host <peer>, port 5201
[ 5] 0.00-5.00 sec 550 MBytes 922 Mbits/sec
[ 5] 5.00-10.00 sec 549 MBytes 921 Mbits/sec
[ 5] 10.00-15.00 sec 550 MBytes 922 Mbits/sec
[ 5] 15.00-20.00 sec 549 MBytes 921 Mbits/sec
[ 5] 20.00-25.00 sec 550 MBytes 922 Mbits/sec
[ 5] 25.00-30.00 sec 549 MBytes 921 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bandwidth
[ 5] 0.00-30.00 sec 3.22 GBytes 921 Mbits/sec
sender
[ 5] 0.00-30.00 sec 3.22 GBytes 921 Mbits/sec
receiver
What to check:
- Single-stream throughput should be near the speed of one slave (since TCP is single-streamed).
- Multi-stream throughput (
iperf3 -P 4) should reach the aggregate. - For a 2-slave 1 Gbps bond, the expected aggregate is ~1.8 Gbps (some overhead).
The switch-side cross-check
The host sees the bond. The switch sees the channel. The two must agree:
Cisco IOS
Switch# show etherchannel summary
Group Port-channel Protocol Ports
------+-------------+-----------+---------------------
10 Po10(SU) LACP Eth1/1(P) Eth1/2(P)
What to check:
- The port-channel is
SU(up, in layer-2 state). - The protocol is
LACP. - The ports are
P(bundled).
Arista EOS
Switch# show etherchannel summary
Group Port-channel Protocol Ports
------+-------------+-----------+---------------------
10 Port-Channel10 LACP Eth1(P) Eth2(P)
Same layout, different syntax.
Switch# show interfaces counters
The interface counters on the switch must match the host-side counters within the normal asymmetric margin (different counter rollover timing, different MTU overhead calculation).
The validation script
The full validation runs the host-side and switch-side commands and reports the result:
#!/bin/bash
# validate-bond.sh — run the canonical validation command set
set -euo pipefail
BOND=${1:-bond0}
HOST=$(hostname)
echo "=== Host: $HOST ==="
echo ""
echo "--- /proc/net/bonding/$BOND ---"
sudo cat /proc/net/bonding/$BOND
echo ""
echo "--- show bonding ---"
show bonding
echo ""
echo "--- ip -s link show $BOND ---"
ip -s link show $BOND
echo ""
echo "--- ip -s link show eth0 ---"
ip -s link show eth0
echo ""
echo "--- ip -s link show eth1 ---"
ip -s link show eth1
echo ""
echo "--- ethtool eth0 ---"
ethtool eth0
echo ""
echo "--- ethtool eth1 ---"
ethtool eth1
echo ""
echo "--- Partner MAC consistency check ---"
PARTNER0=$(sudo grep -A2 "Slave Interface: eth0" /proc/net/bonding/$BOND | grep "Partner MAC" | awk '{print $3}')
PARTNER1=$(sudo grep -A2 "Slave Interface: eth1" /proc/net/bonding/$BOND | grep "Partner MAC" | awk '{print $3}')
if [ "$PARTNER0" = "$PARTNER1" ]; then
echo "Both slaves peer with the same switch ($PARTNER0)"
else
echo "Slaves peer with different switches ($PARTNER0 vs $PARTNER1) — MLAG case"
fi
echo ""
echo "=== End of validation ==="
The script writes the full output to a file, which the operator can attach to the change record. The change-control process always includes the validation output.
Throughput test methodology
The throughput test is the proof that the aggregate is working. The methodology:
- Baseline — run
iperf3 -c <peer> -t 60 -P 1between the host and a known peer. Record the throughput. - Parallel streams — run
iperf3 -c <peer> -t 60 -P 4. The throughput should be roughly 4x the single-stream. - Reverse direction — run
iperf3 -c <peer> -t 60 -Rto test the return direction. - Compare — the throughput should be near the aggregate of the slaves. For a 2-slave 1 Gbps bond, expect ~1.8 Gbps.
vyos@vyos:~$ iperf3 -c <peer> -t 60 -P 4
The -P 4 runs four parallel streams. For a 2-slave bond,
the four streams should distribute across the two slaves per
the hash policy.
How it fails
The production validation failure modes the engineer must recognise:
- /proc says up but throughput is half. The bond is up but only one slave is carrying traffic. The hash policy is likely misconfigured.
- Switch P flag missing. The port-channel is up but one port is not bundled. The LACP negotiation is failing.
- MTU mismatch on validation. The
ping -M do -s 8972fails. The MTU chain is broken. - Speed mismatch. One slave is 100 Mbps and another is 1 Gbps. The aggregation is at the lowest speed.
- Counter mismatch. The host counter and switch counter differ by more than the expected margin. The bridge is dropping frames.
Rollback
The recovery from a failed validation:
- Re-run the validation to confirm the failure mode.
- Identify which command output is wrong.
- Apply the remediation for that mode:
- Wrong mode:
set interfaces bonding bond0 mode '...'; commit; save. - Wrong hash policy:
set interfaces bonding bond0 hash-policy '...'; commit; save. - Wrong MTU:
set interfaces bonding bond0 mtu '...'; commit; save.
- Wrong mode:
- Re-run the validation to confirm the fix.
Production discipline
Cross-course references
The Linux course’s XXII-Linux-NetTroubleshoot covers the
counter and diagnostic discipline. The Observability course’s
XLIX-Observability-NetMetrics covers the dashboard and
alerting side. The Ansible course’s XLII-Ansible-BeyondLinux
covers the script automation and CI integration.
Quiz
Knowledge check · 4 questions
Q1. What is the canonical source of truth for the bond state on a VyOS host?
Q2. A bond of two 1 Gbps slaves carries a single TCP stream at roughly 1 Gbps, not 2 Gbps.
Q3. The bond is up per `/proc/net/bonding/bond0`. The throughput test shows 940 Mbps on a single stream but only 1.1 Gbps on four parallel streams. What is the issue?
The single-stream throughput is 940 Mbps, which is near the speed of one slave. The parallel-stream throughput is 1.1 Gbps, which is barely above the speed of one slave. The expected aggregate is ~1.8 Gbps.
Q4. The validation script shows the bond is up with both slaves up. The throughput test shows the expected aggregate. After one monitoring cycle, the post-validation output shows one slave went down. What is the next step?
The post-change validation was clean. After one monitoring cycle, the post-validation shows one slave down. The bond is degraded but the other slave is still up.
Passing score: 75%. Answers are checked in this browser.