Mental model
A switched LAN with a Layer-2 loop is a disaster. A single broadcast frame circulates forever (Ethernet has no TTL field), gets duplicated at each switch, and within seconds saturates every link. CPUs spike trying to process the storm, MAC tables thrash because the source MAC appears on multiple ports, the network is dead.
But you want redundant cabling for fault tolerance — one cable can be unplugged or damaged at any time. So how do you get redundant cabling without loops?
Spanning Tree Protocol’s answer: logically block the redundant paths until they’re needed. STP runs an election to pick a single “root” switch, then has every other switch compute the best path back to the root. Any port that isn’t on the best path gets blocked — physically connected, but Layer-2 silent.
When a link fails, STP unblocks the previously-blocked port and a new path becomes active. Convergence takes anywhere from 1–2 seconds (RSTP) to ~50 seconds (classic 802.1D).
Three versions you’ll encounter:
| Protocol | Year | Convergence | Default on |
|---|---|---|---|
| STP (802.1D) | 1990 | 30–50 s | Legacy gear only |
| RSTP (802.1w) / Rapid-PVST+ | 2001 | 1–2 s | Modern Cisco default |
| MSTP (802.1s) | 2002 | 1–2 s | Multi-vendor / very-many-VLAN environments |
This page focuses on 802.1D fundamentals plus the RSTP improvements. For full RSTP/MSTP coverage see Rapid STP & MSTP.
Why loops are catastrophic — a worked example
Imagine SW1 and SW2 connected by two parallel cables. PC1 sends a broadcast frame onto SW1.
- SW1 sees the broadcast, floods it out every other port — including both cables to SW2.
- SW2 receives the broadcast on Cable A, floods it out every other port — including Cable B back toward SW1.
- SW1 receives its own broadcast on Cable B, treats it as new, floods it out every other port — including Cable A toward SW2.
- Repeat infinitely. Now there are two copies circulating. Then four. Then eight.
Within 30 seconds the link is saturated. MAC table thrashing makes unicast frames behave erratically too. The CPU is so busy processing storm frames that management access is impossible. The only fix is to physically disconnect a cable and let the network recover.
This is why STP is on by default everywhere. It’s not optional.
How the election works — four steps
Step 1: Pick a root
Every switch starts thinking it is the root. They send BPDUs (Bridge Protocol Data Units) every 2 seconds advertising their Bridge ID, which is:
Bridge ID = (4-bit Priority + 12-bit Extended-System-ID) + 48-bit MAC address
= 8 bytes total
Lowest Bridge ID wins. Since priority comes first in the comparison, that dominates. Default priority is 32768 (sometimes written 32769 = 32768 + 1 because the lower 12 bits of “priority” are actually the VLAN ID — Cisco’s PVST+ encoding).
If priorities tie, MAC address is the tiebreaker. Lower MAC = wins. This is the trap: by default, the oldest switch (often slowest, most loaded) tends to have the lowest MAC and wins by accident.
Step 2: Pick a root port on every other switch
Each non-root switch finds its best path back to the root. “Best” = lowest accumulated path cost (sum of port costs along the path). The interface on that path becomes the Root Port (RP). Every non-root switch has exactly one RP.
Tiebreaker order if costs are equal:
- Lower sender Bridge ID
- Lower sender Port ID
Step 3: Pick a designated port on every segment
For each LAN segment (each link), STP picks the switch with the lowest cost back to root. That switch’s port on this segment becomes the Designated Port (DP).
The root bridge’s ports are all designated ports — by definition, the root has cost 0 to itself.
Step 4: Block everything else
Any port that isn’t a Root Port or a Designated Port becomes Alternate / Blocked (BLK). Traffic doesn’t forward through it. It listens for BPDUs in case the network topology changes and it needs to be unblocked.
Port costs (memorize)
| Link speed | STP cost (802.1D) | RSTP cost |
|---|---|---|
| 10 Mbps | 100 | 2,000,000 |
| 100 Mbps | 19 | 200,000 |
| 1 Gbps | 4 | 20,000 |
| 10 Gbps | 2 | 2,000 |
| 100 Gbps | — | 200 |
The exam usually uses classic 802.1D values (100/19/4/2). Memorize these four.
Path cost = sum of all port costs from your switch back to the root, counting only the port you receive on at each hop.
Bridge ID — the binary detail
Cisco PVST+ encodes Bridge ID like this:
| 4-bit priority (multiple of 4096) | 12-bit VLAN ID | 48-bit MAC |
That’s why setting spanning-tree vlan 10 priority 0 gives bridge priority 10 (priority 0 + VLAN 10 = 10). And why valid priorities are multiples of 4096: 0, 4096, 8192, 12288, 16384, 20480, 24576, 28672, 32768, 36864, … 61440.
You don’t set the priority value directly in practice — use:
SW1(config)# spanning-tree vlan 10 root primary ! sets priority to 24576
SW1(config)# spanning-tree vlan 10 root secondary ! sets priority to 28672
These macros set priorities below the default 32768 so your designated root and backup root win the election regardless of MAC.
The five port states (classic STP)
When STP runs the election, ports move through states:
| State | Forward data? | Learn MAC? | Send BPDU? | Duration |
|---|---|---|---|---|
| Disabled | No | No | No | n/a |
| Blocking | No | No | No | Forever (until topology changes) |
| Listening | No | No | Yes | Forward delay (15s default) |
| Learning | No | Yes | Yes | Forward delay (15s default) |
| Forwarding | Yes | Yes | Yes | Until topology changes |
Total transition Blocking → Forwarding = ~30 seconds (15s Listening + 15s Learning). Plus 20-second Max Age timer if the change is detected via missing BPDUs. That’s the “50 second convergence” of classic STP.
RSTP collapses this to three states:
| RSTP state | Equivalent to STP |
|---|---|
| Discarding | Blocking + Listening + Disabled |
| Learning | Learning |
| Forwarding | Forwarding |
And RSTP doesn’t wait for timers — it uses a sync/proposal handshake to advance to Forwarding immediately when safe. Sub-second convergence in practice.
Cisco STP variants — the alphabet soup
| Variant | What it is |
|---|---|
| STP (802.1D) | The original, one STP instance per network |
| PVST+ (Cisco default historically) | One STP instance per VLAN. Wraps 802.1D inside Cisco tagging. |
| RSTP (802.1w) | Faster 802.1D, sub-second convergence |
| Rapid-PVST+ (Cisco modern default) | RSTP per VLAN. The 2026 standard for Cisco-only networks. |
| MSTP (802.1s) | Groups VLANs into instances to scale. Multi-vendor standard. |
For the CCNA exam: know that Rapid-PVST+ is the default modern Cisco mode. Activate explicitly:
SW1(config)# spanning-tree mode rapid-pvst
BPDU anatomy
A BPDU (Bridge Protocol Data Unit) is the message switches send each other to run STP. Two types:
| BPDU type | Purpose |
|---|---|
| Configuration BPDU | Sent every 2s by the root, propagated by designated ports. Contains root info + path cost + sender ID. |
| Topology Change Notification (TCN) BPDU | Sent when a switch detects a topology change. Propagated back to root. Root then floods configuration BPDUs with the TC flag set. |
BPDUs travel to the multicast MAC 01:80:C2:00:00:00 — every switch listens to that address by default. You can’t filter BPDUs at the data plane unless you specifically configure BPDU Filter (rarely correct).
PortFast + BPDU Guard + Root Guard + Loop Guard
Four STP-related features every modern access network uses. Each protects against a different failure.
PortFast
Skip Listening + Learning on access ports. Port goes straight to Forwarding when link comes up. User PCs and IP phones don’t wait 30 seconds for an IP.
SW1(config-if)# spanning-tree portfast
Global default for access ports:
SW1(config)# spanning-tree portfast default
PortFast on a switch-to-switch link is dangerous — if a real switch plugs in, you bypass STP’s loop-prevention startup. Always pair with BPDU Guard.
BPDU Guard
If a PortFast port ever receives a BPDU, err-disable the port immediately. The assumption: only hosts plug into PortFast ports; if a BPDU arrives, someone plugged in a switch where they shouldn’t have.
SW1(config-if)# spanning-tree bpduguard enable
Global default for PortFast ports:
SW1(config)# spanning-tree portfast bpduguard default
To recover from err-disable: shutdown then no shutdown on the port (after removing the rogue device). Or configure auto-recovery:
SW1(config)# errdisable recovery cause bpduguard
SW1(config)# errdisable recovery interval 300
Root Guard
Prevent an unexpected switch from claiming the root role. If a port receives a “superior BPDU” (better Bridge ID than the current root), the port goes into root-inconsistent state — blocked until the superior BPDU stops.
SW1(config-if)# spanning-tree guard root
Place on distribution-layer downlinks to access switches — these should never see a BPDU claiming root.
Loop Guard
If a designated port stops receiving BPDUs (e.g., a unidirectional link failure where TX works but RX doesn’t), STP normally promotes the formerly-blocked alternate to Forwarding — which can cause a loop if the original link is still half-up.
Loop Guard detects this: if a non-designated port stops receiving BPDUs, it transitions to loop-inconsistent (blocked) instead of forwarding.
SW1(config-if)# spanning-tree guard loop
Or globally:
SW1(config)# spanning-tree loopguard default
UDLD — the layer-1 friend
UDLD (Unidirectional Link Detection) is layer-1 protection that pairs with Loop Guard. It detects a unidirectional fiber link (one direction broken, the other still working) and shuts the port.
SW1(config-if)# udld enable
Loop Guard + UDLD together cover both layer-2 (BPDU starvation) and layer-1 (one-way fiber) failures.
Configuration — the production access-port template
A modern access port that protects against every STP mishap:
SW1(config)# interface Gi1/0/1
SW1(config-if)# switchport mode access
SW1(config-if)# switchport access vlan 10
SW1(config-if)# switchport voice vlan 110
SW1(config-if)# switchport port-security
SW1(config-if)# switchport port-security maximum 3
SW1(config-if)# switchport port-security violation restrict
SW1(config-if)# switchport port-security mac-address sticky
SW1(config-if)# spanning-tree portfast
SW1(config-if)# spanning-tree bpduguard enable
SW1(config-if)# no cdp enable
SW1(config-if)# no lldp transmit
Memorize: PortFast + BPDU Guard on every host port. Port Security to limit MACs. No CDP/LLDP outward — these advertise your network’s identity to whoever plugs in.
Configuration — the production root election template
! Make distribution switch DIST-1 the root for all VLANs
DIST-1(config)# spanning-tree vlan 1-4094 root primary
! Make DIST-2 the secondary
DIST-2(config)# spanning-tree vlan 1-4094 root secondary
! Use Rapid-PVST+ everywhere
ALL_SWITCHES(config)# spanning-tree mode rapid-pvst
! On distribution downlinks (access-facing), apply Root Guard
DIST-1(config-if)# spanning-tree guard root
This pattern (deliberate root + secondary, Rapid-PVST+, Root Guard on access-facing dist ports) is the foundation of every well-designed campus.
Verification
SW1# show spanning-tree
SW1# show spanning-tree vlan 10
SW1# show spanning-tree summary
SW1# show spanning-tree root
SW1# show spanning-tree blockedports
SW1# show spanning-tree interface Gi1/0/1 detail
show spanning-tree is the daily driver. Per VLAN, it tells you:
- Who the root is (Bridge ID, MAC)
- Your local switch’s Bridge ID
- Every port’s role (Root / Designated / Alternate / Backup), state (Forwarding / Discarding), cost, type (P2P / Shared / Edge)
show spanning-tree blockedports quickly lists ports in blocked state — useful for confirming the topology matches your design.
show spanning-tree summary shows STP mode + globally-enabled features (PortFast default, BPDU Guard default, etc.).
The 6-step STP debug
When a network is unstable and you suspect STP:
- Identify the root.
show spanning-tree root. Is it the switch you expect? If not, something’s claiming root unexpectedly. - Check for unexpected topology changes.
show spanning-tree summary | include changes. High count = flapping link generating constant TCs. - Are any ports in inconsistent state?
show spanning-tree | include inconsistent. Root-inconsistent (Root Guard tripped), loop-inconsistent (Loop Guard tripped), or err-disabled (BPDU Guard tripped). - Are timers consistent across the network? All switches in the same STP domain should use the same Hello (2s) and Max Age (20s). Mismatch causes flap.
- Check for unidirectional links.
show udldshows any link in undetermined state. UDLD + Loop Guard catches these. - Look at logging.
show log | i SPANTREEshows BPDU Guard trips, port-state transitions, root changes. Pattern-match.
Worked scenarios
Scenario 1. Three switches in a triangle, all with default priority (32768). MACs: SW1 = aaa, SW2 = bbb, SW3 = ccc (in order). Who becomes root?
Answer: SW1 (lowest MAC since priorities tie). The bridge ID comparison is 32769.aaa vs 32769.bbb vs 32769.ccc — lowest wins.
Scenario 2. You want SW2 to be root for VLAN 10 and root for nothing else. How?
Answer:
SW2(config)# spanning-tree vlan 10 root primary
SW2(config)# spanning-tree vlan 1,20-4094 priority 32768 ! revert to default for others
Or explicitly:
SW2(config)# spanning-tree vlan 10 priority 8192 ! 8192 < 32769, wins for VLAN 10 only
Scenario 3. A new switch added to the network has lower MAC than your current root. What happens?
Answer: It claims root. The whole topology re-converges, blocked ports change, traffic patterns shift. Possibly to a slower path. This is why you always hard-code your designated root with root primary.
Scenario 4. A user accidentally plugs a small unmanaged switch into a PortFast access port (chained their laptop and an old hub). What happens?
Answer: The unmanaged switch doesn’t speak STP, so it just floods broadcasts. If the user happens to have a loop (plugged the same hub into two access ports), you get a broadcast storm. PortFast bypasses STP startup, so the loop forms instantly. Fix: BPDU Guard is the wrong protection here (unmanaged switch doesn’t send BPDUs). Use Storm Control instead:
SW1(config-if)# storm-control broadcast level 1.0
SW1(config-if)# storm-control action shutdown
Scenario 5. Switch port stuck in err-disabled after a BPDU arrived. What do you do?
Answer:
- Investigate:
show log | include LINK-3-UPDOWNto find when.show interface Gi1/0/1 statusshows theerr-disabledreason. - Remove the rogue device.
- Recover:
shutdown+no shutdownon the port. Or wait for auto-recovery if configured.
Scenario 6. Convergence is taking 30+ seconds after a link fails. What’s wrong?
Answer: You’re running classic 802.1D (or Cisco PVST+). Move to Rapid-PVST+:
SW1(config)# spanning-tree mode rapid-pvst
This must be set on every switch in the STP domain. Mixed modes work but at the slow convergence pace of the slowest.
Scenario 7. A blocked port is suddenly forwarding. What changed?
Answer: STP topology change. Either:
- The path it was the alternate for failed (e.g., the root port’s cable was unplugged or the upstream switch died).
- A topology change BPDU told the local switch the previous DR/root is gone.
Check show spanning-tree summary | include changes for the TC count. If high and growing, there’s a flapping link somewhere. Hunt it with show interfaces | include input errors or show log.
Scenario 8. You want PortFast on a server port without disabling BPDU Guard’s protection. Possible?
Answer: PortFast + BPDU Guard is exactly the right combo. PortFast skips state-machine delay; BPDU Guard catches any BPDU arrival. Configure both. The server doesn’t speak STP so BPDUs never arrive legitimately, and the protection stays armed.
Common mistakes
-
Letting the oldest switch win the root election. Default priority + lowest MAC = oldest gear becomes root by accident. Always
root primaryon your designated root. -
Forgetting PortFast on access ports. Without PortFast, a workstation takes ~30s to forward after link-up. Users see “no network” on boot. Enable PortFast.
-
PortFast without BPDU Guard. Rogue switch in a PortFast port → instant loop. Always pair PortFast + BPDU Guard.
-
Different STP modes mixed across switches. PVST+ on one, MST on another, RSTP on a third. Works technically; convergence inconsistent. Standardize.
-
Disabling STP entirely. Almost always wrong. Even “loop-free design” gets a misplugged cable. STP is your safety net.
-
No root planning. New switch added with low MAC → claims root → traffic re-routes badly. Plan root placement.
-
Root Guard missing from access downlinks. Distribution switches should refuse to honor any BPDU claiming superior root on access-facing ports. Without Root Guard, an attacker can run a malicious switch that wins root and pulls traffic through them.
-
Loop Guard + UDLD not deployed on fiber inter-switch trunks. Unidirectional fiber failure is rare but devastating — UDLD detects, Loop Guard contains.
-
Manual priority that doesn’t account for MST/Rapid-PVST+ encoding. Setting
priority 1doesn’t work — must be multiple of 4096. Useroot primaryinstead of raw priority for safety. -
Forgetting that VLAN 1 STP often runs separately on PVST+. Every VLAN has its own STP. Hard-code roots per VLAN (or use a single range macro).
Lab to try tonight
-
Triangle setup — three switches (SW1, SW2, SW3) connected in a full triangle. Two PCs (one on SW2, one on SW3).
-
Default behavior — boot all three with defaults. Run
show spanning-treeon each. Identify the root, the blocked port. Note the convergence aftershutdownof an inter-switch link. -
Force a root —
spanning-tree vlan 1 root primaryon SW1. Confirm SW1 is now root regardless of MAC. Verify byshow spanning-tree root. -
Failover drill — shut the link between SW1 and SW2. Watch the previously-blocked SW2-SW3 link unblock. Time the convergence.
-
Move to Rapid-PVST+ —
spanning-tree mode rapid-pvston all three. Re-time the convergence (should drop to ~1-2 s). -
PortFast + BPDU Guard — on an access port, enable both. Plug in a PC — should come up instantly. Plug in another switch — should err-disable instantly. Recover with shut/no-shut.
-
Root Guard demo — on SW1’s link to SW2, enable
spanning-tree guard root. Attempt to make SW2 root by setting its priority lower. Watch SW1’s port go root-inconsistent. -
MST experiment (advanced) — convert all three switches to
spanning-tree mode mstwith one region. Group VLANs into MST instances. Verify multiple roots can coexist (different instance = different root). -
Storm Control — manually create a Layer-2 loop (loop two ports together with no STP). Watch the storm. Enable
storm-control broadcast level 1.0and watch the port shut down instead of bringing the network down. -
Bonus: UDLD — simulate a unidirectional fiber by adding asymmetric ACLs blocking one direction of BPDUs. Verify UDLD detects.
Cheat strip
| Concept | Plain English |
|---|---|
| Why STP exists | L2 loops melt the network — STP blocks redundant paths until needed |
| Root bridge | The one switch every other points to. Lowest Bridge ID wins. Always hard-code. |
| Bridge ID | Priority (default 32768) + MAC. Lower wins. |
| Root port (RP) | Best path toward root. One per non-root switch. Forwarding. |
| Designated port (DP) | Best port on a segment toward root. Forwarding. |
| Blocked / Alternate | Anything that isn’t RP or DP. Listens for BPDUs only. |
| Port states (classic) | Disabled → Blocking → Listening → Learning → Forwarding |
| Port states (RSTP) | Discarding → Learning → Forwarding |
| Convergence | 802.1D ~50s, RSTP ~1-2s. Always use Rapid-PVST+ |
| STP cost (802.1D) | 10M=100, 100M=19, 1G=4, 10G=2 |
| Default Hello / Max Age / Forward Delay | 2s / 20s / 15s |
| BPDU | Multicast to 01:80:C2:00:00:00 every 2s |
root primary / root secondary | Sets priority to 24576 / 28672 |
| Priority multiples | Must be multiple of 4096 (0, 4096, 8192, …) |
| PortFast | Skip listen/learn on access ports |
| BPDU Guard | Err-disable a port if it receives a BPDU |
| Root Guard | Block a port if it tries to claim superior root |
| Loop Guard | Block port if it stops receiving BPDUs (unidirectional fiber detection) |
| UDLD | Layer-1 unidirectional link detection. Partner to Loop Guard |
| Rapid-PVST+ | Modern Cisco default. One RSTP per VLAN |
| MST (802.1s) | Groups VLANs into instances. Scales to 1000+ VLANs |
| STP storm reality | Without STP, any L2 loop = network down in seconds |