Auto Draft

STP and RSTP on Cisco IOS-XE: Troubleshooting Loops, PortFast, BPDU Guard, and Root Bridge Control

Spanning Tree Protocol is the silent guardian of Layer 2 networks — when it works, you never think about it. When it breaks, you’re hunting a broadcast storm at 2 AM watching your CPU spike to 100% on every switch in the building. After years of working with Cisco Catalyst environments, I’ve developed a systematic approach to STP and RSTP that keeps loops out and convergence fast. This guide covers the real IOS-XE commands you need, with actual show output so you know what healthy looks like before something goes sideways.

STP vs RSTP: What Actually Changed

Classic 802.1D STP has one job: prevent loops. It does that by blocking redundant paths, electing a root bridge, and slowly transitioning ports through Blocking → Listening → Learning → Forwarding states. The problem is “slowly” — 802.1D convergence takes 30–50 seconds by default, which is brutal for any modern network.

802.1w RSTP (Rapid Spanning Tree) collapses those states into three: Discarding, Learning, and Forwarding. More importantly, it introduces proposal/agreement handshakes between switches so ports can transition to Forwarding in under a second on point-to-point links. It also absorbs what used to be optional features — PortFast and UplinkFast are baked into the protocol.

On Cisco IOS-XE, Rapid PVST+ (Per-VLAN Spanning Tree) is the default. You get one independent spanning tree instance per VLAN, which means root placement can be optimized per VLAN for load balancing across uplinks. If you’re in a mixed Cisco-only environment, this is usually what you want. Multiple Spanning Tree (MST/802.1s) maps multiple VLANs to fewer instances and scales better in large deployments — worth considering if you’re running hundreds of VLANs.

Understanding the underlying platform matters too. If you’re unclear on which IOS variant your switch is running, check out our Cisco IOS vs IOS-XE vs IOS-XR comparison — the CLI differences matter when you’re reading TAC documentation.

The Root Bridge Election: Don’t Leave It to Chance

STP elects a root bridge based on Bridge ID: priority (default 32768) plus the VLAN number, then MAC address as a tiebreaker. Left to defaults, the switch with the lowest MAC address wins — which is usually your oldest hardware. That’s a problem.

Always manually set your root bridges. On a Catalyst 9300 acting as distribution-layer root for VLAN 10:

SW-DIST-01(config)# spanning-tree vlan 10 priority 4096
SW-DIST-01(config)# spanning-tree vlan 10 root primary

The root primary macro is convenient — it sets priority to 24576, or 4096 lower than whatever the current root is. But I prefer explicit priorities so there’s no ambiguity. For secondary root:

SW-DIST-02(config)# spanning-tree vlan 10 priority 8192

Verify the election:

SW-DIST-01# show spanning-tree vlan 10

VLAN0010
  Spanning tree enabled protocol rstp
  Root ID    Priority    4106
             Address     10f3.1122.aabb
             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     10f3.1122.aabb
             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/23            Desg FWD 4         128.23   P2p
Gi1/0/24            Desg FWD 4         128.24   P2p

All ports are Designated Forwarding because this switch is the root — every port on the root bridge is a designated port by definition. Notice This bridge is the root in the Root ID section. That’s your confirmation.

Reading Port Roles and States

STP roles and states get conflated. They’re different things:

  • Role: what the port does in the topology (Root, Designated, Alternate, Backup)
  • State: whether it’s passing data (Discarding, Learning, Forwarding)

On an access switch downstream from the root:

SW-ACCESS-01# show spanning-tree vlan 10

VLAN0010
  Spanning tree enabled protocol rstp
  Root ID    Priority    4106
             Address     10f3.1122.aabb
             Cost        4
             Port        1 (GigabitEthernet1/0/1)
             Hello Time   2 sec  Max Age 20 sec  Forward Delay 15 sec

  Bridge ID  Priority    32778  (priority 32768 sys-id-ext 10)
             Address     f872.eabc.3301
             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             Root FWD 4         128.1    P2p
Gi1/0/2             Altn BLK 4         128.2    P2p
Gi1/0/3             Desg FWD 4         128.3    P2p Edge
Gi1/0/4             Desg FWD 4         128.4    P2p Edge

Gi1/0/1 is the Root Port — best path to root. Gi1/0/2 is Alternate (Discarding) — it would become root port if the primary uplink fails. Gi1/0/3 and Gi1/0/4 have the Edge type — those are PortFast-enabled access ports. Port costs default to 4 for GigabitEthernet, 2 for 10G, 1 for 40G and above.

