Skip to main content
RunBook Academy

← All labs in Linux

Lab · advanced · ~60 min

Lab: Build a bond with a VLAN subinterface and verify LACP

B · Nested virtualisationC · Simulation

Objectives

  • Create a bond with two physical interfaces in LACP mode
  • Add a VLAN subinterface on top of the bond
  • Verify LACP negotiation with /proc/net/bonding
  • Test redundancy by failing one link

Prerequisites

This lab builds a production-grade network stack: two physical interfaces bonded with LACP, a VLAN subinterface on top of the bond, and end-to-end verification.

Objective

By the end of this lab, you can:

  • Build a bond with two physical interfaces in LACP mode.
  • Add a VLAN subinterface on the bond.
  • Verify LACP negotiation with /proc/net/bonding/bond0.
  • Test redundancy by simulating one link’s failure.
  • Persist the configuration with Netplan or systemd-networkd.

Architecture

The host has two physical interfaces (eth0 and eth1) connected to two switch ports configured as a single LACP channel. The host presents a single bond interface bond0. A VLAN subinterface bond0.100 carries traffic for VLAN 100.

The switch ports must be configured for LACP active mode. In this lab, if you do not have a real switch available, you can simulate by:

  • Using two VMs with a virtual switch in between.
  • Using nm-connection-editor on a host with two interfaces connected to two physical switch ports.
  • Using veth pairs in a network namespace to create a loop.

For read-only exploration, ip commands work without a switch - the bond stays up even if no aggregation occurs.

Requirements

  • A lab host with two spare physical or virtual interfaces (eth0, eth1) that carry no production traffic.
  • Console, serial, or IPMI/BMC access to the host, confirmed working before you start.
  • Root or sudo on the host.
  • Optionally a switch with the two ports in an LACP channel. The lab works without one; LACP simply never negotiates a partner.

Tasks

Task 1: Read and record the current state

Capture the starting configuration. You need these values to restore the host in Cleanup, and you cannot recover them once the interfaces are torn down.

ip -br link show
ip -br addr show
ethtool eth0 | grep -E 'Speed|Link'
ethtool eth1 | grep -E 'Speed|Link'

# Record the addresses and routes you are about to destroy
ip -o addr show dev eth0 | tee ~/lab-eth0-addr.txt
ip route show | tee ~/lab-routes.txt
ip route get 1.1.1.1 | tee ~/lab-default-path.txt

Confirm eth0 and eth1 are up and at the expected speed, and that ~/lab-default-path.txt does not name eth0 or eth1 as the interface your management traffic uses. If it does, stop and move to the console.

Task 2: Create the bond

sudo modprobe bonding
sudo ip link add bond0 type bond mode 802.3ad miimon 100 lacp_rate fast
sudo ip link set bond0 up

Verify the bond exists, and verify link monitoring is actually on:

ip -d link show bond0
cat /proc/net/bonding/bond0    # shows bond mode but no slaves yet

cat /sys/class/net/bond0/bonding/miimon        # must not be 0
grep 'MII Polling Interval' /proc/net/bonding/bond0

Task 3: Attach the slaves

This is the step that cuts network access. Run it from the console, or from a session on a third interface.

Service impact possibleenslave eth0 and eth1
$ sudo ip link set eth0 down
sudo ip link set eth1 down

sudo ip link set eth0 master bond0
sudo ip link set eth1 master bond0

sudo ip link set eth0 up
sudo ip link set eth1 up

Verify:

cat /proc/net/bonding/bond0

The output should list both slaves with MII Status: up and matching Aggregator ID. If the switch is configured correctly, you will also see partner MAC and key.

Task 4: Test redundancy

There are two failure tests here, and they are not interchangeable. Run both. The first one always passes. Only the second one validates miimon.

Task 4a: Administrative down - always detected

Service impact possiblefail one bond member administratively
$ sudo ip link set eth0 down
cat /proc/net/bonding/bond0
ping -c 3 10.0.0.1   # should still work via eth1

This proves the bond is aggregated and traffic survives on one member. It proves nothing about link monitoring.

Task 4b: Real carrier loss - the test that validates miimon

Cause a genuine carrier loss on eth0 by one of these, in order of preference:

  • Unplug the cable, or remove the transceiver.
  • Ask the network team to shutdown the switch port.
  • On a VM, detach the virtual NIC from its network from the hypervisor, not from inside the guest.

Then read the bond again:

cat /proc/net/bonding/bond0     # eth0 must show MII Status: down
ping -c 3 10.0.0.1              # must still work via eth1

Then restore the cable or re-enable the port, and restore the administrative state:

sudo ip link set eth0 up
sleep 3
cat /proc/net/bonding/bond0

Confirm both slaves are back to MII Status: up before moving on. Do not start Task 5 with a degraded bond.

Task 5: Add a VLAN subinterface

sudo ip link add link bond0 name bond0.100 type vlan id 100
sudo ip link set bond0.100 up
sudo ip addr add 10.100.0.10/24 dev bond0.100

Adding the address already installs the connected route for 10.100.0.0/24, so the VLAN gateway is reachable without touching the default route. If your VLAN subnet is not the one the address implies, add an explicit route instead:

sudo ip route add 10.100.0.0/24 dev bond0.100

Verify:

