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。

选举顺序如下:

  1. 比较到达根桥的路径开销,越小越优。
  2. 如果路径开销相同,比较对端交换机的 BID,越小越优。
  3. 如果对端 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 的选举和状态迁移串起来了。你可以把它当成一张“作战地图”,对照着理解整个流程。

STP 选举与状态迁移流程图 STP 选举与端口状态迁移流程图 1. 根桥选举 比较 BID(优先级 + MAC),最小者当选 2. 根端口选举 每台非根桥选一个 RP(路径开销最小) 3. 指定端口选举 每条链路上选一个 DP(路径开销最小) 4. 端口角色确定 RP / DP 转发,其余端口阻塞 5. 端口状态迁移 Blocking → Listening → Learning → Forwarding Blocking(阻塞) Listening(监听) Learning(学习) Forwarding(转发) 说明: 每个状态默认停留 15 秒(Forward Delay),从 Blocking 到 Forwarding 共需 30 秒

3.6 实战中的 STP 问题

STP 虽然经典,但在实际运维中,它带来的问题也不少。我总结了几种常见场景:

  • 根桥漂移:新接入的交换机 BID 更小,导致根桥切换,网络短暂中断。解决方案是在核心交换机上手动设置较低的优先级。
  • 收敛慢导致丢包:链路故障后,STP 需要 30~50 秒重新计算,期间大量广播帧丢失。建议升级到 RSTP 或 MSTP。
  • BPDU 被丢弃:某些端口配置了 PortFast(用于接入终端),如果误接到交换机,会导致环路。我建议在接入端口上同时启用 BPDU Guard,一旦收到 BPDU 就自动 errdisable。

曾经踩过的坑:有一次我帮客户做网络割接,新加了一台交换机,忘了关它的 STP 优先级。结果它一上线,因为 MAC 地址小,直接抢了根桥。整个网络拓扑重新计算,业务中断了将近一分钟。从那以后,我每次上线新设备,都会先手动把优先级设成 61440(一个很大的值),确认拓扑稳定后再调整。