PortFast and BPDU Guard: Access Port Hardening

PortFast skips the STP listening and learning states on access ports, bringing them to Forwarding immediately when a device connects. Without PortFast, every port takes 30 seconds to come up — fine for inter-switch links, miserable for end users. With RSTP’s edge port concept, PortFast ports that never receive BPDUs are assumed to be edge ports and transition instantly.

Configure PortFast on individual access ports:

SW-ACCESS-01(config)# interface range GigabitEthernet1/0/5 - 20
SW-ACCESS-01(config-if-range)# spanning-tree portfast
SW-ACCESS-01(config-if-range)# spanning-tree bpduguard enable

Or enable it globally for all access ports (recommended if your naming is consistent):

SW-ACCESS-01(config)# spanning-tree portfast default
SW-ACCESS-01(config)# spanning-tree portfast bpduguard default

BPDU Guard is the critical partner. If a PortFast port receives a BPDU — meaning someone plugged in an unmanaged switch or hub — BPDU Guard err-disables that port immediately. This prevents rogue devices from participating in the STP topology. Verify:

SW-ACCESS-01# show spanning-tree detail | include portfast|bpduguard|err-disabled
  The port is in the portfast mode by default
  Bpdu guard is enabled
  Number of topology changes 0  last change occurred 00:00:00 ago

If a port gets err-disabled by BPDU Guard:

SW-ACCESS-01# show interfaces GigabitEthernet1/0/8 status
Port      Name               Status       Vlan       Duplex  Speed Type
Gi1/0/8                      err-disabled 10         auto    auto  10/100/1000BaseTX

SW-ACCESS-01# show errdisable recovery
ErrDisable Reason            Timer Status
-----------------            --------------
bpduguard                    Enabled         (300 seconds)

Auto-recovery is enabled for BPDU Guard here with a 300-second timer. That’s acceptable in some environments, but I usually leave auto-recovery disabled for BPDU Guard — you want a human to investigate before the port comes back up. To manually clear:

SW-ACCESS-01(config)# interface GigabitEthernet1/0/8
SW-ACCESS-01(config-if)# shutdown
SW-ACCESS-01(config-if)# no shutdown

Root Guard and Loop Guard: Protecting Uplinks

Root Guard and Loop Guard protect your uplinks from two different failure modes.

Root Guard prevents a port from becoming a root port. Enable it on ports where you never want to receive a superior BPDU from — typically downlinks to access switches or ports connected to external networks:

SW-DIST-01(config)# interface GigabitEthernet1/0/48
SW-DIST-01(config-if)# spanning-tree guard root

If a superior BPDU arrives on a Root Guard-enabled port, the port goes into root-inconsistent state (blocking) without err-disabling. It recovers automatically if the superior BPDUs stop:

SW-DIST-01# show spanning-tree inconsistentports

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

Number of inconsistent ports (segments) in the system : 1

Loop Guard handles a different scenario: a port that’s supposed to be Alternate/Backup stops receiving BPDUs — maybe because of a unidirectional link failure. Normally, that port would assume the path is clear and transition to Forwarding, potentially creating a loop. Loop Guard keeps it in loop-inconsistent state instead:

SW-DIST-01(config)# interface GigabitEthernet1/0/24
SW-DIST-01(config-if)# spanning-tree guard loop

Or enable globally for all point-to-point links:

SW-DIST-01(config)# spanning-tree loopguard default

Note: Root Guard and Loop Guard are mutually exclusive on the same interface — Root Guard takes precedence. Enable Root Guard on downlinks, Loop Guard on uplinks and redundant inter-switch links. This pairs well with Control Plane Policing, which protects the switch CPU from being overwhelmed by protocol traffic during topology changes.

Troubleshooting: Topology Change Notification Storms

TCN (Topology Change Notification) storms are one of the most common STP headaches. Every time a port transitions, the root bridge floods a TCN across the topology, causing all switches to age out their MAC tables in 15 seconds instead of 300. In a large network, frequent TCNs hammer forwarding performance.

Find which port is causing topology changes:

SW-DIST-01# show spanning-tree detail

 VLAN0010 is executing the rstp compatible Spanning Tree protocol
  Bridge Identifier has priority 4096, sysid 10, address 10f3.1122.aabb
  Configured hello time 2, max age 20, forward delay 15, transmit hold-count 6
  We are the root of the spanning tree
  Topology change flag not set, detected flag not set
  Number of topology changes 847 last change occurred 00:02:13 ago
          from GigabitEthernet1/0/12
  Times:  hold 1, topology change 35, notification 2
          hello 2, max age 20, forward delay 15
  Timers: hello 0, topology change 0, notification 0, aging 300

