Berik Ashimov // senior.it.engineer
Download CV
POSTS / MIKROTIK

Bonding and Spanning Tree on RouterOS 7: Redundancy That Actually Fails Over

// series · MikroTik RouterOS 7 Guide part 20 of 35
  1. ... 17 earlier
  2. VXLAN on RouterOS 7: Layer 2 Over Any IP Network
  3. GRE, IPIP and EoIP on RouterOS 7: Picking the Right Dumb Tunnel
  4. Bonding and Spanning Tree on RouterOS 7: Redundancy That Actually Fails Over
  5. WiFi on RouterOS 7: The wifi Driver, CAPsMAN v2, and Roaming That Works
  6. Containers on RouterOS 7: Useful, Dangerous, and Frequently Misused
  7. ... 13 later
view the full series →

Link redundancy has two classic failure stories. The first: a bond that was never tested fails over for the first time during a real outage — and doesn’t, because the hash policy, the switch side, or the monitoring was wrong all along. The second: someone disables spanning tree “because it slows the network down,” and eight months later a contractor loops two wall ports and takes the site offline with a broadcast storm no one can even log into a switch to stop.

Both are self-inflicted. Both are cheap to prevent. RouterOS does bonding and STP competently — the work is in configuring them deliberately and testing the failure you’re claiming to be protected against.

LACP Bonding

802.3ad (LACP) is the default answer for aggregating links between a RouterOS box and a managed switch: both ends actively negotiate, member failures are detected by protocol, and misconfigurations show up as “bundle won’t form” instead of silent traffic blackholes.

Terminal window
/interface bonding add name=bond1 slaves=sfp-sfpplus1,sfp-sfpplus2 \
mode=802.3ad transmit-hash-policy=layer-2-and-3 \
lacp-rate=1sec mii-interval=100ms comment="Uplink to sw-core"

Then treat bond1 exactly like a physical interface — bridge it, VLAN it (bridge VLAN filtering from earlier in the series applies unchanged), address it.

The parameters that actually matter:

transmit-hash-policy decides how flows map to member links. layer-2 hashes on MACs only — useless on a routed link where every frame has the same two MACs (all traffic lands on one member). layer-2-and-3 adds IPs and is the sane default. layer-3-and-4 adds ports for best distribution across many flows, with the standard caveat that it can (rarely) reorder packets in edge cases like fragmented traffic. Understand one thing above all: a single flow never exceeds one member’s speed. Two bonded 10G links give you 20G of aggregate across many flows, not 20G for one backup job. If one elephant flow must go faster, you need a faster link, not a wider bond.

lacp-rate=1sec makes peers exchange LACPDUs every second instead of every 30, cutting worst-case partner-failure detection from ~90s to ~3s. On direct fiber, link-down detection is instant anyway; LACP rate matters when there’s something in the middle (media converters, provider handoffs) that can keep link up while the path is dead.

mii-interval=100ms is the local carrier check cadence — cheap, leave it tight.

ARP monitoring (link-monitoring=arp with arp-ip-targets=) exists for the paranoid case where carrier stays up but forwarding is broken. It’s mostly useful for non-LACP modes; with 802.3ad, LACPDUs already prove the peer is alive.

On the switch side, the port-channel must exist and match (LACP active, same speed/duplex members). The good news about LACP: mismatches usually fail loudly. Check bundle state with:

Terminal window
/interface bonding monitor bond1
# look for: active-ports, partner-mac — both members listed, partner not 00:00:00:00:00:00

A partner MAC of all zeros means the switch isn’t speaking LACP on that port — the bond is running on one leg with none of the redundancy you think you have.

balance-xor / active-backup are the fallbacks when the far side can’t LACP: active-backup (one live member, one standby) is the honest choice for dumb switches or dual-homing to two independent non-MLAG switches. The balance-* modes without switch cooperation invite MAC flapping on the switch side; use them only when you’ve read exactly what they do.

Testing the Bond

An untested bond is a decorative config. Before production:

