快速生成树之端口角色选择状态机

时间:2022-09-05 23:47:02

1 源码

   rstplib.1.1.02/rolesel.c, rolesel.h

2 功能

   每个网桥拥有一个端口角色选择状态机,负责为每个端口分配角色。

3 端口角色

RSTP中端口角色有如下几种:根端口、指定端口、可选端口、备份端口、弃用端口。

端口角色的分配由以下因素决定:

a) 每个网桥的唯一网桥ID(BridgeIdentifier);

b) 每个网桥端口的路径代价(PortPathCost);

c) 每个网桥端口的端口ID(portId)。

3.1 基础概念:

根网桥:所有网桥中网桥ID最小的那个网桥是该桥接LAN的根网桥。

路径代价:帧经过该端口要花费的代价是该端口的路径代价(可配置)。

根路径代价(网桥):从根网桥到该网桥的最小代价路径中,所有接收帧的端口(即根端口)的路径代价之和是该网桥的根路径代价,根网桥的根路径代价为0。

指定网桥(LAN):接在LAN上的所有网桥中根路径代价最小的那个网桥是该LAN的指定网桥。

根路径代价(LAN): LAN的根路径代价等于该LAN的指定网桥的根路径代价

3.2 端口角色概念:

根端口(网桥):从到根网桥的最小代价路径接收帧的那个端口就是该网桥的根端口,根端口提供了到达根网桥的一条最优路径。

指定端口(LAN):将LAN连到指定网桥的端口是该LAN的指定端口。

备份端口:如果一个网桥是一个LAN的指定网桥,那么除了指定端口外,该网桥的所有接在该LAN上的可工作端口都是备份端口,备份端口是指定端口的一个备份。

可选端口:如果一个端口是可工作的,并且它不是根端口、指定端口或备份端口,那么它就是可选端口,可选端口提供了到达根网桥的另一条可选路径。

弃用端口(可配置):如果该端口是不可工作的(MAC_Operational==FALSE),那么该端口是弃用端口。

当桥接LAN的拓扑结构稳定后:每个LAN仅有一个指定端口,除了根网桥外每个网桥只有一个根端口。

4 代码简析

4.1 状态定义

#define STATES { /

  /* 初始化进入INIT_BRIDGE状态 */

  CHOOSE(INIT_BRIDGE),      /        

  /* 计算端口角色并为每个端口分配角色,如果在计算过程中任一端口的reselect又被置位,那么计算过程立刻将重新开始 */

  CHOOSE(ROLE_SELECTION),   /   

}

4.2 STP_rolesel_enter_state

负责执行切换到某角色后的固定动作。

void STP_rolesel_enter_state (STATE_MACH_T* this)

{

  STPM_T* stpm;

  stpm = this->owner.stpm; // 指向所属网桥

  switch (this->State) {

    case BEGIN:

    case INIT_BRIDGE:

      updtRoleDisableBridge (stpm); // 使本网桥所有端口的selectedRole = DisabledPort

      break;

    case ROLE_SELECTION:

      clearReselectBridge (stpm); // 使本网桥所有端口的reselect = FALSE

      updtRolesBridge (this); // 为本网桥所有端口分配角色

      setSelectedBridge (stpm); // 当本网桥所有端口的reselect == FALSE时,使本网桥所有端口的selected = TRUE

      break;

  }

}

selectedRole:选择的角色,端口角色选择状态机为本端口新选择的角色。

reselect:重选端口角色信号,=TRUE:当rcvBpdu()返回SuperiorDesignatedMsg时或infoIs == Disabled或infoIs == Aged。

selected:角色选择完成标志。

4.3 STP_rolesel_check_conditions

检查倒换条件并进行状态倒换。

Bool STP_rolesel_check_conditions (STATE_MACH_T* s)

{

  STPM_T* stpm;

  register PORT_T* port;

  switch (s->State) {

    /* BEGIN -> INIT_BRIDGE -> ROLE_SELECTION 皆为无条件倒换 */

    case BEGIN:

      return STP_hop_2_state (s, INIT_BRIDGE);

    case INIT_BRIDGE:

      return STP_hop_2_state (s, ROLE_SELECTION);

    case ROLE_SELECTION:

      stpm = s->owner.stpm;

   /* 遍历此网桥的所有端口,如果在计算角色过程中任一端口的reselect又被置位,那么计算过程立刻将重新开始,

    * 即重新切换到ROLE_SELECTION

    */

      for(port = stpm->ports; port; port = port->next) {

        if (port->reselect) {

          return STP_hop_2_state (s, ROLE_SELECTION);

        }

      }

      break;

  }

  return False;

}

5 状态机

快速生成树之端口角色选择状态机