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 defaultglobally, 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 summaryandshow spanning-tree inconsistentportsbefore and after any topology change. - Switch to long pathcost method in 10G+ environments — default
shortcosts 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.
Leave a Reply