许多老师讲一个新协议时,总会“强制性”地给你灌输它的各种规则,导致许多学生死记硬背之后任然一脸懵逼。我当初听stp时 也是遗留了很多问题:比如为什么这么设计;这种机制为什么不能这样改进;如果这么这么的话,会怎么怎么样。太多的不理解导致我的记忆效率大大降低。所以我 希望可以从一个协议的起源,开发的目地,设计师的想法(框架),分类分层地来叙述一种优秀的机制,并且提出它的局限性。

生成树算法终极解析!_算法

 


 

这是一个纯交换层网络的拓扑图(先不考虑主机)。

此拓扑图表面上是一个物理图,但它可以包含许多逻辑无环图。(即pvst,稍后会讲)

(每个交换机上都可以连若干个PC,任意两个PC之间通讯都经过其中的某条路径。)

(请读者学习生成树逻辑时都把想象建立在一张足够大的拓扑图上,因为深刻的理解是基于实用性而产生的而不要死记它的机制)

生成树协议stp(spanning tree protocol)是工作在交换层交换机上的一种防环机制(!!!!!!同时提供冗余)。交换机路径的备份使得环路的出现。因为交换层相对网络层规模较小,才允许广播的存在。(路由器分割广播域而交换机不能)(广播加上环路才形成了广播风暴,因而网络层虽有环路但不需要生成树)

    建议拿pt模拟器做试验。快速生成树协议rstp(rapid spanning tree protocol)较stp优越些。因rstp与stp机制基本相似,且交换机默认开启rstp,本章重点研究rstp。

众所周知顾名思义,一棵物理树的树枝是不会形成环路的,因此一棵生成树的根桥(根网桥,交换机的前身)就是物理树的根节点,非根桥就是物理树的分支点或者树枝末端。以及之后的trunk link(树干链路)模式,他们都是可类比的。某个vlan(记作vlan x),所有开启了vlan x的交换机(且这些交换机相连)构成了一棵关于vlan x的生成树。

!!生成树的原理:在众多交换机中选择一个作为根桥,其余在每个交换机上选择唯一的一条路径通向根桥,再将剩下不用的路径(链路)堵塞。

!!生成树机制的目的:让二层交换机通电相连后在很短时间内自动收敛出一棵或多棵生成树。(这是stp的精髓所在)

生成树算法终极解析!_数据结构_02

 

    一般情况下二层交换机的mac地址表中存储两项内容:1.邻居上与自己相连的端口的mac地址以及相对应的本地端口编号;2.PC主机的mac地 址以及相对应的本地端口编号。交换机的端口模式告诉自己对方是主机还是交换机。对于每条链路的两个端口来说,有且只有一个指定端口,对端是根端口或堵塞端 口。对于每个交换机来说,有且只有一个根端口,其余的是指定或堵塞端口(也叫非指定端口)。注意!文章之后提到的交换机角色,端口角色,端口状态都是基于 某个vlan的,即因vlan而异(非常重要)。

现在正式进入生成树算法的详解。

