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 #include "base.h" 24*4eaa4710SRishi Srivatsavai #include "stpm.h" 25*4eaa4710SRishi Srivatsavai #include "stp_vectors.h" 26*4eaa4710SRishi Srivatsavai 27*4eaa4710SRishi Srivatsavai /* The Port Information State Machine : 17.21 */ 28*4eaa4710SRishi Srivatsavai 29*4eaa4710SRishi Srivatsavai #define STATES { \ 30*4eaa4710SRishi Srivatsavai CHOOSE(DISABLED), \ 31*4eaa4710SRishi Srivatsavai CHOOSE(ENABLED), \ 32*4eaa4710SRishi Srivatsavai CHOOSE(AGED), \ 33*4eaa4710SRishi Srivatsavai CHOOSE(UPDATE), \ 34*4eaa4710SRishi Srivatsavai CHOOSE(CURRENT), \ 35*4eaa4710SRishi Srivatsavai CHOOSE(RECEIVE), \ 36*4eaa4710SRishi Srivatsavai CHOOSE(SUPERIOR), \ 37*4eaa4710SRishi Srivatsavai CHOOSE(REPEAT), \ 38*4eaa4710SRishi Srivatsavai CHOOSE(AGREEMENT) \ 39*4eaa4710SRishi Srivatsavai } 40*4eaa4710SRishi Srivatsavai 41*4eaa4710SRishi Srivatsavai #define GET_STATE_NAME STP_info_get_state_name 42*4eaa4710SRishi Srivatsavai #include "choose.h" 43*4eaa4710SRishi Srivatsavai 44*4eaa4710SRishi Srivatsavai #if 0 /* for debug */ 45*4eaa4710SRishi Srivatsavai void 46*4eaa4710SRishi Srivatsavai _stp_dump (char* title, unsigned char* buff, int len) 47*4eaa4710SRishi Srivatsavai { 48*4eaa4710SRishi Srivatsavai register int iii; 49*4eaa4710SRishi Srivatsavai 50*4eaa4710SRishi Srivatsavai stp_trace ("\n%s:", title); 51*4eaa4710SRishi Srivatsavai for (iii = 0; iii < len; iii++) { 52*4eaa4710SRishi Srivatsavai if (! (iii % 24)) stp_trace ("\n%6d:", iii); 53*4eaa4710SRishi Srivatsavai if (! (iii % 8)) stp_trace (" "); 54*4eaa4710SRishi Srivatsavai stp_trace ("%02lx", (unsigned long) buff[iii]); 55*4eaa4710SRishi Srivatsavai } 56*4eaa4710SRishi Srivatsavai stp_trace ("\n"); 57*4eaa4710SRishi Srivatsavai } 58*4eaa4710SRishi Srivatsavai #endif 59*4eaa4710SRishi Srivatsavai 60*4eaa4710SRishi Srivatsavai static RCVD_MSG_T 61*4eaa4710SRishi Srivatsavai rcvBpdu (STATE_MACH_T* this) 62*4eaa4710SRishi Srivatsavai {/* 17.19.8 */ 63*4eaa4710SRishi Srivatsavai int bridcmp; 64*4eaa4710SRishi Srivatsavai register PORT_T* port = this->owner.port; 65*4eaa4710SRishi Srivatsavai 66*4eaa4710SRishi Srivatsavai if (port->msgBpduType == BPDU_TOPO_CHANGE_TYPE) { 67*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 68*4eaa4710SRishi Srivatsavai if (this->debug) { 69*4eaa4710SRishi Srivatsavai stp_trace ("%s", "rcvBpdu: OtherMsg:BPDU_TOPO_CHANGE_TYPE"); 70*4eaa4710SRishi Srivatsavai } 71*4eaa4710SRishi Srivatsavai #endif 72*4eaa4710SRishi Srivatsavai return OtherMsg; 73*4eaa4710SRishi Srivatsavai } 74*4eaa4710SRishi Srivatsavai 75*4eaa4710SRishi Srivatsavai port->msgPortRole = RSTP_PORT_ROLE_UNKN; 76*4eaa4710SRishi Srivatsavai 77*4eaa4710SRishi Srivatsavai if (BPDU_RSTP == port->msgBpduType) { 78*4eaa4710SRishi Srivatsavai port->msgPortRole = (port->msgFlags & PORT_ROLE_MASK) >> PORT_ROLE_OFFS; 79*4eaa4710SRishi Srivatsavai } 80*4eaa4710SRishi Srivatsavai 81*4eaa4710SRishi Srivatsavai if (RSTP_PORT_ROLE_DESGN == port->msgPortRole || 82*4eaa4710SRishi Srivatsavai BPDU_CONFIG_TYPE == port->msgBpduType) { 83*4eaa4710SRishi Srivatsavai bridcmp = STP_VECT_compare_vector (&port->msgPrio, &port->portPrio); 84*4eaa4710SRishi Srivatsavai 85*4eaa4710SRishi Srivatsavai if (bridcmp < 0 || 86*4eaa4710SRishi Srivatsavai (! STP_VECT_compare_bridge_id (&port->msgPrio.design_bridge, 87*4eaa4710SRishi Srivatsavai &port->portPrio.design_bridge) && 88*4eaa4710SRishi Srivatsavai port->msgPrio.design_port == port->portPrio.design_port && 89*4eaa4710SRishi Srivatsavai STP_compare_times (&port->msgTimes, &port->portTimes))) { 90*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 91*4eaa4710SRishi Srivatsavai if (this->debug) { 92*4eaa4710SRishi Srivatsavai stp_trace ("rcvBpdu: SuperiorDesignateMsg:bridcmp=%d", (int) bridcmp); 93*4eaa4710SRishi Srivatsavai } 94*4eaa4710SRishi Srivatsavai #endif 95*4eaa4710SRishi Srivatsavai return SuperiorDesignateMsg; 96*4eaa4710SRishi Srivatsavai } 97*4eaa4710SRishi Srivatsavai } 98*4eaa4710SRishi Srivatsavai 99*4eaa4710SRishi Srivatsavai if (BPDU_CONFIG_TYPE == port->msgBpduType || 100*4eaa4710SRishi Srivatsavai RSTP_PORT_ROLE_DESGN == port->msgPortRole) { 101*4eaa4710SRishi Srivatsavai if (! STP_VECT_compare_vector (&port->msgPrio, 102*4eaa4710SRishi Srivatsavai &port->portPrio) && 103*4eaa4710SRishi Srivatsavai ! STP_compare_times (&port->msgTimes, &port->portTimes)) { 104*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 105*4eaa4710SRishi Srivatsavai if (this->debug) { 106*4eaa4710SRishi Srivatsavai stp_trace ("%s", "rcvBpdu: RepeatedDesignateMsg"); 107*4eaa4710SRishi Srivatsavai } 108*4eaa4710SRishi Srivatsavai #endif 109*4eaa4710SRishi Srivatsavai return RepeatedDesignateMsg; 110*4eaa4710SRishi Srivatsavai } 111*4eaa4710SRishi Srivatsavai } 112*4eaa4710SRishi Srivatsavai 113*4eaa4710SRishi Srivatsavai if (RSTP_PORT_ROLE_ROOT == port->msgBpduType && 114*4eaa4710SRishi Srivatsavai port->operPointToPointMac && 115*4eaa4710SRishi Srivatsavai ! STP_VECT_compare_bridge_id (&port->msgPrio.design_bridge, 116*4eaa4710SRishi Srivatsavai &port->portPrio.design_bridge) && 117*4eaa4710SRishi Srivatsavai AGREEMENT_BIT & port->msgFlags) { 118*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 119*4eaa4710SRishi Srivatsavai if (this->debug) { 120*4eaa4710SRishi Srivatsavai stp_trace ("%s", "rcvBpdu: ConfirmedRootMsg"); 121*4eaa4710SRishi Srivatsavai } 122*4eaa4710SRishi Srivatsavai #endif 123*4eaa4710SRishi Srivatsavai return ConfirmedRootMsg; 124*4eaa4710SRishi Srivatsavai } 125*4eaa4710SRishi Srivatsavai 126*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 127*4eaa4710SRishi Srivatsavai if (this->debug) { 128*4eaa4710SRishi Srivatsavai if (RSTP_PORT_ROLE_ROOT == port->msgBpduType) { 129*4eaa4710SRishi Srivatsavai if (!port->operPointToPointMac) { 130*4eaa4710SRishi Srivatsavai stp_trace("rcvBpdu: OtherMsg: not point-to-point MAC"); 131*4eaa4710SRishi Srivatsavai } else if (STP_VECT_compare_bridge_id (&port->msgPrio.design_bridge, 132*4eaa4710SRishi Srivatsavai &port->portPrio.design_bridge)) { 133*4eaa4710SRishi Srivatsavai STP_VECT_br_id_print("rcvBpdu: OtherMsg: msgPrio", &port->msgPrio.design_bridge, True); 134*4eaa4710SRishi Srivatsavai STP_VECT_br_id_print("rcvBpdu: portPrio", &port->portPrio.design_bridge, True); 135*4eaa4710SRishi Srivatsavai } else { 136*4eaa4710SRishi Srivatsavai stp_trace("rcvBpdu: OtherMsg: agreement bit not set"); 137*4eaa4710SRishi Srivatsavai } 138*4eaa4710SRishi Srivatsavai } else { 139*4eaa4710SRishi Srivatsavai stp_trace ("rcvBpdu: OtherMsg: type %d", port->msgBpduType); 140*4eaa4710SRishi Srivatsavai } 141*4eaa4710SRishi Srivatsavai } 142*4eaa4710SRishi Srivatsavai #endif 143*4eaa4710SRishi Srivatsavai return OtherMsg; 144*4eaa4710SRishi Srivatsavai } 145*4eaa4710SRishi Srivatsavai 146*4eaa4710SRishi Srivatsavai /* ARGSUSED */ 147*4eaa4710SRishi Srivatsavai static Bool 148*4eaa4710SRishi Srivatsavai recordProposed (STATE_MACH_T* this, char* reason) 149*4eaa4710SRishi Srivatsavai {/* 17.19.9 */ 150*4eaa4710SRishi Srivatsavai register PORT_T* port = this->owner.port; 151*4eaa4710SRishi Srivatsavai 152*4eaa4710SRishi Srivatsavai if (RSTP_PORT_ROLE_DESGN == port->msgPortRole && 153*4eaa4710SRishi Srivatsavai (PROPOSAL_BIT & port->msgFlags) && 154*4eaa4710SRishi Srivatsavai port->operPointToPointMac) { 155*4eaa4710SRishi Srivatsavai return True; 156*4eaa4710SRishi Srivatsavai } 157*4eaa4710SRishi Srivatsavai return False; 158*4eaa4710SRishi Srivatsavai } 159*4eaa4710SRishi Srivatsavai 160*4eaa4710SRishi Srivatsavai static void 161*4eaa4710SRishi Srivatsavai setTcFlags (STATE_MACH_T* this) 162*4eaa4710SRishi Srivatsavai {/* 17.19.13 */ 163*4eaa4710SRishi Srivatsavai register PORT_T* port = this->owner.port; 164*4eaa4710SRishi Srivatsavai 165*4eaa4710SRishi Srivatsavai if (BPDU_TOPO_CHANGE_TYPE == port->msgBpduType) { 166*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 167*4eaa4710SRishi Srivatsavai if (this->debug) { 168*4eaa4710SRishi Srivatsavai stp_trace ("port %s rx rcvdTcn", port->port_name); 169*4eaa4710SRishi Srivatsavai } 170*4eaa4710SRishi Srivatsavai #endif 171*4eaa4710SRishi Srivatsavai port->rcvdTcn = True; 172*4eaa4710SRishi Srivatsavai } else { 173*4eaa4710SRishi Srivatsavai if (TOPOLOGY_CHANGE_BIT & port->msgFlags) { 174*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 175*4eaa4710SRishi Srivatsavai if (this->debug) { 176*4eaa4710SRishi Srivatsavai stp_trace ("(%s-%s) rx rcvdTc 0X%lx", 177*4eaa4710SRishi Srivatsavai port->owner->name, port->port_name, 178*4eaa4710SRishi Srivatsavai (unsigned long) port->msgFlags); 179*4eaa4710SRishi Srivatsavai } 180*4eaa4710SRishi Srivatsavai #endif 181*4eaa4710SRishi Srivatsavai port->rcvdTc = True; 182*4eaa4710SRishi Srivatsavai } 183*4eaa4710SRishi Srivatsavai if (TOPOLOGY_CHANGE_ACK_BIT & port->msgFlags) { 184*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 185*4eaa4710SRishi Srivatsavai if (this->debug) { 186*4eaa4710SRishi Srivatsavai stp_trace ("port %s rx rcvdTcAck 0X%lx", 187*4eaa4710SRishi Srivatsavai port->port_name, 188*4eaa4710SRishi Srivatsavai (unsigned long) port->msgFlags); 189*4eaa4710SRishi Srivatsavai } 190*4eaa4710SRishi Srivatsavai #endif 191*4eaa4710SRishi Srivatsavai port->rcvdTcAck = True; 192*4eaa4710SRishi Srivatsavai } 193*4eaa4710SRishi Srivatsavai } 194*4eaa4710SRishi Srivatsavai } 195*4eaa4710SRishi Srivatsavai 196*4eaa4710SRishi Srivatsavai static void 197*4eaa4710SRishi Srivatsavai updtBPDUVersion (STATE_MACH_T* this) 198*4eaa4710SRishi Srivatsavai {/* 17.19.18 */ 199*4eaa4710SRishi Srivatsavai register PORT_T* port = this->owner.port; 200*4eaa4710SRishi Srivatsavai 201*4eaa4710SRishi Srivatsavai if (BPDU_TOPO_CHANGE_TYPE == port->msgBpduType) { 202*4eaa4710SRishi Srivatsavai port->rcvdSTP = True; 203*4eaa4710SRishi Srivatsavai } 204*4eaa4710SRishi Srivatsavai 205*4eaa4710SRishi Srivatsavai if (port->msgBpduVersion < 2) { 206*4eaa4710SRishi Srivatsavai port->rcvdSTP = True; 207*4eaa4710SRishi Srivatsavai } 208*4eaa4710SRishi Srivatsavai 209*4eaa4710SRishi Srivatsavai if (BPDU_RSTP == port->msgBpduType) { 210*4eaa4710SRishi Srivatsavai /* port->port->owner->ForceVersion >= NORMAL_RSTP 211*4eaa4710SRishi Srivatsavai we have checked in STP_info_rx_bpdu */ 212*4eaa4710SRishi Srivatsavai port->rcvdRSTP = True; 213*4eaa4710SRishi Srivatsavai } 214*4eaa4710SRishi Srivatsavai } 215*4eaa4710SRishi Srivatsavai 216*4eaa4710SRishi Srivatsavai static void 217*4eaa4710SRishi Srivatsavai updtRcvdInfoWhile (STATE_MACH_T* this) 218*4eaa4710SRishi Srivatsavai {/* 17.19.19 */ 219*4eaa4710SRishi Srivatsavai register int eff_age, dm, dt; 220*4eaa4710SRishi Srivatsavai register int hello3; 221*4eaa4710SRishi Srivatsavai register PORT_T* port = this->owner.port; 222*4eaa4710SRishi Srivatsavai 223*4eaa4710SRishi Srivatsavai eff_age = ( + port->portTimes.MaxAge) / 16; 224*4eaa4710SRishi Srivatsavai if (eff_age < 1) eff_age = 1; 225*4eaa4710SRishi Srivatsavai eff_age += port->portTimes.MessageAge; 226*4eaa4710SRishi Srivatsavai 227*4eaa4710SRishi Srivatsavai if (eff_age <= port->portTimes.MaxAge) { 228*4eaa4710SRishi Srivatsavai hello3 = 3 * port->portTimes.HelloTime; 229*4eaa4710SRishi Srivatsavai dm = port->portTimes.MaxAge - eff_age; 230*4eaa4710SRishi Srivatsavai if (dm > hello3) 231*4eaa4710SRishi Srivatsavai dt = hello3; 232*4eaa4710SRishi Srivatsavai else 233*4eaa4710SRishi Srivatsavai dt = dm; 234*4eaa4710SRishi Srivatsavai port->rcvdInfoWhile = dt; 235*4eaa4710SRishi Srivatsavai /**** 236*4eaa4710SRishi Srivatsavai stp_trace ("ma=%d eff_age=%d dm=%d dt=%d p=%s", 237*4eaa4710SRishi Srivatsavai (int) port->portTimes.MessageAge, 238*4eaa4710SRishi Srivatsavai (int) eff_age, (int) dm, (int) dt, port->port_name); 239*4eaa4710SRishi Srivatsavai ****/ 240*4eaa4710SRishi Srivatsavai } else { 241*4eaa4710SRishi Srivatsavai port->rcvdInfoWhile = 0; 242*4eaa4710SRishi Srivatsavai /****/ 243*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 244*4eaa4710SRishi Srivatsavai /*if (this->debug) */ 245*4eaa4710SRishi Srivatsavai { 246*4eaa4710SRishi Srivatsavai stp_trace ("port %s: MaxAge=%d MessageAge=%d HelloTime=%d rcvdInfoWhile=null !", 247*4eaa4710SRishi Srivatsavai port->port_name, 248*4eaa4710SRishi Srivatsavai (int) port->portTimes.MaxAge, 249*4eaa4710SRishi Srivatsavai (int) port->portTimes.MessageAge, 250*4eaa4710SRishi Srivatsavai (int) port->portTimes.HelloTime); 251*4eaa4710SRishi Srivatsavai } 252*4eaa4710SRishi Srivatsavai #endif 253*4eaa4710SRishi Srivatsavai /****/ 254*4eaa4710SRishi Srivatsavai } 255*4eaa4710SRishi Srivatsavai } 256*4eaa4710SRishi Srivatsavai 257*4eaa4710SRishi Srivatsavai 258*4eaa4710SRishi Srivatsavai /* ARGSUSED */ 259*4eaa4710SRishi Srivatsavai void 260*4eaa4710SRishi Srivatsavai STP_info_rx_bpdu (PORT_T* port, struct stp_bpdu_t* bpdu, size_t len) 261*4eaa4710SRishi Srivatsavai { 262*4eaa4710SRishi Srivatsavai #if 0 263*4eaa4710SRishi Srivatsavai _stp_dump ("\nall BPDU", ((unsigned char*) bpdu) - 12, len + 12); 264*4eaa4710SRishi Srivatsavai _stp_dump ("ETH_HEADER", (unsigned char*) &bpdu->eth, 5); 265*4eaa4710SRishi Srivatsavai _stp_dump ("BPDU_HEADER", (unsigned char*) &bpdu->hdr, 4); 266*4eaa4710SRishi Srivatsavai stp_trace ("protocol=%02x%02x version=%02x bpdu_type=%02x\n", 267*4eaa4710SRishi Srivatsavai bpdu->hdr.protocol[0], bpdu->hdr.protocol[1], 268*4eaa4710SRishi Srivatsavai bpdu->hdr.version, bpdu->hdr.bpdu_type); 269*4eaa4710SRishi Srivatsavai 270*4eaa4710SRishi Srivatsavai _stp_dump ("\nBPDU_BODY", (unsigned char*) &bpdu->body, sizeof (BPDU_BODY_T) + 2); 271*4eaa4710SRishi Srivatsavai stp_trace ("flags=%02x\n", bpdu->body.flags); 272*4eaa4710SRishi Srivatsavai _stp_dump ("root_id", bpdu->body.root_id, 8); 273*4eaa4710SRishi Srivatsavai _stp_dump ("root_path_cost", bpdu->body.root_path_cost, 4); 274*4eaa4710SRishi Srivatsavai _stp_dump ("bridge_id", bpdu->body.bridge_id, 8); 275*4eaa4710SRishi Srivatsavai _stp_dump ("port_id", bpdu->body.port_id, 2); 276*4eaa4710SRishi Srivatsavai _stp_dump ("message_age", bpdu->body.message_age, 2); 277*4eaa4710SRishi Srivatsavai _stp_dump ("max_age", bpdu->body.max_age, 2); 278*4eaa4710SRishi Srivatsavai _stp_dump ("hello_time", bpdu->body.hello_time, 2); 279*4eaa4710SRishi Srivatsavai _stp_dump ("forward_delay", bpdu->body.forward_delay, 2); 280*4eaa4710SRishi Srivatsavai _stp_dump ("ver_1_len", bpdu->ver_1_len, 2); 281*4eaa4710SRishi Srivatsavai #endif 282*4eaa4710SRishi Srivatsavai 283*4eaa4710SRishi Srivatsavai /* check bpdu type */ 284*4eaa4710SRishi Srivatsavai switch (bpdu->hdr.bpdu_type) { 285*4eaa4710SRishi Srivatsavai case BPDU_CONFIG_TYPE: 286*4eaa4710SRishi Srivatsavai port->rx_cfg_bpdu_cnt++; 287*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 288*4eaa4710SRishi Srivatsavai if (port->info->debug) 289*4eaa4710SRishi Srivatsavai stp_trace ("CfgBpdu on port %s", port->port_name); 290*4eaa4710SRishi Srivatsavai #endif 291*4eaa4710SRishi Srivatsavai if (port->admin_non_stp) return; 292*4eaa4710SRishi Srivatsavai port->rcvdBpdu = True; 293*4eaa4710SRishi Srivatsavai break; 294*4eaa4710SRishi Srivatsavai case BPDU_TOPO_CHANGE_TYPE: 295*4eaa4710SRishi Srivatsavai port->rx_tcn_bpdu_cnt++; 296*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 297*4eaa4710SRishi Srivatsavai if (port->info->debug) 298*4eaa4710SRishi Srivatsavai stp_trace ("TcnBpdu on port %s", port->port_name); 299*4eaa4710SRishi Srivatsavai #endif 300*4eaa4710SRishi Srivatsavai if (port->admin_non_stp) return; 301*4eaa4710SRishi Srivatsavai port->rcvdBpdu = True; 302*4eaa4710SRishi Srivatsavai port->msgBpduVersion = bpdu->hdr.version; 303*4eaa4710SRishi Srivatsavai port->msgBpduType = bpdu->hdr.bpdu_type; 304*4eaa4710SRishi Srivatsavai return; 305*4eaa4710SRishi Srivatsavai default: 306*4eaa4710SRishi Srivatsavai stp_trace ("RX undef bpdu type=%d", (int) bpdu->hdr.bpdu_type); 307*4eaa4710SRishi Srivatsavai return; 308*4eaa4710SRishi Srivatsavai case BPDU_RSTP: 309*4eaa4710SRishi Srivatsavai port->rx_rstp_bpdu_cnt++; 310*4eaa4710SRishi Srivatsavai if (port->admin_non_stp) return; 311*4eaa4710SRishi Srivatsavai if (port->owner->ForceVersion >= NORMAL_RSTP) { 312*4eaa4710SRishi Srivatsavai port->rcvdBpdu = True; 313*4eaa4710SRishi Srivatsavai } else { 314*4eaa4710SRishi Srivatsavai return; 315*4eaa4710SRishi Srivatsavai } 316*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 317*4eaa4710SRishi Srivatsavai if (port->info->debug) 318*4eaa4710SRishi Srivatsavai stp_trace ("BPDU_RSTP on port %s", port->port_name); 319*4eaa4710SRishi Srivatsavai #endif 320*4eaa4710SRishi Srivatsavai break; 321*4eaa4710SRishi Srivatsavai } 322*4eaa4710SRishi Srivatsavai 323*4eaa4710SRishi Srivatsavai port->msgBpduVersion = bpdu->hdr.version; 324*4eaa4710SRishi Srivatsavai port->msgBpduType = bpdu->hdr.bpdu_type; 325*4eaa4710SRishi Srivatsavai port->msgFlags = bpdu->body.flags; 326*4eaa4710SRishi Srivatsavai 327*4eaa4710SRishi Srivatsavai /* 17.18.11 */ 328*4eaa4710SRishi Srivatsavai STP_VECT_get_vector (&bpdu->body, &port->msgPrio); 329*4eaa4710SRishi Srivatsavai port->msgPrio.bridge_port = port->port_id; 330*4eaa4710SRishi Srivatsavai 331*4eaa4710SRishi Srivatsavai /* 17.18.12 */ 332*4eaa4710SRishi Srivatsavai STP_get_times (&bpdu->body, &port->msgTimes); 333*4eaa4710SRishi Srivatsavai 334*4eaa4710SRishi Srivatsavai /* 17.18.25, 17.18.26 : see setTcFlags() */ 335*4eaa4710SRishi Srivatsavai } 336*4eaa4710SRishi Srivatsavai 337*4eaa4710SRishi Srivatsavai void STP_info_enter_state (STATE_MACH_T* this) 338*4eaa4710SRishi Srivatsavai { 339*4eaa4710SRishi Srivatsavai register PORT_T* port = this->owner.port; 340*4eaa4710SRishi Srivatsavai 341*4eaa4710SRishi Srivatsavai switch (this->State) { 342*4eaa4710SRishi Srivatsavai case BEGIN: 343*4eaa4710SRishi Srivatsavai port->rcvdMsg = OtherMsg; 344*4eaa4710SRishi Srivatsavai port->msgBpduType = (unsigned char)-1; 345*4eaa4710SRishi Srivatsavai port->msgPortRole = RSTP_PORT_ROLE_UNKN; 346*4eaa4710SRishi Srivatsavai port->msgFlags = 0; 347*4eaa4710SRishi Srivatsavai 348*4eaa4710SRishi Srivatsavai /* clear port statistics */ 349*4eaa4710SRishi Srivatsavai port->rx_cfg_bpdu_cnt = 350*4eaa4710SRishi Srivatsavai port->rx_rstp_bpdu_cnt = 351*4eaa4710SRishi Srivatsavai port->rx_tcn_bpdu_cnt = 0; 352*4eaa4710SRishi Srivatsavai /* FALLTHRU */ 353*4eaa4710SRishi Srivatsavai case DISABLED: 354*4eaa4710SRishi Srivatsavai port->rcvdBpdu = port->rcvdRSTP = port->rcvdSTP = False; 355*4eaa4710SRishi Srivatsavai port->updtInfo = port->proposing = False; /* In DISABLED */ 356*4eaa4710SRishi Srivatsavai port->agreed = port->proposed = False; 357*4eaa4710SRishi Srivatsavai port->rcvdInfoWhile = 0; 358*4eaa4710SRishi Srivatsavai port->infoIs = Disabled; 359*4eaa4710SRishi Srivatsavai port->reselect = True; 360*4eaa4710SRishi Srivatsavai port->selected = False; 361*4eaa4710SRishi Srivatsavai break; 362*4eaa4710SRishi Srivatsavai case ENABLED: /* IEEE 802.1y, 17.21, Z.14 */ 363*4eaa4710SRishi Srivatsavai STP_VECT_copy (&port->portPrio, &port->designPrio); 364*4eaa4710SRishi Srivatsavai STP_copy_times (&port->portTimes, &port->designTimes); 365*4eaa4710SRishi Srivatsavai break; 366*4eaa4710SRishi Srivatsavai case AGED: 367*4eaa4710SRishi Srivatsavai port->infoIs = Aged; 368*4eaa4710SRishi Srivatsavai port->reselect = True; 369*4eaa4710SRishi Srivatsavai port->selected = False; 370*4eaa4710SRishi Srivatsavai break; 371*4eaa4710SRishi Srivatsavai case UPDATE: 372*4eaa4710SRishi Srivatsavai STP_VECT_copy (&port->portPrio, &port->designPrio); 373*4eaa4710SRishi Srivatsavai STP_copy_times (&port->portTimes, &port->designTimes); 374*4eaa4710SRishi Srivatsavai port->updtInfo = False; 375*4eaa4710SRishi Srivatsavai port->agreed = port->synced = False; /* In UPDATE */ 376*4eaa4710SRishi Srivatsavai port->proposed = port->proposing = False; /* in UPDATE */ 377*4eaa4710SRishi Srivatsavai port->infoIs = Mine; 378*4eaa4710SRishi Srivatsavai port->newInfo = True; 379*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 380*4eaa4710SRishi Srivatsavai if (this->debug) { 381*4eaa4710SRishi Srivatsavai STP_VECT_br_id_print ("updated: portPrio.design_bridge", 382*4eaa4710SRishi Srivatsavai &port->portPrio.design_bridge, True); 383*4eaa4710SRishi Srivatsavai STP_VECT_br_id_print ("updated: portPrio.root_bridge", 384*4eaa4710SRishi Srivatsavai &port->portPrio.root_bridge, True); 385*4eaa4710SRishi Srivatsavai } 386*4eaa4710SRishi Srivatsavai #endif 387*4eaa4710SRishi Srivatsavai break; 388*4eaa4710SRishi Srivatsavai case CURRENT: 389*4eaa4710SRishi Srivatsavai break; 390*4eaa4710SRishi Srivatsavai case RECEIVE: 391*4eaa4710SRishi Srivatsavai port->rcvdMsg = rcvBpdu (this); 392*4eaa4710SRishi Srivatsavai updtBPDUVersion (this); 393*4eaa4710SRishi Srivatsavai setTcFlags (this); 394*4eaa4710SRishi Srivatsavai port->rcvdBpdu = False; 395*4eaa4710SRishi Srivatsavai break; 396*4eaa4710SRishi Srivatsavai case SUPERIOR: 397*4eaa4710SRishi Srivatsavai STP_VECT_copy (&port->portPrio, &port->msgPrio); 398*4eaa4710SRishi Srivatsavai STP_copy_times (&port->portTimes, &port->msgTimes); 399*4eaa4710SRishi Srivatsavai updtRcvdInfoWhile (this); 400*4eaa4710SRishi Srivatsavai #if 1 /* due 802.1y, Z.7 */ 401*4eaa4710SRishi Srivatsavai port->agreed = False; /* deleted due 802.y in SUPERIOR */ 402*4eaa4710SRishi Srivatsavai port->synced = False; /* due 802.y deleted in SUPERIOR */ 403*4eaa4710SRishi Srivatsavai #endif 404*4eaa4710SRishi Srivatsavai port->proposing = False; /* in SUPERIOR */ 405*4eaa4710SRishi Srivatsavai port->proposed = recordProposed (this, "SUPERIOR"); 406*4eaa4710SRishi Srivatsavai port->infoIs = Received; 407*4eaa4710SRishi Srivatsavai port->reselect = True; 408*4eaa4710SRishi Srivatsavai port->selected = False; 409*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 410*4eaa4710SRishi Srivatsavai if (this->debug) { 411*4eaa4710SRishi Srivatsavai STP_VECT_br_id_print ("stored: portPrio.design_bridge", 412*4eaa4710SRishi Srivatsavai &port->portPrio.design_bridge, True); 413*4eaa4710SRishi Srivatsavai STP_VECT_br_id_print ("stored: portPrio.root_bridge", 414*4eaa4710SRishi Srivatsavai &port->portPrio.root_bridge, True); 415*4eaa4710SRishi Srivatsavai stp_trace ("proposed=%d on port %s", 416*4eaa4710SRishi Srivatsavai (int) port->proposed, port->port_name); 417*4eaa4710SRishi Srivatsavai } 418*4eaa4710SRishi Srivatsavai #endif 419*4eaa4710SRishi Srivatsavai break; 420*4eaa4710SRishi Srivatsavai case REPEAT: 421*4eaa4710SRishi Srivatsavai port->proposed = recordProposed (this, "REPEAT"); 422*4eaa4710SRishi Srivatsavai updtRcvdInfoWhile (this); 423*4eaa4710SRishi Srivatsavai break; 424*4eaa4710SRishi Srivatsavai case AGREEMENT: 425*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 426*4eaa4710SRishi Srivatsavai if (port->roletrns->debug) { 427*4eaa4710SRishi Srivatsavai stp_trace ("(%s-%s) rx AGREEMENT flag !", 428*4eaa4710SRishi Srivatsavai port->owner->name, port->port_name); 429*4eaa4710SRishi Srivatsavai } 430*4eaa4710SRishi Srivatsavai #endif 431*4eaa4710SRishi Srivatsavai 432*4eaa4710SRishi Srivatsavai port->agreed = True; 433*4eaa4710SRishi Srivatsavai port->proposing = False; /* In AGREEMENT */ 434*4eaa4710SRishi Srivatsavai break; 435*4eaa4710SRishi Srivatsavai } 436*4eaa4710SRishi Srivatsavai 437*4eaa4710SRishi Srivatsavai } 438*4eaa4710SRishi Srivatsavai 439*4eaa4710SRishi Srivatsavai Bool STP_info_check_conditions (STATE_MACH_T* this) 440*4eaa4710SRishi Srivatsavai { 441*4eaa4710SRishi Srivatsavai register PORT_T* port = this->owner.port; 442*4eaa4710SRishi Srivatsavai 443*4eaa4710SRishi Srivatsavai if ((! port->portEnabled && port->infoIs != Disabled) || BEGIN == this->State) { 444*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, DISABLED); 445*4eaa4710SRishi Srivatsavai } 446*4eaa4710SRishi Srivatsavai 447*4eaa4710SRishi Srivatsavai switch (this->State) { 448*4eaa4710SRishi Srivatsavai case DISABLED: 449*4eaa4710SRishi Srivatsavai if (port->updtInfo) { 450*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, DISABLED); 451*4eaa4710SRishi Srivatsavai } 452*4eaa4710SRishi Srivatsavai if (port->portEnabled && port->selected) { 453*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, ENABLED); 454*4eaa4710SRishi Srivatsavai } 455*4eaa4710SRishi Srivatsavai if (port->rcvdBpdu) { 456*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, DISABLED); 457*4eaa4710SRishi Srivatsavai } 458*4eaa4710SRishi Srivatsavai break; 459*4eaa4710SRishi Srivatsavai case ENABLED: /* IEEE 802.1y, 17.21, Z.14 */ 460*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, AGED); 461*4eaa4710SRishi Srivatsavai case AGED: 462*4eaa4710SRishi Srivatsavai if (port->selected && port->updtInfo) { 463*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, UPDATE); 464*4eaa4710SRishi Srivatsavai } 465*4eaa4710SRishi Srivatsavai break; 466*4eaa4710SRishi Srivatsavai case UPDATE: 467*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, CURRENT); 468*4eaa4710SRishi Srivatsavai case CURRENT: 469*4eaa4710SRishi Srivatsavai if (port->selected && port->updtInfo) { 470*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, UPDATE); 471*4eaa4710SRishi Srivatsavai } 472*4eaa4710SRishi Srivatsavai 473*4eaa4710SRishi Srivatsavai if (Received == port->infoIs && 474*4eaa4710SRishi Srivatsavai ! port->rcvdInfoWhile && 475*4eaa4710SRishi Srivatsavai ! port->updtInfo && 476*4eaa4710SRishi Srivatsavai ! port->rcvdBpdu) { 477*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, AGED); 478*4eaa4710SRishi Srivatsavai } 479*4eaa4710SRishi Srivatsavai if (port->rcvdBpdu && !port->updtInfo) { 480*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, RECEIVE); 481*4eaa4710SRishi Srivatsavai } 482*4eaa4710SRishi Srivatsavai break; 483*4eaa4710SRishi Srivatsavai case RECEIVE: 484*4eaa4710SRishi Srivatsavai switch (port->rcvdMsg) { 485*4eaa4710SRishi Srivatsavai case SuperiorDesignateMsg: 486*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, SUPERIOR); 487*4eaa4710SRishi Srivatsavai case RepeatedDesignateMsg: 488*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, REPEAT); 489*4eaa4710SRishi Srivatsavai case ConfirmedRootMsg: 490*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, AGREEMENT); 491*4eaa4710SRishi Srivatsavai default: 492*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, CURRENT); 493*4eaa4710SRishi Srivatsavai } 494*4eaa4710SRishi Srivatsavai case SUPERIOR: 495*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, CURRENT); 496*4eaa4710SRishi Srivatsavai case REPEAT: 497*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, CURRENT); 498*4eaa4710SRishi Srivatsavai case AGREEMENT: 499*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, CURRENT); 500*4eaa4710SRishi Srivatsavai } 501*4eaa4710SRishi Srivatsavai 502*4eaa4710SRishi Srivatsavai return False; 503*4eaa4710SRishi Srivatsavai } 504