快速生成樹之端口角色轉移狀態機

 

1 源碼

   rstplib.1.1.02/roletrns.c,roletrns.h。

2 代碼簡析

/* 使本網橋所有端口的同步請求信號sync = TRUE */

static void setSyncBridge (STATE_MACH_T *this)

{

  register PORT_T* port;

  /* this->owner.port:此狀態機所屬的端口

   * this->owner.port->owner:端口所屬的網橋

   * this->owner.port->owner->ports:網橋的端口鏈表的頭端口

   */

  for (port = this->owner.port->owner->ports; port; port = port->next) {

    port->sync = True; /* in ROOT_ PROPOSED (setSyncBridge) */

  }

}

 

reRoot重選根端口信號,該信號由根端口控制。

/* 向所有端口發重選根端口信號reRoot */

static void setReRootBridge (STATE_MACH_T *this)

{

  register PORT_T* port;

  for (port = this->owner.port->owner->ports; port; port = port->next) {

    port->reRoot = True; /* In setReRootBridge */

  }

}

 

/* 該端口所屬的網橋的其他所有端口都已同步 */

static Bool compute_all_synced (PORT_T* this)

{

  register PORT_T* port;

  for (port = this->owner->ports; port; port = port->next) {

    if (port->port_index == this->port_index) continue; // 跳過自身

    if (! port->synced) {

        return False;

    }

  }

  return True;

}

 

/* 判斷是否還有端口爲根端口,沒有則返回TRUE,否則返回FALSE */

static Bool compute_re_rooted (PORT_T* this)

{

  register PORT_T* port;

  for (port = this->owner->ports; port; port = port->next) {

if (port->port_index == this->port_index) continue;

   /* rrWhile:最近根端口定時器 (recent root whileTimer)   

    *初值=FwdDelay

    *當一個端口變成根端口後,它將一直使它=FwdDelay

    *當端口變成丟棄狀態時,它=0

    *用途:它表示該端口還有多久就完全不是根端口了

    *rrWhile!=0:表示該端口目前是或最近是根端口

    *rrWhile==0:表示該端口已經完全不是根端口了

    */

    if (port->rrWhile) {

      return False;

    }

  }

  return True;

}

 

/* 執行狀態動作 */

void STP_roletrns_enter_state (STATE_MACH_T* this)

{

  register PORT_T*           port = this->owner.port;

  register STPM_T*           stpm;

  stpm = port->owner;

  switch (this->State) {

case BEGIN: // 開始狀態,無動作

case INIT_PORT: // 初始化

      /* 本端口當前角色和新選角色都置爲“棄用端口” */

      port->role = port->selectedRole = DisabledPort;

      port->reselect = True; // 重選端口角色信號置True

      port->synced = False; // 同步標誌置False,待同步

      port->sync = True; // 同步請求信號置True

      port->reRoot = True; // 重選根端口信號置True

      port->rrWhile = stpm->rootTimes.ForwardDelay; // 最近根端口定時器設初值

      port->fdWhile = stpm->rootTimes.ForwardDelay;

      /* 最近備份端口定時器,表示該端口還有多久就完全不是備份端口了 */

      port->rbWhile = 0;

      break;

case BLOCK_PORT:

      port->role = port->selectedRole; // 設置新角色-棄用端口

      port->learn =        // 此處空白,即同下面forward賦同樣值,省略寫法

      port->forward = False; // 禁止學習、轉發

      break;

case BLOCKED_PORT:

      /* 轉發延遲定時器重置,使處於棄用、備份、可選的端口保持丟棄狀態 */

      port->fdWhile = stpm->rootTimes.ForwardDelay;

      port->synced = True; /* In BLOCKED_PORT */

      port->rrWhile = 0;

      port->sync = port->reRoot = False; /* BLOCKED_PORT */

      break;

case BACKUP_PORT:

      /* rbWhile最近備份端口定時器,

       * 當一個端口變成備份端口後,將一直使rbWhile =2*HelloTime

       */

      port->rbWhile = 2 * stpm->rootTimes.HelloTime;

      break;

 

    case ROOT_PROPOSED:

      setSyncBridge (this); //使本網橋所有端口的sync = TRUE

      port->proposed = False; // 清除轉發提議接收信號

      break;

case ROOT_AGREED:

      /* 清除進入本狀態的相關觸發信號 */

      port->proposed = port->sync = False;     

port->synced = True;

      port->newInfo = True;

      break;

    case REROOT:

      setReRootBridge (this); // 向所有端口發重選根端口信號

      break;

    case ROOT_PORT:

      port->role = RootPort; // 角色設爲根端口

      port->rrWhile = stpm->rootTimes.ForwardDelay; // 啓動最近根端口定時器

      break;

    case REROOTED:

      port->reRoot = False;

      break;

      /* 轉發延遲定時器fdWhile到期後,端口就可以進行狀態轉移:

       * 丟棄→學習 學習→轉發

       */

    case ROOT_LEARN:

      port->fdWhile = stpm->rootTimes.ForwardDelay;

      port->learn = True;

      break;

    case ROOT_FORWARD:

      port->fdWhile = 0;

      port->forward = True;

      break;

 

    case DESIGNATED_PROPOSE:

      port->proposing = True; // 轉發提議信號,本端口希望快速轉移到轉發狀態

      port->newInfo = True; // 發送新消息信號,導致端口發送狀態機發送一個BPDU

      break;

    case DESIGNATED_SYNCED:

      port->rrWhile = 0; // 使端口變成丟棄狀態

      port->synced = True; // 本端口已同步

      port->sync = False; // 清除同步請求信號

      break;

    case DESIGNATED_RETIRED:

      port->reRoot = False; // 經過重選後,剛從根端口角色退休,清除重選根端口信號

      break;

    case DESIGNATED_PORT:

      port->role = DesignatedPort;

      break;

    case DESIGNATED_LISTEN:

      port->learn = port->forward = False;

      port->fdWhile = stpm->rootTimes.ForwardDelay; // 爲轉移到學習狀態設置定時器

      break;

    case DESIGNATED_LEARN:

      port->learn = True;

      port->fdWhile = stpm->rootTimes.ForwardDelay; // 爲轉移到轉發狀態設置定時器

      break;

    case DESIGNATED_FORWARD:

      port->forward = True;

      port->fdWhile = 0;

      break;

  };

}

 

