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

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. /* Topolgy Change state machine : 17.25 */
  23.   
  24. #include "base.h"
  25. #include "stpm.h"
  26. #include "stp_to.h" /* for STP_OUT_flush_lt */
  27.   
  28. #define STATES { 
  29.   CHOOSE(INIT),             
  30.   CHOOSE(INACTIVE),         
  31.   CHOOSE(TCACTIVE),         
  32.   CHOOSE(DETECTED),         
  33.   CHOOSE(NOTIFIED_TC),          
  34.   CHOOSE(PROPAGATING),          
  35.   CHOOSE(ACKNOWLEDGED),         
  36.   CHOOSE(NOTIFIED_TCN),         
  37. }
  38. #define GET_STATE_NAME STP_topoch_get_state_name
  39. #include "choose.h"
  40. #ifndef STRONGLY_SPEC_802_1W
  41. /* 
  42.  * In many kinds of hardware the function
  43.  * STP_OUT_flush_lt is a) is very hard and b) cannot
  44.  * delete learning emtries per port. The alternate
  45.  * method may be used: we don't care operEdge flag here,
  46.  * but clean learning table once for TopologyChange
  47.  * for all ports, except the received port. I am ready to discuss :(
  48.  * See below word STRONGLY_SPEC_802_1W
  49.  */
  50. #else
  51. static Bool
  52. flush (STATE_MACH_T *this, char* reason) /* 17.19.9 */
  53. {
  54.   register PORT_T* port = this->owner.port;
  55.   Bool bret;
  56.   if (port->operEdge) return True;
  57.   if (this->debug) {
  58.     stp_trace("%s (%s, %s, %s, '%s')",
  59.         "flush", port->port_name, port->owner->name,
  60.         LT_FLASH_ONLY_THE_PORT == type ? "this port" : "other ports",
  61.         reason);
  62.   }
  63.   bret = STP_OUT_flush_lt (port->port_index, port->owner->vlan_id,
  64.                            LT_FLASH_ONLY_THE_PORT, reason);
  65. }
  66. #endif
  67. static void
  68. setTcPropBridge (STATE_MACH_T* this, char* reason) /* 17.19.14 */
  69. {
  70.   register PORT_T* port = this->owner.port;
  71.   register PORT_T* tmp;
  72.   for (tmp = port->owner->ports; tmp; tmp = tmp->next) {
  73.     if (tmp->port_index != port->port_index)
  74.       tmp->tcProp = True;
  75.   }
  76. #ifndef STRONGLY_SPEC_802_1W
  77. #ifdef STP_DBG
  78.   if (this->debug) {
  79.     stp_trace("%s (%s, %s, %s, '%s')",
  80.         "clearFDB", port->port_name, port->owner->name,
  81.         "other ports", reason);
  82.   }
  83. #endif
  84.   STP_OUT_flush_lt (port->port_index, port->owner->vlan_id,
  85.                     LT_FLASH_ALL_PORTS_EXCLUDE_THIS, reason);
  86. #endif
  87. }
  88. static unsigned int
  89. newTcWhile (STATE_MACH_T* this) /* 17.19.7 */
  90. {
  91.   register PORT_T* port = this->owner.port;
  92.   if (port->sendRSTP && port->operPointToPointMac) {
  93.     return 2 * port->owner->rootTimes.HelloTime;
  94.   }
  95.   return port->owner->rootTimes.MaxAge;
  96. }
  97. void
  98. STP_topoch_enter_state (STATE_MACH_T* this)
  99. {
  100.   register PORT_T*      port = this->owner.port;
  101.   switch (this->State) {
  102.     case BEGIN:
  103.     case INIT:
  104. #ifdef STRONGLY_SPEC_802_1W
  105.       flush (this, "topoch INIT");
  106. #endif
  107.       port->tcWhile = 0;
  108.       port->tc =
  109.       port->tcProp =
  110.       port->tcAck = False;
  111.       break;
  112.     case INACTIVE:
  113.       port->rcvdTc =
  114.       port->rcvdTcn =
  115.       port->rcvdTcAck = port->tc = port->tcProp = False;
  116.       break;
  117.     case TCACTIVE:
  118.       break;
  119.     case DETECTED:
  120.       port->tcWhile = newTcWhile (this);
  121. #ifdef STP_DBG
  122.   if (this->debug) 
  123.     stp_trace("DETECTED: tcWhile=%d on port %s", 
  124.         port->tcWhile, port->port_name);
  125. #endif
  126.       setTcPropBridge (this, "DETECTED");
  127.       port->tc = False;  
  128.       break;
  129.     case NOTIFIED_TC:
  130.       port->rcvdTcn = port->rcvdTc = False;
  131.       if (port->role == DesignatedPort) {
  132.         port->tcAck = True;
  133.       }
  134.       setTcPropBridge (this, "NOTIFIED_TC");
  135.       break;
  136.     case PROPAGATING:
  137.       port->tcWhile = newTcWhile (this);
  138. #ifdef STP_DBG
  139.   if (this->debug) 
  140.     stp_trace("PROPAGATING: tcWhile=%d on port %s", 
  141.         port->tcWhile, port->port_name);
  142. #endif
  143. #ifdef STRONGLY_SPEC_802_1W
  144.       flush (this, "topoch PROPAGATING");
  145. #endif
  146.       port->tcProp = False;
  147.       break;
  148.     case ACKNOWLEDGED:
  149.       port->tcWhile = 0;
  150. #ifdef STP_DBG
  151.   if (this->debug) 
  152.     stp_trace("ACKNOWLEDGED: tcWhile=%d on port %s", 
  153.         port->tcWhile, port->port_name);
  154. #endif
  155.       port->rcvdTcAck = False;
  156.       break;
  157.     case NOTIFIED_TCN:
  158.       port->tcWhile = newTcWhile (this);
  159. #ifdef STP_DBG
  160.   if (this->debug) 
  161.     stp_trace("NOTIFIED_TCN: tcWhile=%d on port %s", 
  162.         port->tcWhile, port->port_name);
  163. #endif
  164.       break;
  165.   };
  166. }
  167. Bool
  168. STP_topoch_check_conditions (STATE_MACH_T* this)
  169. {
  170.   register PORT_T*      port = this->owner.port;
  171.   if (BEGIN == this->State) {
  172.     return STP_hop_2_state (this, INIT);
  173.   }
  174.   switch (this->State) {
  175.     case INIT:
  176.       return STP_hop_2_state (this, INACTIVE);
  177.     case INACTIVE:
  178.       if (port->role == RootPort || port->role == DesignatedPort)
  179.         return STP_hop_2_state (this, TCACTIVE);
  180.       if (port->rcvdTc || port->rcvdTcn || port->rcvdTcAck ||
  181.           port->tc || port->tcProp)
  182.         return STP_hop_2_state (this, INACTIVE);
  183.       break;
  184.     case TCACTIVE:
  185.       if (port->role != RootPort && (port->role != DesignatedPort))
  186.         return STP_hop_2_state (this, INIT);
  187.       if (port->tc)
  188.         return STP_hop_2_state (this, DETECTED);
  189.       if (port->rcvdTcn)
  190.         return STP_hop_2_state (this, NOTIFIED_TCN);
  191.       if (port->rcvdTc)
  192.         return STP_hop_2_state (this, NOTIFIED_TC);
  193.       if (port->tcProp && !port->operEdge)
  194.         return STP_hop_2_state (this, PROPAGATING);
  195.       if (port->rcvdTcAck)
  196.         return STP_hop_2_state (this, ACKNOWLEDGED);
  197.       break;
  198.     case DETECTED:
  199.       return STP_hop_2_state (this, TCACTIVE);
  200.     case NOTIFIED_TC:
  201.       return STP_hop_2_state (this, TCACTIVE);
  202.     case PROPAGATING:
  203.       return STP_hop_2_state (this, TCACTIVE);
  204.     case ACKNOWLEDGED:
  205.       return STP_hop_2_state (this, TCACTIVE);
  206.     case NOTIFIED_TCN:
  207.       return STP_hop_2_state (this, NOTIFIED_TC);
  208.   };
  209.   return False;
  210. }