The Definitive Guide for Cisco Enterprise Networks (IOS-XE & NX-OS)
This guide covers Spanning Tree Protocol from first principles through advanced protection features and enterprise design best practices. Every configuration example is shown for both Catalyst (IOS-XE) and Nexus (NX-OS) platforms. It is written for networks of every size — from a two-switch branch office to a multi-building campus.
Part 1: Why Spanning Tree Exists
The Problem: Layer 2 Loops
Ethernet frames have no Time-To-Live field. An IP packet caught in a routing loop eventually dies when its TTL hits zero. A Layer 2 frame caught in a switching loop circulates forever. Worse, switches flood broadcasts, multicasts, and unknown unicasts out every port in the VLAN. When a loop exists, each flooded frame multiplies as it traverses the loop, and within seconds you get:
- Broadcast storms — link utilization pegs at 100%, CPUs on switches and hosts spike as they process an avalanche of broadcasts.
- MAC address table instability — the same source MAC arrives on multiple ports in rapid succession, so switches constantly rewrite their MAC tables and forwarding becomes unpredictable.
- Duplicate frame delivery — hosts receive multiple copies of the same frame, which breaks assumptions many protocols make.
A single accidental loop — a user plugging both wall jacks into a desktop mini-switch, a miscabled patch panel, a misconfigured hypervisor vSwitch — can take down an entire VLAN or an entire site. This is not theoretical; loop-induced outages remain one of the most common causes of catastrophic campus network failures.
The Solution
We want redundant links between switches for fault tolerance, but redundancy creates loops. Spanning Tree Protocol (originally IEEE 802.1D, invented by Radia Perlman) solves this by logically blocking redundant paths, building a loop-free tree topology, and automatically unblocking a backup path when an active link fails.
The critical mental shift for engineers: STP is not primarily a redundancy protocol — it is a loop-prevention protocol. In a well-designed modern network, STP should almost never be the mechanism actively providing failover (that job belongs to routed links, port channels, vPC, or StackWise Virtual). STP is your seatbelt: it should sit quietly, deterministically configured, ready to save you when something unexpected creates a loop.
Part 2: The Fundamentals
2.1 BPDUs — The Language of Spanning Tree
Switches running STP exchange Bridge Protocol Data Units (BPDUs) — small Layer 2 frames sent to the multicast MAC address 01:80:C2:00:00:00 (standard STP) or 01:00:0C:CC:CC:CD (Cisco PVST+/Rapid-PVST+, carried in a SNAP-encapsulated frame with a VLAN tag). BPDUs are never flooded through the switch like data traffic; each switch consumes BPDUs, processes them, and generates its own.
There are two BPDU types in classic 802.1D:
- Configuration BPDUs — carry the topology information used to elect the root and calculate the tree.
- Topology Change Notification (TCN) BPDUs — signal that the topology changed. (In Rapid STP, TCNs are replaced by a TC flag set in normal BPDUs, flooded by any switch that detects the change.)
The key fields inside a configuration BPDU:
| Field | Purpose |
|---|---|
| Root Bridge ID | Who the sender believes is the root (priority + MAC) |
| Root Path Cost | Sender’s cost to reach the root |
| Sender Bridge ID | Identity of the switch sending this BPDU |
| Sender Port ID | Port priority + port number of the sending port |
| Timers | Hello, Max Age, Forward Delay (dictated by the root) |
| Flags | Topology change, proposal/agreement (RSTP), port role (RSTP) |
By default, BPDUs are sent every 2 seconds (the Hello timer). In classic 802.1D only the root originates BPDUs and other switches relay them; in Rapid STP (802.1w), every switch generates its own BPDUs every hello interval, which is one reason RSTP detects failures much faster.
2.2 The Bridge ID and Root Election
Every switch has a Bridge ID (BID): an 8-byte value composed of a 2-byte priority and the switch’s 6-byte base MAC address. Since 802.1t, the priority field is split:
Bridge ID = [4-bit Priority] + [12-bit Extended System ID (VLAN number)] + [48-bit MAC]
Because the VLAN ID occupies 12 bits, the configurable priority must be a multiple of 4096 (0, 4096, 8192, … 61440). Default priority is 32768. The effective priority you see in show spanning-tree is configured priority + VLAN ID — so VLAN 10 with default priority shows 32778.
Root election is simple: the switch with the lowest Bridge ID wins. Lower priority wins first; if priorities tie, the lowest MAC address wins.
This is the single most important fact in STP design, and the source of the most important best practice: if you leave priorities at default, the root bridge is elected by lowest MAC address — which usually means your oldest, weakest switch becomes root. A 15-year-old access switch in a closet becoming root for your entire campus is a real and depressingly common finding in network assessments. Always set root priority deliberately (covered in Part 5).
2.3 Root Path Cost
Once a root is elected, every non-root switch computes its cheapest path to the root. Each interface has a cost based on bandwidth, and a switch’s root path cost is the sum of the costs of the inbound interfaces along the path from the root to that switch. When a BPDU is received, the receiving switch adds the cost of the port it arrived on.
Two cost scales exist:
| Link Speed | Short (legacy 802.1D, 16-bit) | Long (802.1t, 32-bit) |
|---|---|---|
| 10 Mbps | 100 | 2,000,000 |
| 100 Mbps | 19 | 200,000 |
| 1 Gbps | 4 | 20,000 |
| 10 Gbps | 2 | 2,000 |
| 25 Gbps | 2 (!) | 800 |
| 40 Gbps | 1 | 500 |
| 100 Gbps | 1 (!) | 200 |
| 400 Gbps | 1 (!) | 50 |
Notice the problem with the short scale: it cannot distinguish 40G from 100G from 400G (all cost 1), or 10G from 25G. IOS-XE still defaults to short cost values; NX-OS also defaults to short. In any network with links faster than 10 Gbps, enable long path cost everywhere (it must be consistent domain-wide):
! IOS-XE and NX-OS — same command
spanning-tree pathcost method long
MST always uses long cost values by design.
2.4 Port Roles
After the root is elected and costs are computed, every port gets a role:
- Root Port (RP) — on every non-root switch, the single port with the best path to the root. The root bridge itself has no root ports.
- Designated Port (DP) — on every segment, exactly one port is the designated port: the one advertising the best BPDU onto that segment. All ports on the root bridge are designated.
- Alternate Port — a blocked port that has a path to the root through another switch; it’s the backup for the root port. (RSTP terminology; classic STP just called these “blocking.”)
- Backup Port — a blocked port that is a redundant connection to a segment the same switch already serves as designated (rare — typically requires a hub or a self-loop).
- Disabled — administratively shut down.
Tie-breaking sequence — when a switch must choose between multiple candidate ports/BPDUs, it compares in strict order:
- Lowest root bridge ID
- Lowest root path cost
- Lowest sender bridge ID
- Lowest sender port ID (priority, then number)
Memorize this sequence. Nearly every “why is this port blocking?” question is answered by walking these four steps.
2.5 Port States
Classic 802.1D states:
| State | Learns MACs? | Forwards Data? | Duration |
|---|---|---|---|
| Blocking | No | No | Up to 20s (Max Age) before transitioning |
| Listening | No | No | 15s (Forward Delay) |
| Learning | Yes | No | 15s (Forward Delay) |
| Forwarding | Yes | Yes | Steady state |
| Disabled | No | No | Administrative |
This means classic STP takes 30–50 seconds to bring a port to forwarding. That’s 30–50 seconds of outage on every topology change and every port bring-up — unacceptable by modern standards, and the direct motivation for both PortFast and Rapid STP.
Rapid STP (802.1w) collapses the states to three:
| RSTP State | Equivalent |
|---|---|
| Discarding | Blocking + Listening + Disabled |
| Learning | Learning |
| Forwarding | Forwarding |
RSTP achieves sub-second convergence on point-to-point links using a proposal/agreement handshake: a designated port proposes to forward; the downstream switch synchronizes (blocks its other non-edge designated ports), agrees, and both ends go to forwarding immediately — no timers involved. Timers remain only as a fallback for shared (hub) segments and interoperation with legacy 802.1D switches.
2.6 Timers
Three timers govern classic STP behavior, and they are dictated by the root bridge to the entire domain:
- Hello (2s) — interval between BPDUs.
- Max Age (20s) — how long a switch retains BPDU information before considering it stale. In classic STP, an indirect failure takes Max Age to detect.
- Forward Delay (15s) — the length of the Listening and Learning states.
Best practice: never tune these timers. The temptation to “speed up STP” by shrinking timers is how classic networks got destabilized. The correct fix for slow convergence is Rapid-PVST+ or MST (both 802.1w-based), which make the timers largely irrelevant. Leave timers at default, full stop.
2.7 Topology Change and Its Real Cost
When a topology change (TC) occurs, switches flush their MAC address tables (in RSTP, immediately for affected ports; in classic STP, by shortening MAC aging to Forward Delay). Until the tables are relearned, traffic to unknown destinations is flooded. In a large flat VLAN, a topology change can cause a measurable flood spike — this is why unnecessary TCs matter.
Here’s the crucial detail: in RSTP, only non-edge ports generate topology changes. A port configured as an edge port (PortFast) going up or down does not trigger a TC. In a campus where hundreds of PCs power on and off daily, failing to configure PortFast on access ports means hundreds of needless topology changes, MAC flushes, and flooding events per day. This — not just faster port bring-up — is why PortFast on every access port is mandatory, not optional.
Part 3: The STP Family — Which Version and Why
3.1 The Lineup
| Protocol | Standard | Instances | Convergence | Cisco Support |
|---|---|---|---|---|
| STP | 802.1D | 1 for all VLANs | 30–50s | Legacy |
| PVST+ | Cisco | 1 per VLAN | 30–50s | Legacy default on very old IOS |
| Rapid-PVST+ | Cisco (802.1w per VLAN) | 1 per VLAN | Sub-second to a few seconds | Default on modern IOS-XE and NX-OS |
| MST | 802.1s | 1 per instance (VLANs mapped to instances) | Sub-second to a few seconds | Fully supported both platforms |
3.2 Rapid-PVST+ — The Enterprise Default
Rapid-PVST+ runs an independent 802.1w instance per VLAN. Its advantages:
- Simplicity. Zero mapping configuration. Add a VLAN, it gets a tree.
- Per-VLAN load sharing. You can make one distribution switch root for odd VLANs and the other root for even VLANs, using both uplinks.
- Fast convergence via proposal/agreement and built-in equivalents of UplinkFast/BackboneFast.
Its cost: one BPDU stream and one STP state machine per VLAN per port. With 500 VLANs trunked on a port, that’s 500 BPDUs every 2 seconds on that port and 500 logical port instances the CPU must maintain. Every platform has a documented limit on total logical ports (VLANs × trunk ports). Exceed it and you get delayed BPDU processing — which can cause false loop detection or, worse, actual forwarding loops.
Use Rapid-PVST+ when: VLAN count is moderate (as a rough rule, under ~200–300 VLANs across your trunks), you value operational simplicity, and your domain is all-Cisco. This describes the majority of enterprise campus networks, which is why it’s the default recommendation.
3.3 MST — For Scale and Multi-Vendor
MST (802.1s) maps all your VLANs onto a small number of instances (typically 2–3). Each instance is one 802.1w tree. 4,000 VLANs mapped to 2 instances = 2 BPDU state machines instead of 4,000.
MST introduces the concept of a region: switches with an identical region name, revision number, and VLAN-to-instance mapping table form one region and share instance-based trees. A mismatch in any of the three silently places a switch in a different region — the #1 MST operational pitfall. Inside a region, MST also runs IST (instance 0), which handles interaction with non-MST switches at the region boundary.
Use MST when: VLAN count is high (hundreds to thousands), you interoperate with non-Cisco switches (MST is the IEEE standard), or you’re building a large L2 domain (e.g., some data center and service-provider designs).
MST design rules that save you pain:
- Plan your VLAN-to-instance mapping once, up front, with room to grow. Changing the mapping later is disruptive — a mapping change is a region change, and the network re-converges.
- Map VLANs to instances before creating them where possible; pre-map ranges (e.g., VLANs 1–2000 → instance 1, 2001–4094 → instance 2) so future VLANs land predictably.
- Keep the number of instances small: 2 data instances is usually enough for root load-splitting (instance 1 rooted on distribution-A, instance 2 on distribution-B).
- Document and template the region config. Deploy it via automation so name/revision/mapping never drift.
3.4 Interoperability Notes
- Rapid-PVST+ falls back to classic 802.1D behavior on a per-port basis when it hears legacy BPDUs. One old switch doesn’t slow the whole network, just its segment.
- MST and Rapid-PVST+ interoperate through the IST at region boundaries; it works, but keep boundaries simple and deliberate. Best practice for migrations: move region by region, keeping the root inside the MST region.
- Never mix per-VLAN roots inconsistently across a PVST+/MST boundary; the boundary requires consistent root placement (PVST simulation on NX-OS will actually error-disable inconsistent boundary ports — a feature, not a bug).
3.5 Setting the Mode
IOS-XE:
spanning-tree mode rapid-pvst
! or
spanning-tree mode mst
NX-OS:
spanning-tree mode rapid-pvst ! default
! or
spanning-tree mode mst
MST region config (identical concept both platforms):
spanning-tree mode mst
spanning-tree mst configuration
name CAMPUS-CORE
revision 1
instance 1 vlan 1-2000
instance 2 vlan 2001-4094
Verify region consistency with show spanning-tree mst configuration — the digest value must match on every switch in the region.
Part 4: The Advanced Feature Toolkit
This is where good STP designs are made. Each feature answers a specific question: what could go wrong on this port, and how do I contain it?
4.1 PortFast (Edge Ports)
What it does: Skips Listening/Learning and puts the port immediately into forwarding when it comes up. Equally important: the port is treated as an RSTP edge port, so its up/down transitions do not generate topology changes.
Where: Every port that connects to an end host — PCs, phones, printers, servers, APs, cameras. Never on a port that might connect to another switch (a PortFast port that receives a BPDU immediately loses its PortFast/edge status and behaves as a normal STP port, so it’s self-correcting — but don’t rely on that).
IOS-XE:
interface GigabitEthernet1/0/10
description ACCESS - User Workstation
switchport mode access
spanning-tree portfast
! Trunk to a host (hypervisor, server with tagged VLANs):
interface TenGigabitEthernet1/0/48
switchport mode trunk
spanning-tree portfast trunk
NX-OS (terminology: “port type edge”):
interface Ethernet1/10
switchport mode access
spanning-tree port type edge
! Trunk to a host:
interface Ethernet1/48
switchport mode trunk
spanning-tree port type edge trunk
Global defaults (apply edge behavior to all access ports at once):
! IOS-XE
spanning-tree portfast default
! NX-OS
spanning-tree port type edge default
If you use the global default, explicitly configure inter-switch links as normal/network ports. Many shops prefer per-interface configuration via templates for clarity — either approach is fine; consistency is what matters.
⚠️ spanning-tree portfast trunk on IOS-XE and port type edge trunk on NX-OS are for hosts that need tagged VLANs (hypervisors), not for switch uplinks. Applying edge-trunk to an actual switch-to-switch link is a classic way to create a temporary loop during convergence.
4.2 BPDU Guard
What it does: Error-disables a port the instant a BPDU is received on it. This is the enforcement mechanism behind PortFast: PortFast assumes no switch lives on the port; BPDU Guard enforces it.
Why you need it: The user who plugs a home switch or a second cable into the wall jack. The contractor who daisy-chains switches. The rogue access point in bridge mode. BPDU Guard converts each of these from a potential campus-wide loop into a single shut-down port and a log message.
Best practice: enable BPDU Guard globally so it automatically protects every edge port, present and future:
IOS-XE:
spanning-tree portfast bpduguard default
! (applies to all PortFast-enabled ports)
! Or per interface:
interface GigabitEthernet1/0/10
spanning-tree bpduguard enable
NX-OS:
spanning-tree port type edge bpduguard default
! Or per interface:
interface Ethernet1/10
spanning-tree bpduguard enable
Recovery: an err-disabled port stays down until someone bounces it — unless you enable auto-recovery. In large environments, auto-recovery with a sane interval reduces helpdesk load; if the offending device is still there, the port simply err-disables again.
! IOS-XE
errdisable recovery cause bpduguard
errdisable recovery interval 300
! NX-OS
errdisable recovery cause bpduguard
errdisable recovery interval 300
Verdict: mandatory. Global BPDU Guard on edge ports is the single highest-value STP hardening command in existence.
4.3 BPDU Filter
What it does: Stops BPDUs from being sent — and, depending on how it’s applied, ignores received ones.
This feature has two very different personalities:
- Global (
spanning-tree portfast bpdufilter default/ NX-OSspanning-tree port type edge bpdufilter default): PortFast/edge ports stop sending BPDUs after a few initial ones. If a BPDU is received, the port loses BPDU filtering and PortFast and reverts to normal STP operation. This is the relatively safe form — its purpose is cosmetic/interop (don’t chatter BPDUs at end hosts, some of which — certain NIC teaming setups, paranoid security appliances — react badly to them). - Per-interface (
spanning-tree bpdufilter enable): the port neither sends nor processes BPDUs. STP is effectively disabled on that port. If anything resembling a loop touches that port, nothing will stop it.
Best practice: do not use per-interface BPDU Filter in enterprise networks. Every senior engineer has a story about an interface-level bpdufilter that someone applied “to stop that annoying err-disable” and that later turned a maintenance-window cabling mistake into an outage. The legitimate use cases are narrow (e.g., a demarc to a provider where you must not exchange BPDUs and you fully control physical topology — and even then, storm control and hard thought are required). If you think you need it, prefer:
- BPDU Guard (block the foreign switch), or
- A routed (L3) handoff (no STP to worry about at all).
If you use global BPDU Filter for host-facing quietness, always pair it with global BPDU Guard — Guard triggers on BPDU receipt before the port fully reverts, keeping the enforcement intact.
4.4 Root Guard
What it does: On a port where it’s enabled, if a superior BPDU arrives (one that would win root election), the port goes into root-inconsistent (broken) state — blocking for that VLAN — until the superior BPDUs stop. It enforces where the root bridge is allowed to be.
Where: On designated ports facing parts of the network that must never contain the root:
- Distribution ports facing access switches.
- Ports facing third parties: partner connections, extranet switches, service-provider L2 handoffs, tenant networks.
- Ports facing anything managed by another team that you don’t trust to keep priorities intact.
Why: Without it, any switch anywhere in the L2 domain configured (or defaulted, via low MAC) with a better bridge ID silently becomes root, and your entire traffic pattern re-forms around a closet switch or a partner’s device. Root Guard makes root placement a policy, not a suggestion.
IOS-XE / NX-OS (same command):
interface <downlink-to-access-or-third-party>
spanning-tree guard root
Note: Root Guard is inherently per-port and directional — enable it on the ports pointing away from where the root legitimately lives. Never enable it on your actual uplinks toward the root (you’d block your own root path). Root Guard and Loop Guard are mutually exclusive on a port.
4.5 Loop Guard
What it does: Protects against unidirectional failures. Normally, if a blocking (alternate) port stops receiving BPDUs, STP assumes the upstream switch is gone and transitions the port to forwarding — that’s the design. But if BPDUs stopped because of a unidirectional fault (one fiber strand dead, a transceiver failing in one direction, a congested CPU not sending BPDUs), the link is still passing data one way, and unblocking the port creates a loop. Loop Guard says: “this port has historically received BPDUs; if they stop, do NOT go forwarding — go loop-inconsistent and wait.” When BPDUs resume, the port recovers automatically.
Where: On ports that should be receiving BPDUs — root and alternate ports, i.e., access-layer uplinks and inter-switch links. The convenient deployment is global, which applies it intelligently to point-to-point non-edge ports:
! IOS-XE
spanning-tree loopguard default
! NX-OS
spanning-tree loopguard default
Loop Guard vs. UDLD: They overlap but are complementary. UDLD (Unidirectional Link Detection) is a Cisco Layer 2 protocol that detects unidirectional links by echoing device/port identity, and works per physical link (including individual members of a port channel, which Loop Guard — operating on the logical port — can’t see). Loop Guard is STP-aware and catches cases UDLD can’t (like an overloaded supervisor that stops sending BPDUs while the link itself is fine). Best practice on fiber inter-switch links: run both. Global loopguard + UDLD in aggressive mode on fiber uplinks:
! IOS-XE — global for fiber ports:
udld aggressive
! or per interface:
interface TenGigabitEthernet1/1/1
udld port aggressive
! NX-OS:
feature udld
udld aggressive
(Aggressive mode err-disables the port when the UDLD relationship is lost and can’t be re-established; normal mode just flags it. On modern point-to-point fiber, aggressive is the usual enterprise choice.)
4.6 Bridge Assurance (NX-OS “port type network”)
What it does: Turns BPDUs into a bidirectional hello/keepalive. On a port configured as a network port, BPDUs are sent on all ports including blocking and alternate ports, and are expected from the neighbor. If BPDUs stop arriving, the port goes to BA-inconsistent (blocking) — the opposite of classic STP’s “no BPDUs = safe to forward” assumption. This defends against unidirectional links and against a neighbor whose control plane has wedged (running but not processing STP — the nightmare scenario).
Requirements: Rapid-PVST+ or MST, point-to-point links, and both ends must be configured as network ports. If one side runs Bridge Assurance and the other doesn’t send BPDUs on blocked ports, the BA side will block the link permanently.
NX-OS (where this feature shines — it’s the standard for inter-switch links in Nexus designs):
spanning-tree port type network default ! careful: makes ALL ports network type
! Better — explicit per inter-switch link:
interface Ethernet1/49
description UPLINK to AGG-1
spanning-tree port type network
IOS-XE: Bridge Assurance exists on some Catalyst platforms (spanning-tree bridge assurance is enabled globally by default where supported, and activates on ports set to spanning-tree portfast network), but support varies by platform and it’s far less commonly deployed on Catalyst campus gear. In mixed Nexus/Catalyst environments, verify support on the specific Catalyst platform before setting network-type on the Catalyst side of a link; when in doubt, use port type normal on the Nexus side facing devices that don’t do Bridge Assurance.
Where: In NX-OS data center designs, every switch-to-switch link should be port type network. It pairs with the NX-OS three-way port typing philosophy: every port is edge (host), network (switch, with Bridge Assurance), or normal (everything else / interop).
4.7 Legacy Features You Should Know (and Not Configure)
- UplinkFast / BackboneFast — classic PVST+ optimizations for direct uplink failure and indirect failure convergence. Rapid-PVST+ and MST include these mechanisms natively; the commands are unnecessary (and rejected/ignored) in rapid modes. If you see them in a config, it’s a sign the config predates rapid STP.
- PVST Simulation (NX-OS) — enabled by default; lets an MST-mode Nexus interoperate with Rapid-PVST+ neighbors. Know it exists so the
PVST Sim Inconsistentport state doesn’t surprise you during migrations.
4.8 The Companion Feature: Storm Control
Not an STP feature, but it belongs in every STP hardening conversation: storm control rate-limits broadcast/multicast/unknown-unicast on a port. It’s your defense-in-depth layer for loops that form where STP can’t see them — inside an unmanaged switch, a virtual switch, or a bridged host. STP can’t detect a loop that doesn’t pass BPDUs through it in a detectable way; storm control caps the damage.
! IOS-XE — access port:
interface GigabitEthernet1/0/10
storm-control broadcast level pps 1k
storm-control multicast level pps 2k
storm-control action trap
! NX-OS:
interface Ethernet1/10
storm-control broadcast level 1.00
storm-control multicast level 2.00
Tune thresholds to your traffic profile (measure first — some environments legitimately push high multicast). Start with action trap (alert only) if you’re unsure, then move to shutdown for edge ports once baselined.
Part 5: Enterprise Design Best Practices
5.1 The Golden Rules
-
Run Rapid-PVST+ or MST. Never classic PVST+/802.1D. If any switch in your network shows
ieeemode, migrating it is your first project. -
Deterministic root placement. Explicitly configure the primary and secondary root. The root belongs at the distribution/aggregation layer (or core in a collapsed design) — the point where your L2 and L3 topologies should be congruent. Your STP root should sit on the same box as your default gateway (HSRP/VRRP active, or the vPC pair).
-
Set the primary root priority to a low explicit value and the secondary one step higher:
! IOS-XE / NX-OS — primary root (per VLAN or VLAN range): spanning-tree vlan 1-4094 priority 4096 ! on DIST-A spanning-tree vlan 1-4094 priority 8192 ! on DIST-B ! MST equivalent: spanning-tree mst 0-2 priority 4096 ! etc.Prefer explicit priorities over the
spanning-tree vlan X root primarymacro. The macro computes a priority relative to the current root at the moment you run it (typically 24576 or current-root-minus-4096) and writes that static number into the config — it does not track future changes and can land you at values that a later rogue device can still beat. Explicit4096/8192is unambiguous, template-friendly, and leaves room below only for values you’d notice. (Why not 0? Priority 0 works, but keeping 4096 as “primary” leaves 0 available as a break-glass override during migrations.) -
Every host port: PortFast/edge + global BPDU Guard. No exceptions. This pair eliminates the most common loop cause (user-side switches) and the most common instability cause (host ports generating topology changes).
-
Guard the root: Root Guard on all distribution ports facing access switches and on every port facing equipment you don’t administer.
-
Guard against unidirection: global Loop Guard + UDLD aggressive on fiber inter-switch links. On NX-OS,
port type network(Bridge Assurance) on all inter-switch links. -
Long path-cost method everywhere if you have >10G links (and even if you don’t — it future-proofs):
spanning-tree pathcost method longon every switch. Deploy consistently; mixed cost methods cause asymmetric tie-breaking. -
Don’t touch the timers. Ever.
-
Keep VLANs off trunks they don’t need (
switchport trunk allowed vlanpruning, done manually and deliberately — not VTP pruning). Every VLAN on a trunk is another logical STP port, another tree to compute, and another domain a loop can propagate through. Match trunk allowed lists to actual need. -
Never run a VLAN through the core in a routed-core design. VLANs should terminate at their distribution pair. A VLAN that spans distribution blocks makes the whole campus one failure domain.
-
Shrink the L2 domain relentlessly. The best STP design is the one with the least STP. Route where you can, switch where you must (see 5.4).
-
Don’t disable STP. Ever. Anywhere. Even on “point-to-point only” segments, even in overlay fabrics’ underlays, even “temporarily.” The cost of running it is near zero; the cost of the one loop it would have caught is your weekend and possibly your job. If a design requires disabling STP on a port, redesign it as a routed port.
5.2 Reference Architecture: Classic Three-Tier / Collapsed-Core Campus (IOS-XE)
Topology: Access switches (or stacks) dual-uplinked to a distribution pair. Distribution pair interconnected. L3 at distribution; core is routed (or distribution is the core in a collapsed design).
Distribution A (root):
spanning-tree mode rapid-pvst
spanning-tree pathcost method long
spanning-tree loopguard default
spanning-tree vlan 1-4094 priority 4096
! Downlinks to access:
interface range TenGigabitEthernet1/0/1 - 24
description DOWNLINK to Access
switchport mode trunk
switchport trunk allowed vlan 10,20,30,110
spanning-tree guard root
udld port aggressive
Distribution B (secondary root): identical, with priority 8192.
Optional per-VLAN load-sharing variant: DIST-A priority 4096 for VLANs 10,30 / 8192 for 20,110; DIST-B mirrored. Only worthwhile if the access uplinks are not port-channeled and you actually want both uplinks passing traffic — see 5.4 for why MEC/vPC designs make this unnecessary.
Access switch:
spanning-tree mode rapid-pvst
spanning-tree pathcost method long
spanning-tree loopguard default
spanning-tree portfast bpduguard default
errdisable recovery cause bpduguard
errdisable recovery interval 300
! Host ports:
interface range GigabitEthernet1/0/1 - 44
switchport mode access
switchport access vlan 10
spanning-tree portfast
storm-control broadcast level pps 1k
storm-control action shutdown
! Uplinks:
interface range TenGigabitEthernet1/1/1 - 2
description UPLINK to DIST
switchport mode trunk
switchport trunk allowed vlan 10,20,30,110
udld port aggressive
Deliberately absent from the access switch: any priority command. Access switches keep default priority 32768 — they must never win a root election, and Root Guard upstream enforces it.
5.3 Reference Architecture: NX-OS Aggregation with vPC
In Nexus designs, vPC (Virtual Port Channel) lets two switches present one logical port channel to downstream devices — so STP sees no loop and no blocked port at all. STP remains as the safety net.
Aggregation pair (both switches — vPC config abbreviated to STP-relevant parts):
spanning-tree mode rapid-pvst
spanning-tree pathcost method long
spanning-tree port type edge bpduguard default
spanning-tree port type network default
spanning-tree vlan 1-4094 priority 4096 ! SAME on both vPC peers — see below
vpc domain 10
peer-switch
peer-gateway
...
interface port-channel10
description vPC PEER-LINK
spanning-tree port type network
vpc peer-link
interface port-channel20
description vPC to ACCESS-1
switchport mode trunk
spanning-tree port type normal
spanning-tree guard root
vpc 20
Key vPC/STP interactions to internalize:
peer-switchmakes both vPC peers present the same bridge ID, acting as one logical root. With peer-switch, configure identical priority on both peers. Without it, the operational primary handles BPDUs and you’d set primary/secondary priorities normally. Use peer-switch in pure-vPC topologies — it removes an STP re-convergence when peer roles change.- The vPC peer-link is always
port type network(Bridge Assurance on). - Downstream vPCs to switches that don’t support Bridge Assurance:
port type normal. Downstream to hosts/servers:port type edgeoredge trunk. - Even though vPC makes the topology loop-free from STP’s perspective, all the guard features stay on. vPC failure modes (peer-link loss mishandling, dual-active) are exactly when you’ll be glad STP is still underneath.
Orphan ports (single-attached devices on a vPC switch) deserve attention in design reviews — they’re outside vPC’s protection model and behave differently during peer-link failures.
5.4 Design Evolution: Engineering STP Out of the Critical Path
Best practice has converged on a simple idea: STP should never be the thing blocking a link or providing failover — it should be the insurance policy underneath a design that’s loop-free by construction. The tools, in rough order of prevalence:
- Port channels (LACP) — two links in a LAG are one STP port. No blocked link, both links forward, sub-second LACP failover. Always bundle parallel inter-switch links.
- StackWise / StackWise Virtual (Catalyst) — the distribution pair becomes one logical switch; access uplinks become a Multi-chassis EtherChannel (MEC). STP sees a two-node point-to-point topology: nothing to block.
- vPC (Nexus) — same outcome, dual control planes.
- Routed access — push L3 down to the access layer; every inter-switch link is a routed port; STP exists only inside each access switch for its local VLANs. The most robust classic design — at the cost of VLANs not spanning access switches.
- Fabrics (SD-Access/VXLAN-EVPN) — L2 extension is provided as an overlay service over a routed underlay. STP runs only at the fabric edge toward classic L2 segments, and edge protections (BPDU Guard) matter more than ever there.
The corollary: in a modern design, if show spanning-tree shows a blocking port on an inter-switch link, that’s usually a design smell — a link that should have been a port channel member, a routed link, or part of a MEC.
5.5 Sizing Guidance
Small (1–10 switches, single site): Collapsed core. Rapid-PVST+. Root = the L3/collapsed-core switch (priority 4096; its partner or your “next-best” switch at 8192). Global PortFast+BPDU Guard, loopguard default, port-channel the uplinks. This is a 20-line template — deploy it on day one; small networks grow into big ones with their defaults intact.
Medium (10–50 switches, campus): Distribution pairs per building/block, StackWise Virtual or vPC at distribution, L3 between distribution and core, VLANs contained per distribution block. Rapid-PVST+ unless VLAN count is high. Full guard suite. Per-VLAN root split only if uplinks aren’t MEC’d.
Large (50+ switches, multi-building/DC): Strongly consider MST if L2 domains are wide or VLAN counts are high; otherwise routed access or a fabric. NX-OS aggregation with vPC + Bridge Assurance in the DC. Automate the STP template (the guard features are exactly the kind of config that drifts). Monitor logical port counts against platform limits.
Part 6: Verification, Monitoring, and Troubleshooting
6.1 The Commands You’ll Live In
show spanning-tree summary ! modes, guard features, port state counts per VLAN
show spanning-tree root ! who's root per VLAN, your root port and cost
show spanning-tree vlan 10 ! full per-VLAN detail
show spanning-tree vlan 10 detail ! + TC counts and *where the last TC came from*
show spanning-tree interface Te1/0/1 detail
show spanning-tree inconsistentports ! anything held down by root/loop guard or BA
show spanning-tree blockedports
show errdisable recovery ! IOS-XE
show interface status err-disabled ! NX-OS: show interface status | i err
show udld neighbors
show spanning-tree mst configuration ! region name/revision/digest — must match
6.2 Reading show spanning-tree Like a Pro
For each VLAN, verify three things against your design document, not your assumptions:
- Root ID = the switch you intended. On the root itself you’ll see
This bridge is the root. - Root port and cost make sense. On an access switch, the root port should be an uplink port-channel with the expected cost.
- The right ports show the right types. Edge ports show
P2p Edge(IOS-XE) /(vPC) networkoredgetypes (NX-OS). An access uplink showingP2pand Desg when you expected Root means traffic is flowing a path you didn’t design.
6.3 Troubleshooting Playbook
Symptom: intermittent slowness / MAC flapping / high broadcast. Suspect an active or micro loop.
show spanning-tree vlan X detailon the root — look atNumber of topology changesandoccurred ... ago, and cruciallyfrom <interface>. Chase the TC source hop by hop toward the access layer.show mac address-table … | include <flapping-mac>and check logs forMACFLAPnotifications — the two ports flapping delineate the loop path.- Once found: it’s almost always an edge without BPDU Guard, a bpdufilter interface, or an unmanaged device bridging two ports.
Symptom: constant topology changes. Almost always a host port without PortFast (every phone reboot = TC), or a flapping inter-switch link. The TC detail output tells you which port. Fix the port type; don’t chase the symptom.
Symptom: port in root-inconsistent. Root Guard did its job — something downstream is advertising a superior BPDU. Find the device sending it (show spanning-tree inconsistentports, then look at the downstream switch’s priority). Either it’s a rogue (remove/fix it) or your priority plan has a gap.
Symptom: port in loop-inconsistent or BA-inconsistent. BPDUs stopped arriving on a port that expects them: unidirectional link, dead transceiver, or a neighbor with a wedged control plane / mismatched port type (BA on one side only). Check show udld neighbors, transceiver light levels, and the neighbor’s CPU before bouncing anything.
Symptom: new switch added, entire network re-converged / traffic path changed. The new switch had a lower bridge ID (or default priorities were in play) and won root. This is the outage Root Guard + explicit priorities prevents. Fix priorities, add Root Guard at the boundary the switch came in through.
Symptom (MST): switch appears in wrong region / instances not matching. Compare show spanning-tree mst configuration digests. One VLAN added to a mapping on one switch and not the others is enough to split the region.
6.4 Monitor These Proactively
- Err-disabled ports (BPDU Guard hits) — each one is an attempted-loop event worth knowing about. Syslog + trap to your NMS.
- Topology change rate per VLAN — a healthy steady-state network has near-zero TCs. Alert on bursts.
- Root bridge identity per VLAN — a change in root ID should page someone.
- Inconsistent-port events (root/loop guard, BA) — these are your guards firing; each has a story.
- Logical port count vs. platform limit (
show spanning-tree summary totals) on trunk-dense switches.
Part 7: Quick-Reference
Feature Placement Cheat Sheet
| Feature | Host ports | Access uplinks | Dist downlinks | Inter-switch (core/agg) | 3rd-party facing |
|---|---|---|---|---|---|
| PortFast / edge | ✅ | ❌ | ❌ | ❌ | ❌ |
| BPDU Guard | ✅ (global) | ❌ | ❌ | ❌ | ✅ often |
| BPDU Filter | ⚠️ global only, rarely | ❌ never | ❌ never | ❌ never | ⚠️ last resort |
| Root Guard | – | ❌ (it’s toward root!) | ✅ | – | ✅ |
| Loop Guard | – | ✅ (global) | ✅ (global) | ✅ (global) | – |
| UDLD aggressive | – | ✅ (fiber) | ✅ (fiber) | ✅ (fiber) | – |
| Bridge Assurance (NX-OS network type) | ❌ | ✅ | ✅ | ✅ + peer-link | ❌ (unless both ends support) |
| Storm control | ✅ | optional | optional | optional | ✅ |
Minimum Viable Hardening (paste-ready)
IOS-XE global:
spanning-tree mode rapid-pvst
spanning-tree pathcost method long
spanning-tree loopguard default
spanning-tree portfast bpduguard default
errdisable recovery cause bpduguard
errdisable recovery interval 300
udld aggressive
NX-OS global:
spanning-tree mode rapid-pvst
spanning-tree pathcost method long
spanning-tree loopguard default
spanning-tree port type edge bpduguard default
errdisable recovery cause bpduguard
errdisable recovery interval 300
feature udld
udld aggressive
Plus, on the two switches that should be root: spanning-tree vlan 1-4094 priority 4096 / 8192. Plus PortFast/edge on host ports, Root Guard on distribution downlinks and third-party ports, and network-type on NX-OS inter-switch links.
The One-Paragraph Philosophy
Design the topology to be loop-free without STP (port channels, MEC/vPC/StackWise, routed links). Pin the root explicitly where the gateway lives and guard that decision (priorities + Root Guard). Make every host port an enforced edge (PortFast + BPDU Guard). Assume links will fail asymmetrically and control planes will wedge (Loop Guard, UDLD, Bridge Assurance). Cap the blast radius of what slips through (storm control, small L2 domains, pruned trunks). Then leave STP alone — no timer tuning, no filters, no disabling — and monitor it for the events that mean your guards just saved you.
Configurations verified against Rapid-PVST+/MST behavior on Catalyst 9000-series IOS-XE and Nexus 9000-series NX-OS. Command syntax can vary slightly by platform and release; always confirm against the configuration guide for your specific version.