STP 生成树协议
本文最后更新于 2026-01-09,文章内容可能已经过时。
一、概述和原理:
A、缘由:
随着局域网规模的不断扩大,越来越多的交换机被用来实现主机之间的互连。为了防止产生故障,交换机在互连时一般都会使用冗余链路来实现备份。冗余链路虽然增强了网络的可靠性,但是也会产生环路,而环路会带来一系列的问题,继而导致通信质量下降,甚至通信业务中断等问题。STP通过构造一棵树来消除交换网络中的环路。

1、广播风暴:
根据交换机的转发原则,如果交换机从一个端口上接收到的是一个广播帧,或者是一个目的MAC地址未知的单播帧,则会将这个帧向除源端口之外的所有其他端口转发。如果交换网络中有环路,则这个帧会被无限转发,此时便会形成广播风暴,网络中也会充斥着重复的数据帧。
本例中,主机A向外发送了一个单播帧,假设此单播帧的目的MAC地址在网络中所有交换机MAC地址表中都暂时不存在。SWB接收到此帧后,将其转发SWA和SWC,SWA和SWC也会将此帧转发到除了接收此帧的其他所有端口,结果此帧又会被再次转发给SWB,这种循环会一直持续,于是便产生了广播风暴。交换机性能会因此急速下降,并会导致业务中断。

2、MAC地址动荡:
交换机是根据所接收到的数据帧的源地址和接收端口生成MAC地址表项的。
主机A向外发送一个单播帧,假设此单播帧的目的MAC地址在网络中所有交换机的MAC地址表中都暂时不存在。SWB收到此数据帧之后,在MAC地址表中生成一个MAC地址表项,00-01-02-03-04-AA,对应端口为G0/0/3,并将其从G0/0/1和G0/0/2端口转发。此例仅以SWB从G0/0/1端口转发此帧为例进行说明。
SWA接收到此帧后,由于MAC地址表中没有对应此帧目的MAC地址的表项,所以SWA会将此帧从G0/0/2转发出去。
SWC接收到此帧后,由于MAC地址表中也没有对应此帧目的MAC地址的表项,所以SWC会将此帧从G0/0/2端口发送回SWB,也会发给主机B。
SWB从G0/0/2接口接收到此数据帧之后,会在MAC地址表中删除原有的相关表项,生成一个新的表项,00-01-02-03-04-AA,对应端口为G0/0/2。此过程会不断重复,从而导致MAC地址表震荡。

B、STP原理:
1、协议简述:
STP的基本原理是,通过在交换机之间传递一种特殊的协议报文,网桥协议数据单元(Bridge Protocol Data Unit,简称BPDU),来确定网络的拓扑结构。BPDU有两种,配置BPDU(Configuration BPDU)和TCN BPDU。前者是用于计算无环的生成树的,后者则是用于在二层网络拓扑发生变化时产生用来缩短MAC表项的刷新时间的。该协议可应用于环路网络,通过一定的算法实现路径冗余,同时将环路修剪成无环路的树型网络
IEEE协会通过了IEEE802.1d协议,即开天辟地的第一代生成树协议STP,这个协议和其他协议一样,都是随着网络的不断发展而不断更新换代的。到现在为止,该协议一共有三代;
第一代:STP/RSTP
第二代:PVST/PVST+(思科特有)
第三代:MTSTP/MSTP


2、工作原理:
通过阻断冗余链路将一个有环路的桥接网络修剪成一个无环路的树形拓扑结构,即:能够确保数据帧在某一时刻从一个源出发,到达网络中任何一个目标的路径只有一条,而其他的路径都处于非激活状态(不能进行转发),如果在网络中发现某条正在使用的链路出现故障时,网络中开启了STP技术的交换机会将非激活状态的阻塞端口打开,恢复曾经断开的链路,确保网络的连通性。其过程如下:
选举一个根桥。
每个非根交换机选举一个根端口。
每个网段选举一个指定端口。
阻塞非根、非指定端口。
生成树修剪后网络拓扑如下所示:



如上图所示:从PC0到达PC1的数据帧会经过中间由三台交换机组成的环路,STP协议会选择一条最短的路径让数据帧从PC0到达PC1。假如,STP协议通过计算,认为走2路—>3路到达PC1是最短路径,那么1路就会处于非激活状态,即1路上有关的端口会处于堵塞状态。如果交换机S1出现了故障导致2路和3路不能走了,那么STP就会激活1路,确保数据帧能够到达PC1
二、选举过程:
A、术语介绍:
在学习STP树之前,需要了解几个基本术语:桥、桥的MAC地址,桥的ID、端口ID
桥:早期交换机一般只有二个转发端口,所以那个时候的交换机常常被称为“网桥”,后来“桥”这个术语一直沿用至今,但并不是指只有二个转发端口的交换机了,而是泛指任意多端口的交换机,目前“桥”和“交换机”这二个术语是可以混用的
桥的MAC地址:我们知道一个桥有多个转发端口,每个端口都有一个MAC地址,通常,我们把端口编号最小的那个端口的MAC地址作为整个桥的MAC地址。
桥ID(BID):一个桥(交换机)的桥ID由二部分组成,即:桥优先级+桥的MAC地址;其中桥优先级的值可以人为设定,默认0x8000(相当于十进制32768),取值范围是0~65535,优先级16bit位,其余48bit位为桥MAC地址
端口ID(PID):一个桥(交换机)的某个端口ID由二部分组成,即:端口优先级+端口编号;端口优先级的值是可以人为设定的。不同厂商的设备对于二部分所占用的字节数可能有所不同 。

