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

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. #include "base.h"
  23. #include "stpm.h"
  24. /* The Port Information State Machine : 17.21 */
  25. #define STATES { 
  26.   CHOOSE(DISABLED), 
  27.   CHOOSE(ENABLED),  
  28.   CHOOSE(AGED),     
  29.   CHOOSE(UPDATE),   
  30.   CHOOSE(CURRENT),  
  31.   CHOOSE(RECEIVE),  
  32.   CHOOSE(SUPERIOR), 
  33.   CHOOSE(REPEAT),   
  34.   CHOOSE(AGREEMENT),    
  35. }
  36. #define GET_STATE_NAME STP_info_get_state_name
  37. #include "choose.h"
  38. #if 0 /* for debug */
  39. void
  40. _stp_dump (char* title, unsigned char* buff, int len)
  41. {
  42.   register int iii;
  43.   printf ("n%s:", title);
  44.   for (iii = 0; iii < len; iii++) {
  45.     if (! (iii % 24)) Print ("n%6d:", iii);
  46.     if (! (iii % 8)) Print (" ");
  47.     Print ("%02lx", (unsigned long) buff[iii]);
  48.   }
  49.   Print ("n");
  50. }
  51. #endif
  52. static RCVD_MSG_T
  53. rcvBpdu (STATE_MACH_T* this)
  54. {/* 17.19.8 */
  55.   int   bridcmp;
  56.   register PORT_T* port = this->owner.port;
  57.   if (port->msgBpduType == BPDU_TOPO_CHANGE_TYPE) {
  58. #ifdef STP_DBG
  59.     if (this->debug) {
  60.         stp_trace ("%s", "OtherMsg:BPDU_TOPO_CHANGE_TYPE");
  61.     }
  62. #endif
  63.     return OtherMsg;
  64.   }
  65.   port->msgPortRole = RSTP_PORT_ROLE_UNKN;
  66.   if (BPDU_RSTP == port->msgBpduType) {
  67.     port->msgPortRole = (port->msgFlags & PORT_ROLE_MASK) >> PORT_ROLE_OFFS;
  68.   }
  69.   if (RSTP_PORT_ROLE_DESGN == port->msgPortRole ||
  70.       BPDU_CONFIG_TYPE == port->msgBpduType) {
  71.     bridcmp = STP_VECT_compare_vector (&port->msgPrio, &port->portPrio);
  72.     if (bridcmp < 0 ||
  73.         (! STP_VECT_compare_bridge_id (&port->msgPrio.design_bridge,
  74.                                        &port->portPrio.design_bridge) &&
  75.          port->msgPrio.design_port == port->portPrio.design_port      &&
  76.          STP_compare_times (&port->msgTimes, &port->portTimes))) {
  77. #ifdef STP_DBG
  78.          if (this->debug) {
  79.            stp_trace ("SuperiorDesignateMsg:bridcmp=%d", (int) bridcmp);
  80.          }
  81. #endif
  82.       return SuperiorDesignateMsg;
  83.     }
  84.   }
  85.   if (BPDU_CONFIG_TYPE == port->msgBpduType ||
  86.       RSTP_PORT_ROLE_DESGN == port->msgPortRole) {
  87.     if (! STP_VECT_compare_vector (&port->msgPrio,
  88.                                    &port->portPrio) &&
  89.         ! STP_compare_times (&port->msgTimes, &port->portTimes)) {
  90. #ifdef STP_DBG
  91.         if (this->debug) {
  92.           stp_trace ("%s", "RepeatedDesignateMsg");
  93.         }
  94. #endif
  95.         return RepeatedDesignateMsg;
  96.     }
  97.   }
  98.   if (RSTP_PORT_ROLE_ROOT == port->msgBpduType                    &&
  99.       port->operPointToPointMac                                   &&
  100.       ! STP_VECT_compare_bridge_id (&port->msgPrio.design_bridge,
  101.                                     &port->portPrio.design_bridge) &&
  102.       AGREEMENT_BIT & port->msgFlags) {
  103. #ifdef STP_DBG
  104.     if (this->debug) {
  105.       stp_trace ("%s", "ConfirmedRootMsg");
  106.     }
  107. #endif
  108.     return ConfirmedRootMsg;
  109.   }
  110.   
  111. #ifdef STP_DBG
  112.     if (this->debug) {
  113.       stp_trace ("%s", "OtherMsg");
  114.     }
  115. #endif
  116.   return OtherMsg;
  117. }
  118. static Bool
  119. recordProposed (STATE_MACH_T* this, char* reason)
  120. {/* 17.19.9 */
  121.   register PORT_T* port = this->owner.port;
  122.   if (RSTP_PORT_ROLE_DESGN == port->msgPortRole &&
  123.       (PROPOSAL_BIT & port->msgFlags)           &&
  124.       port->operPointToPointMac) {
  125.     return True;
  126.   }
  127.   return False;
  128. }
  129. static Bool
  130. setTcFlags (STATE_MACH_T* this)
  131. {/* 17.19.13 */
  132.   register PORT_T* port = this->owner.port;
  133.   if (BPDU_TOPO_CHANGE_TYPE == port->msgBpduType) {
  134. #ifdef STP_DBG
  135.       if (this->debug) {
  136.         stp_trace ("port %s rx rcvdTcn", port->port_name);
  137.       }
  138. #endif
  139.     port->rcvdTcn = True;
  140.   } else {
  141.     if (TOLPLOGY_CHANGE_BIT & port->msgFlags) {
  142. #ifdef STP_DBG
  143.       if (this->debug) {
  144.         stp_trace ("(%s-%s) rx rcvdTc 0X%lx",
  145.             port->owner->name, port->port_name,
  146.             (unsigned long) port->msgFlags);
  147.       }
  148. #endif
  149.       port->rcvdTc = True;
  150.     }
  151.     if (TOLPLOGY_CHANGE_ACK_BIT & port->msgFlags) {
  152. #ifdef STP_DBG
  153.       if (this->debug) {
  154.         stp_trace ("port %s rx rcvdTcAck 0X%lx",
  155.             port->port_name,
  156.             (unsigned long) port->msgFlags);
  157.       }
  158. #endif
  159.       port->rcvdTcAck = True;
  160.     }
  161.   }
  162.   return True;
  163. }
  164. static Bool
  165. updtBPDUVersion (STATE_MACH_T* this)
  166. {/* 17.19.18 */
  167.   register PORT_T* port = this->owner.port;
  168.   if (BPDU_TOPO_CHANGE_TYPE == port->msgBpduType) {
  169.     port->rcvdSTP = True;
  170.   }
  171.   if (port->msgBpduVersion < 2) {
  172.     port->rcvdSTP = True;
  173.   }
  174.   
  175.   if (BPDU_RSTP == port->msgBpduType) {
  176.     /* port->port->owner->ForceVersion >= NORMAL_RSTP
  177.        we have checked in STP_info_rx_bpdu */
  178.     port->rcvdRSTP = True;
  179.   }
  180.   return True;
  181. }
  182. static Bool
  183. updtRcvdInfoWhile (STATE_MACH_T* this)
  184. {/* 17.19.19 */
  185.   register int eff_age, dm, dt;
  186.   register int hello3;
  187.   register PORT_T* port = this->owner.port;
  188.   
  189.   eff_age = ( + port->portTimes.MaxAge) / 16;
  190.   if (eff_age < 1) eff_age = 1;
  191.   eff_age += port->portTimes.MessageAge;
  192.   if (eff_age <= port->portTimes.MaxAge) {
  193.     hello3 = 3 *  port->portTimes.HelloTime;
  194.     dm = port->portTimes.MaxAge - eff_age;
  195.     if (dm > hello3)
  196.       dt = hello3;
  197.     else
  198.       dt = dm;
  199.     port->rcvdInfoWhile = dt;
  200. /****
  201.     stp_trace ("ma=%d eff_age=%d dm=%d dt=%d p=%s",
  202.                (int) port->portTimes.MessageAge,
  203.                (int) eff_age, (int) dm, (int) dt, port->port_name);
  204. ****/
  205.   } else {
  206.     port->rcvdInfoWhile = 0;
  207. /****/
  208. #ifdef STP_DBG
  209.     /*if (this->debug) */
  210.     {
  211.       stp_trace ("port %s: MaxAge=%d MessageAge=%d HelloTime=%d rcvdInfoWhile=null !",
  212.             port->port_name,
  213.                 (int) port->portTimes.MaxAge,
  214.                 (int) port->portTimes.MessageAge,
  215.                 (int) port->portTimes.HelloTime);
  216.     }
  217. #endif
  218. /****/
  219.   }
  220.   return True;
  221. }
  222. void
  223. STP_info_rx_bpdu (PORT_T* port, struct stp_bpdu_t* bpdu, size_t len)
  224. {  
  225. #if 0
  226.   _stp_dump ("nall BPDU", ((unsigned char*) bpdu) - 12, len + 12);
  227.   _stp_dump ("ETH_HEADER", (unsigned char*) &bpdu->eth, 5);
  228.   _stp_dump ("BPDU_HEADER", (unsigned char*) &bpdu->hdr, 4);
  229.   printf ("protocol=%02x%02x version=%02x bpdu_type=%02xn",
  230.      bpdu->hdr.protocol[0], bpdu->hdr.protocol[1],
  231.      bpdu->hdr.version, bpdu->hdr.bpdu_type);
  232.   _stp_dump ("nBPDU_BODY", (unsigned char*) &bpdu->body, sizeof (BPDU_BODY_T) + 2);
  233.   printf ("flags=%02xn", bpdu->body.flags);
  234.   _stp_dump ("root_id", bpdu->body.root_id, 8);
  235.   _stp_dump ("root_path_cost", bpdu->body.root_path_cost, 4);
  236.   _stp_dump ("bridge_id", bpdu->body.bridge_id, 8);
  237.   _stp_dump ("port_id", bpdu->body.port_id, 2);
  238.   _stp_dump ("message_age", bpdu->body.message_age, 2);
  239.   _stp_dump ("max_age", bpdu->body.max_age, 2);
  240.   _stp_dump ("hello_time", bpdu->body.hello_time, 2);
  241.   _stp_dump ("forward_delay", bpdu->body.forward_delay, 2);
  242.   _stp_dump ("ver_1_len", bpdu->ver_1_len, 2);
  243. #endif
  244.   
  245.   /* check bpdu type */
  246.   switch (bpdu->hdr.bpdu_type) {
  247.     case BPDU_CONFIG_TYPE:
  248.       port->rx_cfg_bpdu_cnt++;
  249. #if 0 /* def STP_DBG */
  250.       if (port->info->debug) 
  251.         stp_trace ("CfgBpdu on port %s", port->port_name);
  252. #endif
  253.       if (port->admin_non_stp) return;
  254.       port->rcvdBpdu = True;
  255.       break;
  256.     case BPDU_TOPO_CHANGE_TYPE:
  257.       port->rx_tcn_bpdu_cnt++;
  258. #if 0 /* def STP_DBG */
  259.       if (port->info->debug)
  260.         stp_trace ("TcnBpdu on port %s", port->port_name);
  261. #endif
  262.       if (port->admin_non_stp) return;
  263.       port->rcvdBpdu = True;
  264.       port->msgBpduVersion = bpdu->hdr.version;
  265.       port->msgBpduType = bpdu->hdr.bpdu_type;
  266.       return;
  267.     default:
  268.       stp_trace ("RX undef bpdu type=%d", (int) bpdu->hdr.bpdu_type);
  269.       return;
  270.     case BPDU_RSTP:
  271.       port->rx_rstp_bpdu_cnt++;
  272.       if (port->admin_non_stp) return;
  273.       if (port->owner->ForceVersion >= NORMAL_RSTP) {
  274.         port->rcvdBpdu = True;
  275.       } else {          
  276.         return;
  277.       }
  278. #if 0 /* def STP_DBG */
  279.       if (port->info->debug)
  280.         stp_trace ("BPDU_RSTP on port %s", port->port_name);
  281. #endif
  282.       break;
  283.   }
  284.   port->msgBpduVersion = bpdu->hdr.version;
  285.   port->msgBpduType =    bpdu->hdr.bpdu_type;
  286.   port->msgFlags =       bpdu->body.flags;
  287.   /* 17.18.11 */
  288.   STP_VECT_get_vector (&bpdu->body, &port->msgPrio);
  289.   port->msgPrio.bridge_port = port->port_id;
  290.   /* 17.18.12 */
  291.   STP_get_times (&bpdu->body, &port->msgTimes);
  292.   /* 17.18.25, 17.18.26 : see setTcFlags() */
  293. }
  294. void STP_info_enter_state (STATE_MACH_T* this)
  295. {
  296.   register PORT_T* port = this->owner.port;
  297.   switch (this->State) {
  298.     case BEGIN:
  299.       port->rcvdMsg = OtherMsg;
  300.       port->msgBpduType = -1;
  301.       port->msgPortRole = RSTP_PORT_ROLE_UNKN;
  302.       port->msgFlags = 0;
  303.       /* clear port statistics */
  304.       port->rx_cfg_bpdu_cnt =
  305.       port->rx_rstp_bpdu_cnt =
  306.       port->rx_tcn_bpdu_cnt = 0;
  307.       
  308.     case DISABLED:
  309.       port->rcvdBpdu = port->rcvdRSTP = port->rcvdSTP = False;
  310.       port->updtInfo = port->proposing = False; /* In DISABLED */
  311.       port->agreed = port->proposed = False;
  312.       port->rcvdInfoWhile = 0;
  313.       port->infoIs = Disabled;
  314.       port->reselect = True;
  315.       port->selected = False;
  316.       break;
  317.     case ENABLED: /* IEEE 802.1y, 17.21, Z.14 */
  318.       STP_VECT_copy (&port->portPrio, &port->designPrio);
  319.       STP_copy_times (&port->portTimes, &port->designTimes);
  320.       break;
  321.     case AGED:
  322.       port->infoIs = Aged;
  323.       port->reselect = True;
  324.       port->selected = False;
  325.       break;
  326.     case UPDATE:
  327.       STP_VECT_copy (&port->portPrio, &port->designPrio);
  328.       STP_copy_times (&port->portTimes, &port->designTimes);
  329.       port->updtInfo = False;
  330.       port->agreed = port->synced = False; /* In UPDATE */
  331.       port->proposed = port->proposing = False; /* in UPDATE */
  332.       port->infoIs = Mine;
  333.       port->newInfo = True;
  334. #ifdef STP_DBG
  335.       if (this->debug) {
  336.         STP_VECT_br_id_print ("updated: portPrio.design_bridge",
  337.                             &port->portPrio.design_bridge, True);
  338.       }
  339. #endif
  340.       break;
  341.     case CURRENT:
  342.       break;
  343.     case RECEIVE:
  344.       port->rcvdMsg = rcvBpdu (this);
  345.       updtBPDUVersion (this);
  346.       setTcFlags (this);
  347.       port->rcvdBpdu = False;
  348.       break;
  349.     case SUPERIOR:
  350.       STP_VECT_copy (&port->portPrio, &port->msgPrio);
  351.       STP_copy_times (&port->portTimes, &port->msgTimes);
  352.       updtRcvdInfoWhile (this);
  353. #if 1 /* due 802.1y, Z.7 */
  354.       port->agreed = False; /* deleted due 802.y in SUPERIOR */
  355.       port->synced = False; /* due 802.y deleted in SUPERIOR */
  356. #endif
  357.       port->proposing = False; /* in SUPERIOR */
  358.       port->proposed = recordProposed (this, "SUPERIOR");
  359.       port->infoIs = Received;
  360.       port->reselect = True;
  361.       port->selected = False;
  362. #ifdef STP_DBG
  363.       if (this->debug) {
  364.         STP_VECT_br_id_print ("stored: portPrio.design_bridge",
  365.                             &port->portPrio.design_bridge, True);
  366.         stp_trace ("proposed=%d on port %s",
  367.                    (int) port->proposed, port->port_name);
  368.       }
  369. #endif
  370.       break;
  371.     case REPEAT:
  372.       port->proposed = recordProposed (this, "REPEAT");
  373.       updtRcvdInfoWhile (this);
  374.       break;
  375.   case AGREEMENT:
  376. #ifdef STP_DBG
  377.       if (port->roletrns->debug) {
  378.         stp_trace ("(%s-%s) rx AGREEMENT flag !",
  379.             port->owner->name, port->port_name);
  380.       }
  381. #endif
  382.       
  383.       port->agreed = True;
  384.       port->proposing = False; /* In AGREEMENT */
  385.       break;
  386.   }
  387. }
  388. Bool STP_info_check_conditions (STATE_MACH_T* this)
  389. {
  390.   register PORT_T* port = this->owner.port;
  391.   if ((! port->portEnabled && port->infoIs != Disabled) || BEGIN == this->State) {
  392.     return STP_hop_2_state (this, DISABLED);
  393.   }
  394.   switch (this->State) {
  395.     case DISABLED:
  396.       if (port->updtInfo) {
  397.         return STP_hop_2_state (this, DISABLED);
  398.       }
  399.       if (port->portEnabled && port->selected) {
  400.         return STP_hop_2_state (this, ENABLED);
  401.       }
  402.       if (port->rcvdBpdu) {
  403.         return STP_hop_2_state (this, DISABLED);
  404.       }
  405.       break; 
  406.     case ENABLED: /* IEEE 802.1y, 17.21, Z.14 */
  407.       return STP_hop_2_state (this, AGED);
  408.       break; 
  409.     case AGED:
  410.       if (port->selected && port->updtInfo) {
  411.         return STP_hop_2_state (this, UPDATE);
  412.       }
  413.       break;
  414.     case UPDATE:
  415.       return STP_hop_2_state (this, CURRENT);
  416.       break;
  417.     case CURRENT:
  418.       if (port->selected && port->updtInfo) {
  419.         return STP_hop_2_state (this, UPDATE);
  420.       }
  421.       if (Received == port->infoIs       &&
  422.           ! port->rcvdInfoWhile &&
  423.           ! port->updtInfo               &&
  424.           ! port->rcvdBpdu) {
  425.         return STP_hop_2_state (this, AGED);
  426.       }
  427.       if (port->rcvdBpdu && !port->updtInfo) {
  428.         return STP_hop_2_state (this, RECEIVE);
  429.       }
  430.       break;
  431.     case RECEIVE:
  432.       switch (port->rcvdMsg) {
  433.         case SuperiorDesignateMsg:
  434.           return STP_hop_2_state (this, SUPERIOR);
  435.         case RepeatedDesignateMsg:
  436.           return STP_hop_2_state (this, REPEAT);
  437.         case ConfirmedRootMsg:
  438.           return STP_hop_2_state (this, AGREEMENT);
  439.         default:
  440.           return STP_hop_2_state (this, CURRENT);
  441.       }
  442.       break;
  443.     case SUPERIOR:
  444.       return STP_hop_2_state (this, CURRENT);
  445.       break;
  446.     case REPEAT:
  447.       return STP_hop_2_state (this, CURRENT);
  448.       break;
  449.     case AGREEMENT:
  450.       return STP_hop_2_state (this, CURRENT);
  451.       break;
  452.   }
  453.   return False;
  454. }