前言
在数据链路层中,有时为了提高系统的冗余性,常常引入冗余链路。但在冗余链路中,很容易引发广播风暴以及 MAC 地址表不稳定等故障现象。为解决交换网络中的环路问题 提出了生成树协议 STP (Spanning Tree Protocol)。
生成树概论
随着局域网规模的不断扩大,越来越多的交换机被用来实现主机之间的互连。在经典网络中,上级交换机出现故障时,下联设备将会直接断网。
为了解决此类问题,交换机在互连时一般都会使用冗余链路来实现备份。冗余链路虽然增强了网络的可靠性,但是也会产生环路,而环路会带来一系列的问题。

下面是二层环路容易产生的问题:
- 广播风暴 :在交换网络中存在环路,数据帧会一直在环路中传播导致网络故障。
- MAC地址表漂移 :同一个数据帧在同一个交换机的不同端口处不断切换导致的MAC漂移。

而 生成树 (Spanning Tree)解决冗余网络的环路问题,通过选取一个指定的根和端口,其他端口阻塞的方式来解决环路问题。
当线路故障的时候,生成树协议会自动解除其他可用的端口的阻塞,阻塞故障的链路。

STP工作原理
生成树协议 STP 是一个用于局域网中,将网络变成一个无环树,以消除环路的协议。 运行该协议的设备通过彼此交互信息而发现网络中的环路,并对某些接口进行阻塞以消除环路。
STP 在网络中运行后会持续监控网络的状态,当网络出现拓扑变更时 STP 能够感知并且进行自动响应 从而使得网络状态适应新的拓扑结构,保证网络可靠性。
STP的工作原理简单来说如图所示:

我们一个个分析STP中的一些概念。
桥ID与根桥
桥ID (Bridge ID, BID)是由 16 位的桥优先级 Bridge Priority 与 48 位的桥 MAC 地址构成。每一个有着STP的交换机都有一个唯一的桥ID。
网络中,桥优先级是可以配置的,取值范围是 0~65535 ,默认值为 32768, 可以修改但是修改值必须为 4096 的倍数。
优先级越小,说明优先级越高 。优先级最高的设备,会被选举为 根桥 (Root Bridge)。如果优先级相同,则会比较 MAC 地址, MAC地址越小则越优先。

STP 的主要作用之一是在整个交换网络中由根桥开始,计算出一棵无环的树 STP 树。
开销
每一个接口都维护着一个 开销 (Cost)值,接口的Cost主要用于计算根路径开销,也就是到达根桥的开销。
默认情况下端口的开销和端口的带宽有关, 带宽越高,开销越小 。因为存在不同的计算方法,需要根据实际情况分析。

根路径开销 (RPC, Root Path Cost)是 交换机某个接口到根桥的总开销的累计 。一台设备从某个接口到达根桥的 RPC 等于从根桥到该设备沿途所有接口的 Cost 累加。如图,例如根桥为SW1,SW3的接口2(GE 0/0/1)的RPC为它自己的Cost(20000),加上沿途经过SW2的接口1产生的Cost(500),得到RPC = 20000+500.

我们为了标记每个接口方便,使用 接口 ID (PID, Port ID) 来标识每个接口。它是一个16位的数,高 4 bit 是接口优先级,低12 bit 是接口编号。优先级范围是0~240,取值为16的整数倍,默认为128。

BPDU
我们知道,在封装与解封装中的协议基本单位是PDU(Protocol Data Unit). BPDU 是生成树协议中用到的PDU,它有两种类型:配置 BPDU 和 TCN BPDU 。
配置BPDU包含了BID、Cost和端口ID等参数 。STP协议通过在交换机之间传递配置BPDU来选举根交换机,以及确定每个交换机端口的角色和状态。在初始化过程中,每个桥都主动发送配置BPDU。在网络拓扑稳定以后, 只有根桥主动发送配置BPDU ,其他交换机在收到上游传来的配置BPDU后,才会发送自己的配置BPDU。
TCN BPDU是指下游交换机感知到拓扑发生变化时向上游发送的拓扑变化通知。
它的header如下:

STP过程
STP过程分为四步:
- 根桥选取
- 根端口选取
- 每条链路指定端口选取
- 非指定接口被阻塞
根桥选取
STP在交换网络中开始工作时 都认为自己是根桥 ,它们都会向网络互相发送配置BPDU。当交换机收到网络中其他设备发送来的 BPDU 后,会比较 BPDU 中的根桥 ID 和自己的BID。
优先级最小、MAC地址最小的选取为根桥 。交换机不断交互BPDU,同时对BID进行比较,最终选举一台BID最小的交换机作为根桥,其他的则为非根桥。

根端口选取
一个非根桥设备上会有多个端口与网络相连,为了保证从某台非根桥设备到根桥设备的工作路径是最优且唯一的,就必须从该非根桥设备的端口中确定出一个被称为 根端口 (Root Port)的端口,由根端口来作为该非根桥设备与根桥设备之间进行报文交互的端口。
在选举出根桥后,根桥仍然持续发送BPDU,而非根桥将持续不断的收到根桥发送BPDU。每一台非根桥交换机都会在自己的接口中选举出一个接口,非根桥交换机上有且只会有一个根接口。
根端口选取是 首先比较根路径开销 (RPC), RPC值越小,越优选 。当RPC相同时,比较上行交换机的BID, BID值越小,越优选 。当上行交换机BID相同时,比较上行交换机的PID, PID越小,越优先 。当上行交换机的PID相同时,则比较本地交换机的PID, PID值越小,越优先。

指定端口选取
根接口选举出来后,非根桥会使用其在该接口上收到的最优BPDU进行计算,然后将计算得到的配置BPDU与除了根接口之外的 其他所有接口所收到的配置BPDU 进行比较。计算得最优的接口为 指定接口 。即图中SW2与SW3之间进行比较。
一般情况下,根桥的所有接口都是指定接口。

每个链路( Link )选举一个指定端口,用于向这个链路发送 BPDU 。
阻塞非指定端口
一台交换机上,既不是根接口,又不是指定接口的接口被称为非指定接口。STP会对这些非指定端口进行 逻辑阻塞 ,即这些端口不能转发由终端计算机产生并发送的帧。一旦非指定端口被逻辑阻塞后,STP树( 无环路工作拓扑)就生成了
此时,所有的端口都可以接收并处理BPDU,但只有根端口和指定端口可以转发用户数据帧。

总结一下:
- 根桥: BID最小的交换机。
- 根端口: 离根桥最近的端口。
- 指定端口: 根桥所有参与生成树选举的端口。
例如如下的网络拓扑中。

- 选择根桥,找到BID最小的。它们优先级都一样的情况下,SW1的MAC地址最小,所以SW1为根桥。
- 选择根端口,即其他交换机中与根桥距离最近的端口。如图中与SW1相连的SW2的GE 0/0/1端口和SW3的GE 0/0/1端口为根端口。
- 找到指定端口,首先根桥上的所有端口都是指定端口。故SW1的GE 0/0/0和GE 0/0/1均为指定端口。接下来计算其他端口收到的BPDU最优结果。SW2的GE 0/0/2端口接收到 SW3 的配置 BPDU,比较它们的BID,发现SW2的BID更小,同理在SW3中比较SW2和SW3,得到SW2的GE 0/0/2端口为指定端口。
- 最终确定非根非指定端口,非指定端口的SW3的GE 0/0/2端口为预备端口。
端口状态
每个端口有着如下状态:
| Status | Description |
|---|---|
| Disable | 禁用状态。端口既不处理和转发BPDU报文,也不转发用户流量。 |
| Blocking | 阻塞状态。端口仅仅能接收并处理BPDU,不能转发BPDU,也不能转发用户流量。此状态是预备端口的最终状态。 |
| Listening | 侦听状态。端口可以转发BPDU报文,但不能转发用户流量。 |
| Learning | 学习状态。端口可根据收到的用户流量构建MAC地址表,但不转发用户流量。Learning状态是为了防止临时环路。 |
| Forwarding | 转发状态。端口既可转发用户流量也可转发BPDU报文,只有根端口或指定端口才能进入Forwarding状态。 |
状态转移图(STD)如下:
后记
在这篇文章中,我们详细地探讨了生成树协议(STP)的工作原理和应用。我们了解到,STP通过选取一个指定的根和端口,其他端口阻塞的方式来解决环路问题。当线路故障的时候,生成树协议会自动解除其他可用的端口的阻塞,阻塞故障的链路。这种机制极大地提高了网络的稳定性和可靠性。希望这篇文章能帮助你更好地理解和应用STP。