Bool STP_roletrns_check_conditions (STATE_MACH_T* this)

{

  /* 初始化進入INIT_PORT狀態 */

  if (BEGIN == this->State) {

    return STP_hop_2_state (this, INIT_PORT);

  }

 

  /* 若端口角色有變,則根據新選擇的角色跳到對應狀態,分爲三個子狀態機:

   * (1) 棄用、備份、可選端口的端口角色轉移狀態機:BLOCK_PORT;

   * (2) 根端口的端口角色轉移狀態機ROOT_PORT;

   * (3) 指定端口的端口角色轉移狀態機DESIGNATED_PORT;

   */

  if (port->role != port->selectedRole &&

      port->selected &&

      ! port->updtInfo) {

    switch (port->selectedRole) {

      case DisabledPort:

      case AlternatePort:

      case BackupPort:

        return STP_hop_2_state (this, BLOCK_PORT);

      case RootPort:

        return STP_hop_2_state (this, ROOT_PORT);

      case DesignatedPort:

        return STP_hop_2_state (this, DESIGNATED_PORT);

      default:

        return False;

    }

  }

 

  switch (this->State) {

  /* 棄用、備份、可選端口的端口角色轉移狀態機:

   * 使處於棄用、備份、可選的端口保持丟棄狀態

   */

case BLOCK_PORT:

     /* 端口角色選擇尚未完成或有信息待更新時直接返回 */

     if (!port->selected || port->updtInfo) break;   

     /* 既非學習又非轉發,則進入阻塞態 */

     if (!port->learning && !port->forwarding) {

        return STP_hop_2_state (this, BLOCKED_PORT);

      }

    break;

case BLOCKED_PORT:

   

    /* 同步請求信號、重選根端口信號等非同步事件則維持阻塞 */

    if (port->fdWhile != stpm->rootTimes.ForwardDelay ||

          port->sync                ||

          port->reRoot              ||

          !port->synced) {

        return STP_hop_2_state (this, BLOCKED_PORT);

    }

    /* 角色爲備份端口,則進入BACKUP_PORT,並一直使rbWhile =2*HelloTime */

    if (port->rbWhile != 2 * stpm->rootTimes.HelloTime &&

          port->role == BackupPort) {

        return STP_hop_2_state (this, BACKUP_PORT);

    }

    break;

case BACKUP_PORT:

    return STP_hop_2_state (this, BLOCKED_PORT);

    /*根端口的端口角色轉移狀態機:

     * (1) 使處於根端口的端口保持轉發狀態;

     * (2) 負責與父網橋指定端口完成握手協議

     */

 

     /*指定端口的端口角色轉移狀態機:

      * 使處於指定端口的端口保持轉發狀態

      */

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章