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 /* STP PORT instance : 17.18, 17.15 */ 24*4eaa4710SRishi Srivatsavai 25*4eaa4710SRishi Srivatsavai #include "base.h" 26*4eaa4710SRishi Srivatsavai #include "stpm.h" 27*4eaa4710SRishi Srivatsavai #include "stp_in.h" 28*4eaa4710SRishi Srivatsavai 29*4eaa4710SRishi Srivatsavai /* #include "rolesel.h" */ 30*4eaa4710SRishi Srivatsavai #include "portinfo.h" 31*4eaa4710SRishi Srivatsavai #include "roletrns.h" 32*4eaa4710SRishi Srivatsavai #include "sttrans.h" 33*4eaa4710SRishi Srivatsavai #include "topoch.h" 34*4eaa4710SRishi Srivatsavai #include "migrate.h" 35*4eaa4710SRishi Srivatsavai #include "transmit.h" 36*4eaa4710SRishi Srivatsavai #include "p2p.h" 37*4eaa4710SRishi Srivatsavai #include "pcost.h" 38*4eaa4710SRishi Srivatsavai #include "edge.h" 39*4eaa4710SRishi Srivatsavai 40*4eaa4710SRishi Srivatsavai #include "stp_to.h" /* for STP_OUT_get_port_name & STP_OUT_get_port_link_status */ 41*4eaa4710SRishi Srivatsavai 42*4eaa4710SRishi Srivatsavai int port_trace_flags; 43*4eaa4710SRishi Srivatsavai 44*4eaa4710SRishi Srivatsavai PORT_T * 45*4eaa4710SRishi Srivatsavai STP_port_create (STPM_T* stpm, int port_index) 46*4eaa4710SRishi Srivatsavai { 47*4eaa4710SRishi Srivatsavai PORT_T* this; 48*4eaa4710SRishi Srivatsavai UID_STP_PORT_CFG_T port_cfg; 49*4eaa4710SRishi Srivatsavai register int iii; 50*4eaa4710SRishi Srivatsavai unsigned short port_prio; 51*4eaa4710SRishi Srivatsavai 52*4eaa4710SRishi Srivatsavai /* check, if the port has just been added */ 53*4eaa4710SRishi Srivatsavai for (this = stpm->ports; this; this = this->next) { 54*4eaa4710SRishi Srivatsavai if (this->port_index == port_index) { 55*4eaa4710SRishi Srivatsavai return NULL; 56*4eaa4710SRishi Srivatsavai } 57*4eaa4710SRishi Srivatsavai } 58*4eaa4710SRishi Srivatsavai 59*4eaa4710SRishi Srivatsavai STP_NEW_IN_LIST(this, PORT_T, stpm->ports, "port create"); 60*4eaa4710SRishi Srivatsavai 61*4eaa4710SRishi Srivatsavai this->owner = stpm; 62*4eaa4710SRishi Srivatsavai this->machines = NULL; 63*4eaa4710SRishi Srivatsavai this->port_index = port_index; 64*4eaa4710SRishi Srivatsavai this->port_name = strdup (STP_OUT_get_port_name (port_index)); 65*4eaa4710SRishi Srivatsavai this->uptime = 0; 66*4eaa4710SRishi Srivatsavai 67*4eaa4710SRishi Srivatsavai STP_OUT_get_init_port_cfg (stpm->vlan_id, port_index, &port_cfg); 68*4eaa4710SRishi Srivatsavai port_prio = port_cfg.port_priority; 69*4eaa4710SRishi Srivatsavai this->admin_non_stp = port_cfg.admin_non_stp; 70*4eaa4710SRishi Srivatsavai this->adminEdge = port_cfg.admin_edge; 71*4eaa4710SRishi Srivatsavai this->adminPCost = port_cfg.admin_port_path_cost; 72*4eaa4710SRishi Srivatsavai this->adminPointToPointMac = port_cfg.admin_point2point; 73*4eaa4710SRishi Srivatsavai 74*4eaa4710SRishi Srivatsavai this->LinkDelay = DEF_LINK_DELAY; 75*4eaa4710SRishi Srivatsavai this->port_id = (port_prio << 8) + port_index; 76*4eaa4710SRishi Srivatsavai 77*4eaa4710SRishi Srivatsavai iii = 0; 78*4eaa4710SRishi Srivatsavai this->timers[iii++] = &this->fdWhile; 79*4eaa4710SRishi Srivatsavai this->timers[iii++] = &this->helloWhen; 80*4eaa4710SRishi Srivatsavai this->timers[iii++] = &this->mdelayWhile; 81*4eaa4710SRishi Srivatsavai this->timers[iii++] = &this->rbWhile; 82*4eaa4710SRishi Srivatsavai this->timers[iii++] = &this->rcvdInfoWhile; 83*4eaa4710SRishi Srivatsavai this->timers[iii++] = &this->rrWhile; 84*4eaa4710SRishi Srivatsavai this->timers[iii++] = &this->tcWhile; 85*4eaa4710SRishi Srivatsavai this->timers[iii++] = &this->txCount; 86*4eaa4710SRishi Srivatsavai this->timers[iii++] = &this->lnkWhile; 87*4eaa4710SRishi Srivatsavai 88*4eaa4710SRishi Srivatsavai /* create and bind port state machines */ 89*4eaa4710SRishi Srivatsavai STP_STATE_MACH_IN_LIST(topoch); 90*4eaa4710SRishi Srivatsavai 91*4eaa4710SRishi Srivatsavai STP_STATE_MACH_IN_LIST(migrate); 92*4eaa4710SRishi Srivatsavai 93*4eaa4710SRishi Srivatsavai STP_STATE_MACH_IN_LIST(p2p); 94*4eaa4710SRishi Srivatsavai 95*4eaa4710SRishi Srivatsavai STP_STATE_MACH_IN_LIST(edge); 96*4eaa4710SRishi Srivatsavai 97*4eaa4710SRishi Srivatsavai STP_STATE_MACH_IN_LIST(pcost) 98*4eaa4710SRishi Srivatsavai 99*4eaa4710SRishi Srivatsavai STP_STATE_MACH_IN_LIST(info); 100*4eaa4710SRishi Srivatsavai 101*4eaa4710SRishi Srivatsavai STP_STATE_MACH_IN_LIST(roletrns); 102*4eaa4710SRishi Srivatsavai 103*4eaa4710SRishi Srivatsavai STP_STATE_MACH_IN_LIST(sttrans); 104*4eaa4710SRishi Srivatsavai 105*4eaa4710SRishi Srivatsavai STP_STATE_MACH_IN_LIST(transmit); 106*4eaa4710SRishi Srivatsavai 107*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 108*4eaa4710SRishi Srivatsavai 109*4eaa4710SRishi Srivatsavai #if 0 110*4eaa4710SRishi Srivatsavai this->roletrns->ignoreHop2State = 14; /* DESIGNATED_PORT; */ 111*4eaa4710SRishi Srivatsavai this->info->ignoreHop2State = 3; /* CURRENT */ 112*4eaa4710SRishi Srivatsavai this->transmit->ignoreHop2State = 3; /* IDLE */ 113*4eaa4710SRishi Srivatsavai this->edge->ignoreHop2State = 0; /* DISABLED; */ 114*4eaa4710SRishi Srivatsavai #endif 115*4eaa4710SRishi Srivatsavai 116*4eaa4710SRishi Srivatsavai #if 0 117*4eaa4710SRishi Srivatsavai this->info->debug = 1; 118*4eaa4710SRishi Srivatsavai this->pcost->debug = 1; 119*4eaa4710SRishi Srivatsavai this->p2p->debug = 1; 120*4eaa4710SRishi Srivatsavai this->edge->debug = 1; 121*4eaa4710SRishi Srivatsavai this->migrate->debug = 1; 122*4eaa4710SRishi Srivatsavai this->sttrans->debug = 1; 123*4eaa4710SRishi Srivatsavai this->topoch->debug = 1; 124*4eaa4710SRishi Srivatsavai this->roletrns->debug = 1; 125*4eaa4710SRishi Srivatsavai #endif 126*4eaa4710SRishi Srivatsavai this->sttrans->debug = 1; 127*4eaa4710SRishi Srivatsavai 128*4eaa4710SRishi Srivatsavai #endif 129*4eaa4710SRishi Srivatsavai return this; 130*4eaa4710SRishi Srivatsavai } 131*4eaa4710SRishi Srivatsavai 132*4eaa4710SRishi Srivatsavai void 133*4eaa4710SRishi Srivatsavai STP_port_init (PORT_T* this, STPM_T* stpm, Bool check_link) 134*4eaa4710SRishi Srivatsavai { 135*4eaa4710SRishi Srivatsavai if (check_link) { 136*4eaa4710SRishi Srivatsavai this->adminEnable = STP_OUT_get_port_link_status (this->port_index); 137*4eaa4710SRishi Srivatsavai STP_VECT_create (&this->designPrio, 138*4eaa4710SRishi Srivatsavai &stpm->BrId, 139*4eaa4710SRishi Srivatsavai 0, 140*4eaa4710SRishi Srivatsavai &stpm->BrId, 141*4eaa4710SRishi Srivatsavai this->port_id, 142*4eaa4710SRishi Srivatsavai this->port_id); 143*4eaa4710SRishi Srivatsavai STP_copy_times (&this->designTimes, &stpm->rootTimes); 144*4eaa4710SRishi Srivatsavai } 145*4eaa4710SRishi Srivatsavai 146*4eaa4710SRishi Srivatsavai /* reset timers */ 147*4eaa4710SRishi Srivatsavai this->fdWhile = 148*4eaa4710SRishi Srivatsavai this->helloWhen = 149*4eaa4710SRishi Srivatsavai this->mdelayWhile = 150*4eaa4710SRishi Srivatsavai this->rbWhile = 151*4eaa4710SRishi Srivatsavai this->rcvdInfoWhile = 152*4eaa4710SRishi Srivatsavai this->rrWhile = 153*4eaa4710SRishi Srivatsavai this->tcWhile = 154*4eaa4710SRishi Srivatsavai this->txCount = 0; 155*4eaa4710SRishi Srivatsavai 156*4eaa4710SRishi Srivatsavai this->msgPortRole = RSTP_PORT_ROLE_UNKN; 157*4eaa4710SRishi Srivatsavai this->selectedRole = DisabledPort; 158*4eaa4710SRishi Srivatsavai this->sendRSTP = True; 159*4eaa4710SRishi Srivatsavai this->operSpeed = STP_OUT_get_port_oper_speed (this->port_index); 160*4eaa4710SRishi Srivatsavai this->p2p_recompute = True; 161*4eaa4710SRishi Srivatsavai } 162*4eaa4710SRishi Srivatsavai 163*4eaa4710SRishi Srivatsavai void 164*4eaa4710SRishi Srivatsavai STP_port_delete (PORT_T* this) 165*4eaa4710SRishi Srivatsavai { 166*4eaa4710SRishi Srivatsavai STPM_T* stpm; 167*4eaa4710SRishi Srivatsavai register PORT_T* prev; 168*4eaa4710SRishi Srivatsavai register PORT_T* tmp; 169*4eaa4710SRishi Srivatsavai register STATE_MACH_T* stater; 170*4eaa4710SRishi Srivatsavai register void* pv; 171*4eaa4710SRishi Srivatsavai 172*4eaa4710SRishi Srivatsavai stpm = this->owner; 173*4eaa4710SRishi Srivatsavai 174*4eaa4710SRishi Srivatsavai free (this->port_name); 175*4eaa4710SRishi Srivatsavai for (stater = this->machines; stater; ) { 176*4eaa4710SRishi Srivatsavai pv = (void*) stater->next; 177*4eaa4710SRishi Srivatsavai STP_state_mach_delete (stater); 178*4eaa4710SRishi Srivatsavai stater = (STATE_MACH_T*) pv; 179*4eaa4710SRishi Srivatsavai } 180*4eaa4710SRishi Srivatsavai 181*4eaa4710SRishi Srivatsavai prev = NULL; 182*4eaa4710SRishi Srivatsavai for (tmp = stpm->ports; tmp; tmp = tmp->next) { 183*4eaa4710SRishi Srivatsavai if (tmp->port_index == this->port_index) { 184*4eaa4710SRishi Srivatsavai if (prev) { 185*4eaa4710SRishi Srivatsavai prev->next = this->next; 186*4eaa4710SRishi Srivatsavai } else { 187*4eaa4710SRishi Srivatsavai stpm->ports = this->next; 188*4eaa4710SRishi Srivatsavai } 189*4eaa4710SRishi Srivatsavai STP_FREE(this, "stp instance"); 190*4eaa4710SRishi Srivatsavai break; 191*4eaa4710SRishi Srivatsavai } 192*4eaa4710SRishi Srivatsavai prev = tmp; 193*4eaa4710SRishi Srivatsavai } 194*4eaa4710SRishi Srivatsavai } 195*4eaa4710SRishi Srivatsavai 196*4eaa4710SRishi Srivatsavai int 197*4eaa4710SRishi Srivatsavai STP_port_rx_bpdu (PORT_T* this, BPDU_T* bpdu, size_t len) 198*4eaa4710SRishi Srivatsavai { 199*4eaa4710SRishi Srivatsavai STP_info_rx_bpdu (this, bpdu, len); 200*4eaa4710SRishi Srivatsavai 201*4eaa4710SRishi Srivatsavai return 0; 202*4eaa4710SRishi Srivatsavai } 203*4eaa4710SRishi Srivatsavai 204*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 205*4eaa4710SRishi Srivatsavai int STP_port_trace_state_machine (PORT_T* this, char* mach_name, int enadis) 206*4eaa4710SRishi Srivatsavai { 207*4eaa4710SRishi Srivatsavai STATE_MACH_T *stater; 208*4eaa4710SRishi Srivatsavai int nmatch = 0; 209*4eaa4710SRishi Srivatsavai 210*4eaa4710SRishi Srivatsavai for (stater = this->machines; stater; stater = stater->next) { 211*4eaa4710SRishi Srivatsavai if (! strcmp (mach_name, "all") || ! strcmp (mach_name, stater->name)) { 212*4eaa4710SRishi Srivatsavai if (stater->debug != enadis) 213*4eaa4710SRishi Srivatsavai { 214*4eaa4710SRishi Srivatsavai stp_trace ("port %s on %s trace %-8s (was %s) now %s", 215*4eaa4710SRishi Srivatsavai this->port_name, this->owner->name, 216*4eaa4710SRishi Srivatsavai stater->name, 217*4eaa4710SRishi Srivatsavai stater->debug ? " enabled" :"disabled", 218*4eaa4710SRishi Srivatsavai enadis ? " enabled" :"disabled"); 219*4eaa4710SRishi Srivatsavai } 220*4eaa4710SRishi Srivatsavai stater->debug = enadis; 221*4eaa4710SRishi Srivatsavai nmatch++; 222*4eaa4710SRishi Srivatsavai } 223*4eaa4710SRishi Srivatsavai } 224*4eaa4710SRishi Srivatsavai 225*4eaa4710SRishi Srivatsavai if (nmatch == 0) { 226*4eaa4710SRishi Srivatsavai stp_trace("port %s no such state machine as '%s'", this->port_name, 227*4eaa4710SRishi Srivatsavai mach_name); 228*4eaa4710SRishi Srivatsavai return STP_No_Such_State_Machine; 229*4eaa4710SRishi Srivatsavai } 230*4eaa4710SRishi Srivatsavai 231*4eaa4710SRishi Srivatsavai return 0; 232*4eaa4710SRishi Srivatsavai } 233*4eaa4710SRishi Srivatsavai 234*4eaa4710SRishi Srivatsavai void STP_port_trace_flags (char* title, PORT_T* this) 235*4eaa4710SRishi Srivatsavai { 236*4eaa4710SRishi Srivatsavai unsigned long flag = 0L; 237*4eaa4710SRishi Srivatsavai 238*4eaa4710SRishi Srivatsavai if (!port_trace_flags) return; 239*4eaa4710SRishi Srivatsavai 240*4eaa4710SRishi Srivatsavai if (this->reRoot) flag |= 0x000001L; 241*4eaa4710SRishi Srivatsavai if (this->sync) flag |= 0x000002L; 242*4eaa4710SRishi Srivatsavai if (this->synced) flag |= 0x000004L; 243*4eaa4710SRishi Srivatsavai 244*4eaa4710SRishi Srivatsavai if (this->proposed) flag |= 0x000010L; 245*4eaa4710SRishi Srivatsavai if (this->proposing) flag |= 0x000020L; 246*4eaa4710SRishi Srivatsavai if (this->agreed) flag |= 0x000040L; 247*4eaa4710SRishi Srivatsavai if (this->updtInfo) flag |= 0x000080L; 248*4eaa4710SRishi Srivatsavai 249*4eaa4710SRishi Srivatsavai if (this->operEdge) flag |= 0x000100L; 250*4eaa4710SRishi Srivatsavai stp_trace (" %-12s: flags=0x%04lx fdWhile=%d port=%s", title, flag, this->fdWhile, this->port_name); 251*4eaa4710SRishi Srivatsavai } 252*4eaa4710SRishi Srivatsavai 253*4eaa4710SRishi Srivatsavai #endif 254