Port 12 (GigabitEthernet1/0/12) of VLAN0010 is designated forwarding
   Port path cost 4, Port priority 128, Port Identifier 128.12.
   ...
   Number of transitions to forwarding state: 423
   Link type is point-to-point by Internal
   BPDU: sent 2847, received 0

847 topology changes from Gi1/0/12 — that port is flapping. Check the physical connection, the device attached, and whether BPDU Guard or PortFast is configured. If it’s an uplink that should have RSTP rapid transitions, that’s different than an access port bouncing.

Also check interface counters:

SW-DIST-01# show interfaces GigabitEthernet1/0/12 counters errors
Port         Align-Err FCS-Err  Xmit-Err Rcv-Err  UnderSize OutDiscards
Gi1/0/12             0       0         0       0          0           0

No physical errors here — more likely a device that’s flapping. Check CDP to see what’s connected:

SW-DIST-01# show cdp neighbors GigabitEthernet1/0/12 detail
-------------------------
Device ID: AP-FLOOR2-07
Entry address(es):
  IP address: 192.168.10.45
Platform: cisco AIR-CAP3702I-A-K9,  Capabilities: Trans-Bridge
...

It’s a wireless AP. APs should have PortFast enabled on their switch ports — they’re endpoints, not switches. The AP might be rebooting repeatedly, or it’s a standalone AP that’s incorrectly propagating BPDUs. Add PortFast and BPDU Guard to that port.

STP Tuning: Hello Time, Max Age, and Forward Delay

With RSTP, you rarely need to touch these timers — the proposal/agreement mechanism handles fast convergence. But in environments where you’re mixing 802.1D and 802.1w (legacy switches), or when you have MST boundaries, understanding the timers matters.

SW-DIST-01(config)# spanning-tree vlan 10 hello-time 2
SW-DIST-01(config)# spanning-tree vlan 10 max-age 20
SW-DIST-01(config)# spanning-tree vlan 10 forward-time 15

The classic rule: max-age must be ≥ 2 × (hello-time + 1), and forward-delay must be ≥ (max-age / 2) + 1. The defaults (2/20/15) satisfy this. Reducing these for faster convergence in a pure 802.1D environment is possible but risky — RSTP’s rapid mechanisms are a better solution than timer tuning.

For MST-specific timer configuration:

SW-DIST-01(config)# spanning-tree mst configuration
SW-DIST-01(config-mst)# name PROD-REGION
SW-DIST-01(config-mst)# revision 1
SW-DIST-01(config-mst)# instance 1 vlan 10-99
SW-DIST-01(config-mst)# instance 2 vlan 100-199
SW-DIST-01(config-mst)# end

SW-DIST-01(config)# spanning-tree mode mst
SW-DIST-01(config)# spanning-tree mst 1 priority 4096
SW-DIST-01(config)# spanning-tree mst 2 priority 8192

Verifying STP Health: A Pre-Change Checklist

Before any network change involving Layer 2, run through this verification sequence:

# Check all VLAN STP states for inconsistencies
show spanning-tree summary

# Look at root bridge placement per VLAN
show spanning-tree root

# Any ports in inconsistent state?
show spanning-tree inconsistentports

# Check topology change history
show spanning-tree detail | include topology|change

# Verify BPDU Guard configuration
show spanning-tree interface GigabitEthernet1/0/1 detail

Sample output from show spanning-tree summary:

SW-DIST-01# show spanning-tree summary
Switch is in rapid-pvst mode
Root bridge for: VLAN0001 VLAN0010 VLAN0020 VLAN0030 VLAN0040 VLAN0050
EtherChannel misconfig guard is enabled
Extended system ID           is enabled
Portfast Default             is disabled
PortFast BPDU Guard Default  is disabled
Portfast BPDU Filter Default is disabled
Loopguard Default            is disabled
PVST Simulation              is enabled
Bridge Assurance             is enabled
UplinkFast                   is disabled
BackboneFast                 is disabled
Configured Pathcost method used is short

Name                   Blocking Listening Learning Forwarding STP Active
---------------------- -------- --------- -------- ---------- ----------
VLAN0001                     0         0        0          6          6
VLAN0010                     1         0        0          5          6
VLAN0020                     1         0        0          7          8
VLAN0030                     0         0        0          4          4
---------------------- -------- --------- -------- ---------- ----------
4 vlans                       2         0        0         22         24

