3. STP 协议原理:根桥、端口选举与状态迁移
STP,全称 Spanning Tree Protocol,中文叫生成树协议。说白了,它的使命就一个——在物理环路的网络里,逻辑上切断冗余链路,让数据包只走一条无环路径。你想想看,如果交换机之间用两根线连着,广播帧就会在两个端口之间来回弹,形成广播风暴,整个网络瞬间瘫痪。我早年刚入行时,就亲眼见过一个客户因为误接环路,整栋楼的办公网络卡了半小时,最后只能拔线重启。
STP 的核心机制,是通过一套选举流程,选出一个“老大”和几条“主干道”,然后把多余的端口阻塞掉。这套选举流程,就是咱们今天要啃的硬骨头。
3.1 根桥选举:谁才是网络里的“老大”?
STP 的第一步,是选出一台交换机作为根桥(Root Bridge)。根桥是整个生成树的逻辑中心,所有路径计算都以它为基准。
选举的依据是 BID(Bridge ID,桥ID)。BID 由两部分组成:
- 桥优先级(Bridge Priority):默认值 32768,可手动调整,范围 0~65535。
- MAC 地址:交换机背板的物理地址,全球唯一。
选举规则很简单:先比较优先级,数值越小越优;优先级相同,再比较 MAC 地址,MAC 越小越优。
核心结论:根桥就是网络中 BID 最小的那台交换机。你可以在核心层交换机上手动把优先级改成 4096 或 8192,确保它成为根桥,避免次优路径。
我记得有一次帮一个金融客户做网络改造,他们核心交换机没调优先级,结果一台接入层的老旧交换机因为 MAC 地址更小,莫名其妙成了根桥。所有流量都绕到那台低端设备上,延迟飙升。后来我把核心交换机的优先级改成 4096,问题立刻解决。
3.2 根端口与指定端口:谁该转发,谁该阻塞?
根桥选出来后,每台非根桥交换机都要选一个根端口(Root Port,RP),每条链路上要选一个指定端口(Designated Port,DP),剩下的端口就是阻塞端口(Alternate Port,AP)。
3.2.1 根端口选举
根端口是每台非根桥交换机上,到达根桥路径开销最小的端口。路径开销(Path Cost)由链路带宽决定,带宽越高,开销越小。比如千兆链路开销是 4,百兆链路是 19。
选举顺序如下:
- 比较到达根桥的路径开销,越小越优。
- 如果路径开销相同,比较对端交换机的 BID,越小越优。
- 如果对端 BID 也相同,比较对端端口的 Port ID(端口优先级 + 端口号),越小越优。
避坑指南:我曾经遇到过一个案例,两台交换机之间做了链路聚合,但 STP 没把聚合口当成一个逻辑口来算开销,导致根端口选到了其中一条物理链路上,另一条被阻塞。后来我配置了 Port Channel 并启用 STP 兼容模式,才恢复正常。
3.2.2 指定端口选举
指定端口是每条链路上唯一负责转发 BPDU 和数据的端口。选举规则:
- 比较端口所在交换机到达根桥的路径开销,越小越优。
- 如果路径开销相同,比较交换机的 BID,越小越优。
- 如果 BID 也相同,比较端口自身的 Port ID,越小越优。
根桥上的所有端口,默认都是指定端口。因为根桥到达自己的路径开销是 0,没人比它更小。
3.3 端口状态迁移:从阻塞到转发,要等多久?
STP 端口有 5 种状态,迁移过程是有时间延迟的。这个延迟,恰恰是网络收敛慢的根源。
| 状态 | 说明 | 是否转发数据 | 是否学习 MAC |
|---|---|---|---|
| Disabled | 端口被管理员关闭或物理链路断开 | 否 | 否 |
| Blocking | 端口逻辑阻塞,只收 BPDU,不收数据 | 否 | 否 |
| Listening | 端口开始参与 STP 选举,监听 BPDU | 否 | 否 |
| Learning | 端口开始学习 MAC 地址,但不转发数据 | 否 | 是 |
| Forwarding | 端口正常转发数据帧和 BPDU | 是 | 是 |
默认情况下,从 Blocking 到 Forwarding 需要经历 30 秒(15 秒 Listening + 15 秒 Learning)。这就是为什么你插上网线后,要等半分钟才能上网。嗯,这里要注意,如果网络拓扑频繁变化,这 30 秒就会导致大量丢包。
重要提醒:STP 的收敛时间默认是 30~50 秒。对于实时性要求高的业务(比如 VoIP、视频会议),这个延迟是不可接受的。后面章节我会讲 RSTP(快速生成树)和 MSTP(多生成树),它们能把收敛时间缩短到 1~2 秒。
3.4 BPDU 报文结构:STP 的“心跳”长什么样?
STP 的所有决策,都依赖于交换机之间交换的 BPDU(Bridge Protocol Data Unit,桥协议数据单元)。BPDU 分为两种:
- 配置 BPDU:由根桥周期性发送(默认每 2 秒一次),用于维护生成树。
- TCN BPDU:当拓扑发生变化时,由非根桥发送给根桥,触发重新计算。
配置 BPDU 的报文结构如下:
字段 长度(字节) 说明
Protocol Identifier 2 协议标识,固定为 0
Protocol Version Identifier 1 版本号,STP 为 0
BPDU Type 1 配置 BPDU 为 0x00,TCN 为 0x80
Flags 1 包含 TC 标志和 TCA 标志
Root Identifier 8 根桥的 BID(优先级 + MAC)
Root Path Cost 4 到达根桥的路径开销
Bridge Identifier 8 发送该 BPDU 的交换机 BID
Port Identifier 2 发送该 BPDU 的端口 ID
Message Age 2 BPDU 从根桥发出后经过的时间
Max Age 2 BPDU 最大存活时间,默认 20 秒
Hello Time 2 BPDU 发送间隔,默认 2 秒
Forward Delay 2 端口状态迁移延迟,默认 15 秒
你不需要背下每个字段,但要知道:Root Identifier 和 Root Path Cost 是选举的核心依据。交换机收到 BPDU 后,会提取这两个字段,跟自己算出来的值做比较,从而决定端口角色。
我的习惯:排查 STP 问题时,我通常会先抓包看 BPDU。如果发现某台交换机发出的 BPDU 里 Root Identifier 不是预期的根桥,那说明它收到了更优的 BPDU,根桥可能变了。这时候用 show spanning-tree 命令确认一下,往往能快速定位问题。
3.5 核心逻辑流程图
下面这张 SVG 图,把 STP 的选举和状态迁移串起来了。你可以把它当成一张“作战地图”,对照着理解整个流程。
3.6 实战中的 STP 问题
STP 虽然经典,但在实际运维中,它带来的问题也不少。我总结了几种常见场景:
- 根桥漂移:新接入的交换机 BID 更小,导致根桥切换,网络短暂中断。解决方案是在核心交换机上手动设置较低的优先级。
- 收敛慢导致丢包:链路故障后,STP 需要 30~50 秒重新计算,期间大量广播帧丢失。建议升级到 RSTP 或 MSTP。
- BPDU 被丢弃:某些端口配置了 PortFast(用于接入终端),如果误接到交换机,会导致环路。我建议在接入端口上同时启用 BPDU Guard,一旦收到 BPDU 就自动 errdisable。
曾经踩过的坑:有一次我帮客户做网络割接,新加了一台交换机,忘了关它的 STP 优先级。结果它一上线,因为 MAC 地址小,直接抢了根桥。整个网络拓扑重新计算,业务中断了将近一分钟。从那以后,我每次上线新设备,都会先手动把优先级设成 61440(一个很大的值),确认拓扑稳定后再调整。