STP and RSTP on Cisco IOS-XE: Spanning Tree Deep Dive for Network Engineers

STP and RSTP on Cisco IOS-XE: Spanning Tree Deep Dive for Network Engineers

Why Spanning Tree Still Matters in 2026

Every time I walk into a network outage and the first thing the on-call engineer says is “the switches are acting weird,” my gut goes straight to Spanning Tree. STP is one of those foundational technologies most engineers understand at a surface level — root bridge, blocked ports, no loops — but few have internalized enough to troubleshoot confidently under pressure.

This guide covers STP and RSTP as they actually run on Cisco IOS-XE: root bridge election, port roles and states, the protection features you must enable, and real CLI output so you know exactly what healthy looks like. If you’ve worked with VLANs for any length of time, you already know that a misconfigured STP topology can black-hole traffic in ways that look deceptively like a routing problem.

STP 101: What It Actually Does

Ethernet switches flood unknown unicast and broadcast frames out every port. Without a loop-prevention mechanism, a single broadcast in a redundant Layer 2 topology would circulate forever — a broadcast storm that saturates links in milliseconds and brings your network to its knees. STP (802.1D) solves this by electing a root bridge and then mathematically computing which ports should forward and which should block, leaving a single active path between any two devices while keeping redundant links ready.

The classic 802.1D STP has a major flaw: convergence takes 30–50 seconds. If a link fails, STP runs through listening and learning states before a previously blocked port can start forwarding. That’s an eternity for production traffic. RSTP (802.1w), introduced in 2001 and now the default on virtually all modern Cisco switches, fixes this by replacing the timer-based state machine with a proposal/agreement handshake between adjacent switches, enabling sub-second convergence in most topologies.

On Cisco IOS-XE, the mode you’re running determines which protocol is in use:

Switch# show spanning-tree summary
Switch is in rapid-pvst mode
Root bridge for: VLAN0001, VLAN0010, VLAN0020, VLAN0100

Name                   Blocking Listening Learning Forwarding STP Active
---------------------- -------- --------- -------- ---------- ----------
VLAN0001                     0         0        0          4          4
VLAN0010                     0         0        0          4          4
VLAN0020                     1         0        0          3          4
VLAN0100                     1         0        0          3          4

rapid-pvst is the standard — Rapid Per-VLAN Spanning Tree Plus. Each VLAN runs its own STP instance, which lets you load-balance across uplinks by making different switches the root for different VLANs. The alternative, mst (Multiple Spanning Tree), maps multiple VLANs to a smaller number of instances and is worth considering in very large environments, but Rapid PVST covers most production needs.

Root Bridge Election and Manipulation

The root bridge is the switch with the lowest Bridge ID — a combination of priority (default 32768) and MAC address. Every other switch in the topology computes the shortest path to the root and blocks ports accordingly. Letting STP elect a root bridge based on the lowest MAC address in your environment is a recipe for surprises: a cheap access switch with a low MAC could become root and force traffic through a suboptimal path.

Always manually set your root bridge on the core or distribution switches:

! Set primary root for VLAN 10 and 20
CoreSW(config)# spanning-tree vlan 10,20 priority 4096

! Or use the macro that sets priority to 24576 (or lower if needed)
CoreSW(config)# spanning-tree vlan 10,20 root primary

! Set secondary root (priority 28672)
CoreSW2(config)# spanning-tree vlan 10,20 root secondary

Verify the result:

CoreSW# show spanning-tree vlan 10

VLAN0010
  Spanning tree enabled protocol rstp
  Root ID    Priority    4106
             Address     b4e9.b0a1.1200
             This bridge is the root
             Hello Time   2 sec  Max Age 20 sec  Forward Delay 15 sec

  Bridge ID  Priority    4106   (priority 4096 sys-id-ext 10)
             Address     b4e9.b0a1.1200
             Hello Time   2 sec  Max Age 20 sec  Forward Delay 15 sec
             Aging Time  300 sec

Interface           Role Sts Cost      Prio.Nbr Type
------------------- ---- --- --------- -------- --------------------------------
Gi1/0/1             Desg FWD 4         128.1    P2p
Gi1/0/2             Desg FWD 4         128.2    P2p
Gi1/0/3             Desg FWD 4         128.3    P2p
Gi1/0/24            Desg FWD 4         128.24   P2p

