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