首先,交换机没有“眼睛”,只能通过相互间约定好的协议来获悉整个拓扑图。给通了电的交换机的某个端口一插上网线,它就检测到(就像插入耳机)并从这根线向外发送bpdu(但它并不知道这根线后面是什么情况并开始竞选。因此即使拓扑中没有环,stp竞选也会正常进行(stp不能检测到环路,只能避免环路)。

网桥协议数据单元BPDU(Bridge Protocol Data Unit)是用于生成树计算(竞选)的核心数据帧。有一点须要注意,bpdu是基于特定交换机的,即不同的个交换机有不同的bpdu。交换机之间通过发送比较它来完成竞选。注意,在竞选过程中,交换机只把自身的bpdu不断地复制并发给所有邻居,但邻居不会把这个bpdu转发给下一个邻居。

Bpdu数据帧包含以下主要字段:首先是vlan ID(代表这是vlan几的bpdu),bpdu的标识以及版本号(区分stp与rstp),根桥的id(优先级与mac地址),cost(自己到根桥的最佳开销),自身的id(优先级与mac),端口id(发出bpdu的本地端口号和端口优先级),最大老化时间(自己到根桥的跳数,单位秒)。(若想了解完整字段请登录思科官网)

每个交换机单位时间内(2s)发送Bpdu的数量取决于本地开启vlan数量和激活端口(up状态)数量。假如交换机A检测到有三个端口被插入网线,且在它的vlan database中开启了vlan 2、3、4,则交换机A每两秒就要从各个端口向外发各个vlan的bpdu,总共3*4=12个(前提是端口上先配置trunk link模式)(每条链路只需在一边的端口配trunk即可)(若网络中只有vlan1则不需trunk因为vlan1没有标签)(数据从主机进入交换机被加上标签,从access链路出去时删除标签,trunk模式让vlan标签不被删除)。

(交换机收到某一个vlan的数据,若该vlan本地未开启,则数据直接丢弃,不学习mac)。

首先开始竞选根桥。(对于vlan x,接收到所有vlan x的bpdu情况下)交换机A根桥id字段的初始值是自己id,每收到比该值更优的id(比如收到交换机B发来的bpdu)(先比较优先级再比较mac)就将该值更新为它。根桥id字段的更新伴随着cost字段的更新(根桥id字段不变时,cost字段也可能更新,即找到一个去往根桥的更优路径),其初始值是0,更新后变为B的cost字段值再加上AB之间链路的开销(所有邻接链路的开销存储记录在交换机中)即使自己到根桥的开销。也就是说交换机初始认为自己就是根桥。

(端口收到一个未知数据帧,先扫描其表示与版本字段以确定它是个bpdu帧,再扫描vlan id字段以确定它是vlan几的bpdu,然后将它与自己相对应vlan的bpdu比较)

可以想象,以此机制,经过足够长的时间(几秒钟)每个交换机的vlan x的根桥id字段达到一致。

根桥选好后非根桥就开始选根端口(本质就是选择唯一一条最优路径(每个vlan)通向根桥)(其实自从根桥id字段从初始值开始更新起,根端口的竞选就开始了)。根端口竞选和根桥竞选很类似,也是一种“逐优更新法”在交换机内存中有一块区域(记为m)专门存储根端口的端口编号(如f0/1)。如在上个例子中,B发送的bpdu改变了A的bpdu(根桥id和cost字段),则A的区域m内的值变为刚才接收bpdu的端口编号。当A又收到交换机C的bpdu,若其优化(更新)了自己的根桥id字段则区域m随之更新,若没有优化而是与自己的根桥id字段一样则看它是否改变了自己的cost字段(即C与B的cost字段进行竞争),若B与C的cost字段值相等则比较B与C的自身id字段谁更优以决定m区域值是否改变。

如果此时你已经乱了请别急,之后我会总结出一个总的流程给你看。

到了竞选的最后一步:竞选指定桥(决定之后不用的链路的哪一端保持堵塞状态/丢弃状态)。首先要搞清楚,指定桥是基于链路的,每条链路两端的交换机中有且只有一个指定桥,或者说每个交换机可以既是指定桥也是非指定桥(对于不同端口)。指定桥那一边的端口叫指定端口。指定桥的竞选:先比较cost字段再比较自身id字段(bridge id)。所以,根端口对应的端口永远是指定端口,根桥上的已激活的端口都是指定端口。(竞选失败的端口就成为非指定端口)。好了,交换机上的根端口和指定端口都确定了之后,非指定端口就一直处于堵塞状态。根端口,指定端口以及一直未收到vlan x的bpdu的端口(比如连接PC的或连接的某个交换机没有启动vlan x)过30秒后进入转发状态(之后再说)。

!!以上竞选过程中(rstp),所有端口都处于丢弃状态(discarding)(或堵塞状态)(注意堵塞与禁用状态的区别:禁用指down状态如强行关闭和未插入网线的端口,不能接收转发数据;而堵塞端口可以接受发送bpdu,但不能转发(他人的)数据帧)。而正常工作状态下,除了堵塞端口(指替代端口和备份端口,也叫非指定端口)(对于每个vlan)其余端口皆处于转发状态。(学习状态只是一种过渡状态,即堵塞端口一直处于堵塞状态,而根端口与指定端口将从堵塞状态过渡到转发状态)

到此为止,所有竞选结束了。在逻辑上竞选的大致顺序是:1.竞选根桥2.竞选根端口3.竞选指定端口(指定桥)。但事实上他们三者的竞选几乎是同时进行的。在物理层面上,每收到一个bpdu之后的几毫秒内,交换机的多个内存字段(如根桥id,到根桥cost,根端口编号,指定端口编号等)会依次发生更新。直到这些字段连续15秒内未发生任何变化(计时器)(对于每个vlan而言),交换机就认为竞选已结束(网络已收敛完毕),然后非堵塞端口进入学习状态。

(某些特殊端口,如连接PC的端口和连接某个没有启动vlan x的交换机的端口,由于端口角色默认是所在链路上的指定端口,因为一直没收到对方发来的关于vlan x的bpdu,该端口角色字段一直未更新,最终也处于转发转发状态)(合情合理)。

学习状态并不是很重要,端口仍处于堵塞状态,只是在这一阶段学习邻居和PC的mac地址。学习状态也持续15秒,之后就进入转发状态(即正常工作状态)。所以一般来说交换层网络交换机从通电连接到可以正常工作需30秒左右(在rstp下)。

当所有交换机进入转发状态后,网络也就“通”了,至此,交换机不用再那么频繁地向邻居发送bpdu占用带宽了。对于每棵生成树,因为是转发状态交换机只需转发根桥的bpdu向身后的生成树成员。此行为的目的:维护生成树。每个根桥都广播自身的bpdu到所有成员(成员不在发送自己的bpdu了)。所有非根桥在最大老化时间内都要监听到对应根桥的bpdu并且广播它,不然就认为该生成树已受到了破坏。

若交换网络真的发生了故障(比如其中某根网线突然被剪断了),那就有一部分交换机收不到根桥的bpdu。 为了维护生成树的完整,替代端口变成交换机上的根端口。大多数的堵塞端口(正常工作情况下)都是替代端口(只有当相邻交换机之间存在两条链路时,其中一条 是备份链路)。因为替代端口的对面必定是指定端口,因此可以通过这个替代端口从对方交换机抵达根桥。因此不需要重算生成树,这事rstp的改进之处。(局部等待30s)

但若网络没有故障,而是被接入了若干新的交换机,或者并入了一个更大的交换网络,那么每个vlan生成树就要重新开始从头计算了。具体的机制是:(因为网络变化,必须让所有交换机知晓,并停止工作回到竞选的初始状态)检测到网络变化(vlan x)的交换机发送一个特殊的bpdu到它的“前任”根桥(通过一个个根端口)。这个bpdu叫拓扑更改通知 TCN(Topology Change Notification)(区分于bpsu版本字段)。因为生成树重算非常重要,TCN的传送采用可靠连接,因此相对应的确认消息叫TCA(Topology Change Acknowledge),它们建立在每两个交换机之间。前任根桥收到后再通知树上的所有成员。(但个人认为不需要通知根桥,直接广播扩散到所有成员即可)

    以上就是生成树算法的收敛机制与维护机制,有没有感觉到它是个很聪明的算法?不过rstp还有许多进步的功能,如portfast等子协议,若想了解详情以及最新消息,请进入思科官网搜索(www.cisco.com)。

<完>