Notice the priority is 4106, not 4096 — that’s 4096 + the VLAN ID (10). This is the sys-id-ext encoding that allows per-VLAN priorities without consuming a larger number space.

Port Roles, Port States, and RSTP Convergence

RSTP defines four port roles:

  • Root Port — the single port on a non-root switch with the best path cost to the root bridge. Forwards traffic.
  • Designated Port — the port on a segment that is closest to the root bridge. Forwards traffic. Every active segment has exactly one designated port.
  • Alternate Port — a backup to the root port, receiving BPDUs from another switch that has a better path to root. Blocks traffic but can become root port immediately on failure (no listening/learning delay) — this is the key RSTP speedup.
  • Backup Port — a backup to a designated port on the same shared segment. Rare in point-to-point Ethernet topologies.

RSTP collapses the classic five STP states into three: Discarding, Learning, and Forwarding. The proposal/agreement mechanism moves a port from Discarding to Forwarding almost immediately on a point-to-point link once the downstream switch agrees to take all its ports into discarding first.

AccSW# show spanning-tree vlan 10 detail

 VLAN0010 is executing the rstp compatible Spanning Tree protocol
  Bridge Identifier has priority 32768, sysid 10, address a4b2.3901.cc00
  Configured hello time 2, max age 20, forward delay 15, transmit hold-count 6
  We are not the root of the spanning tree
  Topology change flag not set, detected flag not set
  Number of topology changes 2 last change occurred 4:12:33 ago
          from GigabitEthernet1/0/48

 GigabitEthernet1/0/1 of VLAN0010 is root forwarding
   Port info             port id 128.1   priority 128  cost 4
   Designated root       has priority 4106, address b4e9.b0a1.1200
   Designated bridge     has priority 4106, address b4e9.b0a1.1200
   Designated port       id 128.1, priority 128  cost 0
   Timers: message age 1, forward delay 0, hold 0
   Number of transitions to forwarding state: 2
   Link type is point-to-point by default
   BPDU: sent 0, received 12350

 GigabitEthernet1/0/48 of VLAN0010 is alternate discarding
   Port info             port id 128.48  priority 128  cost 4
   Designated root       has priority 4106, address b4e9.b0a1.1200
   Designated bridge     has priority 28682, address c8f7.5022.aa00
   Timers: message age 2, forward delay 0, hold 0
   Number of transitions to forwarding state: 1
   Link type is point-to-point by default
   BPDU: sent 0, received 8901

That Gi1/0/48 in Alternate Discarding is your redundant uplink — blocked, but it’ll take over instantly if Gi1/0/1 goes down. That “instantly” is what separates RSTP from classic STP.

The Protection Features You Must Enable

Running STP without protection features is like leaving your management plane unguarded — a topic we’ve covered in detail in our CoPP guide. The switch CPU processes BPDUs, and an attacker or a misconfigured device sending superior BPDUs can cause topology changes across your entire network.

PortFast

PortFast skips the listening and learning states and immediately moves a port to forwarding. Only use this on access ports connected to end hosts — never on trunk ports or switch-to-switch links.

! Enable on a specific access port
AccSW(config)# interface GigabitEthernet1/0/5
AccSW(config-if)# spanning-tree portfast

! Enable globally on all access ports (recommended)
AccSW(config)# spanning-tree portfast default

BPDU Guard

BPDU Guard shuts down a PortFast-enabled port the moment it receives a BPDU. If a switch or rogue access point is plugged into an access port, it will be immediately err-disabled. This prevents topology manipulation from end-user segments.

! Enable globally (applies to all PortFast-enabled ports)
AccSW(config)# spanning-tree portfast bpduguard default

! Or per-interface
AccSW(config-if)# spanning-tree bpduguard enable

When a port is err-disabled by BPDU Guard:

AccSW# show interfaces GigabitEthernet1/0/5 status

Port      Name               Status       Vlan       Duplex  Speed Type
Gi1/0/5                      err-disabled 10         auto    auto  10/100/1000BaseTX

%PM-4-ERR_DISABLE: bpduguard error detected on Gi1/0/5, putting Gi1/0/5 in err-disable state

