roletrns.c
上传用户:allwinjm
上传日期:2021-08-29
资源大小:99k
文件大小:12k
源码类别:

Internet/IE编程

开发平台:

Unix_Linux

  1. /************************************************************************ 
  2.  * RSTP library - Rapid Spanning Tree (802.1t, 802.1w) 
  3.  * Copyright (C) 2001-2003 Optical Access 
  4.  * Author: Alex Rozin 
  5.  * 
  6.  * This file is part of RSTP library. 
  7.  * 
  8.  * RSTP library is free software; you can redistribute it and/or modify it 
  9.  * under the terms of the GNU Lesser General Public License as published by the 
  10.  * Free Software Foundation; version 2.1 
  11.  * 
  12.  * RSTP library is distributed in the hope that it will be useful, but 
  13.  * WITHOUT ANY WARRANTY; without even the implied warranty of 
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser 
  15.  * General Public License for more details. 
  16.  * 
  17.  * You should have received a copy of the GNU Lesser General Public License 
  18.  * along with RSTP library; see the file COPYING.  If not, write to the Free 
  19.  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 
  20.  * 02111-1307, USA. 
  21.  **********************************************************************/
  22. /* Port Role Transitions state machine : 17.24 */
  23.  
  24. #include "base.h"
  25. #include "stpm.h"
  26. #define STATES { 
  27.    CHOOSE(INIT_PORT),       
  28.    CHOOSE(BLOCK_PORT),      
  29.    CHOOSE(BLOCKED_PORT),    
  30.    CHOOSE(BACKUP_PORT),     
  31.    CHOOSE(ROOT_PROPOSED),   
  32.    CHOOSE(ROOT_AGREED),     
  33.    CHOOSE(REROOT),      
  34.    CHOOSE(ROOT_PORT),       
  35.    CHOOSE(REROOTED),        
  36.    CHOOSE(ROOT_LEARN),      
  37.    CHOOSE(ROOT_FORWARD),    
  38.    CHOOSE(DESIGNATED_PROPOSE),  
  39.    CHOOSE(DESIGNATED_SYNCED),   
  40.    CHOOSE(DESIGNATED_RETIRED),  
  41.    CHOOSE(DESIGNATED_PORT), 
  42.    CHOOSE(DESIGNATED_LISTEN),   
  43.    CHOOSE(DESIGNATED_LEARN),    
  44.    CHOOSE(DESIGNATED_FORWARD),  
  45. }
  46. #define GET_STATE_NAME STP_roletrns_get_state_name
  47. #include "choose.h"
  48. static void
  49. setSyncBridge (STATE_MACH_T *this)
  50. {
  51.   register PORT_T* port;
  52.   for (port = this->owner.port->owner->ports; port; port = port->next) {
  53.     port->sync = True; /* in ROOT_PROPOSED (setSyncBridge) */
  54.   }
  55. }
  56. static void
  57. setReRootBridge (STATE_MACH_T *this)
  58. {
  59.   register PORT_T* port;
  60.   for (port = this->owner.port->owner->ports; port; port = port->next) {
  61.     port->reRoot = True; /* In setReRootBridge */
  62.   }
  63. }
  64. static Bool
  65. compute_all_synced (PORT_T* this)
  66. {
  67.   register PORT_T* port;
  68.   for (port = this->owner->ports; port; port = port->next) {
  69.     if (port->port_index == this->port_index) continue;
  70.     if (! port->synced) {
  71.         return False;
  72.     }
  73.   }
  74.   return True;
  75. }
  76. static Bool
  77. compute_re_rooted (PORT_T* this)
  78. {
  79.   register PORT_T* port;
  80.   for (port = this->owner->ports; port; port = port->next) {
  81.     if (port->port_index == this->port_index) continue;
  82.     if (port->rrWhile) {
  83.       return False;
  84.     }
  85.   }
  86.   return True;
  87. }
  88. void
  89. STP_roletrns_enter_state (STATE_MACH_T* this)
  90. {
  91.   register PORT_T*           port = this->owner.port;
  92.   register STPM_T*           stpm;
  93.   stpm = port->owner;
  94.   switch (this->State) {
  95.     case BEGIN:
  96.     case INIT_PORT:
  97. #if 0 /* due 802.1y Z.4 */
  98.       port->role = DisabledPort;
  99. #else
  100.       port->role = port->selectedRole = DisabledPort;
  101.       port->reselect = True;
  102. #endif
  103.       port->synced = False; /* in INIT */
  104.       port->sync = True; /* in INIT */
  105.       port->reRoot = True; /* in INIT_PORT */
  106.       port->rrWhile = stpm->rootTimes.ForwardDelay;
  107.       port->fdWhile = stpm->rootTimes.ForwardDelay;
  108.       port->rbWhile = 0; 
  109. #ifdef STP_DBG
  110.       if (this->debug)
  111.         STP_port_trace_flags ("after init", port);
  112. #endif
  113.       break;
  114.     case BLOCK_PORT:
  115.       port->role = port->selectedRole;
  116.       port->learn =
  117.       port->forward = False;
  118.       break;
  119.     case BLOCKED_PORT:
  120.       port->fdWhile = stpm->rootTimes.ForwardDelay;
  121.       port->synced = True; /* In BLOCKED_PORT */
  122.       port->rrWhile = 0;
  123.       port->sync = port->reRoot = False; /* BLOCKED_PORT */
  124.       break;
  125.     case BACKUP_PORT:
  126.       port->rbWhile = 2 * stpm->rootTimes.HelloTime;
  127.       break;
  128.     /* 17.23.2 */
  129.     case ROOT_PROPOSED:
  130.       setSyncBridge (this);
  131.       port->proposed = False;
  132. #ifdef STP_DBG
  133.       if (this->debug) 
  134.         STP_port_trace_flags ("ROOT_PROPOSED", port);
  135. #endif
  136.       break;
  137.     case ROOT_AGREED:
  138.       port->proposed = port->sync = False; /* in ROOT_AGREED */
  139.       port->synced = True; /* In ROOT_AGREED */
  140.       port->newInfo = True;
  141. #ifdef STP_DBG
  142.       if (this->debug)
  143.         STP_port_trace_flags ("ROOT_AGREED", port);
  144. #endif
  145.       break;
  146.     case REROOT:
  147.       setReRootBridge (this);
  148. #ifdef STP_DBG
  149.       if (this->debug)
  150.         STP_port_trace_flags ("REROOT", port);
  151. #endif
  152.       break;
  153.     case ROOT_PORT:
  154.       port->role = RootPort;
  155.       port->rrWhile = stpm->rootTimes.ForwardDelay;
  156. #ifdef STP_DBG
  157.       if (this->debug)
  158.         STP_port_trace_flags ("ROOT_PORT", port);
  159. #endif
  160.       break;
  161.     case REROOTED:
  162.       port->reRoot = False; /* In REROOTED */
  163. #ifdef STP_DBG
  164.       if (this->debug)
  165.         STP_port_trace_flags ("REROOTED", port);
  166. #endif
  167.       break;
  168.     case ROOT_LEARN:
  169.       port->fdWhile = stpm->rootTimes.ForwardDelay;
  170.       port->learn = True;
  171. #ifdef STP_DBG
  172.       if (this->debug)
  173.         STP_port_trace_flags ("ROOT_LEARN", port);
  174. #endif
  175.       break;
  176.     case ROOT_FORWARD:
  177.       port->fdWhile = 0;
  178.       port->forward = True;
  179. #ifdef STP_DBG
  180.       if (this->debug)
  181.         STP_port_trace_flags ("ROOT_FORWARD", port);
  182. #endif
  183.       break;
  184.     /* 17.23.3 */
  185.     case DESIGNATED_PROPOSE:
  186.       port->proposing = True; /* in DESIGNATED_PROPOSE */
  187.       port->newInfo = True;
  188. #ifdef STP_DBG
  189.       if (this->debug)
  190.         STP_port_trace_flags ("DESIGNATED_PROPOSE", port);
  191. #endif
  192.       break;
  193.     case DESIGNATED_SYNCED:
  194.       port->rrWhile = 0;
  195.       port->synced = True; /* DESIGNATED_SYNCED */
  196.       port->sync = False; /* DESIGNATED_SYNCED */
  197. #ifdef STP_DBG
  198.       if (this->debug)
  199.         STP_port_trace_flags ("DESIGNATED_SYNCED", port);
  200. #endif
  201.       break;
  202.     case DESIGNATED_RETIRED:
  203.       port->reRoot = False; /* DESIGNATED_RETIRED */
  204. #ifdef STP_DBG
  205.       if (this->debug)
  206.         STP_port_trace_flags ("DESIGNATED_RETIRED", port);
  207. #endif
  208.       break;
  209.     case DESIGNATED_PORT:
  210.       port->role = DesignatedPort;
  211. #ifdef STP_DBG
  212.       if (this->debug)
  213.         STP_port_trace_flags ("DESIGNATED_PORT", port);
  214. #endif
  215.       break;
  216.     case DESIGNATED_LISTEN:
  217.       port->learn = port->forward = False;
  218.       port->fdWhile = stpm->rootTimes.ForwardDelay;
  219. #ifdef STP_DBG
  220.       if (this->debug)
  221.         STP_port_trace_flags ("DESIGNATED_LISTEN", port);
  222. #endif
  223.       break;
  224.     case DESIGNATED_LEARN:
  225.       port->learn = True;
  226.       port->fdWhile = stpm->rootTimes.ForwardDelay;
  227. #ifdef STP_DBG
  228.       if (this->debug)
  229.         STP_port_trace_flags ("DESIGNATED_LEARN", port);
  230. #endif
  231.       break;
  232.     case DESIGNATED_FORWARD:
  233.       port->forward = True;
  234.       port->fdWhile = 0;
  235. #ifdef STP_DBG
  236.       if (this->debug)
  237.         STP_port_trace_flags ("DESIGNATED_FORWARD", port);
  238. #endif
  239.       break;
  240.   };
  241. }
  242.     
  243. Bool
  244. STP_roletrns_check_conditions (STATE_MACH_T* this)
  245. {
  246.   register PORT_T           *port = this->owner.port;
  247.   register STPM_T           *stpm;
  248.   Bool                      allSynced;
  249.   Bool                      allReRooted;
  250.   stpm = port->owner;
  251.   if (BEGIN == this->State) {
  252.     return STP_hop_2_state (this, INIT_PORT);
  253.   }
  254.   if (port->role != port->selectedRole &&
  255.       port->selected &&
  256.       ! port->updtInfo) {
  257.     switch (port->selectedRole) {
  258.       case DisabledPort:
  259.       case AlternatePort:
  260.       case BackupPort:
  261. #if 0 /* def STP_DBG */
  262.         if (this->debug) {
  263.           stp_trace ("hop to BLOCK_PORT role=%d selectedRole=%d",
  264.                                 (int) port->role, (int) port->selectedRole);
  265.         }
  266. #endif
  267.         return STP_hop_2_state (this, BLOCK_PORT);
  268.       case RootPort:
  269.         return STP_hop_2_state (this, ROOT_PORT);
  270.       case DesignatedPort:
  271.         return STP_hop_2_state (this, DESIGNATED_PORT);
  272.       default:
  273.         return False;
  274.     }
  275.   }
  276.   switch (this->State) {
  277.     /* 17.23.1 */
  278.     case INIT_PORT:
  279.       return STP_hop_2_state (this, BLOCK_PORT);
  280.     case BLOCK_PORT:
  281.       if (!port->selected || port->updtInfo) break;
  282.       if (!port->learning && !port->forwarding) {
  283.         return STP_hop_2_state (this, BLOCKED_PORT);
  284.       }
  285.       break;
  286.     case BLOCKED_PORT:
  287.       if (!port->selected || port->updtInfo) break;
  288.       if (port->fdWhile != stpm->rootTimes.ForwardDelay ||
  289.           port->sync                ||
  290.           port->reRoot              ||
  291.           !port->synced) {
  292.         return STP_hop_2_state (this, BLOCKED_PORT);
  293.       }
  294.       if (port->rbWhile != 2 * stpm->rootTimes.HelloTime &&
  295.           port->role == BackupPort) {
  296.         return STP_hop_2_state (this, BACKUP_PORT);
  297.       }
  298.       break;
  299.     case BACKUP_PORT:
  300.       return STP_hop_2_state (this, BLOCKED_PORT);
  301.     /* 17.23.2 */
  302.     case ROOT_PROPOSED:
  303.       return STP_hop_2_state (this, ROOT_PORT);
  304.     case ROOT_AGREED:
  305.       return STP_hop_2_state (this, ROOT_PORT);
  306.     case REROOT:
  307.       return STP_hop_2_state (this, ROOT_PORT);
  308.     case ROOT_PORT:
  309.       if (!port->selected || port->updtInfo) break;
  310.       if (!port->forward && !port->reRoot) {
  311.         return STP_hop_2_state (this, REROOT);
  312.       }
  313.       allSynced = compute_all_synced (port);
  314.       if ((port->proposed && allSynced) ||
  315.           (!port->synced && allSynced)) {
  316.         return STP_hop_2_state (this, ROOT_AGREED);
  317.       }
  318.       if (port->proposed && !port->synced) {
  319.         return STP_hop_2_state (this, ROOT_PROPOSED);
  320.       }
  321.       allReRooted = compute_re_rooted (port);
  322.       if ((!port->fdWhile || 
  323.            ((allReRooted && !port->rbWhile) && stpm->ForceVersion >=2)) &&
  324.           port->learn && !port->forward) {
  325.         return STP_hop_2_state (this, ROOT_FORWARD);
  326.       }
  327.       if ((!port->fdWhile || 
  328.            ((allReRooted && !port->rbWhile) && stpm->ForceVersion >=2)) &&
  329.           !port->learn) {
  330.         return STP_hop_2_state (this, ROOT_LEARN);
  331.       }
  332.       if (port->reRoot && port->forward) {
  333.         return STP_hop_2_state (this, REROOTED);
  334.       }
  335.       if (port->rrWhile != stpm->rootTimes.ForwardDelay) {
  336.         return STP_hop_2_state (this, ROOT_PORT);
  337.       }
  338.       break;
  339.     case REROOTED:
  340.       return STP_hop_2_state (this, ROOT_PORT);
  341.     case ROOT_LEARN:
  342.       return STP_hop_2_state (this, ROOT_PORT);
  343.     case ROOT_FORWARD:
  344.       return STP_hop_2_state (this, ROOT_PORT);
  345.     /* 17.23.3 */
  346.     case DESIGNATED_PROPOSE:
  347.       return STP_hop_2_state (this, DESIGNATED_PORT);
  348.     case DESIGNATED_SYNCED:
  349.       return STP_hop_2_state (this, DESIGNATED_PORT);
  350.     case DESIGNATED_RETIRED:
  351.       return STP_hop_2_state (this, DESIGNATED_PORT);
  352.     case DESIGNATED_PORT:
  353.       if (!port->selected || port->updtInfo) break;
  354.       if (!port->forward && !port->agreed && !port->proposing && !port->operEdge) {
  355.         return STP_hop_2_state (this, DESIGNATED_PROPOSE);
  356.       }
  357.       if (!port->rrWhile && port->reRoot) {
  358.         return STP_hop_2_state (this, DESIGNATED_RETIRED);
  359.       }
  360.       
  361.       if (!port->learning && !port->forwarding && !port->synced) {
  362.         return STP_hop_2_state (this, DESIGNATED_SYNCED);
  363.       }
  364.       if (port->agreed && !port->synced) {
  365.         return STP_hop_2_state (this, DESIGNATED_SYNCED);
  366.       }
  367.       if (port->operEdge && !port->synced) {
  368.         return STP_hop_2_state (this, DESIGNATED_SYNCED);
  369.       }
  370.       if (port->sync && port->synced) {
  371.         return STP_hop_2_state (this, DESIGNATED_SYNCED);
  372.       }
  373.       if ((!port->fdWhile || port->agreed || port->operEdge) &&
  374.           (!port->rrWhile  || !port->reRoot) &&
  375.           !port->sync &&
  376.           (port->learn && !port->forward)) {
  377.         return STP_hop_2_state (this, DESIGNATED_FORWARD);
  378.       }
  379.       if ((!port->fdWhile || port->agreed || port->operEdge) &&
  380.           (!port->rrWhile  || !port->reRoot) &&
  381.           !port->sync && !port->learn) {
  382.         return STP_hop_2_state (this, DESIGNATED_LEARN);
  383.       }
  384.       if (((port->sync && !port->synced) ||
  385.            (port->reRoot && port->rrWhile)) &&
  386.           !port->operEdge && (port->learn || port->forward)) {
  387.         return STP_hop_2_state (this, DESIGNATED_LISTEN);
  388.       }
  389.       break;
  390.     case DESIGNATED_LISTEN:
  391.       return STP_hop_2_state (this, DESIGNATED_PORT);
  392.     case DESIGNATED_LEARN:
  393.       return STP_hop_2_state (this, DESIGNATED_PORT);
  394.     case DESIGNATED_FORWARD:
  395.       return STP_hop_2_state (this, DESIGNATED_PORT);
  396.   };
  397.   return False;
  398. }