Terminal window
# Watch state live from another session
/interface bonding monitor bond1
# Pull member 1 (administratively — or physically, better)
/interface ethernet disable sfp-sfpplus1
# traffic must continue; check pings from a LAN host, not just the router
/interface ethernet enable sfp-sfpplus1
# repeat for the other member

Do it with real traffic flowing and count lost pings. LACP failover should cost you at most a couple of packets. Log what you saw; that’s your baseline for the 3 AM comparison.

Spanning Tree: The Insurance You Don’t Get to Cancel

Every bridge you create on RouterOS has a protocol-mode. The choices are none, stp, rstp (default), and mstp.

Terminal window
/interface bridge set br-lan protocol-mode=rstp priority=0x1000

RSTP is the correct default and there is almost no legitimate reason to set none on a bridge that touches access ports. RSTP converges in a few seconds (contrast with classic STP’s 30–50s — the “STP is slow” folklore is about a protocol from 1990 that you shouldn’t be running), and its job is singular: when someone creates a physical loop — patch cable between two wall jacks, unmanaged desk switch plugged into itself, a second “helpful” uplink — RSTP blocks the redundant path instead of letting the broadcast storm melt the network. A storm doesn’t degrade the network; it removes it, including your management path to fix it.

Priority: the root bridge should be your core switch, chosen on purpose. Set your RouterOS bridge priority accordingly — lower value wins root. An access-layer device accidentally becoming STP root (default priorities everywhere) gives you a topology where traffic hairpins through the weakest box. Set core to 0x1000, distribution higher, access default.

Edge ports: ports facing end hosts should skip the listening/learning delay and not generate topology changes when a laptop unplugs:

Terminal window
/interface bridge port set [find interface=ether5] edge=yes

An edge port that later hears a BPDU automatically falls back to non-edge — safe by design. For extra rigor on ports where no bridge should ever appear, add bpdu-guard=yes: the port shuts down if a BPDU arrives, turning “contractor plugged in a switch” into a ticket instead of a topology change.

MSTP maps VLANs to multiple spanning-tree instances so different VLANs can use different redundant paths. If you’re running a VLAN-filtering bridge with genuinely redundant L2 paths per VLAN region, MSTP is there — but be honest about whether your topology needs it. Most MikroTik deployments have exactly one L2 path plus loops-by-accident; RSTP covers that with a fraction of the configuration surface.

One RouterOS-specific note: STP settings live on the bridge, and hardware-offloaded bridge ports on switch chips still participate correctly — but always verify after changing protocol-mode that offload flags (H) survived, since some feature combinations push traffic to CPU (the bridge VLAN article has the full offload compatibility discussion).

Bond + Bridge + VLANs Together

The full stack, in the order that avoids lockouts:

Terminal window
/interface bonding add name=bond1 slaves=sfp-sfpplus1,sfp-sfpplus2 mode=802.3ad \
transmit-hash-policy=layer-2-and-3
/interface bridge port add bridge=br-lan interface=bond1
/interface bridge vlan add bridge=br-lan tagged=br-lan,bond1 vlan-ids=10,20,30

The bond is one logical port to the bridge and to VLAN filtering. LACP handles member failure below; RSTP handles topology loops above; VLAN filtering segments traffic through it all. Each layer does one job.

Verification

Terminal window
/interface bonding monitor bond1
/interface bridge monitor br-lan # root bridge ID, root port, topology changes
/interface bridge port print detail # role: root/designated, edge flag, H flag
/log print where message~"topology"

A healthy network shows a stable root you chose, zero unexpected topology changes over days, and both bond members active. Topology-change counters climbing without cabling work means an edge port isn’t marked edge — or something is flapping.

Closing Thoughts

Redundancy is a claim, and claims get tested. Bond with LACP and pull each cable while watching traffic; run RSTP everywhere with a deliberately chosen root, edge ports marked, and BPDU guard where switches must never appear. The half hour this costs is the difference between “we lost a link at 02:10, nobody noticed” and the two incident stories this article opened with. I’ve configured the VyOS equivalents in that series’ HA article — the concepts are identical, which is exactly why they’re worth internalizing once, properly.

// share