1*55fea89dSDan Cross /************************************************************************
2*55fea89dSDan Cross  * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
3*55fea89dSDan Cross  * Copyright (C) 2001-2003 Optical Access
4*55fea89dSDan Cross  * Author: Alex Rozin
5*55fea89dSDan Cross  *
6*55fea89dSDan Cross  * This file is part of RSTP library.
7*55fea89dSDan Cross  *
8*55fea89dSDan Cross  * RSTP library is free software; you can redistribute it and/or modify it
9*55fea89dSDan Cross  * under the terms of the GNU Lesser General Public License as published by the
10*55fea89dSDan Cross  * Free Software Foundation; version 2.1
11*55fea89dSDan Cross  *
12*55fea89dSDan Cross  * RSTP library is distributed in the hope that it will be useful, but
13*55fea89dSDan Cross  * WITHOUT ANY WARRANTY; without even the implied warranty of
14*55fea89dSDan Cross  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
15*55fea89dSDan Cross  * General Public License for more details.
16*55fea89dSDan Cross  *
17*55fea89dSDan Cross  * You should have received a copy of the GNU Lesser General Public License
18*55fea89dSDan Cross  * along with RSTP library; see the file COPYING.  If not, write to the Free
19*55fea89dSDan Cross  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20*55fea89dSDan Cross  * 02111-1307, USA.
214eaa4710SRishi Srivatsavai  **********************************************************************/
224eaa4710SRishi Srivatsavai 
234eaa4710SRishi Srivatsavai /* Port Role Selection state machine : 17.22 */
244eaa4710SRishi Srivatsavai 
254eaa4710SRishi Srivatsavai #include "base.h"
264eaa4710SRishi Srivatsavai #include "stpm.h"
274eaa4710SRishi Srivatsavai #include "stp_vectors.h"
284eaa4710SRishi Srivatsavai 
294eaa4710SRishi Srivatsavai #define STATES { \
304eaa4710SRishi Srivatsavai   CHOOSE(INIT_BRIDGE),      \
314eaa4710SRishi Srivatsavai   CHOOSE(ROLE_SELECTION)   \
324eaa4710SRishi Srivatsavai }
334eaa4710SRishi Srivatsavai 
344eaa4710SRishi Srivatsavai #define GET_STATE_NAME STP_rolesel_get_state_name
354eaa4710SRishi Srivatsavai #include "choose.h"
364eaa4710SRishi Srivatsavai 
374eaa4710SRishi Srivatsavai #if 0
384eaa4710SRishi Srivatsavai void stp_dbg_break_point (PORT_T * port, STPM_T* stpm)
394eaa4710SRishi Srivatsavai {
404eaa4710SRishi Srivatsavai }
414eaa4710SRishi Srivatsavai #endif
424eaa4710SRishi Srivatsavai 
434eaa4710SRishi Srivatsavai static Bool
_is_backup_port(PORT_T * port,STPM_T * this)444eaa4710SRishi Srivatsavai _is_backup_port (PORT_T* port, STPM_T* this)
454eaa4710SRishi Srivatsavai {
464eaa4710SRishi Srivatsavai   if (!STP_VECT_compare_bridge_id
474eaa4710SRishi Srivatsavai       (&port->portPrio.design_bridge, &this->BrId)) {
484eaa4710SRishi Srivatsavai #if 0 /* def STP_DBG */
494eaa4710SRishi Srivatsavai     if (port->info->debug) {
504eaa4710SRishi Srivatsavai       STP_VECT_br_id_print ("portPrio.design_bridge",
514eaa4710SRishi Srivatsavai                             &port->portPrio.design_bridge, True);
524eaa4710SRishi Srivatsavai       STP_VECT_br_id_print ("            this->BrId",
534eaa4710SRishi Srivatsavai                             &this->BrId, True);
544eaa4710SRishi Srivatsavai     }
554eaa4710SRishi Srivatsavai     stp_dbg_break_point (port, this);
564eaa4710SRishi Srivatsavai #endif
574eaa4710SRishi Srivatsavai     return True;
584eaa4710SRishi Srivatsavai   } else {
594eaa4710SRishi Srivatsavai     return False;
604eaa4710SRishi Srivatsavai   }
614eaa4710SRishi Srivatsavai }
624eaa4710SRishi Srivatsavai 
634eaa4710SRishi Srivatsavai /* ARGSUSED */
644eaa4710SRishi Srivatsavai static void
setRoleSelected(char * reason,STPM_T * stpm,PORT_T * port,PORT_ROLE_T newRole)654eaa4710SRishi Srivatsavai setRoleSelected (char* reason, STPM_T* stpm, PORT_T* port,
664eaa4710SRishi Srivatsavai                 PORT_ROLE_T newRole)
674eaa4710SRishi Srivatsavai {
684eaa4710SRishi Srivatsavai #ifdef STP_DBG
694eaa4710SRishi Srivatsavai   char* new_role_name;
704eaa4710SRishi Srivatsavai #endif
714eaa4710SRishi Srivatsavai 
724eaa4710SRishi Srivatsavai   port->selectedRole = newRole;
734eaa4710SRishi Srivatsavai 
744eaa4710SRishi Srivatsavai   if (newRole == port->role)
754eaa4710SRishi Srivatsavai     return;
764eaa4710SRishi Srivatsavai 
774eaa4710SRishi Srivatsavai   switch (newRole) {
784eaa4710SRishi Srivatsavai     case DisabledPort:
794eaa4710SRishi Srivatsavai #ifdef STP_DBG
804eaa4710SRishi Srivatsavai       new_role_name = "Disabled";
814eaa4710SRishi Srivatsavai #endif
824eaa4710SRishi Srivatsavai       break;
834eaa4710SRishi Srivatsavai     case AlternatePort:
844eaa4710SRishi Srivatsavai #ifdef STP_DBG
854eaa4710SRishi Srivatsavai       new_role_name = "Alternate";
864eaa4710SRishi Srivatsavai #endif
874eaa4710SRishi Srivatsavai       break;
884eaa4710SRishi Srivatsavai     case BackupPort:
894eaa4710SRishi Srivatsavai #ifdef STP_DBG
904eaa4710SRishi Srivatsavai       new_role_name = "Backup";
914eaa4710SRishi Srivatsavai #endif
924eaa4710SRishi Srivatsavai       break;
934eaa4710SRishi Srivatsavai     case RootPort:
944eaa4710SRishi Srivatsavai #ifdef STP_DBG
954eaa4710SRishi Srivatsavai       new_role_name = "Root";
964eaa4710SRishi Srivatsavai #endif
974eaa4710SRishi Srivatsavai       break;
984eaa4710SRishi Srivatsavai     case DesignatedPort:
994eaa4710SRishi Srivatsavai #ifdef STP_DBG
1004eaa4710SRishi Srivatsavai       new_role_name = "Designated";
1014eaa4710SRishi Srivatsavai #endif
1024eaa4710SRishi Srivatsavai       break;
1034eaa4710SRishi Srivatsavai     case NonStpPort:
1044eaa4710SRishi Srivatsavai #ifdef STP_DBG
1054eaa4710SRishi Srivatsavai       new_role_name = "NonStp";
1064eaa4710SRishi Srivatsavai #endif
1074eaa4710SRishi Srivatsavai       port->role = newRole;
1084eaa4710SRishi Srivatsavai       break;
1094eaa4710SRishi Srivatsavai     default:
1104eaa4710SRishi Srivatsavai #ifdef STP_DBG
1114eaa4710SRishi Srivatsavai       stp_trace ("%s-%s:port %s => Unknown (%d ?)",
1124eaa4710SRishi Srivatsavai                  reason, stpm->name, port->port_name, (int) newRole);
1134eaa4710SRishi Srivatsavai #else
1144eaa4710SRishi Srivatsavai       abort();
1154eaa4710SRishi Srivatsavai #endif
1164eaa4710SRishi Srivatsavai       return;
1174eaa4710SRishi Srivatsavai   }
1184eaa4710SRishi Srivatsavai 
1194eaa4710SRishi Srivatsavai #ifdef STP_DBG
1204eaa4710SRishi Srivatsavai   if (port->roletrns->debug)
1214eaa4710SRishi Srivatsavai     stp_trace ("%s(%s-%s) => %s",
1224eaa4710SRishi Srivatsavai                reason, stpm->name, port->port_name, new_role_name);
1234eaa4710SRishi Srivatsavai #endif
1244eaa4710SRishi Srivatsavai }
1254eaa4710SRishi Srivatsavai 
1264eaa4710SRishi Srivatsavai static void
updtRoleDisableBridge(STPM_T * this)1274eaa4710SRishi Srivatsavai updtRoleDisableBridge (STPM_T* this)
1284eaa4710SRishi Srivatsavai {               /* 17.10.20 */
1294eaa4710SRishi Srivatsavai   register PORT_T *port;
1304eaa4710SRishi Srivatsavai 
1314eaa4710SRishi Srivatsavai   for (port = this->ports; port; port = port->next) {
1324eaa4710SRishi Srivatsavai     port->selectedRole = DisabledPort;
1334eaa4710SRishi Srivatsavai   }
1344eaa4710SRishi Srivatsavai }
1354eaa4710SRishi Srivatsavai 
1364eaa4710SRishi Srivatsavai static void
clearReselectBridge(STPM_T * this)1374eaa4710SRishi Srivatsavai clearReselectBridge (STPM_T* this)
1384eaa4710SRishi Srivatsavai {               /* 17.19.1 */
1394eaa4710SRishi Srivatsavai   register PORT_T *port;
1404eaa4710SRishi Srivatsavai 
1414eaa4710SRishi Srivatsavai   for (port = this->ports; port; port = port->next) {
1424eaa4710SRishi Srivatsavai     port->reselect = False;
1434eaa4710SRishi Srivatsavai   }
1444eaa4710SRishi Srivatsavai }
1454eaa4710SRishi Srivatsavai 
1464eaa4710SRishi Srivatsavai static void
updtRootPrio(STATE_MACH_T * this)1474eaa4710SRishi Srivatsavai updtRootPrio (STATE_MACH_T* this)
1484eaa4710SRishi Srivatsavai {
1494eaa4710SRishi Srivatsavai   PRIO_VECTOR_T rootPathPrio;   /* 17.4.2.2 */
1504eaa4710SRishi Srivatsavai   register PORT_T *port;
1514eaa4710SRishi Srivatsavai   register STPM_T *stpm;
1524eaa4710SRishi Srivatsavai   register unsigned int dm;
1534eaa4710SRishi Srivatsavai 
1544eaa4710SRishi Srivatsavai   stpm = this->owner.stpm;
1554eaa4710SRishi Srivatsavai 
1564eaa4710SRishi Srivatsavai   for (port = stpm->ports; port; port = port->next) {
1574eaa4710SRishi Srivatsavai     if (port->admin_non_stp) {
1584eaa4710SRishi Srivatsavai       continue;
1594eaa4710SRishi Srivatsavai     }
1604eaa4710SRishi Srivatsavai 
1614eaa4710SRishi Srivatsavai     if (Disabled == port->infoIs)
1624eaa4710SRishi Srivatsavai       continue;
1634eaa4710SRishi Srivatsavai     if (Aged == port->infoIs)
1644eaa4710SRishi Srivatsavai       continue;
1654eaa4710SRishi Srivatsavai     if (Mine == port->infoIs) {
1664eaa4710SRishi Srivatsavai #if 0 /* def STP_DBG */
1674eaa4710SRishi Srivatsavai       stp_dbg_break_point (port); /* for debugger break point */
1684eaa4710SRishi Srivatsavai #endif
1694eaa4710SRishi Srivatsavai       continue;
1704eaa4710SRishi Srivatsavai     }
1714eaa4710SRishi Srivatsavai 
1724eaa4710SRishi Srivatsavai     STP_VECT_copy (&rootPathPrio, &port->portPrio);
1734eaa4710SRishi Srivatsavai     rootPathPrio.root_path_cost += port->operPCost;
1744eaa4710SRishi Srivatsavai 
1754eaa4710SRishi Srivatsavai     if (STP_VECT_compare_vector (&rootPathPrio, &stpm->rootPrio) < 0) {
1764eaa4710SRishi Srivatsavai       STP_VECT_copy (&stpm->rootPrio, &rootPathPrio);
1774eaa4710SRishi Srivatsavai       STP_copy_times (&stpm->rootTimes, &port->portTimes);
1784eaa4710SRishi Srivatsavai       dm = (8 +  stpm->rootTimes.MaxAge) / 16;
1794eaa4710SRishi Srivatsavai       if (!dm)
1804eaa4710SRishi Srivatsavai         dm = 1;
1814eaa4710SRishi Srivatsavai       stpm->rootTimes.MessageAge += dm;
1824eaa4710SRishi Srivatsavai #ifdef STP_DBG
1834eaa4710SRishi Srivatsavai       if (port->roletrns->debug)
1844eaa4710SRishi Srivatsavai           stp_trace ("updtRootPrio: dm=%d rootTimes.MessageAge=%d on port %s",
1854eaa4710SRishi Srivatsavai                  (int) dm, (int) stpm->rootTimes.MessageAge,
1864eaa4710SRishi Srivatsavai                  port->port_name);
1874eaa4710SRishi Srivatsavai #endif
1884eaa4710SRishi Srivatsavai     }
1894eaa4710SRishi Srivatsavai   }
1904eaa4710SRishi Srivatsavai }
1914eaa4710SRishi Srivatsavai 
1924eaa4710SRishi Srivatsavai static void
updtRolesBridge(STATE_MACH_T * this)1934eaa4710SRishi Srivatsavai updtRolesBridge (STATE_MACH_T* this)
1944eaa4710SRishi Srivatsavai {               /* 17.19.21 */
1954eaa4710SRishi Srivatsavai   register PORT_T* port;
1964eaa4710SRishi Srivatsavai   register STPM_T* stpm;
1974eaa4710SRishi Srivatsavai #ifdef STP_DBG
1984eaa4710SRishi Srivatsavai   PORT_ID old_root_port; /* for tracing of root port changing */
1994eaa4710SRishi Srivatsavai #endif
2004eaa4710SRishi Srivatsavai 
2014eaa4710SRishi Srivatsavai   stpm = this->owner.stpm;
2024eaa4710SRishi Srivatsavai #ifdef STP_DBG
2034eaa4710SRishi Srivatsavai   old_root_port = stpm->rootPortId;
2044eaa4710SRishi Srivatsavai #endif
2054eaa4710SRishi Srivatsavai 
2064eaa4710SRishi Srivatsavai   STP_VECT_create (&stpm->rootPrio, &stpm->BrId, 0, &stpm->BrId, 0, 0);
2074eaa4710SRishi Srivatsavai   STP_copy_times (&stpm->rootTimes, &stpm->BrTimes);
2084eaa4710SRishi Srivatsavai   stpm->rootPortId = 0;
2094eaa4710SRishi Srivatsavai 
2104eaa4710SRishi Srivatsavai   updtRootPrio (this);
2114eaa4710SRishi Srivatsavai 
2124eaa4710SRishi Srivatsavai   for (port = stpm->ports; port; port = port->next) {
2134eaa4710SRishi Srivatsavai     if (port->admin_non_stp) {
2144eaa4710SRishi Srivatsavai       continue;
2154eaa4710SRishi Srivatsavai     }
2164eaa4710SRishi Srivatsavai     STP_VECT_create (&port->designPrio,
2174eaa4710SRishi Srivatsavai              &stpm->rootPrio.root_bridge,
2184eaa4710SRishi Srivatsavai              stpm->rootPrio.root_path_cost,
2194eaa4710SRishi Srivatsavai              &stpm->BrId, port->port_id, port->port_id);
2204eaa4710SRishi Srivatsavai     STP_copy_times (&port->designTimes, &stpm->rootTimes);
2214eaa4710SRishi Srivatsavai 
2224eaa4710SRishi Srivatsavai #if 0
2234eaa4710SRishi Srivatsavai #ifdef STP_DBG
2244eaa4710SRishi Srivatsavai     if (port->roletrns->debug) {
2254eaa4710SRishi Srivatsavai       STP_VECT_br_id_print ("ch:designPrio.design_bridge",
2264eaa4710SRishi Srivatsavai                             &port->designPrio.design_bridge, True);
2274eaa4710SRishi Srivatsavai     }
2284eaa4710SRishi Srivatsavai #endif
2294eaa4710SRishi Srivatsavai #endif
2304eaa4710SRishi Srivatsavai   }
2314eaa4710SRishi Srivatsavai 
2324eaa4710SRishi Srivatsavai   stpm->rootPortId = stpm->rootPrio.bridge_port;
2334eaa4710SRishi Srivatsavai 
2344eaa4710SRishi Srivatsavai #ifdef STP_DBG
2354eaa4710SRishi Srivatsavai   if (old_root_port != stpm->rootPortId) {
2364eaa4710SRishi Srivatsavai     if (! stpm->rootPortId) {
2374eaa4710SRishi Srivatsavai       stp_trace ("bridge %s became root", stpm->name);
2384eaa4710SRishi Srivatsavai     } else {
2394eaa4710SRishi Srivatsavai       stp_trace ("bridge %s new root port: %s",
2404eaa4710SRishi Srivatsavai         stpm->name,
2414eaa4710SRishi Srivatsavai         STP_stpm_get_port_name_by_id (stpm, stpm->rootPortId));
2424eaa4710SRishi Srivatsavai     }
2434eaa4710SRishi Srivatsavai   }
2444eaa4710SRishi Srivatsavai #endif
2454eaa4710SRishi Srivatsavai 
2464eaa4710SRishi Srivatsavai   for (port = stpm->ports; port; port = port->next) {
2474eaa4710SRishi Srivatsavai     if (port->admin_non_stp) {
2484eaa4710SRishi Srivatsavai       setRoleSelected ("Non", stpm, port, NonStpPort);
2494eaa4710SRishi Srivatsavai       port->forward = port->learn = True;
2504eaa4710SRishi Srivatsavai       continue;
2514eaa4710SRishi Srivatsavai     }
2524eaa4710SRishi Srivatsavai 
2534eaa4710SRishi Srivatsavai     switch (port->infoIs) {
2544eaa4710SRishi Srivatsavai       case Disabled:
2554eaa4710SRishi Srivatsavai         setRoleSelected ("Dis", stpm, port, DisabledPort);
2564eaa4710SRishi Srivatsavai         break;
2574eaa4710SRishi Srivatsavai       case Aged:
2584eaa4710SRishi Srivatsavai         setRoleSelected ("Age", stpm, port, DesignatedPort);
2594eaa4710SRishi Srivatsavai         port->updtInfo = True;
2604eaa4710SRishi Srivatsavai         break;
2614eaa4710SRishi Srivatsavai       case Mine:
2624eaa4710SRishi Srivatsavai         setRoleSelected ("Mine", stpm, port, DesignatedPort);
2634eaa4710SRishi Srivatsavai         if (0 != STP_VECT_compare_vector (&port->portPrio,
2644eaa4710SRishi Srivatsavai                       &port->designPrio) ||
2654eaa4710SRishi Srivatsavai             0 != STP_compare_times (&port->portTimes,
2664eaa4710SRishi Srivatsavai                   &port->designTimes)) {
2674eaa4710SRishi Srivatsavai             port->updtInfo = True;
2684eaa4710SRishi Srivatsavai         }
2694eaa4710SRishi Srivatsavai         break;
2704eaa4710SRishi Srivatsavai       case Received:
2714eaa4710SRishi Srivatsavai         if (stpm->rootPortId == port->port_id) {
2724eaa4710SRishi Srivatsavai           setRoleSelected ("Rec", stpm, port, RootPort);
2734eaa4710SRishi Srivatsavai         } else if (STP_VECT_compare_vector (&port->designPrio, &port->portPrio) < 0) {
2744eaa4710SRishi Srivatsavai           /* Note: this important piece has been inserted after
2754eaa4710SRishi Srivatsavai            * discussion with Mick Sieman and reading 802.1y Z1 */
2764eaa4710SRishi Srivatsavai           setRoleSelected ("Rec", stpm, port, DesignatedPort);
2774eaa4710SRishi Srivatsavai           port->updtInfo = True;
2784eaa4710SRishi Srivatsavai           break;
2794eaa4710SRishi Srivatsavai         } else {
2804eaa4710SRishi Srivatsavai           if (_is_backup_port (port, stpm)) {
2814eaa4710SRishi Srivatsavai             setRoleSelected ("rec", stpm, port, BackupPort);
2824eaa4710SRishi Srivatsavai           } else {
2834eaa4710SRishi Srivatsavai             setRoleSelected ("rec", stpm, port, AlternatePort);
2844eaa4710SRishi Srivatsavai           }
2854eaa4710SRishi Srivatsavai         }
2864eaa4710SRishi Srivatsavai         port->updtInfo = False;
2874eaa4710SRishi Srivatsavai         break;
2884eaa4710SRishi Srivatsavai       default:
2894eaa4710SRishi Srivatsavai         stp_trace ("undef infoIs=%d", (int) port->infoIs);
2904eaa4710SRishi Srivatsavai         break;
2914eaa4710SRishi Srivatsavai     }
2924eaa4710SRishi Srivatsavai   }
2934eaa4710SRishi Srivatsavai 
2944eaa4710SRishi Srivatsavai }
2954eaa4710SRishi Srivatsavai 
2964eaa4710SRishi Srivatsavai 
2974eaa4710SRishi Srivatsavai static Bool
setSelectedBridge(STPM_T * this)2984eaa4710SRishi Srivatsavai setSelectedBridge (STPM_T* this)
2994eaa4710SRishi Srivatsavai {
3004eaa4710SRishi Srivatsavai   register PORT_T* port;
3014eaa4710SRishi Srivatsavai 
3024eaa4710SRishi Srivatsavai   for (port = this->ports; port; port = port->next) {
3034eaa4710SRishi Srivatsavai     if (port->reselect) {
3044eaa4710SRishi Srivatsavai #ifdef STP_DBG
3054eaa4710SRishi Srivatsavai       stp_trace ("setSelectedBridge: TRUE=reselect on port %s", port->port_name);
3064eaa4710SRishi Srivatsavai #endif
3074eaa4710SRishi Srivatsavai       return False;
3084eaa4710SRishi Srivatsavai     }
3094eaa4710SRishi Srivatsavai   }
3104eaa4710SRishi Srivatsavai 
3114eaa4710SRishi Srivatsavai   for (port = this->ports; port; port = port->next) {
3124eaa4710SRishi Srivatsavai     port->selected = True;
3134eaa4710SRishi Srivatsavai   }
3144eaa4710SRishi Srivatsavai 
3154eaa4710SRishi Srivatsavai   return True;
3164eaa4710SRishi Srivatsavai }
3174eaa4710SRishi Srivatsavai 
3184eaa4710SRishi Srivatsavai void
STP_rolesel_enter_state(STATE_MACH_T * this)3194eaa4710SRishi Srivatsavai STP_rolesel_enter_state (STATE_MACH_T* this)
3204eaa4710SRishi Srivatsavai {
3214eaa4710SRishi Srivatsavai   STPM_T* stpm;
3224eaa4710SRishi Srivatsavai 
3234eaa4710SRishi Srivatsavai   stpm = this->owner.stpm;
3244eaa4710SRishi Srivatsavai 
3254eaa4710SRishi Srivatsavai   switch (this->State) {
3264eaa4710SRishi Srivatsavai     case BEGIN:
3274eaa4710SRishi Srivatsavai     case INIT_BRIDGE:
3284eaa4710SRishi Srivatsavai       updtRoleDisableBridge (stpm);
3294eaa4710SRishi Srivatsavai       break;
3304eaa4710SRishi Srivatsavai     case ROLE_SELECTION:
3314eaa4710SRishi Srivatsavai       clearReselectBridge (stpm);
3324eaa4710SRishi Srivatsavai       updtRolesBridge (this);
3334eaa4710SRishi Srivatsavai       (void) setSelectedBridge (stpm);
3344eaa4710SRishi Srivatsavai       break;
3354eaa4710SRishi Srivatsavai   }
3364eaa4710SRishi Srivatsavai }
3374eaa4710SRishi Srivatsavai 
3384eaa4710SRishi Srivatsavai Bool
STP_rolesel_check_conditions(STATE_MACH_T * s)3394eaa4710SRishi Srivatsavai STP_rolesel_check_conditions (STATE_MACH_T* s)
3404eaa4710SRishi Srivatsavai {
3414eaa4710SRishi Srivatsavai   STPM_T* stpm;
3424eaa4710SRishi Srivatsavai   register PORT_T* port;
3434eaa4710SRishi Srivatsavai 
3444eaa4710SRishi Srivatsavai   /*
3454eaa4710SRishi Srivatsavai    * This doesn't look right.  Why should we hop state twice in a single check
3464eaa4710SRishi Srivatsavai    * condition call?  It means we can never perform the enter-state action for
3474eaa4710SRishi Srivatsavai    * INIT_BRIDGE.
3484eaa4710SRishi Srivatsavai    */
3494eaa4710SRishi Srivatsavai #ifdef carlsonj_removed
3504eaa4710SRishi Srivatsavai   if (BEGIN == s->State) {
3514eaa4710SRishi Srivatsavai     (void) STP_hop_2_state (s, INIT_BRIDGE);
3524eaa4710SRishi Srivatsavai   }
3534eaa4710SRishi Srivatsavai #endif
3544eaa4710SRishi Srivatsavai 
3554eaa4710SRishi Srivatsavai   switch (s->State) {
3564eaa4710SRishi Srivatsavai     case BEGIN:
3574eaa4710SRishi Srivatsavai       return STP_hop_2_state (s, INIT_BRIDGE);
3584eaa4710SRishi Srivatsavai     case INIT_BRIDGE:
3594eaa4710SRishi Srivatsavai       return STP_hop_2_state (s, ROLE_SELECTION);
3604eaa4710SRishi Srivatsavai     case ROLE_SELECTION:
3614eaa4710SRishi Srivatsavai       stpm = s->owner.stpm;
3624eaa4710SRishi Srivatsavai       for (port = stpm->ports; port; port = port->next) {
3634eaa4710SRishi Srivatsavai         if (port->reselect) {
3644eaa4710SRishi Srivatsavai           /* stp_trace ("reselect on port %s", port->port_name); */
3654eaa4710SRishi Srivatsavai           return STP_hop_2_state (s, ROLE_SELECTION);
3664eaa4710SRishi Srivatsavai         }
3674eaa4710SRishi Srivatsavai       }
3684eaa4710SRishi Srivatsavai       break;
3694eaa4710SRishi Srivatsavai   }
3704eaa4710SRishi Srivatsavai 
3714eaa4710SRishi Srivatsavai   return False;
3724eaa4710SRishi Srivatsavai }
3734eaa4710SRishi Srivatsavai 
3744eaa4710SRishi Srivatsavai void
STP_rolesel_update_stpm(STPM_T * this)3754eaa4710SRishi Srivatsavai STP_rolesel_update_stpm (STPM_T* this)
3764eaa4710SRishi Srivatsavai {
3774eaa4710SRishi Srivatsavai   register PORT_T* port;
3784eaa4710SRishi Srivatsavai   PRIO_VECTOR_T rootPathPrio;   /* 17.4.2.2 */
3794eaa4710SRishi Srivatsavai 
3804eaa4710SRishi Srivatsavai   stp_trace ("%s", "??? STP_rolesel_update_stpm ???");
3814eaa4710SRishi Srivatsavai   STP_VECT_create (&rootPathPrio, &this->BrId, 0, &this->BrId, 0, 0);
3824eaa4710SRishi Srivatsavai 
3834eaa4710SRishi Srivatsavai   if (!this->rootPortId ||
3844eaa4710SRishi Srivatsavai       STP_VECT_compare_vector (&rootPathPrio, &this->rootPrio) < 0) {
3854eaa4710SRishi Srivatsavai     STP_VECT_copy (&this->rootPrio, &rootPathPrio);
3864eaa4710SRishi Srivatsavai   }
3874eaa4710SRishi Srivatsavai 
3884eaa4710SRishi Srivatsavai   for (port = this->ports; port; port = port->next) {
3894eaa4710SRishi Srivatsavai     STP_VECT_create (&port->designPrio,
3904eaa4710SRishi Srivatsavai              &this->rootPrio.root_bridge,
3914eaa4710SRishi Srivatsavai              this->rootPrio.root_path_cost,
3924eaa4710SRishi Srivatsavai              &this->BrId, port->port_id, port->port_id);
3934eaa4710SRishi Srivatsavai     if (Received != port->infoIs || this->rootPortId == port->port_id) {
3944eaa4710SRishi Srivatsavai       STP_VECT_copy (&port->portPrio, &port->designPrio);
3954eaa4710SRishi Srivatsavai     }
3964eaa4710SRishi Srivatsavai     port->reselect = True;
3974eaa4710SRishi Srivatsavai     port->selected = False;
3984eaa4710SRishi Srivatsavai   }
3994eaa4710SRishi Srivatsavai }
4004eaa4710SRishi Srivatsavai 
401