B、选举四步走:
1、选举根桥:
交换机启动后就自动开始进行生成树收敛计算。默认情况下,所有交换机启动时都认为自己是根桥,自己的所有端口都为指定端口,这样BPDU报文就可以通过所有端口转发。对端交换机收到BPDU报文后,会比较BPDU中的根桥ID和自己的桥ID。如果收到的BPDU报文中的桥ID优先级低,接收交换机会继续通告自己的配置BPDU报文给邻居交换机。如果收到的BPDU报文中的桥ID优先级高,则交换机会修改自己的BPDU报文的根桥ID字段,宣告新的根桥。
综上所述总结便是:
优先级最高的设备(数值越小越优先)会被选举为根桥。
如果优先级相同,则会比较MAC地址,MAC地址越小则越优先。
如图,交换机S1、S2、S3都使用了默认的桥优先级32768,显然S1的BID最小,所以最终S1被选举为根桥

2、确定根端口:
根桥确定后,其它没有成为根桥的交换机都成为非根桥,一台非根桥设备可能会有多个端口于网络相连,为了保证从某台非根桥设备到根桥的工作路径是最优且唯一,必须从该非根桥设备的端口中确定出一个被成为“根端口”的端口,由根端口来作为非根桥设备于根桥设备之间进行报文交互的端口,一台非根桥设备上最多只能有一个根端口。
非根桥在选举根端口时分别依据:比较本交换机到根桥的累计路径开销(RPC)最小的端口、对端交换机的桥ID(BID)最小的端口、比较对端端口的端口ID(PID)最小的的端口;本交换机端口(PID)最小的端口。一个运行STP协议的网络中,我们将某个交换机的端口到根桥的累计路径开销(即从该端口到根路径经过的所有链路的路径开销的和)称为这个端口的根路径开销(Root Path Cost,RPC),链路的路径开销 于端口速率有关,端口转发速率越大,则路径开销越小。

以下为各种情况举例:
根据RPC选举根端口

如图,假定S1已被选为根桥,现在S3需要从1 端口和2端口中确定除根端口。显然,S3的2端口的RPC为20 000;S3的1端口的RPC为200 000+20 000=22 0000,交换机会将RPC最小的那个端口确定为自己的根端口,因此,S3将2端口确定为自己的根端口,同理,S2将自己的1端口确定为根端口。
根据对端BID选举根端口

在实际应用中一台非根桥设备上的RPC可能是相同的,如图所示,假定S1已被选为根桥。对于S4而言,1端口和2端口到根桥的RPC都是相同的,这种情况下就需要根据对端BID(桥ID)来选举根端口。对于S4而言,它的对端BID也就是S2的BID和S3的BID。相比较之后假设S2的BID小,则1端口为S4根端口;反之,2端口就为S4的根端口。
根据对端PID选举根端口

如图,二台设备在这种连接方式下非根桥的RPC、对端BID均是相同的,这种情况下需要根据对端PID来选举根端口。对于S2而言,它的对端PID就是Root的GE0/0/1口和GE0/0/2口,假设Root的端口优先级都是128,那么Root的端口编号就是1和2。显然Root的GE 0/0/1的PID更小,所以与之相连接的S2设备的GE 0/0/1端口就被选为根端口。
根据本端PID选举根端口

如图,二台设备中间通过一台HUB相连接。在这种方式下的非根桥的RPC、对端BID、对端PID均是相同的,这种情况就需要根据本端PID来选举根端口。假设S2的端口优先级都是128,那么显然1端口的PID更小。因此,S2的1端口就被选为了根端口。
3、确定指定端口:
根端口保证了交换机与根桥之间工作路径的唯一性和最优性。为了防止工作环路的存在,网络中每个网段与根桥之间的工作路径也必须是唯一且最优的。当一个网段有两条及以上的路径通往根桥时,与该网段相连的交换机就必须确定出一个唯一的指定端口。指定端口也是通过比较RPC来确定的,RPC较小的端口将成为指定端口。如果RPC相同,则需要比较BID、PID等。
如图,假定S1已被选举为根桥,并且假定各链路的开销均相等。显然,S2将GE 0/0/1确定为自己的根端口,S3也将GE 0/0/1确定为自己的根端口。在S1与S2,、S1与S3的之间的网段上,很明显Ethernet 0/0/1和Ethernet 0/0/2均为指定端口。在S2与S3之间的网段中,由于两个端口的RPC是相同的,所以这时就需要比较S2和S3的BID;假定S2的BID小于S3的BID,那么就将S2的GE 0/0/2端口选举为该网段的指定端口。
注:通过以上的例子,其实不难发现一个规律:根桥上所有的端口,都是指定端口。

