1*4eaa4710SRishi Srivatsavai /************************************************************************ 2*4eaa4710SRishi Srivatsavai * RSTP library - Rapid Spanning Tree (802.1t, 802.1w) 3*4eaa4710SRishi Srivatsavai * Copyright (C) 2001-2003 Optical Access 4*4eaa4710SRishi Srivatsavai * Author: Alex Rozin 5*4eaa4710SRishi Srivatsavai * 6*4eaa4710SRishi Srivatsavai * This file is part of RSTP library. 7*4eaa4710SRishi Srivatsavai * 8*4eaa4710SRishi Srivatsavai * RSTP library is free software; you can redistribute it and/or modify it 9*4eaa4710SRishi Srivatsavai * under the terms of the GNU Lesser General Public License as published by the 10*4eaa4710SRishi Srivatsavai * Free Software Foundation; version 2.1 11*4eaa4710SRishi Srivatsavai * 12*4eaa4710SRishi Srivatsavai * RSTP library is distributed in the hope that it will be useful, but 13*4eaa4710SRishi Srivatsavai * WITHOUT ANY WARRANTY; without even the implied warranty of 14*4eaa4710SRishi Srivatsavai * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 15*4eaa4710SRishi Srivatsavai * General Public License for more details. 16*4eaa4710SRishi Srivatsavai * 17*4eaa4710SRishi Srivatsavai * You should have received a copy of the GNU Lesser General Public License 18*4eaa4710SRishi Srivatsavai * along with RSTP library; see the file COPYING. If not, write to the Free 19*4eaa4710SRishi Srivatsavai * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 20*4eaa4710SRishi Srivatsavai * 02111-1307, USA. 21*4eaa4710SRishi Srivatsavai **********************************************************************/ 22*4eaa4710SRishi Srivatsavai 23*4eaa4710SRishi Srivatsavai /* Port Role Transitions state machine : 17.24 */ 24*4eaa4710SRishi Srivatsavai 25*4eaa4710SRishi Srivatsavai #include "base.h" 26*4eaa4710SRishi Srivatsavai 27*4eaa4710SRishi Srivatsavai #include "stpm.h" 28*4eaa4710SRishi Srivatsavai 29*4eaa4710SRishi Srivatsavai #define STATES { \ 30*4eaa4710SRishi Srivatsavai CHOOSE(INIT_PORT), \ 31*4eaa4710SRishi Srivatsavai CHOOSE(BLOCK_PORT), \ 32*4eaa4710SRishi Srivatsavai CHOOSE(BLOCKED_PORT), \ 33*4eaa4710SRishi Srivatsavai CHOOSE(BACKUP_PORT), \ 34*4eaa4710SRishi Srivatsavai CHOOSE(ROOT_PROPOSED), \ 35*4eaa4710SRishi Srivatsavai CHOOSE(ROOT_AGREED), \ 36*4eaa4710SRishi Srivatsavai CHOOSE(REROOT), \ 37*4eaa4710SRishi Srivatsavai CHOOSE(ROOT_PORT), \ 38*4eaa4710SRishi Srivatsavai CHOOSE(REROOTED), \ 39*4eaa4710SRishi Srivatsavai CHOOSE(ROOT_LEARN), \ 40*4eaa4710SRishi Srivatsavai CHOOSE(ROOT_FORWARD), \ 41*4eaa4710SRishi Srivatsavai CHOOSE(DESIGNATED_PROPOSE), \ 42*4eaa4710SRishi Srivatsavai CHOOSE(DESIGNATED_SYNCED), \ 43*4eaa4710SRishi Srivatsavai CHOOSE(DESIGNATED_RETIRED), \ 44*4eaa4710SRishi Srivatsavai CHOOSE(DESIGNATED_PORT), \ 45*4eaa4710SRishi Srivatsavai CHOOSE(DESIGNATED_LISTEN), \ 46*4eaa4710SRishi Srivatsavai CHOOSE(DESIGNATED_LEARN), \ 47*4eaa4710SRishi Srivatsavai CHOOSE(DESIGNATED_FORWARD) \ 48*4eaa4710SRishi Srivatsavai } 49*4eaa4710SRishi Srivatsavai 50*4eaa4710SRishi Srivatsavai #define GET_STATE_NAME STP_roletrns_get_state_name 51*4eaa4710SRishi Srivatsavai #include "choose.h" 52*4eaa4710SRishi Srivatsavai 53*4eaa4710SRishi Srivatsavai static void 54*4eaa4710SRishi Srivatsavai setSyncBridge (STATE_MACH_T *this) 55*4eaa4710SRishi Srivatsavai { 56*4eaa4710SRishi Srivatsavai register PORT_T* port; 57*4eaa4710SRishi Srivatsavai 58*4eaa4710SRishi Srivatsavai for (port = this->owner.port->owner->ports; port; port = port->next) { 59*4eaa4710SRishi Srivatsavai port->sync = True; /* in ROOT_PROPOSED (setSyncBridge) */ 60*4eaa4710SRishi Srivatsavai } 61*4eaa4710SRishi Srivatsavai } 62*4eaa4710SRishi Srivatsavai 63*4eaa4710SRishi Srivatsavai static void 64*4eaa4710SRishi Srivatsavai setReRootBridge (STATE_MACH_T *this) 65*4eaa4710SRishi Srivatsavai { 66*4eaa4710SRishi Srivatsavai register PORT_T* port; 67*4eaa4710SRishi Srivatsavai 68*4eaa4710SRishi Srivatsavai for (port = this->owner.port->owner->ports; port; port = port->next) { 69*4eaa4710SRishi Srivatsavai port->reRoot = True; /* In setReRootBridge */ 70*4eaa4710SRishi Srivatsavai } 71*4eaa4710SRishi Srivatsavai } 72*4eaa4710SRishi Srivatsavai 73*4eaa4710SRishi Srivatsavai static Bool 74*4eaa4710SRishi Srivatsavai compute_all_synced (PORT_T* this) 75*4eaa4710SRishi Srivatsavai { 76*4eaa4710SRishi Srivatsavai register PORT_T* port; 77*4eaa4710SRishi Srivatsavai 78*4eaa4710SRishi Srivatsavai for (port = this->owner->ports; port; port = port->next) { 79*4eaa4710SRishi Srivatsavai if (port->port_index == this->port_index) continue; 80*4eaa4710SRishi Srivatsavai if (! port->synced) { 81*4eaa4710SRishi Srivatsavai return False; 82*4eaa4710SRishi Srivatsavai } 83*4eaa4710SRishi Srivatsavai } 84*4eaa4710SRishi Srivatsavai 85*4eaa4710SRishi Srivatsavai return True; 86*4eaa4710SRishi Srivatsavai } 87*4eaa4710SRishi Srivatsavai 88*4eaa4710SRishi Srivatsavai static Bool 89*4eaa4710SRishi Srivatsavai compute_re_rooted (PORT_T* this) 90*4eaa4710SRishi Srivatsavai { 91*4eaa4710SRishi Srivatsavai register PORT_T* port; 92*4eaa4710SRishi Srivatsavai 93*4eaa4710SRishi Srivatsavai for (port = this->owner->ports; port; port = port->next) { 94*4eaa4710SRishi Srivatsavai if (port->port_index == this->port_index) continue; 95*4eaa4710SRishi Srivatsavai if (port->rrWhile) { 96*4eaa4710SRishi Srivatsavai return False; 97*4eaa4710SRishi Srivatsavai } 98*4eaa4710SRishi Srivatsavai } 99*4eaa4710SRishi Srivatsavai return True; 100*4eaa4710SRishi Srivatsavai } 101*4eaa4710SRishi Srivatsavai 102*4eaa4710SRishi Srivatsavai void 103*4eaa4710SRishi Srivatsavai STP_roletrns_enter_state (STATE_MACH_T* this) 104*4eaa4710SRishi Srivatsavai { 105*4eaa4710SRishi Srivatsavai register PORT_T* port = this->owner.port; 106*4eaa4710SRishi Srivatsavai register STPM_T* stpm; 107*4eaa4710SRishi Srivatsavai 108*4eaa4710SRishi Srivatsavai stpm = port->owner; 109*4eaa4710SRishi Srivatsavai 110*4eaa4710SRishi Srivatsavai switch (this->State) { 111*4eaa4710SRishi Srivatsavai case BEGIN: 112*4eaa4710SRishi Srivatsavai case INIT_PORT: 113*4eaa4710SRishi Srivatsavai #if 0 /* due 802.1y Z.4 */ 114*4eaa4710SRishi Srivatsavai port->role = DisabledPort; 115*4eaa4710SRishi Srivatsavai #else 116*4eaa4710SRishi Srivatsavai port->role = port->selectedRole = DisabledPort; 117*4eaa4710SRishi Srivatsavai port->reselect = True; 118*4eaa4710SRishi Srivatsavai #endif 119*4eaa4710SRishi Srivatsavai port->synced = False; /* in INIT */ 120*4eaa4710SRishi Srivatsavai port->sync = True; /* in INIT */ 121*4eaa4710SRishi Srivatsavai port->reRoot = True; /* in INIT_PORT */ 122*4eaa4710SRishi Srivatsavai port->rrWhile = stpm->rootTimes.ForwardDelay; 123*4eaa4710SRishi Srivatsavai port->fdWhile = stpm->rootTimes.ForwardDelay; 124*4eaa4710SRishi Srivatsavai port->rbWhile = 0; 125*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 126*4eaa4710SRishi Srivatsavai if (this->debug) 127*4eaa4710SRishi Srivatsavai STP_port_trace_flags ("after init", port); 128*4eaa4710SRishi Srivatsavai #endif 129*4eaa4710SRishi Srivatsavai break; 130*4eaa4710SRishi Srivatsavai case BLOCK_PORT: 131*4eaa4710SRishi Srivatsavai port->role = port->selectedRole; 132*4eaa4710SRishi Srivatsavai port->learn = 133*4eaa4710SRishi Srivatsavai port->forward = False; 134*4eaa4710SRishi Srivatsavai break; 135*4eaa4710SRishi Srivatsavai case BLOCKED_PORT: 136*4eaa4710SRishi Srivatsavai port->fdWhile = stpm->rootTimes.ForwardDelay; 137*4eaa4710SRishi Srivatsavai port->synced = True; /* In BLOCKED_PORT */ 138*4eaa4710SRishi Srivatsavai port->rrWhile = 0; 139*4eaa4710SRishi Srivatsavai port->sync = port->reRoot = False; /* BLOCKED_PORT */ 140*4eaa4710SRishi Srivatsavai break; 141*4eaa4710SRishi Srivatsavai case BACKUP_PORT: 142*4eaa4710SRishi Srivatsavai port->rbWhile = 2 * stpm->rootTimes.HelloTime; 143*4eaa4710SRishi Srivatsavai break; 144*4eaa4710SRishi Srivatsavai 145*4eaa4710SRishi Srivatsavai /* 17.23.2 */ 146*4eaa4710SRishi Srivatsavai case ROOT_PROPOSED: 147*4eaa4710SRishi Srivatsavai setSyncBridge (this); 148*4eaa4710SRishi Srivatsavai port->proposed = False; 149*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 150*4eaa4710SRishi Srivatsavai if (this->debug) 151*4eaa4710SRishi Srivatsavai STP_port_trace_flags ("ROOT_PROPOSED", port); 152*4eaa4710SRishi Srivatsavai #endif 153*4eaa4710SRishi Srivatsavai break; 154*4eaa4710SRishi Srivatsavai case ROOT_AGREED: 155*4eaa4710SRishi Srivatsavai port->proposed = port->sync = False; /* in ROOT_AGREED */ 156*4eaa4710SRishi Srivatsavai port->synced = True; /* In ROOT_AGREED */ 157*4eaa4710SRishi Srivatsavai port->newInfo = True; 158*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 159*4eaa4710SRishi Srivatsavai if (this->debug) 160*4eaa4710SRishi Srivatsavai STP_port_trace_flags ("ROOT_AGREED", port); 161*4eaa4710SRishi Srivatsavai #endif 162*4eaa4710SRishi Srivatsavai break; 163*4eaa4710SRishi Srivatsavai case REROOT: 164*4eaa4710SRishi Srivatsavai setReRootBridge (this); 165*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 166*4eaa4710SRishi Srivatsavai if (this->debug) 167*4eaa4710SRishi Srivatsavai STP_port_trace_flags ("REROOT", port); 168*4eaa4710SRishi Srivatsavai #endif 169*4eaa4710SRishi Srivatsavai break; 170*4eaa4710SRishi Srivatsavai case ROOT_PORT: 171*4eaa4710SRishi Srivatsavai port->role = RootPort; 172*4eaa4710SRishi Srivatsavai port->rrWhile = stpm->rootTimes.ForwardDelay; 173*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 174*4eaa4710SRishi Srivatsavai if (this->debug) 175*4eaa4710SRishi Srivatsavai STP_port_trace_flags ("ROOT_PORT", port); 176*4eaa4710SRishi Srivatsavai #endif 177*4eaa4710SRishi Srivatsavai break; 178*4eaa4710SRishi Srivatsavai case REROOTED: 179*4eaa4710SRishi Srivatsavai port->reRoot = False; /* In REROOTED */ 180*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 181*4eaa4710SRishi Srivatsavai if (this->debug) 182*4eaa4710SRishi Srivatsavai STP_port_trace_flags ("REROOTED", port); 183*4eaa4710SRishi Srivatsavai #endif 184*4eaa4710SRishi Srivatsavai break; 185*4eaa4710SRishi Srivatsavai case ROOT_LEARN: 186*4eaa4710SRishi Srivatsavai port->fdWhile = stpm->rootTimes.ForwardDelay; 187*4eaa4710SRishi Srivatsavai port->learn = True; 188*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 189*4eaa4710SRishi Srivatsavai if (this->debug) 190*4eaa4710SRishi Srivatsavai STP_port_trace_flags ("ROOT_LEARN", port); 191*4eaa4710SRishi Srivatsavai #endif 192*4eaa4710SRishi Srivatsavai break; 193*4eaa4710SRishi Srivatsavai case ROOT_FORWARD: 194*4eaa4710SRishi Srivatsavai port->fdWhile = 0; 195*4eaa4710SRishi Srivatsavai port->forward = True; 196*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 197*4eaa4710SRishi Srivatsavai if (this->debug) 198*4eaa4710SRishi Srivatsavai STP_port_trace_flags ("ROOT_FORWARD", port); 199*4eaa4710SRishi Srivatsavai #endif 200*4eaa4710SRishi Srivatsavai break; 201*4eaa4710SRishi Srivatsavai 202*4eaa4710SRishi Srivatsavai /* 17.23.3 */ 203*4eaa4710SRishi Srivatsavai case DESIGNATED_PROPOSE: 204*4eaa4710SRishi Srivatsavai port->proposing = True; /* in DESIGNATED_PROPOSE */ 205*4eaa4710SRishi Srivatsavai port->newInfo = True; 206*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 207*4eaa4710SRishi Srivatsavai if (this->debug) 208*4eaa4710SRishi Srivatsavai STP_port_trace_flags ("DESIGNATED_PROPOSE", port); 209*4eaa4710SRishi Srivatsavai #endif 210*4eaa4710SRishi Srivatsavai break; 211*4eaa4710SRishi Srivatsavai case DESIGNATED_SYNCED: 212*4eaa4710SRishi Srivatsavai port->rrWhile = 0; 213*4eaa4710SRishi Srivatsavai port->synced = True; /* DESIGNATED_SYNCED */ 214*4eaa4710SRishi Srivatsavai port->sync = False; /* DESIGNATED_SYNCED */ 215*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 216*4eaa4710SRishi Srivatsavai if (this->debug) 217*4eaa4710SRishi Srivatsavai STP_port_trace_flags ("DESIGNATED_SYNCED", port); 218*4eaa4710SRishi Srivatsavai #endif 219*4eaa4710SRishi Srivatsavai break; 220*4eaa4710SRishi Srivatsavai case DESIGNATED_RETIRED: 221*4eaa4710SRishi Srivatsavai port->reRoot = False; /* DESIGNATED_RETIRED */ 222*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 223*4eaa4710SRishi Srivatsavai if (this->debug) 224*4eaa4710SRishi Srivatsavai STP_port_trace_flags ("DESIGNATED_RETIRED", port); 225*4eaa4710SRishi Srivatsavai #endif 226*4eaa4710SRishi Srivatsavai break; 227*4eaa4710SRishi Srivatsavai case DESIGNATED_PORT: 228*4eaa4710SRishi Srivatsavai port->role = DesignatedPort; 229*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 230*4eaa4710SRishi Srivatsavai if (this->debug) 231*4eaa4710SRishi Srivatsavai STP_port_trace_flags ("DESIGNATED_PORT", port); 232*4eaa4710SRishi Srivatsavai #endif 233*4eaa4710SRishi Srivatsavai break; 234*4eaa4710SRishi Srivatsavai case DESIGNATED_LISTEN: 235*4eaa4710SRishi Srivatsavai port->learn = port->forward = False; 236*4eaa4710SRishi Srivatsavai port->fdWhile = stpm->rootTimes.ForwardDelay; 237*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 238*4eaa4710SRishi Srivatsavai if (this->debug) 239*4eaa4710SRishi Srivatsavai STP_port_trace_flags ("DESIGNATED_LISTEN", port); 240*4eaa4710SRishi Srivatsavai #endif 241*4eaa4710SRishi Srivatsavai break; 242*4eaa4710SRishi Srivatsavai case DESIGNATED_LEARN: 243*4eaa4710SRishi Srivatsavai port->learn = True; 244*4eaa4710SRishi Srivatsavai port->fdWhile = stpm->rootTimes.ForwardDelay; 245*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 246*4eaa4710SRishi Srivatsavai if (this->debug) 247*4eaa4710SRishi Srivatsavai STP_port_trace_flags ("DESIGNATED_LEARN", port); 248*4eaa4710SRishi Srivatsavai #endif 249*4eaa4710SRishi Srivatsavai break; 250*4eaa4710SRishi Srivatsavai case DESIGNATED_FORWARD: 251*4eaa4710SRishi Srivatsavai port->forward = True; 252*4eaa4710SRishi Srivatsavai port->fdWhile = 0; 253*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 254*4eaa4710SRishi Srivatsavai if (this->debug) 255*4eaa4710SRishi Srivatsavai STP_port_trace_flags ("DESIGNATED_FORWARD", port); 256*4eaa4710SRishi Srivatsavai #endif 257*4eaa4710SRishi Srivatsavai break; 258*4eaa4710SRishi Srivatsavai }; 259*4eaa4710SRishi Srivatsavai } 260*4eaa4710SRishi Srivatsavai 261*4eaa4710SRishi Srivatsavai Bool 262*4eaa4710SRishi Srivatsavai STP_roletrns_check_conditions (STATE_MACH_T* this) 263*4eaa4710SRishi Srivatsavai { 264*4eaa4710SRishi Srivatsavai register PORT_T *port = this->owner.port; 265*4eaa4710SRishi Srivatsavai register STPM_T *stpm; 266*4eaa4710SRishi Srivatsavai Bool allSynced; 267*4eaa4710SRishi Srivatsavai Bool allReRooted; 268*4eaa4710SRishi Srivatsavai 269*4eaa4710SRishi Srivatsavai stpm = port->owner; 270*4eaa4710SRishi Srivatsavai 271*4eaa4710SRishi Srivatsavai if (BEGIN == this->State) { 272*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, INIT_PORT); 273*4eaa4710SRishi Srivatsavai } 274*4eaa4710SRishi Srivatsavai 275*4eaa4710SRishi Srivatsavai if (port->role != port->selectedRole && 276*4eaa4710SRishi Srivatsavai port->selected && 277*4eaa4710SRishi Srivatsavai ! port->updtInfo) { 278*4eaa4710SRishi Srivatsavai switch (port->selectedRole) { 279*4eaa4710SRishi Srivatsavai case DisabledPort: 280*4eaa4710SRishi Srivatsavai case AlternatePort: 281*4eaa4710SRishi Srivatsavai case BackupPort: 282*4eaa4710SRishi Srivatsavai #if 0 /* def STP_DBG */ 283*4eaa4710SRishi Srivatsavai if (this->debug) { 284*4eaa4710SRishi Srivatsavai stp_trace ("hop to BLOCK_PORT role=%d selectedRole=%d", 285*4eaa4710SRishi Srivatsavai (int) port->role, (int) port->selectedRole); 286*4eaa4710SRishi Srivatsavai } 287*4eaa4710SRishi Srivatsavai #endif 288*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, BLOCK_PORT); 289*4eaa4710SRishi Srivatsavai case RootPort: 290*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, ROOT_PORT); 291*4eaa4710SRishi Srivatsavai case DesignatedPort: 292*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, DESIGNATED_PORT); 293*4eaa4710SRishi Srivatsavai default: 294*4eaa4710SRishi Srivatsavai return False; 295*4eaa4710SRishi Srivatsavai } 296*4eaa4710SRishi Srivatsavai } 297*4eaa4710SRishi Srivatsavai 298*4eaa4710SRishi Srivatsavai switch (this->State) { 299*4eaa4710SRishi Srivatsavai /* 17.23.1 */ 300*4eaa4710SRishi Srivatsavai case INIT_PORT: 301*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, BLOCK_PORT); 302*4eaa4710SRishi Srivatsavai case BLOCK_PORT: 303*4eaa4710SRishi Srivatsavai if (!port->selected || port->updtInfo) break; 304*4eaa4710SRishi Srivatsavai if (!port->learning && !port->forwarding) { 305*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, BLOCKED_PORT); 306*4eaa4710SRishi Srivatsavai } 307*4eaa4710SRishi Srivatsavai break; 308*4eaa4710SRishi Srivatsavai case BLOCKED_PORT: 309*4eaa4710SRishi Srivatsavai if (!port->selected || port->updtInfo) break; 310*4eaa4710SRishi Srivatsavai if (port->fdWhile != stpm->rootTimes.ForwardDelay || 311*4eaa4710SRishi Srivatsavai port->sync || 312*4eaa4710SRishi Srivatsavai port->reRoot || 313*4eaa4710SRishi Srivatsavai !port->synced) { 314*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, BLOCKED_PORT); 315*4eaa4710SRishi Srivatsavai } 316*4eaa4710SRishi Srivatsavai if (port->rbWhile != 2 * stpm->rootTimes.HelloTime && 317*4eaa4710SRishi Srivatsavai port->role == BackupPort) { 318*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, BACKUP_PORT); 319*4eaa4710SRishi Srivatsavai } 320*4eaa4710SRishi Srivatsavai break; 321*4eaa4710SRishi Srivatsavai case BACKUP_PORT: 322*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, BLOCKED_PORT); 323*4eaa4710SRishi Srivatsavai 324*4eaa4710SRishi Srivatsavai /* 17.23.2 */ 325*4eaa4710SRishi Srivatsavai case ROOT_PROPOSED: 326*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, ROOT_PORT); 327*4eaa4710SRishi Srivatsavai case ROOT_AGREED: 328*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, ROOT_PORT); 329*4eaa4710SRishi Srivatsavai case REROOT: 330*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, ROOT_PORT); 331*4eaa4710SRishi Srivatsavai case ROOT_PORT: 332*4eaa4710SRishi Srivatsavai if (!port->selected || port->updtInfo) break; 333*4eaa4710SRishi Srivatsavai if (!port->forward && !port->reRoot) { 334*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, REROOT); 335*4eaa4710SRishi Srivatsavai } 336*4eaa4710SRishi Srivatsavai allSynced = compute_all_synced (port); 337*4eaa4710SRishi Srivatsavai if ((port->proposed && allSynced) || 338*4eaa4710SRishi Srivatsavai (!port->synced && allSynced)) { 339*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, ROOT_AGREED); 340*4eaa4710SRishi Srivatsavai } 341*4eaa4710SRishi Srivatsavai if (port->proposed && !port->synced) { 342*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, ROOT_PROPOSED); 343*4eaa4710SRishi Srivatsavai } 344*4eaa4710SRishi Srivatsavai 345*4eaa4710SRishi Srivatsavai allReRooted = compute_re_rooted (port); 346*4eaa4710SRishi Srivatsavai if ((!port->fdWhile || 347*4eaa4710SRishi Srivatsavai ((allReRooted && !port->rbWhile) && stpm->ForceVersion >=2)) && 348*4eaa4710SRishi Srivatsavai port->learn && !port->forward) { 349*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, ROOT_FORWARD); 350*4eaa4710SRishi Srivatsavai } 351*4eaa4710SRishi Srivatsavai if ((!port->fdWhile || 352*4eaa4710SRishi Srivatsavai ((allReRooted && !port->rbWhile) && stpm->ForceVersion >=2)) && 353*4eaa4710SRishi Srivatsavai !port->learn) { 354*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, ROOT_LEARN); 355*4eaa4710SRishi Srivatsavai } 356*4eaa4710SRishi Srivatsavai 357*4eaa4710SRishi Srivatsavai if (port->reRoot && port->forward) { 358*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, REROOTED); 359*4eaa4710SRishi Srivatsavai } 360*4eaa4710SRishi Srivatsavai if (port->rrWhile != stpm->rootTimes.ForwardDelay) { 361*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, ROOT_PORT); 362*4eaa4710SRishi Srivatsavai } 363*4eaa4710SRishi Srivatsavai break; 364*4eaa4710SRishi Srivatsavai case REROOTED: 365*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, ROOT_PORT); 366*4eaa4710SRishi Srivatsavai case ROOT_LEARN: 367*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, ROOT_PORT); 368*4eaa4710SRishi Srivatsavai case ROOT_FORWARD: 369*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, ROOT_PORT); 370*4eaa4710SRishi Srivatsavai 371*4eaa4710SRishi Srivatsavai /* 17.23.3 */ 372*4eaa4710SRishi Srivatsavai case DESIGNATED_PROPOSE: 373*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, DESIGNATED_PORT); 374*4eaa4710SRishi Srivatsavai case DESIGNATED_SYNCED: 375*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, DESIGNATED_PORT); 376*4eaa4710SRishi Srivatsavai case DESIGNATED_RETIRED: 377*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, DESIGNATED_PORT); 378*4eaa4710SRishi Srivatsavai case DESIGNATED_PORT: 379*4eaa4710SRishi Srivatsavai if (!port->selected || port->updtInfo) break; 380*4eaa4710SRishi Srivatsavai 381*4eaa4710SRishi Srivatsavai if (!port->forward && !port->agreed && !port->proposing && !port->operEdge) { 382*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, DESIGNATED_PROPOSE); 383*4eaa4710SRishi Srivatsavai } 384*4eaa4710SRishi Srivatsavai 385*4eaa4710SRishi Srivatsavai if (!port->rrWhile && port->reRoot) { 386*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, DESIGNATED_RETIRED); 387*4eaa4710SRishi Srivatsavai } 388*4eaa4710SRishi Srivatsavai 389*4eaa4710SRishi Srivatsavai if (!port->learning && !port->forwarding && !port->synced) { 390*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, DESIGNATED_SYNCED); 391*4eaa4710SRishi Srivatsavai } 392*4eaa4710SRishi Srivatsavai 393*4eaa4710SRishi Srivatsavai if (port->agreed && !port->synced) { 394*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, DESIGNATED_SYNCED); 395*4eaa4710SRishi Srivatsavai } 396*4eaa4710SRishi Srivatsavai if (port->operEdge && !port->synced) { 397*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, DESIGNATED_SYNCED); 398*4eaa4710SRishi Srivatsavai } 399*4eaa4710SRishi Srivatsavai if (port->sync && port->synced) { 400*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, DESIGNATED_SYNCED); 401*4eaa4710SRishi Srivatsavai } 402*4eaa4710SRishi Srivatsavai 403*4eaa4710SRishi Srivatsavai if ((!port->fdWhile || port->agreed || port->operEdge) && 404*4eaa4710SRishi Srivatsavai (!port->rrWhile || !port->reRoot) && 405*4eaa4710SRishi Srivatsavai !port->sync && 406*4eaa4710SRishi Srivatsavai (port->learn && !port->forward)) { 407*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, DESIGNATED_FORWARD); 408*4eaa4710SRishi Srivatsavai } 409*4eaa4710SRishi Srivatsavai if ((!port->fdWhile || port->agreed || port->operEdge) && 410*4eaa4710SRishi Srivatsavai (!port->rrWhile || !port->reRoot) && 411*4eaa4710SRishi Srivatsavai !port->sync && !port->learn) { 412*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, DESIGNATED_LEARN); 413*4eaa4710SRishi Srivatsavai } 414*4eaa4710SRishi Srivatsavai if (((port->sync && !port->synced) || 415*4eaa4710SRishi Srivatsavai (port->reRoot && port->rrWhile)) && 416*4eaa4710SRishi Srivatsavai !port->operEdge && (port->learn || port->forward)) { 417*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, DESIGNATED_LISTEN); 418*4eaa4710SRishi Srivatsavai } 419*4eaa4710SRishi Srivatsavai break; 420*4eaa4710SRishi Srivatsavai case DESIGNATED_LISTEN: 421*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, DESIGNATED_PORT); 422*4eaa4710SRishi Srivatsavai case DESIGNATED_LEARN: 423*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, DESIGNATED_PORT); 424*4eaa4710SRishi Srivatsavai case DESIGNATED_FORWARD: 425*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, DESIGNATED_PORT); 426*4eaa4710SRishi Srivatsavai }; 427*4eaa4710SRishi Srivatsavai 428*4eaa4710SRishi Srivatsavai return False; 429*4eaa4710SRishi Srivatsavai } 430*4eaa4710SRishi Srivatsavai 431*4eaa4710SRishi Srivatsavai 432