ip -d link show bond0.100
ip route show dev bond0.100
ping -c 3 10.100.0.1

The VLAN tag is 100; the host can reach the VLAN gateway.

Task 6: Test VLAN redundancy

Service impact possiblefail one member under VLAN traffic
$ sudo ip link set eth0 down
ping -c 3 10.100.0.1   # should still work via eth1
sudo ip link set eth0 up

The VLAN rides on the bond; bond redundancy propagates to the VLAN.

Task 7: Persist with Netplan

# /etc/netplan/99-bond-vlan.yaml
network:
  version: 2
  renderer: networkd
  ethernets:
    eth0:
      dhcp4: no
    eth1:
      dhcp4: no
  bonds:
    bond0:
      interfaces:
        - eth0
        - eth1
      parameters:
        mode: 802.3ad
        lacp-rate: fast
        transmit-hash-policy: layer3+4
        mii-monitor-interval: 100
  vlans:
    bond0.100:
      id: 100
      link: bond0
      addresses:
        - 10.100.0.10/24
      # Add a default route here ONLY if this VLAN really is the
      # host's default egress path. If the host reaches the world
      # over a separate management interface, leave it out - a
      # second default route either conflicts or hijacks egress.
      # routes:
      #   - to: default
      #     via: 10.100.0.1

Apply safely. netplan try applies the configuration and automatically rolls it back after 120 seconds unless you confirm, which is exactly the protection you want when a network change can cut your session:

sudo netplan try

Then commit:

sudo netplan apply

Verify:

cat /proc/net/bonding/bond0
ip -d link show bond0.100
ip route show
ping 10.100.0.1

Task 8: Document the rollback

The rollback is to delete the new file and re-apply:

sudo rm /etc/netplan/99-bond-vlan.yaml
sudo netplan apply

This restores any earlier configuration (often DHCP on eth0).

Validation

  • The bond has two slaves with matching Aggregator ID.
  • cat /sys/class/net/bond0/bonding/miimon prints a non-zero value, and /proc/net/bonding/bond0 reports a matching MII Polling Interval.
  • LACP partner information is populated (when connected to a switch).
  • Pulling one cable - not ip link set eth0 down - does not break connectivity, and /proc/net/bonding/bond0 shows that member as MII Status: down.
  • The VLAN subinterface is reachable and rides the bond’s redundancy.
  • The configuration survives a reboot (after netplan apply).

Cleanup

Run cleanup from the console too. Tearing the bond down removes the host’s addressing along with it.

Open the captures you took in Task 1 (~/lab-eth0-addr.txt and ~/lab-routes.txt) before you start. You are about to need the original address, prefix length and default gateway, and after the teardown there is nowhere left to read them from.

Service impact possibletear down the bond
$ # 1. Remove the VLAN and the bond
sudo ip link set bond0.100 down
sudo ip link del bond0.100

sudo ip link set eth0 nomaster
sudo ip link set eth1 nomaster

sudo ip link set bond0 down
sudo ip link del bond0

# 2. Remove the persisted config, if you created it in Task 7
sudo rm -f /etc/netplan/99-bond-vlan.yaml

Now restore addressing. Substitute the values you recorded in Task 1; the ones below are only an example:

sudo ip link set eth0 up
sudo ip link set eth1 up

# Static example - use YOUR recorded address and prefix
sudo ip addr add 192.0.2.25/24 dev eth0
sudo ip route add default via 192.0.2.1 dev eth0

If the host was on DHCP before the lab, the cleaner restore is to let the renderer rebuild the configuration rather than typing addresses back by hand:

sudo netplan apply          # rebuilds from /etc/netplan/*.yaml
# or, on a networkd host without netplan:
sudo systemctl restart systemd-networkd

Verify the host is genuinely back before you close the console:

# Substitute your own values before running:
GATEWAY=192.0.2.1

ip -br addr show
ip route show
ip route get 1.1.1.1     # compare with ~/lab-default-path.txt
ping -c 3 "$GATEWAY"

The lab is only cleaned up when ip route show and ip -br addr show match what you recorded in Task 1. Removing what you built is not the same as restoring what was there.

What you learned

  • LACP requires switch configuration. Without it, the bond stays up but no aggregation occurs.
  • A VLAN on a bond inherits the bond’s redundancy.
  • /proc/net/bonding/bond0 is the canonical diagnostic.
  • netplan try is the safe way to apply remote network changes.
  • Enslaving an interface requires taking it down, so any bond build cuts the session running over that interface. Out-of-band access is a prerequisite for the work, not a fallback.
  • Record addresses and routes before you destroy them. A cleanup that removes what you built but does not restore what was there leaves the host unreachable.
  • A second default route either conflicts or hijacks egress. Adding one is a separate, deliberate change with its own rollback.

Deliverables

  • · A working bond with two slaves
  • · A VLAN subinterface carrying production traffic
  • · Output of /proc/net/bonding/bond0 showing all slaves up
  • · A documented test of link failure and recovery

Verification status

Last reviewed
2026-08-09
Executed end to end
not yet run on hardware

The commands and configuration here have been reviewed against the verified software versions, but nobody has run this lab start to finish on a system meeting its prerequisites. Treat the Expected Outcome as the intended result rather than an observed one, and keep the Cleanup section to hand.