4、阻塞备用端口:
在确定了根端口和指定端口之后,交换机上所有剩余的非根端口和非指定端口统称为备用端口。STP会对这些端口进行逻辑阻塞。所谓逻辑阻塞是指这些备用端口不能转发终端计算机产生并发送的帧,这些帧也被称为用户数据帧。不过,备用端口可以接受并处理STP协议帧。根端口和指定端口既可以发送和接收STP协议帧,又可以转发用户数据帧。

C、端口状态和定时器:
STP接口状态(五个):禁用、阻塞、侦听、学习、转发



三、STP相关变更机制:
A、根桥故障:
在稳定的STP拓扑里,非根桥会定期 2s 收到来自根桥的BPDU报文。
如果根桥发生了故障,停止发送BPDU报文,下游交换机就无法收到来自根桥的BPDU报文。
如果下游交换机一直收不到BPDU报文,Max Age定时器就会超时(Max Age的默认值为20秒),从而导致已经收到的BPDU报文失效,此时,非根交换机会互相发送配置BPDU报文,重新选举新的根桥。
整体大致需要50s等待故障恢复的,20s是老化时间(发现根桥故障),30s是确定完根桥之后端口状态变化的时间(15s+15s:Blocking——>Frowarding)

B、直连链路故障:
交换机检测到直连链路故障后,会将预备端口转换为根端口。预备端口会在30s后恢复到转发状态。
此例中,SWA和SWB使用了两条链路互连,其中一条是主用链路,另外一条是备份链路。生成树正常收敛之后,如果SWB检测到根端口的链路发生物理故障,则其Alternate端口会迁移到Listening、Learning、Forwarding状态,经过两倍的Forward Delay后恢复到转发状态。

C、非直连链路故障:
间接链路故障进入到转发状态需要50s(MAX age + Forwarding delay * 2)
本例中,SWB与SWA之间的链路发生了某种故障(非物理层故障),SWB因此一直收不到来自SWA的BPDU报文。等待Max Age定时器超时后,SWB会认为根桥SWA不再有效,并认为自己是根桥,于是开始发送自己的BPDU报文给SWC,通知SWC自己作为新的根桥。在此期间,由于SWC的Alternate端口再也不能收到包含原根桥ID的BPDU报文。其Max Age定时器超时后,SWC会切换Alternate端口为指定端口并且转发来自其根端口的BPDU报文给SWB。所以,Max Age定时器超时后,SWB、SWC几乎同时会收到对方发来的BPDU。经过STP重新计算后,SWB放弃宣称自己是根桥并重新确定端口角色。非直连链路故障后,由于需要等待Max Age加上两倍的Forward Delay时间,端口需要大约50秒才能恢复到转发状态。

D、拓扑变化:
1、拓扑变化收敛原理:
在交换网络中,交换机依赖MAC地址表转发数据帧。缺省情况下,MAC地址表项的老化时间是300秒。如果生成树拓扑发生变化,交换机转发数据的路径也会随着发生改变,此时MAC地址表中未及时老化掉的表项会导致数据转错误,因此在拓扑发生变化后需要及时更新MAC地址表项。
本例中,SWB中的MAC地址表项定义了通过端口GigabitEthernet 0/0/3可以到达主机A,通过端口GigabitEthernet 0/0/1可以到达主机B。由于SWC的根端口产生故障,导致生成树拓扑重新收敛,在生成树拓扑完成收敛之后,从主机A到主机B的帧仍然不能到达目的地。这是因为MAC地址表项老化时间是300秒,主机A发往主机B的帧到达SWB后,SWB会继续通过端口GigabitEthernet 0/0/1转发该数据帧。
为了避免MAC地址错误,所以在拓扑变化过程中,根桥会通过TCN BPDU报文获知生成树拓扑里发生了故障。因此TCN BPDU报文只能由非根桥发出,通告给根桥。根桥生成TC用来通知其他交换机加速老化现有的MAC地址表项。

以图为例,其拓扑变更以及MAC地址表项更新的具体过程如下:
SWC感知到网络拓扑发生变化后,会不间断地向SWB发送TCN BPDU报文。
SWB收到SWC发来的TCN BPDU报文后,会把配置BPDU报文中的Flags的TCA位设置1,然后发送给SWC,告知SWC停止发送TCN BPDU报文。
SWB向根桥转发TCN BPDU报文。
SWA把配置BPDU报文中的Flags的TC位设置为1后发送,通知下游设备把MAC地址表项的老化时间由默认的300秒修改为Forward Delay的时间(默认为15秒)。
最多等待15秒之后,SWB中的错误MAC地址表项会被自动清除。此后,SWB就能重新开始MAC表项的学习及转发操作。

2、STP触发拓扑改变条件:
一个端口从forwarding状态过渡到disable或blocking状态。
一个非根桥如果从指定端口接收到TCN BPDU包,需要向根桥装发TCN BPDU包。
一个端口进入转发状态,并且本地已存在一个指端端口。