Two ports blocking across two VLANs — that’s expected redundancy, not a problem. If you see ports in Listening or Learning state for more than a second or two, something is reconverging. If you see unexpected blocking, check path costs and root placement.

VLAN segmentation is fundamental to making STP manageable — fewer VLANs per spanning tree instance reduces topology complexity. Our guide on VLANs and network segmentation covers the design side of this in detail.

Bridge Assurance: Catching Silent Failures

Bridge Assurance is an IOS-XE feature that sends BPDUs on all ports in all STP states — including ports that RSTP would leave in Forwarding. If a port stops receiving BPDUs, it moves to a BA-inconsistent blocking state. This catches unidirectional failures and misconfigured ports that stop participating in STP.

Bridge Assurance is enabled by default on IOS-XE with RSTP/PVST+. It only runs on point-to-point links (most inter-switch links) and shouldn’t run on edge ports:

SW-DIST-01# show spanning-tree bridge-assurance
Bridge Assurance is enabled

SW-DIST-01# show spanning-tree interface GigabitEthernet1/0/1 detail
 Port 1 (GigabitEthernet1/0/1) of VLAN0010 is designated forwarding
   ...
   Link type is point-to-point by default
   Bridge Assurance is enabled and oper state is BA consistent
   BPDU: sent 14237, received 14230

If you see BA inconsistent on a port, investigate immediately — the remote side stopped sending BPDUs. Check the remote switch’s STP configuration and whether Bridge Assurance is enabled on both ends (it must be, or one side will stop participating).

Common STP Gotchas on Catalyst 9000 Series

A few IOS-XE-specific issues worth knowing:

Pathcost method: The default is short (values up to 65535), which causes all links above 1Gbps to have cost 1. For modern high-speed environments, switch to long:

SW-DIST-01(config)# spanning-tree pathcost method long

This gives you differentiated costs: 4 for 1G, 2 for 10G, 1 for 100G — actually useful for traffic engineering.

PVST Simulation: If you’re connecting a Cisco switch (Rapid PVST+) to an 802.1w MST or 802.1D switch from another vendor, watch for PVST simulation mode. The Cisco switch will interoperate, but the per-VLAN topology information from PVST+ gets summarized into the single 802.1w instance, which can cause unexpected blocking.

EtherChannel and STP: A misconfigured EtherChannel can cause STP to see individual physical links as separate paths, creating loops. Always verify EtherChannel state before changing STP parameters on bundled interfaces:

SW-DIST-01# show etherchannel summary
Flags:  D - down        P - bundled in port-channel
        I - stand-alone s - suspended
        H - Hot-standby (LACP only)

Number of channel-groups in use: 2
Number of aggregators:           2

Group  Port-channel  Protocol    Ports
------+-------------+-----------+-----------------------------------------------
1      Po1(SU)         LACP      Gi1/0/23(P) Gi1/0/24(P)
2      Po2(SU)         LACP      Gi1/0/21(P) Gi1/0/22(P)

Both channels show SU (layer2 Up) with all member ports bundled (P). STP treats each port-channel as a single logical interface, which is what you want. If any member shows I (stand-alone), that port is participating in STP independently — potential loop risk.

For deeper troubleshooting methodology on Cisco IOS-XE, the same diagnostic mindset applies to other protocols — our OSPF troubleshooting guide covers a similar systematic approach for Layer 3 adjacency issues.

STP Best Practices Summary

A hardened STP configuration on IOS-XE comes down to a few non-negotiable practices:

  • Set explicit root bridges — never rely on MAC address tiebreakers. Set primary and secondary roots manually for every VLAN or MST instance.
  • PortFast + BPDU Guard on all access ports — every end-device port should skip STP convergence and be protected against rogue switches. Use portfast bpduguard default globally, then confirm per-port.
  • Root Guard on downlinks — prevent access switches from ever influencing root bridge elections at the distribution layer.
  • Loop Guard on uplinks — protect against unidirectional fiber failures causing blocked ports to open.
  • Verify before you change — run show spanning-tree summary and show spanning-tree inconsistentports before and after any topology change.
  • Switch to long pathcost method in 10G+ environments — default short costs make all high-speed links look equal.
  • Monitor topology changes — frequent TCNs are a symptom, not a root cause. Find the flapping port and fix it.

Spanning Tree done right is invisible — it builds once and holds. The engineers who understand it are the ones who can diagnose a broadcast storm in minutes instead of hours. Get your root bridge placement intentional, lock down access ports with BPDU Guard, and use Bridge Assurance to catch silent failures before they become outages.

Enjoying this post?

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