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 Transitions state machine : 17.24 */
24*55fea89dSDan Cross 
254eaa4710SRishi Srivatsavai #include "base.h"
264eaa4710SRishi Srivatsavai 
274eaa4710SRishi Srivatsavai #include "stpm.h"
284eaa4710SRishi Srivatsavai 
294eaa4710SRishi Srivatsavai #define STATES { \
304eaa4710SRishi Srivatsavai    CHOOSE(INIT_PORT),       \
314eaa4710SRishi Srivatsavai    CHOOSE(BLOCK_PORT),      \
324eaa4710SRishi Srivatsavai    CHOOSE(BLOCKED_PORT),    \
334eaa4710SRishi Srivatsavai    CHOOSE(BACKUP_PORT),     \
344eaa4710SRishi Srivatsavai    CHOOSE(ROOT_PROPOSED),   \
354eaa4710SRishi Srivatsavai    CHOOSE(ROOT_AGREED),     \
364eaa4710SRishi Srivatsavai    CHOOSE(REROOT),      \
374eaa4710SRishi Srivatsavai    CHOOSE(ROOT_PORT),       \
384eaa4710SRishi Srivatsavai    CHOOSE(REROOTED),        \
394eaa4710SRishi Srivatsavai    CHOOSE(ROOT_LEARN),      \
404eaa4710SRishi Srivatsavai    CHOOSE(ROOT_FORWARD),    \
414eaa4710SRishi Srivatsavai    CHOOSE(DESIGNATED_PROPOSE),  \
424eaa4710SRishi Srivatsavai    CHOOSE(DESIGNATED_SYNCED),   \
434eaa4710SRishi Srivatsavai    CHOOSE(DESIGNATED_RETIRED),  \
444eaa4710SRishi Srivatsavai    CHOOSE(DESIGNATED_PORT), \
454eaa4710SRishi Srivatsavai    CHOOSE(DESIGNATED_LISTEN),   \
464eaa4710SRishi Srivatsavai    CHOOSE(DESIGNATED_LEARN),    \
474eaa4710SRishi Srivatsavai    CHOOSE(DESIGNATED_FORWARD)  \
484eaa4710SRishi Srivatsavai }
494eaa4710SRishi Srivatsavai 
504eaa4710SRishi Srivatsavai #define GET_STATE_NAME STP_roletrns_get_state_name
514eaa4710SRishi Srivatsavai #include "choose.h"
524eaa4710SRishi Srivatsavai 
534eaa4710SRishi Srivatsavai static void
setSyncBridge(STATE_MACH_T * this)544eaa4710SRishi Srivatsavai setSyncBridge (STATE_MACH_T *this)
554eaa4710SRishi Srivatsavai {
564eaa4710SRishi Srivatsavai   register PORT_T* port;
574eaa4710SRishi Srivatsavai 
584eaa4710SRishi Srivatsavai   for (port = this->owner.port->owner->ports; port; port = port->next) {
594eaa4710SRishi Srivatsavai     port->sync = True; /* in ROOT_PROPOSED (setSyncBridge) */
604eaa4710SRishi Srivatsavai   }
614eaa4710SRishi Srivatsavai }
624eaa4710SRishi Srivatsavai 
634eaa4710SRishi Srivatsavai static void
setReRootBridge(STATE_MACH_T * this)644eaa4710SRishi Srivatsavai setReRootBridge (STATE_MACH_T *this)
654eaa4710SRishi Srivatsavai {
664eaa4710SRishi Srivatsavai   register PORT_T* port;
674eaa4710SRishi Srivatsavai 
684eaa4710SRishi Srivatsavai   for (port = this->owner.port->owner->ports; port; port = port->next) {
694eaa4710SRishi Srivatsavai     port->reRoot = True; /* In setReRootBridge */
704eaa4710SRishi Srivatsavai   }
714eaa4710SRishi Srivatsavai }
724eaa4710SRishi Srivatsavai 
734eaa4710SRishi Srivatsavai static Bool
compute_all_synced(PORT_T * this)744eaa4710SRishi Srivatsavai compute_all_synced (PORT_T* this)
754eaa4710SRishi Srivatsavai {
764eaa4710SRishi Srivatsavai   register PORT_T* port;
774eaa4710SRishi Srivatsavai 
784eaa4710SRishi Srivatsavai   for (port = this->owner->ports; port; port = port->next) {
794eaa4710SRishi Srivatsavai     if (port->port_index == this->port_index) continue;
804eaa4710SRishi Srivatsavai     if (! port->synced) {
814eaa4710SRishi Srivatsavai         return False;
824eaa4710SRishi Srivatsavai     }
834eaa4710SRishi Srivatsavai   }
844eaa4710SRishi Srivatsavai 
854eaa4710SRishi Srivatsavai   return True;
864eaa4710SRishi Srivatsavai }
874eaa4710SRishi Srivatsavai 
884eaa4710SRishi Srivatsavai static Bool
compute_re_rooted(PORT_T * this)894eaa4710SRishi Srivatsavai compute_re_rooted (PORT_T* this)
904eaa4710SRishi Srivatsavai {
914eaa4710SRishi Srivatsavai   register PORT_T* port;
924eaa4710SRishi Srivatsavai 
934eaa4710SRishi Srivatsavai   for (port = this->owner->ports; port; port = port->next) {
944eaa4710SRishi Srivatsavai     if (port->port_index == this->port_index) continue;
954eaa4710SRishi Srivatsavai     if (port->rrWhile) {
964eaa4710SRishi Srivatsavai       return False;
974eaa4710SRishi Srivatsavai     }
984eaa4710SRishi Srivatsavai   }
994eaa4710SRishi Srivatsavai   return True;
1004eaa4710SRishi Srivatsavai }
1014eaa4710SRishi Srivatsavai 
1024eaa4710SRishi Srivatsavai void
STP_roletrns_enter_state(STATE_MACH_T * this)1034eaa4710SRishi Srivatsavai STP_roletrns_enter_state (STATE_MACH_T* this)
1044eaa4710SRishi Srivatsavai {
1054eaa4710SRishi Srivatsavai   register PORT_T*           port = this->owner.port;
1064eaa4710SRishi Srivatsavai   register STPM_T*           stpm;
1074eaa4710SRishi Srivatsavai 
1084eaa4710SRishi Srivatsavai   stpm = port->owner;
1094eaa4710SRishi Srivatsavai 
1104eaa4710SRishi Srivatsavai   switch (this->State) {
1114eaa4710SRishi Srivatsavai     case BEGIN:
1124eaa4710SRishi Srivatsavai     case INIT_PORT:
1134eaa4710SRishi Srivatsavai #if 0 /* due 802.1y Z.4 */
1144eaa4710SRishi Srivatsavai       port->role = DisabledPort;
1154eaa4710SRishi Srivatsavai #else
1164eaa4710SRishi Srivatsavai       port->role = port->selectedRole = DisabledPort;
1174eaa4710SRishi Srivatsavai       port->reselect = True;
1184eaa4710SRishi Srivatsavai #endif
1194eaa4710SRishi Srivatsavai       port->synced = False; /* in INIT */
1204eaa4710SRishi Srivatsavai       port->sync = True; /* in INIT */
1214eaa4710SRishi Srivatsavai       port->reRoot = True; /* in INIT_PORT */
1224eaa4710SRishi Srivatsavai       port->rrWhile = stpm->rootTimes.ForwardDelay;
1234eaa4710SRishi Srivatsavai       port->fdWhile = stpm->rootTimes.ForwardDelay;
124*55fea89dSDan Cross       port->rbWhile = 0;
1254eaa4710SRishi Srivatsavai #ifdef STP_DBG
1264eaa4710SRishi Srivatsavai       if (this->debug)
1274eaa4710SRishi Srivatsavai         STP_port_trace_flags ("after init", port);
1284eaa4710SRishi Srivatsavai #endif
1294eaa4710SRishi Srivatsavai       break;
1304eaa4710SRishi Srivatsavai     case BLOCK_PORT:
1314eaa4710SRishi Srivatsavai       port->role = port->selectedRole;
1324eaa4710SRishi Srivatsavai       port->learn =
1334eaa4710SRishi Srivatsavai       port->forward = False;
1344eaa4710SRishi Srivatsavai       break;
1354eaa4710SRishi Srivatsavai     case BLOCKED_PORT:
1364eaa4710SRishi Srivatsavai       port->fdWhile = stpm->rootTimes.ForwardDelay;
1374eaa4710SRishi Srivatsavai       port->synced = True; /* In BLOCKED_PORT */
1384eaa4710SRishi Srivatsavai       port->rrWhile = 0;
1394eaa4710SRishi Srivatsavai       port->sync = port->reRoot = False; /* BLOCKED_PORT */
1404eaa4710SRishi Srivatsavai       break;
1414eaa4710SRishi Srivatsavai     case BACKUP_PORT:
1424eaa4710SRishi Srivatsavai       port->rbWhile = 2 * stpm->rootTimes.HelloTime;
1434eaa4710SRishi Srivatsavai       break;
1444eaa4710SRishi Srivatsavai 
1454eaa4710SRishi Srivatsavai     /* 17.23.2 */
1464eaa4710SRishi Srivatsavai     case ROOT_PROPOSED:
1474eaa4710SRishi Srivatsavai       setSyncBridge (this);
1484eaa4710SRishi Srivatsavai       port->proposed = False;
1494eaa4710SRishi Srivatsavai #ifdef STP_DBG
150*55fea89dSDan Cross       if (this->debug)
1514eaa4710SRishi Srivatsavai         STP_port_trace_flags ("ROOT_PROPOSED", port);
1524eaa4710SRishi Srivatsavai #endif
1534eaa4710SRishi Srivatsavai       break;
1544eaa4710SRishi Srivatsavai     case ROOT_AGREED:
1554eaa4710SRishi Srivatsavai       port->proposed = port->sync = False; /* in ROOT_AGREED */
1564eaa4710SRishi Srivatsavai       port->synced = True; /* In ROOT_AGREED */
1574eaa4710SRishi Srivatsavai       port->newInfo = True;
1584eaa4710SRishi Srivatsavai #ifdef STP_DBG
1594eaa4710SRishi Srivatsavai       if (this->debug)
1604eaa4710SRishi Srivatsavai         STP_port_trace_flags ("ROOT_AGREED", port);
1614eaa4710SRishi Srivatsavai #endif
1624eaa4710SRishi Srivatsavai       break;
1634eaa4710SRishi Srivatsavai     case REROOT:
1644eaa4710SRishi Srivatsavai       setReRootBridge (this);
1654eaa4710SRishi Srivatsavai #ifdef STP_DBG
1664eaa4710SRishi Srivatsavai       if (this->debug)
1674eaa4710SRishi Srivatsavai         STP_port_trace_flags ("REROOT", port);
1684eaa4710SRishi Srivatsavai #endif
1694eaa4710SRishi Srivatsavai       break;
1704eaa4710SRishi Srivatsavai     case ROOT_PORT:
1714eaa4710SRishi Srivatsavai       port->role = RootPort;
1724eaa4710SRishi Srivatsavai       port->rrWhile = stpm->rootTimes.ForwardDelay;
1734eaa4710SRishi Srivatsavai #ifdef STP_DBG
1744eaa4710SRishi Srivatsavai       if (this->debug)
1754eaa4710SRishi Srivatsavai         STP_port_trace_flags ("ROOT_PORT", port);
1764eaa4710SRishi Srivatsavai #endif
1774eaa4710SRishi Srivatsavai       break;
1784eaa4710SRishi Srivatsavai     case REROOTED:
1794eaa4710SRishi Srivatsavai       port->reRoot = False; /* In REROOTED */
1804eaa4710SRishi Srivatsavai #ifdef STP_DBG
1814eaa4710SRishi Srivatsavai       if (this->debug)
1824eaa4710SRishi Srivatsavai         STP_port_trace_flags ("REROOTED", port);
1834eaa4710SRishi Srivatsavai #endif
1844eaa4710SRishi Srivatsavai       break;
1854eaa4710SRishi Srivatsavai     case ROOT_LEARN:
1864eaa4710SRishi Srivatsavai       port->fdWhile = stpm->rootTimes.ForwardDelay;
1874eaa4710SRishi Srivatsavai       port->learn = True;
1884eaa4710SRishi Srivatsavai #ifdef STP_DBG
1894eaa4710SRishi Srivatsavai       if (this->debug)
1904eaa4710SRishi Srivatsavai         STP_port_trace_flags ("ROOT_LEARN", port);
1914eaa4710SRishi Srivatsavai #endif
1924eaa4710SRishi Srivatsavai       break;
1934eaa4710SRishi Srivatsavai     case ROOT_FORWARD:
1944eaa4710SRishi Srivatsavai       port->fdWhile = 0;
1954eaa4710SRishi Srivatsavai       port->forward = True;
1964eaa4710SRishi Srivatsavai #ifdef STP_DBG
1974eaa4710SRishi Srivatsavai       if (this->debug)
1984eaa4710SRishi Srivatsavai         STP_port_trace_flags ("ROOT_FORWARD", port);
1994eaa4710SRishi Srivatsavai #endif
2004eaa4710SRishi Srivatsavai       break;
2014eaa4710SRishi Srivatsavai 
2024eaa4710SRishi Srivatsavai     /* 17.23.3 */
2034eaa4710SRishi Srivatsavai     case DESIGNATED_PROPOSE:
2044eaa4710SRishi Srivatsavai       port->proposing = True; /* in DESIGNATED_PROPOSE */
2054eaa4710SRishi Srivatsavai       port->newInfo = True;
2064eaa4710SRishi Srivatsavai #ifdef STP_DBG
2074eaa4710SRishi Srivatsavai       if (this->debug)
2084eaa4710SRishi Srivatsavai         STP_port_trace_flags ("DESIGNATED_PROPOSE", port);
2094eaa4710SRishi Srivatsavai #endif
2104eaa4710SRishi Srivatsavai       break;
2114eaa4710SRishi Srivatsavai     case DESIGNATED_SYNCED:
2124eaa4710SRishi Srivatsavai       port->rrWhile = 0;
2134eaa4710SRishi Srivatsavai       port->synced = True; /* DESIGNATED_SYNCED */
2144eaa4710SRishi Srivatsavai       port->sync = False; /* DESIGNATED_SYNCED */
2154eaa4710SRishi Srivatsavai #ifdef STP_DBG
2164eaa4710SRishi Srivatsavai       if (this->debug)
2174eaa4710SRishi Srivatsavai         STP_port_trace_flags ("DESIGNATED_SYNCED", port);
2184eaa4710SRishi Srivatsavai #endif
2194eaa4710SRishi Srivatsavai       break;
2204eaa4710SRishi Srivatsavai     case DESIGNATED_RETIRED:
2214eaa4710SRishi Srivatsavai       port->reRoot = False; /* DESIGNATED_RETIRED */
2224eaa4710SRishi Srivatsavai #ifdef STP_DBG
2234eaa4710SRishi Srivatsavai       if (this->debug)
2244eaa4710SRishi Srivatsavai         STP_port_trace_flags ("DESIGNATED_RETIRED", port);
2254eaa4710SRishi Srivatsavai #endif
2264eaa4710SRishi Srivatsavai       break;
2274eaa4710SRishi Srivatsavai     case DESIGNATED_PORT:
2284eaa4710SRishi Srivatsavai       port->role = DesignatedPort;
2294eaa4710SRishi Srivatsavai #ifdef STP_DBG
2304eaa4710SRishi Srivatsavai       if (this->debug)
2314eaa4710SRishi Srivatsavai         STP_port_trace_flags ("DESIGNATED_PORT", port);
2324eaa4710SRishi Srivatsavai #endif
2334eaa4710SRishi Srivatsavai       break;
2344eaa4710SRishi Srivatsavai     case DESIGNATED_LISTEN:
2354eaa4710SRishi Srivatsavai       port->learn = port->forward = False;
2364eaa4710SRishi Srivatsavai       port->fdWhile = stpm->rootTimes.ForwardDelay;
2374eaa4710SRishi Srivatsavai #ifdef STP_DBG
2384eaa4710SRishi Srivatsavai       if (this->debug)
2394eaa4710SRishi Srivatsavai         STP_port_trace_flags ("DESIGNATED_LISTEN", port);
2404eaa4710SRishi Srivatsavai #endif
2414eaa4710SRishi Srivatsavai       break;
2424eaa4710SRishi Srivatsavai     case DESIGNATED_LEARN:
2434eaa4710SRishi Srivatsavai       port->learn = True;
2444eaa4710SRishi Srivatsavai       port->fdWhile = stpm->rootTimes.ForwardDelay;
2454eaa4710SRishi Srivatsavai #ifdef STP_DBG
2464eaa4710SRishi Srivatsavai       if (this->debug)
2474eaa4710SRishi Srivatsavai         STP_port_trace_flags ("DESIGNATED_LEARN", port);
2484eaa4710SRishi Srivatsavai #endif
2494eaa4710SRishi Srivatsavai       break;
2504eaa4710SRishi Srivatsavai     case DESIGNATED_FORWARD:
2514eaa4710SRishi Srivatsavai       port->forward = True;
2524eaa4710SRishi Srivatsavai       port->fdWhile = 0;
2534eaa4710SRishi Srivatsavai #ifdef STP_DBG
2544eaa4710SRishi Srivatsavai       if (this->debug)
2554eaa4710SRishi Srivatsavai         STP_port_trace_flags ("DESIGNATED_FORWARD", port);
2564eaa4710SRishi Srivatsavai #endif
2574eaa4710SRishi Srivatsavai       break;
2584eaa4710SRishi Srivatsavai   };
2594eaa4710SRishi Srivatsavai }
260*55fea89dSDan Cross 
2614eaa4710SRishi Srivatsavai Bool
STP_roletrns_check_conditions(STATE_MACH_T * this)2624eaa4710SRishi Srivatsavai STP_roletrns_check_conditions (STATE_MACH_T* this)
2634eaa4710SRishi Srivatsavai {
2644eaa4710SRishi Srivatsavai   register PORT_T           *port = this->owner.port;
2654eaa4710SRishi Srivatsavai   register STPM_T           *stpm;
2664eaa4710SRishi Srivatsavai   Bool                      allSynced;
2674eaa4710SRishi Srivatsavai   Bool                      allReRooted;
2684eaa4710SRishi Srivatsavai 
2694eaa4710SRishi Srivatsavai   stpm = port->owner;
2704eaa4710SRishi Srivatsavai 
2714eaa4710SRishi Srivatsavai   if (BEGIN == this->State) {
2724eaa4710SRishi Srivatsavai     return STP_hop_2_state (this, INIT_PORT);
2734eaa4710SRishi Srivatsavai   }
2744eaa4710SRishi Srivatsavai 
2754eaa4710SRishi Srivatsavai   if (port->role != port->selectedRole &&
2764eaa4710SRishi Srivatsavai       port->selected &&
2774eaa4710SRishi Srivatsavai       ! port->updtInfo) {
2784eaa4710SRishi Srivatsavai     switch (port->selectedRole) {
2794eaa4710SRishi Srivatsavai       case DisabledPort:
2804eaa4710SRishi Srivatsavai       case AlternatePort:
2814eaa4710SRishi Srivatsavai       case BackupPort:
2824eaa4710SRishi Srivatsavai #if 0 /* def STP_DBG */
2834eaa4710SRishi Srivatsavai         if (this->debug) {
2844eaa4710SRishi Srivatsavai           stp_trace ("hop to BLOCK_PORT role=%d selectedRole=%d",
2854eaa4710SRishi Srivatsavai                                 (int) port->role, (int) port->selectedRole);
2864eaa4710SRishi Srivatsavai         }
2874eaa4710SRishi Srivatsavai #endif
2884eaa4710SRishi Srivatsavai         return STP_hop_2_state (this, BLOCK_PORT);
2894eaa4710SRishi Srivatsavai       case RootPort:
2904eaa4710SRishi Srivatsavai         return STP_hop_2_state (this, ROOT_PORT);
2914eaa4710SRishi Srivatsavai       case DesignatedPort:
2924eaa4710SRishi Srivatsavai         return STP_hop_2_state (this, DESIGNATED_PORT);
2934eaa4710SRishi Srivatsavai       default:
2944eaa4710SRishi Srivatsavai         return False;
2954eaa4710SRishi Srivatsavai     }
2964eaa4710SRishi Srivatsavai   }
2974eaa4710SRishi Srivatsavai 
2984eaa4710SRishi Srivatsavai   switch (this->State) {
2994eaa4710SRishi Srivatsavai     /* 17.23.1 */
3004eaa4710SRishi Srivatsavai     case INIT_PORT:
3014eaa4710SRishi Srivatsavai       return STP_hop_2_state (this, BLOCK_PORT);
3024eaa4710SRishi Srivatsavai     case BLOCK_PORT:
3034eaa4710SRishi Srivatsavai       if (!port->selected || port->updtInfo) break;
3044eaa4710SRishi Srivatsavai       if (!port->learning && !port->forwarding) {
3054eaa4710SRishi Srivatsavai         return STP_hop_2_state (this, BLOCKED_PORT);
3064eaa4710SRishi Srivatsavai       }
3074eaa4710SRishi Srivatsavai       break;
3084eaa4710SRishi Srivatsavai     case BLOCKED_PORT:
3094eaa4710SRishi Srivatsavai       if (!port->selected || port->updtInfo) break;
3104eaa4710SRishi Srivatsavai       if (port->fdWhile != stpm->rootTimes.ForwardDelay ||
3114eaa4710SRishi Srivatsavai           port->sync                ||
3124eaa4710SRishi Srivatsavai           port->reRoot              ||
3134eaa4710SRishi Srivatsavai           !port->synced) {
3144eaa4710SRishi Srivatsavai         return STP_hop_2_state (this, BLOCKED_PORT);
3154eaa4710SRishi Srivatsavai       }
3164eaa4710SRishi Srivatsavai       if (port->rbWhile != 2 * stpm->rootTimes.HelloTime &&
3174eaa4710SRishi Srivatsavai           port->role == BackupPort) {
3184eaa4710SRishi Srivatsavai         return STP_hop_2_state (this, BACKUP_PORT);
3194eaa4710SRishi Srivatsavai       }
3204eaa4710SRishi Srivatsavai       break;
3214eaa4710SRishi Srivatsavai     case BACKUP_PORT:
3224eaa4710SRishi Srivatsavai       return STP_hop_2_state (this, BLOCKED_PORT);
3234eaa4710SRishi Srivatsavai 
3244eaa4710SRishi Srivatsavai     /* 17.23.2 */
3254eaa4710SRishi Srivatsavai     case ROOT_PROPOSED:
3264eaa4710SRishi Srivatsavai       return STP_hop_2_state (this, ROOT_PORT);
3274eaa4710SRishi Srivatsavai     case ROOT_AGREED:
3284eaa4710SRishi Srivatsavai       return STP_hop_2_state (this, ROOT_PORT);
3294eaa4710SRishi Srivatsavai     case REROOT:
3304eaa4710SRishi Srivatsavai       return STP_hop_2_state (this, ROOT_PORT);
3314eaa4710SRishi Srivatsavai     case ROOT_PORT:
3324eaa4710SRishi Srivatsavai       if (!port->selected || port->updtInfo) break;
3334eaa4710SRishi Srivatsavai       if (!port->forward && !port->reRoot) {
3344eaa4710SRishi Srivatsavai         return STP_hop_2_state (this, REROOT);
3354eaa4710SRishi Srivatsavai       }
3364eaa4710SRishi Srivatsavai       allSynced = compute_all_synced (port);
3374eaa4710SRishi Srivatsavai       if ((port->proposed && allSynced) ||
3384eaa4710SRishi Srivatsavai           (!port->synced && allSynced)) {
3394eaa4710SRishi Srivatsavai         return STP_hop_2_state (this, ROOT_AGREED);
3404eaa4710SRishi Srivatsavai       }
3414eaa4710SRishi Srivatsavai       if (port->proposed && !port->synced) {
3424eaa4710SRishi Srivatsavai         return STP_hop_2_state (this, ROOT_PROPOSED);
3434eaa4710SRishi Srivatsavai       }
3444eaa4710SRishi Srivatsavai 
3454eaa4710SRishi Srivatsavai       allReRooted = compute_re_rooted (port);
346*55fea89dSDan Cross       if ((!port->fdWhile ||
3474eaa4710SRishi Srivatsavai            ((allReRooted && !port->rbWhile) && stpm->ForceVersion >=2)) &&
3484eaa4710SRishi Srivatsavai           port->learn && !port->forward) {
3494eaa4710SRishi Srivatsavai         return STP_hop_2_state (this, ROOT_FORWARD);
3504eaa4710SRishi Srivatsavai       }
351*55fea89dSDan Cross       if ((!port->fdWhile ||
3524eaa4710SRishi Srivatsavai            ((allReRooted && !port->rbWhile) && stpm->ForceVersion >=2)) &&
3534eaa4710SRishi Srivatsavai           !port->learn) {
3544eaa4710SRishi Srivatsavai         return STP_hop_2_state (this, ROOT_LEARN);
3554eaa4710SRishi Srivatsavai       }
3564eaa4710SRishi Srivatsavai 
3574eaa4710SRishi Srivatsavai       if (port->reRoot && port->forward) {
3584eaa4710SRishi Srivatsavai         return STP_hop_2_state (this, REROOTED);
3594eaa4710SRishi Srivatsavai       }
3604eaa4710SRishi Srivatsavai       if (port->rrWhile != stpm->rootTimes.ForwardDelay) {
3614eaa4710SRishi Srivatsavai         return STP_hop_2_state (this, ROOT_PORT);
3624eaa4710SRishi Srivatsavai       }
3634eaa4710SRishi Srivatsavai       break;
3644eaa4710SRishi Srivatsavai     case REROOTED:
3654eaa4710SRishi Srivatsavai       return STP_hop_2_state (this, ROOT_PORT);
3664eaa4710SRishi Srivatsavai     case ROOT_LEARN:
3674eaa4710SRishi Srivatsavai       return STP_hop_2_state (this, ROOT_PORT);
3684eaa4710SRishi Srivatsavai     case ROOT_FORWARD:
3694eaa4710SRishi Srivatsavai       return STP_hop_2_state (this, ROOT_PORT);
3704eaa4710SRishi Srivatsavai 
3714eaa4710SRishi Srivatsavai     /* 17.23.3 */
3724eaa4710SRishi Srivatsavai     case DESIGNATED_PROPOSE:
3734eaa4710SRishi Srivatsavai       return STP_hop_2_state (this, DESIGNATED_PORT);
3744eaa4710SRishi Srivatsavai     case DESIGNATED_SYNCED:
3754eaa4710SRishi Srivatsavai       return STP_hop_2_state (this, DESIGNATED_PORT);
3764eaa4710SRishi Srivatsavai     case DESIGNATED_RETIRED:
3774eaa4710SRishi Srivatsavai       return STP_hop_2_state (this, DESIGNATED_PORT);
3784eaa4710SRishi Srivatsavai     case DESIGNATED_PORT:
3794eaa4710SRishi Srivatsavai       if (!port->selected || port->updtInfo) break;
3804eaa4710SRishi Srivatsavai 
3814eaa4710SRishi Srivatsavai       if (!port->forward && !port->agreed && !port->proposing && !port->operEdge) {
3824eaa4710SRishi Srivatsavai         return STP_hop_2_state (this, DESIGNATED_PROPOSE);
3834eaa4710SRishi Srivatsavai       }
3844eaa4710SRishi Srivatsavai 
3854eaa4710SRishi Srivatsavai       if (!port->rrWhile && port->reRoot) {
3864eaa4710SRishi Srivatsavai         return STP_hop_2_state (this, DESIGNATED_RETIRED);
3874eaa4710SRishi Srivatsavai       }
388*55fea89dSDan Cross 
3894eaa4710SRishi Srivatsavai       if (!port->learning && !port->forwarding && !port->synced) {
3904eaa4710SRishi Srivatsavai         return STP_hop_2_state (this, DESIGNATED_SYNCED);
3914eaa4710SRishi Srivatsavai       }
3924eaa4710SRishi Srivatsavai 
3934eaa4710SRishi Srivatsavai       if (port->agreed && !port->synced) {
3944eaa4710SRishi Srivatsavai         return STP_hop_2_state (this, DESIGNATED_SYNCED);
3954eaa4710SRishi Srivatsavai       }
3964eaa4710SRishi Srivatsavai       if (port->operEdge && !port->synced) {
3974eaa4710SRishi Srivatsavai         return STP_hop_2_state (this, DESIGNATED_SYNCED);
3984eaa4710SRishi Srivatsavai       }
3994eaa4710SRishi Srivatsavai       if (port->sync && port->synced) {
4004eaa4710SRishi Srivatsavai         return STP_hop_2_state (this, DESIGNATED_SYNCED);
4014eaa4710SRishi Srivatsavai       }
4024eaa4710SRishi Srivatsavai 
4034eaa4710SRishi Srivatsavai       if ((!port->fdWhile || port->agreed || port->operEdge) &&
4044eaa4710SRishi Srivatsavai           (!port->rrWhile  || !port->reRoot) &&
4054eaa4710SRishi Srivatsavai           !port->sync &&
4064eaa4710SRishi Srivatsavai           (port->learn && !port->forward)) {
4074eaa4710SRishi Srivatsavai         return STP_hop_2_state (this, DESIGNATED_FORWARD);
4084eaa4710SRishi Srivatsavai       }
4094eaa4710SRishi Srivatsavai       if ((!port->fdWhile || port->agreed || port->operEdge) &&
4104eaa4710SRishi Srivatsavai           (!port->rrWhile  || !port->reRoot) &&
4114eaa4710SRishi Srivatsavai           !port->sync && !port->learn) {
4124eaa4710SRishi Srivatsavai         return STP_hop_2_state (this, DESIGNATED_LEARN);
4134eaa4710SRishi Srivatsavai       }
4144eaa4710SRishi Srivatsavai       if (((port->sync && !port->synced) ||
4154eaa4710SRishi Srivatsavai            (port->reRoot && port->rrWhile)) &&
4164eaa4710SRishi Srivatsavai           !port->operEdge && (port->learn || port->forward)) {
4174eaa4710SRishi Srivatsavai         return STP_hop_2_state (this, DESIGNATED_LISTEN);
4184eaa4710SRishi Srivatsavai       }
4194eaa4710SRishi Srivatsavai       break;
4204eaa4710SRishi Srivatsavai     case DESIGNATED_LISTEN:
4214eaa4710SRishi Srivatsavai       return STP_hop_2_state (this, DESIGNATED_PORT);
4224eaa4710SRishi Srivatsavai     case DESIGNATED_LEARN:
4234eaa4710SRishi Srivatsavai       return STP_hop_2_state (this, DESIGNATED_PORT);
4244eaa4710SRishi Srivatsavai     case DESIGNATED_FORWARD:
4254eaa4710SRishi Srivatsavai       return STP_hop_2_state (this, DESIGNATED_PORT);
4264eaa4710SRishi Srivatsavai   };
4274eaa4710SRishi Srivatsavai 
4284eaa4710SRishi Srivatsavai   return False;
4294eaa4710SRishi Srivatsavai }
4304eaa4710SRishi Srivatsavai 
4314eaa4710SRishi Srivatsavai 
432