To recover manually: shutdown then no shutdown. To auto-recover after a timer:

AccSW(config)# errdisable recovery cause bpduguard
AccSW(config)# errdisable recovery interval 300

Root Guard

Root Guard prevents a port from ever becoming the root port, even if it receives a superior BPDU. Enable it on ports facing downstream switches where the root bridge should never be. If a superior BPDU arrives, the port enters root-inconsistent state (discarding) rather than triggering a re-election.

! Enable on uplink-facing ports of distribution switches
DistSW(config)# interface range GigabitEthernet1/0/25-48
DistSW(config-if-range)# spanning-tree guard root
DistSW# show spanning-tree inconsistentports

Name                   Interface              Inconsistency
---------------------- ---------------------- ------------------
VLAN0010               GigabitEthernet1/0/36  Root Inconsistent

Loop Guard

Loop Guard protects against unidirectional link failures, where a port stops receiving BPDUs (because the upstream direction fails) but the port doesn’t go down (because the downstream direction still works). Without Loop Guard, the port would transition from blocking to forwarding and create a loop. With Loop Guard, the port enters loop-inconsistent state instead.

! Enable globally (recommended on non-PortFast ports)
CoreSW(config)# spanning-tree loopguard default

Note: Root Guard and Loop Guard are mutually exclusive on the same port — they serve different purposes and the switch will reject enabling both simultaneously.

Troubleshooting STP Issues

STP problems usually manifest as: intermittent packet loss, spanning tree topology changes flooding the network, or a complete segment going dark. Here’s the diagnostic workflow.

Step 1: Check for Topology Changes

CoreSW# show spanning-tree detail | include ieee|change|from|occurring

 Number of topology changes 847 last change occurred 0:00:12 ago
         from GigabitEthernet1/0/12

847 topology changes is a red flag. Every TC ages out the MAC table across the segment, causing floods until switches relearn. A port flapping is the usual culprit — check the logs:

CoreSW# show logging | include Gi1/0/12
Jul 11 09:43:22.102: %LINK-3-UPDOWN: Interface GigabitEthernet1/0/12, changed state to down
Jul 11 09:43:24.118: %LINK-3-UPDOWN: Interface GigabitEthernet1/0/12, changed state to up

Step 2: Verify Root Bridge Placement

CoreSW# show spanning-tree vlan 10 | include Root ID|This bridge
  Root ID    Priority    4106
             Address     b4e9.b0a1.1200
             This bridge is the root

If “This bridge is the root” doesn’t appear on your intended root switch, something has gone wrong — likely another switch with a lower priority or MAC has taken over. Check all switches:

AccSW# show spanning-tree vlan 10 | include Root ID|Address
  Root ID    Priority    4106
             Address     b4e9.b0a1.1200

Cross-check that MAC against your switch inventory. If it’s an unknown device, you have an unauthorized switch in the topology.

Step 3: Check for STP Inconsistencies

CoreSW# show spanning-tree inconsistentports

Name                   Interface              Inconsistency
---------------------- ---------------------- ------------------

No ports are in an inconsistent state.

Any entries here mean Loop Guard or Root Guard has triggered. Investigate the port and the connected device immediately.

Step 4: Debug BPDU Exchange (with caution)

For deep troubleshooting on a specific port, you can momentarily enable debug. Be careful — on a busy switch this can generate significant CPU load:

! Enable on specific interface only
CoreSW# debug spanning-tree bpdu interface GigabitEthernet1/0/1

Jul 11 09:50:01.003: STP: VLAN0010 rx BPDU: config protocol = rstp, packet from GigabitEthernet1/0/1  , linktype IEEE_CSMA, enctype 2, encsize 17
Jul 11 09:50:01.003: STP: enc C8:F7:50:22:AA:00 C8:F7:50:22:AA:00 00 26
Jul 11 09:50:01.003: STP: Data:  0000 0000 00 00 04 0A B4E9 B0A1 1200 0000 00 00 0400 0A
CoreSW# undebug all

PVST+ Load Balancing: Making Redundancy Actually Useful

Per-VLAN STP lets you run different root bridges for different VLANs, distributing traffic load across your uplinks rather than blocking one link entirely. This is a significant operational advantage over older STP designs — one of the practical reasons the Cisco IOS-XE platform has become the standard for modern campus deployments.

