STP协议
为了提高网络可靠性,交换网络中通常会使用冗余链路,冗余链路会给交换网络带来环路风险。生成树协议STP(Spanning Tree Protocol)就是在提高网络可靠性的同时,避免环路的种种问题。
二层环路的问题
广播风暴
对于BUM帧,交换机会执行无条件的泛洪,如果交换机网络中存在环路,这个帧会被无限转发,瞬间耗尽交换机的 CPU 和链路带宽。
主机会收到重复的数据帧
对于BUM帧,由于广播风暴的存在,网络中充斥着重复的广播帧。
对于单播帧,原本的已知单播被“退化”成了未知单播,从而被泛洪。一是MAC表震荡,导致触发了保护机制删除了表项。二是由于链路拥塞,交换机收不到目标主机的回应导致表项无法老化删除。
MAC地址表震荡
网络变得随机和不可预测。
补充1:BUM帧,即Broadcast (广播帧)、Unknown Unicast (未知单播帧)、Multicast (组播帧)。广播帧目标MAC为FF:FF:FF:FF:FF:FF;组播帧目标MAC最后一个字节最低位为1,在为开启IGMP Snooping(互联网组管理协议嗅探)等技术前,被当做广播帧处理;未知单播帧只指交换机MAC地址表查不到,执行和广播相同的操作。
补充2:交换机内部处理 MAC 表震荡时,会看到同一个源 MAC 在多个端口间快速迁移,并触发 MAC 地址漂移(MAC Flapping) 告警。为了保护硬件转发芯片,很多交换机有个默认动作:直接把那个反复震荡的 MAC 地址表项“冻结”甚至删除,直到震荡停止再重新学习。
生成树的构建过程
STP的作用:一是消除环路,通过阻断冗余链路来消除环路。二是链路备份,当活动路径发生故障时,激活备份链路。

为什么STP大量使用“桥”术语,比如根桥(Root Bridge)、桥ID(Bridge ID)、桥协议数据单元(BPDU)?
STP 的原始标准 IEEE 802.1D 诞生于 1990 年。在那个年代,用来连接两个网段的网络设备就叫“网桥”,它通常是只有两个端口的“二层转发盒子”。 而我们今天熟悉的、有大量端口的交换机,在技术本质上就是多端口网桥。当 STP 协议被发明出来时,大家还没用上“交换机”这个词,所以整个协议的标准术语全用了“桥”。
Cisco AGS+,一个典型网桥。
Kalpana EtherSwitch EPS-1500,最早的以太网交换机之一。
BPDU
交换机之间通过 BPDU 报文交换生成树信息,里面包含:
- Root ID —— 根桥 ID
- Root Path Cost —— 发送者到根桥的路径开销
- BID —— 发送BPDU的设备BID (4位优先级+12位系统ID扩展+48位交换机背板地址)
- PID —— 发送BPDU的端口PID (4位优先级+12位端口编号)
Step 1 选举根桥
比较BID,先比较优先级,后比较MAC地址,越小越好。
默认优先级32768,可以手动配置为4096的倍数。
建议手动指定根桥,防止误接抢根,造成整个生成树重新生成。
1 | stp root primary 等效于 stp priority 0 |
Step 2 选举根端口
在非根桥设备上,选举离根桥最近的端口,简称RP,以下参数越小越好。
- 比较入方向的累计路径开销,即收到的 BPDU 中的根路径开销字段 + 本端口自己的端口开销。
- 比较发送者BID(如果两个以上的路径的累计路径开销相同)。
- 比较发送者PID(如果两个以上的端口连接到同一交换机)。
- 比较自身接口的PID (如果使用了HUB这种设备)。
Step 3 选举指定端口
Designated Port 简称DP
指定端口在每个链路(即冲突域)上选择,每段链路只会选择一个。
- 比较累计路径开销。
- 比较端口所在的交换机的BID。
- 比较端口的PID(如果使用了HUB这种设备)。
Step 4 阻塞非根&非指定端口
网络收敛后,只有指定端口和根端口可以转发数据。
其他端口在经典STP中被称为阻塞端口,Blocking Port,在RSTP中被称为预备端口,Alternate port,简称AP,被阻塞,不能转发数据,只能够从所连网段的指定交换机接收到BPDU报文,并以此来监视链路的状态。
端口状态转换
为了防止临时环路,在定义了端口角色的基础上,还定义了端口状态。
| 端口状态 | 行为 | 解释 |
|---|---|---|
| Disabled 禁用状态 | 不处理BPDU,也不转发用户流量 | 比如端口状态是down |
| Blocking 阻塞状态 | 接收BPDU,不能转发。 | 阻塞端口的长期工作形态 |
| Listening 侦听状态 | 收发BPDU,不学习MAC,不转发用户流量 | DP和RP的临时状态,15s确保全网选举一致,防止临时环路 |
| Learning 学习状态 | 收发BPDU,学习MAC,不转发用户流量 | 在无环拓扑上预建MAC表,减少转发初期的未知单播泛洪,经15秒后进入Forwarding |
| Forwarding 转发状态 | 收发BPDU,学习MAC,转发用户流量 | DP和RP最终正常工作状态 |
这是华为的图:

Learning状态存在的原因:
一是减少未知单播泛洪。在转发前,完成MAC表的构建,收到数据即刻开始转发,尽可能减少未知单播泛洪。
二是构建无环MAC表。不开启STP的时候,端口直接学习MAC地址;开启STP后,在了解网络的拓扑环境(那个端口被阻塞了)后,在Learning状态可以建立无环的MAC表。
Listening状态存在的原因:
防止临时环路。确保网络中的所有交换机都完成了选举,这个时候只做一件事,处理BPDU报文,使得整个网络达成一致。如果没有这个状态,尽管最终还是会完成选举,但是已经产生的错误MAC表项,只能等老化时间结束后才能消除。
Blocking状态存在的原因:
一是物理环路需要逻辑断开。这也是使用STP去解决二层环路的目的。
二是需要作为充当备份。在收不到BPDU时候,触发重新选举。
是阻塞端口的长期工作状态,或者说是备用端口的最终状态。
BPDU
BPDU字段含义

| 字段 | 含义 | 典型值 |
|---|---|---|
| PID | 协议ID | 0,表示使用的是 IEEE 802.1D 生成树协议。 |
| PVI | 协议版本ID | STP 为0,RSTP 为2,MSTP 为3。 |
| BPDU Type | BPDU类型 | 配置 BPDU——0x00 | TCN BPDU——0x80。 |
| Flags | 标志 | TC | TCA |
| Root ID | 根桥ID | 根桥的优先级和MAC地址组成 |
| RPC | 根路径开销 | 到根桥的最短路径开销。 |
| Bridge ID | 指定桥ID | 指定桥的优先级和MAC地址组成。 |
| Port ID | 指定端口ID | 指定端口的优先级和端口号组成。 |
| Message Age | 配置BPDU在网络中传播的生存期。 | 根桥始发为0,每经过一台设备+1,超过20时候丢弃。 |
| Max Age | 配置BPDU在设备中的最大生存期。 | 20s |
| Hello Time | 配置BPDU发送的周期 | 2s |
| Fwd Delay | 端口状态迁移的延时 | 15s |
TCN-BPDU
配置BPDU —-> 只有DP会发送,RP和AP只能被动接收,RP可以修改并转发。用于生成树的选举、周期性的维护。
TCN-BPDU —-> 只有在拓扑变化时RP才会发送,实现全网所有设备清空MAC地址表。
几个名词:
TCN:Topology Change Notification 拓扑变化通知(TCN-BPDU,一个独立短小的报文)
TCA:Topology Change Acknowledgment 拓扑变化确认(配置BPDU的标志位)
TC:Topology Change 拓扑变更(配置BPDU的标志位)

使用TCN-BPDU的原因是:为了解决错误的MAC表项只能等老化时间结束才能改变
如果生成树拓扑发生变化,交换机转发数据的路径也会随着发生改变,此时MAC地址表中未及时老化掉的表项会导致数据转发错误,因此在拓扑发生变化后需要及时清空MAC地址表项。
拓扑改变导致MAC地址表错误
网络中的某个交换机检测到以下两点,即表明拓扑改变
- 阻塞端口进入Forwarding状态
- 处于Forwarding状态的RP或者DP端口进入Blocking状态
此后
- RP逐级发送TCN-BPDU,2s发一次
- 上游交换机立刻回传TCA置位的配置BPDU,然后使用RP向上发送TCN-BPDU
- 根桥收到后,向全网泛洪TC置位的配置BPDU,共发送35s,收到此消息的交换机,会将老化时间改为Fwd Delay(15s)。
一个典型的例子是:


