Mental model
Spanning Tree’s correctness depends on every switch agreeing on a single root bridge and stable port roles. Two ways this gets broken:
-
Someone plugs a switch into a user-facing access port. The new switch sends BPDUs. STP recalculates. Topology destabilizes. Sometimes the new switch even wins the root election if its bridge ID happens to be lower — now traffic flows through some random switch in a meeting room.
-
A downstream switch tries to become root. Whether by accident (someone hardcoded a low priority) or attack (someone trying to force traffic through their device), an unexpected switch claiming root status can hijack your topology.
BPDU Guard fixes #1. Root Guard fixes #2. Both are essential in production switching environments.
BPDU Guard — protect access ports
The premise: PCs, printers, IP phones, IoT — none of them send BPDUs. So if a port that should connect only to end devices ever receives a BPDU, something is wrong. Maybe someone connected a switch. Maybe a misconfigured device. Either way, the safe response is to shut the port.
BPDU Guard does exactly that: any BPDU on a protected port → err-disable the port immediately.
Where it goes
On every access port that has PortFast enabled:
SW1(config-if)# switchport mode access
SW1(config-if)# spanning-tree portfast ! skip listening/learning
SW1(config-if)# spanning-tree bpduguard enable ! shut on BPDU
PortFast + BPDU Guard is the standard combo. PortFast skips STP states for instant forwarding on access ports; BPDU Guard catches anyone abusing that.
Global default
You can enable both globally so every PortFast port automatically gets BPDU Guard:
SW1(config)# spanning-tree portfast bpduguard default
SW1(config)# spanning-tree portfast default
Now every access port with PortFast also has BPDU Guard, automatically. Best practice.
Root Guard — pin the root bridge
The premise: you’ve deliberately chosen a root bridge (e.g. a core switch with spanning-tree vlan 1 root primary). You don’t want some downstream switch — a closet switch, a user-deployed device — claiming better priority and becoming root.
Root Guard protects this by inspecting BPDUs arriving on a designated port. If an incoming BPDU is “superior” (better priority than the current root’s), Root Guard blocks the port rather than letting it influence root election.
The port enters a special root-inconsistent state. Once the superior BPDUs stop arriving, the port recovers automatically (no manual intervention).
Where it goes
On ports facing downstream switches — switches that should never be root:
SW1(config)# interface GigabitEthernet0/24
SW1(config-if)# spanning-tree guard root
That’s it. The port now refuses to let anything “better” through it.
When it kicks in
*Mar 1 12:34:56: STP: VLAN0010 Gi0/24 received superior BPDU, blocked by root guard
*Mar 1 12:35:01: STP: VLAN0010 Gi0/24 root guard inconsistent (no superior BPDUs for 30s, recovering)
First message: blocked. Second message: superior BPDUs stopped, port recovers automatically.
When to use each
| Port type | BPDU Guard | Root Guard |
|---|---|---|
| Access port (PCs, phones, IoT) | ✓ | ✗ |
| Trunk to downstream switch (closet, distribution) | ✗ | ✓ |
| Trunk to upstream switch (where root might be) | ✗ | ✗ |
BPDU Guard is binary — no BPDUs allowed here at all. Use on access ports.
Root Guard is conditional — BPDUs OK, but they better not be better than the current root. Use on downstream-facing trunks.
BPDU Filter — the dangerous cousin
There’s also BPDU Filter, which silently drops BPDUs without err-disabling. It sounds safer but it’s not — it lets a connected switch operate as if it’s a loop-free endpoint, which can cause real loops if the connection forms a loop.
BPDU Filter is dangerous. Avoid it. BPDU Guard is the right tool.
! NEVER do this on access ports
SW1(config-if)# spanning-tree bpdufilter enable ! silent drop — DON'T
The one legitimate use of BPDU Filter: on ports that genuinely need to never send/receive BPDUs (rare service-provider edge cases). For 99% of CCNA-level networks, don’t.
Recovery from err-disable
BPDU Guard puts the port in err-disable. Recovery options:
Manual
SW1(config)# interface Gi0/5
SW1(config-if)# shutdown
SW1(config-if)# no shutdown
Auto-recovery
SW1(config)# errdisable recovery cause bpduguard
SW1(config)# errdisable recovery interval 300 ! 5 minutes
After 5 minutes, the port comes back up automatically. If the offending BPDUs are still arriving, it shuts again. Cycles until someone investigates.
Common mistakes
-
PortFast on a trunk port. PortFast is for access ports only. A trunk in PortFast mode is a loop waiting to happen. The default config prevents this on Catalyst, but mis-applied
spanning-tree portfast trunkon a real trunk = bad. -
BPDU Guard without PortFast. Pointless — non-PortFast access ports go through listening/learning anyway, so a BPDU during that time is normal. Together they form the bundle.
-
Root Guard on an upstream port facing the actual root. Now your switch refuses to learn the legitimate root. Catastrophic. Apply Root Guard only on downstream ports.
-
Forgetting err-disable recovery. A momentary BPDU arrival → port permanently down until someone notices. Configure recovery (with caution — don’t auto-recover if the cause is unclear).
-
Confusing BPDU Guard and BPDU Filter. BPDU Guard shuts on BPDU. BPDU Filter silently drops. Guard is safe; Filter is dangerous. Test before deploying either.
-
No documentation. When the port flaps to err-disable at 3 AM, the on-call engineer needs to know “this is BPDU Guard — someone connected an unauthorized switch.” Document the policy.
Lab to try tonight
- One switch, two PCs on access ports, plus a spare switch for testing.
- Configure PortFast + BPDU Guard on the access ports:
interface range Gi0/1 - 24
switchport mode access
spanning-tree portfast
spanning-tree bpduguard enable
- Plug PC into Gi0/1. Verify it works.
- Replace PC with the spare switch. Watch Gi0/1 err-disable as soon as the spare switch sends a BPDU.
- Confirm:
show interfaces status err-disabledand the logs. - Restore:
shutthenno shut. Or configureerrdisable recovery cause bpduguard. - Now apply Root Guard on a trunk:
spanning-tree guard root. - From the downstream switch, force a low bridge priority that would otherwise win root election. Verify Root Guard blocks the port and logs
root guard inconsistent.
Cheat strip
| Concept | Plain English |
|---|---|
| BPDU Guard | Access port + PortFast — err-disable on any BPDU |
| Root Guard | Downstream trunk — block port if superior BPDU arrives |
| BPDU Filter | Silently drop BPDUs. Dangerous — avoid. |
| PortFast | Skip STP listening/learning — instant forwarding on access ports |
spanning-tree portfast bpduguard default | Global — enable both on all PortFast ports |
spanning-tree guard root | Per-interface — block port if it would change root |
| err-disable recovery | Auto-recover after N seconds |
| root-inconsistent | Special Root Guard state — recovers when superior BPDUs stop |