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

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 Selection state machine : 17.22 */
  23. #include "base.h"
  24. #include "stpm.h"
  25. #define STATES { 
  26.   CHOOSE(INIT_BRIDGE),      
  27.   CHOOSE(ROLE_SELECTION),   
  28. }
  29. #define GET_STATE_NAME STP_rolesel_get_state_name
  30. #include "choose.h"
  31. #ifdef STP_DBG
  32. void stp_dbg_break_point (PORT_T * port, STPM_T* stpm)
  33. {
  34. }
  35. #endif
  36. static Bool
  37. _is_backup_port (PORT_T* port, STPM_T* this)
  38. {
  39.   if (!STP_VECT_compare_bridge_id
  40.       (&port->portPrio.design_bridge, &this->BrId)) {
  41. #if 0 /* def STP_DBG */
  42.     if (port->info->debug) {
  43.       STP_VECT_br_id_print ("portPrio.design_bridge",
  44.                             &port->portPrio.design_bridge, True);
  45.       STP_VECT_br_id_print ("            this->BrId",
  46.                             &this->BrId, True);
  47.     }
  48.     stp_dbg_break_point (port, this);
  49. #endif
  50.     return True;
  51.   } else {
  52.     return False;
  53.   }
  54. }
  55. static void
  56. setRoleSelected (char* reason, STPM_T* stpm, PORT_T* port,
  57.                 PORT_ROLE_T newRole)
  58. {
  59.   char* new_role_name;
  60.   port->selectedRole = newRole;
  61.   if (newRole == port->role)
  62.     return;
  63.   switch (newRole) {
  64.     case DisabledPort:
  65.       new_role_name = "Disabled";
  66.       break;
  67.     case AlternatePort:
  68.       new_role_name = "Alternate";
  69.       break;
  70.     case BackupPort:
  71.       new_role_name = "Backup";
  72.       break;
  73.     case RootPort:
  74.       new_role_name = "Root";
  75.       break;
  76.     case DesignatedPort:
  77.       new_role_name = "Designated";
  78.       break;
  79.     case NonStpPort:
  80.       new_role_name = "NonStp";
  81.       port->role = newRole;
  82.       break;
  83.     default:
  84.       stp_trace ("%s-%s:port %s => Unknown (%d ?)",
  85.                  reason, stpm->name, port->port_name, (int) newRole);
  86.       return;
  87.   }
  88. #ifdef STP_DBG
  89.   if (port->roletrns->debug)
  90.     stp_trace ("%s(%s-%s) => %s",
  91.                reason, stpm->name, port->port_name, new_role_name);
  92. #endif
  93. }
  94. static void
  95. updtRoleDisableBridge (STPM_T* this)
  96. {               /* 17.10.20 */
  97.   register PORT_T *port;
  98.   for (port = this->ports; port; port = port->next) {
  99.     port->selectedRole = DisabledPort;
  100.   }
  101. }
  102. static void
  103. clearReselectBridge (STPM_T* this)
  104. {               /* 17.19.1 */
  105.   register PORT_T *port;
  106.   for (port = this->ports; port; port = port->next) {
  107.     port->reselect = False;
  108.   }
  109. }
  110. static void
  111. updtRootPrio (STATE_MACH_T* this)
  112. {
  113.   PRIO_VECTOR_T rootPathPrio;   /* 17.4.2.2 */
  114.   register PORT_T *port;
  115.   register STPM_T *stpm;
  116.   register unsigned int dm;
  117.   stpm = this->owner.stpm;
  118.   for (port = stpm->ports; port; port = port->next) {
  119.     if (port->admin_non_stp) {
  120.       continue;
  121.     }
  122.     if (Disabled == port->infoIs)
  123.       continue;
  124.     if (Aged == port->infoIs)
  125.       continue;
  126.     if (Mine == port->infoIs) {
  127. #if 0 /* def STP_DBG */
  128.       stp_dbg_break_point (port); /* for debugger break point */
  129. #endif
  130.       continue;
  131.     }
  132.     STP_VECT_copy (&rootPathPrio, &port->portPrio);
  133.     rootPathPrio.root_path_cost += port->operPCost;
  134.     if (STP_VECT_compare_vector (&rootPathPrio, &stpm->rootPrio) < 0) {
  135.       STP_VECT_copy (&stpm->rootPrio, &rootPathPrio);
  136.       STP_copy_times (&stpm->rootTimes, &port->portTimes);
  137.       dm = (8 +  stpm->rootTimes.MaxAge) / 16;
  138.       if (!dm)
  139.         dm = 1;
  140.       stpm->rootTimes.MessageAge += dm;
  141. #ifdef STP_DBG
  142.       if (port->roletrns->debug)
  143.           stp_trace ("updtRootPrio: dm=%d rootTimes.MessageAge=%d on port %s",
  144.                  (int) dm, (int) stpm->rootTimes.MessageAge,
  145.                  port->port_name);
  146. #endif
  147.     }
  148.   }
  149. }
  150. static void
  151. updtRolesBridge (STATE_MACH_T* this)
  152. {               /* 17.19.21 */
  153.   register PORT_T* port;
  154.   register STPM_T* stpm;
  155.   PORT_ID old_root_port; /* for tracing of root port changing */
  156.   stpm = this->owner.stpm;
  157.   old_root_port = stpm->rootPortId;
  158.   STP_VECT_create (&stpm->rootPrio, &stpm->BrId, 0, &stpm->BrId, 0, 0);
  159.   STP_copy_times (&stpm->rootTimes, &stpm->BrTimes);
  160.   stpm->rootPortId = 0;
  161.   updtRootPrio (this);
  162.   for (port = stpm->ports; port; port = port->next) {
  163.     if (port->admin_non_stp) {
  164.       continue;
  165.     }
  166.     STP_VECT_create (&port->designPrio,
  167.              &stpm->rootPrio.root_bridge,
  168.              stpm->rootPrio.root_path_cost,
  169.              &stpm->BrId, port->port_id, port->port_id);
  170.     STP_copy_times (&port->designTimes, &stpm->rootTimes);
  171. #if 0
  172. #ifdef STP_DBG
  173.     if (port->roletrns->debug) {
  174.       STP_VECT_br_id_print ("ch:designPrio.design_bridge",
  175.                             &port->designPrio.design_bridge, True);
  176.     }
  177. #endif
  178. #endif
  179.   }
  180.   stpm->rootPortId = stpm->rootPrio.bridge_port;
  181. #ifdef STP_DBG
  182.   if (old_root_port != stpm->rootPortId) {
  183.     if (! stpm->rootPortId) {
  184.       stp_trace ("nbrige %s became root", stpm->name);
  185.     } else {
  186.       stp_trace ("nbrige %s new root port: %s",
  187.         stpm->name,
  188.         STP_stpm_get_port_name_by_id (stpm, stpm->rootPortId));
  189.     }
  190.   }
  191. #endif
  192.   for (port = stpm->ports; port; port = port->next) {
  193.     if (port->admin_non_stp) {
  194.       setRoleSelected ("Non", stpm, port, NonStpPort);
  195.       port->forward = port->learn = True;
  196.       continue;
  197.     }
  198.     switch (port->infoIs) {
  199.       case Disabled:
  200.         setRoleSelected ("Dis", stpm, port, DisabledPort);
  201.         break;
  202.       case Aged:
  203.         setRoleSelected ("Age", stpm, port, DesignatedPort);
  204.         port->updtInfo = True;
  205.         break;
  206.       case Mine:
  207.         setRoleSelected ("Mine", stpm, port, DesignatedPort);
  208.         if (0 != STP_VECT_compare_vector (&port->portPrio,
  209.                       &port->designPrio) ||
  210.             0 != STP_compare_times (&port->portTimes,
  211.                   &port->designTimes)) {
  212.             port->updtInfo = True;
  213.         }
  214.         break;
  215.       case Received:
  216.         if (stpm->rootPortId == port->port_id) {
  217.           setRoleSelected ("Rec", stpm, port, RootPort);
  218.         } else if (STP_VECT_compare_vector (&port->designPrio, &port->portPrio) < 0) {
  219.           /* Note: this important piece has been inserted after
  220.            * discussion with Mick Sieman and reading 802.1y Z1 */
  221.           setRoleSelected ("Rec", stpm, port, DesignatedPort);
  222.           port->updtInfo = True;
  223.           break;
  224.         } else {
  225.           if (_is_backup_port (port, stpm)) {
  226.             setRoleSelected ("rec", stpm, port, BackupPort);
  227.           } else {
  228.             setRoleSelected ("rec", stpm, port, AlternatePort);
  229.           }
  230.         }
  231.         port->updtInfo = False;
  232.         break;
  233.       default:
  234.         stp_trace ("undef infoIs=%d", (int) port->infoIs);
  235.         break;
  236.     }
  237.   }
  238. }
  239. static Bool
  240. setSelectedBridge (STPM_T* this)
  241. {
  242.   register PORT_T* port;
  243.   for (port = this->ports; port; port = port->next) {
  244.     if (port->reselect) {
  245. #ifdef STP_DBG
  246.       stp_trace ("setSelectedBridge: TRUE=reselect on port %s", port->port_name);
  247. #endif
  248.       return False;
  249.     }
  250.   }
  251.   for (port = this->ports; port; port = port->next) {
  252.     port->selected = True;
  253.   }
  254.   return True;
  255. }
  256. void
  257. STP_rolesel_enter_state (STATE_MACH_T* this)
  258. {
  259.   STPM_T* stpm;
  260.   stpm = this->owner.stpm;
  261.   switch (this->State) {
  262.     case BEGIN:
  263.     case INIT_BRIDGE:
  264.       updtRoleDisableBridge (stpm);
  265.       break;
  266.     case ROLE_SELECTION:
  267.       clearReselectBridge (stpm);
  268.       updtRolesBridge (this);
  269.       setSelectedBridge (stpm);
  270.       break;
  271.   }
  272. }
  273. Bool
  274. STP_rolesel_check_conditions (STATE_MACH_T* s)
  275. {
  276.   STPM_T* stpm;
  277.   register PORT_T* port;
  278.   if (BEGIN == s->State) {
  279.     STP_hop_2_state (s, INIT_BRIDGE);
  280.   }
  281.   switch (s->State) {
  282.     case BEGIN:
  283.       return STP_hop_2_state (s, INIT_BRIDGE);
  284.     case INIT_BRIDGE:
  285.       return STP_hop_2_state (s, ROLE_SELECTION);
  286.     case ROLE_SELECTION:
  287.       stpm = s->owner.stpm;
  288.       for (port = stpm->ports; port; port = port->next) {
  289.         if (port->reselect) {
  290.           /* stp_trace ("reselect on port %s", port->port_name); */
  291.           return STP_hop_2_state (s, ROLE_SELECTION);
  292.         }
  293.       }
  294.       break;
  295.   }
  296.   return False;
  297. }
  298. void
  299. STP_rolesel_update_stpm (STPM_T* this)
  300. {
  301.   register PORT_T* port;
  302.   PRIO_VECTOR_T rootPathPrio;   /* 17.4.2.2 */
  303.   stp_trace ("%s", "??? STP_rolesel_update_stpm ???");
  304.   STP_VECT_create (&rootPathPrio, &this->BrId, 0, &this->BrId, 0, 0);
  305.   if (!this->rootPortId ||
  306.       STP_VECT_compare_vector (&rootPathPrio, &this->rootPrio) < 0) {
  307.     STP_VECT_copy (&this->rootPrio, &rootPathPrio);
  308.   }
  309.   for (port = this->ports; port; port = port->next) {
  310.     STP_VECT_create (&port->designPrio,
  311.              &this->rootPrio.root_bridge,
  312.              this->rootPrio.root_path_cost,
  313.              &this->BrId, port->port_id, port->port_id);
  314.     if (Received != port->infoIs || this->rootPortId == port->port_id) {
  315.       STP_VECT_copy (&port->portPrio, &port->designPrio);
  316.     }
  317.     port->reselect = True;
  318.     port->selected = False;
  319.   }
  320. }