! CoreSW-A is root for VLANs 1-50, secondary for 51-100
CoreSW-A(config)# spanning-tree vlan 1-50 root primary
CoreSW-A(config)# spanning-tree vlan 51-100 root secondary

! CoreSW-B is root for VLANs 51-100, secondary for 1-50
CoreSW-B(config)# spanning-tree vlan 51-100 root primary
CoreSW-B(config)# spanning-tree vlan 1-50 root secondary

Verify traffic is actually split:

CoreSW-A# show spanning-tree summary totals

Root bridge for:   VLAN0001-VLAN0050

Name                   Blocking Listening Learning Forwarding STP Active
---------------------- -------- --------- -------- ---------- ----------
50 vlans                     25         0        0        125        150

With 50 VLANs root on each switch, both uplinks are actively carrying traffic — true link utilization instead of half your bandwidth sitting in Alternate Discarding.

STP Tuning: Path Cost and Port Priority

Modern Cisco IOS-XE uses long-mode path costs by default for Gigabit links and above. Confirm the setting and use it to influence root port selection without touching switch priorities:

CoreSW(config)# spanning-tree pathcost method long

Long-mode cost reference: 1Gbps = 20000, 10Gbps = 2000, 100Gbps = 200. Lower cost wins. To manually prefer one uplink:

AccSW(config)# interface GigabitEthernet1/0/1
AccSW(config-if)# spanning-tree vlan 10 cost 10000

This makes Gi1/0/1 the preferred root port for VLAN 10 against any other uplink running the default 20000 cost.

The IOS-XE Commands You Should Have Memorized

A quick reference for engineers who deal with STP regularly — these are the commands you want in muscle memory for fast triage, much like the systematic approach covered in our OSPF troubleshooting guide:

! Global STP health summary
show spanning-tree summary

! Per-VLAN topology (most useful)
show spanning-tree vlan <vlan-id>

! Detailed state including timers and BPDU counts
show spanning-tree vlan <vlan-id> detail

! All ports and their STP state
show spanning-tree vlan <vlan-id> interface

! Topology change history and counts
show spanning-tree detail | include change|from|ieee

! Any blocked or inconsistent ports
show spanning-tree inconsistentports

! Verify PortFast and BPDU Guard status
show spanning-tree interface <int> portfast

! See all err-disabled ports
show interfaces status err-disabled

Common STP Gotchas to Watch For

Unmanaged switches in the topology. A consumer switch plugged into an access port starts sending BPDUs. If BPDU Guard isn’t enabled, it can participate in STP. If it has a lower MAC address than your root bridge, it may win root election for certain VLANs — instantly degrading your topology.

Trunk ports without explicit VLAN pruning. When STP runs an instance per VLAN, the overhead adds up. A trunk carrying 200 VLANs runs 200 independent STP instances. Prune VLANs aggressively on trunk ports with switchport trunk allowed vlan to limit the blast radius of topology changes.

Access ports with PortFast but without BPDU Guard. PortFast without BPDU Guard is only half the protection. An employee who daisy-chains a switch under their desk will participate in STP elections from that access port. Always pair them.

Missing secondary root configuration. If your primary root switch fails and no secondary is configured, STP will elect a root based on MAC address — potentially one of your access switches. The result is a suboptimal traffic path you’ll need to correct manually. Always configure a secondary root.

Inconsistent STP modes. Mixing rapid-pvst and pvst on the same network forces the faster protocol to fall back to 802.1D timers at the boundary. Verify all switches in a domain run the same mode with show spanning-tree summary | include mode.

Final Thoughts

STP and RSTP are decades-old, but they remain the Layer 2 loop-prevention foundation of virtually every enterprise campus network. The difference between an engineer who “knows” STP and one who truly understands it usually becomes apparent at 2am during an outage. Root bridge election, port role transitions, protection features, and the show commands above — that’s the working knowledge that separates confident troubleshooting from guesswork.

Next time you’re onboarding a new switch or chasing mystery packet loss, show spanning-tree summary is where you start. It’s usually right there.

Enjoying this post?

Get more guides like this delivered straight to your inbox. No spam, just tech and trails.