1 /************************************************************************ 2 * RSTP library - Rapid Spanning Tree (802.1t, 802.1w) 3 * Copyright (C) 2001-2003 Optical Access 4 * Author: Alex Rozin 5 * 6 * This file is part of RSTP library. 7 * 8 * RSTP library is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU Lesser General Public License as published by the 10 * Free Software Foundation; version 2.1 11 * 12 * RSTP library is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public License 18 * along with RSTP library; see the file COPYING. If not, write to the Free 19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 20 * 02111-1307, USA. 21 **********************************************************************/ 22 23 /* STP PORT instance : 17.18, 17.15 */ 24 25 #include "base.h" 26 #include "stpm.h" 27 #include "stp_in.h" 28 29 /* #include "rolesel.h" */ 30 #include "portinfo.h" 31 #include "roletrns.h" 32 #include "sttrans.h" 33 #include "topoch.h" 34 #include "migrate.h" 35 #include "transmit.h" 36 #include "p2p.h" 37 #include "pcost.h" 38 #include "edge.h" 39 40 #include "stp_to.h" /* for STP_OUT_get_port_name & STP_OUT_get_port_link_status */ 41 42 int port_trace_flags; 43 44 PORT_T * 45 STP_port_create (STPM_T* stpm, int port_index) 46 { 47 PORT_T* this; 48 UID_STP_PORT_CFG_T port_cfg; 49 register int iii; 50 unsigned short port_prio; 51 52 /* check, if the port has just been added */ 53 for (this = stpm->ports; this; this = this->next) { 54 if (this->port_index == port_index) { 55 return NULL; 56 } 57 } 58 59 STP_NEW_IN_LIST(this, PORT_T, stpm->ports, "port create"); 60 61 this->owner = stpm; 62 this->machines = NULL; 63 this->port_index = port_index; 64 this->port_name = strdup (STP_OUT_get_port_name (port_index)); 65 this->uptime = 0; 66 67 STP_OUT_get_init_port_cfg (stpm->vlan_id, port_index, &port_cfg); 68 port_prio = port_cfg.port_priority; 69 this->admin_non_stp = port_cfg.admin_non_stp; 70 this->adminEdge = port_cfg.admin_edge; 71 this->adminPCost = port_cfg.admin_port_path_cost; 72 this->adminPointToPointMac = port_cfg.admin_point2point; 73 74 this->LinkDelay = DEF_LINK_DELAY; 75 this->port_id = (port_prio << 8) + port_index; 76 77 iii = 0; 78 this->timers[iii++] = &this->fdWhile; 79 this->timers[iii++] = &this->helloWhen; 80 this->timers[iii++] = &this->mdelayWhile; 81 this->timers[iii++] = &this->rbWhile; 82 this->timers[iii++] = &this->rcvdInfoWhile; 83 this->timers[iii++] = &this->rrWhile; 84 this->timers[iii++] = &this->tcWhile; 85 this->timers[iii++] = &this->txCount; 86 this->timers[iii++] = &this->lnkWhile; 87 88 /* create and bind port state machines */ 89 STP_STATE_MACH_IN_LIST(topoch); 90 91 STP_STATE_MACH_IN_LIST(migrate); 92 93 STP_STATE_MACH_IN_LIST(p2p); 94 95 STP_STATE_MACH_IN_LIST(edge); 96 97 STP_STATE_MACH_IN_LIST(pcost) 98 99 STP_STATE_MACH_IN_LIST(info); 100 101 STP_STATE_MACH_IN_LIST(roletrns); 102 103 STP_STATE_MACH_IN_LIST(sttrans); 104 105 STP_STATE_MACH_IN_LIST(transmit); 106 107 #ifdef STP_DBG 108 109 #if 0 110 this->roletrns->ignoreHop2State = 14; /* DESIGNATED_PORT; */ 111 this->info->ignoreHop2State = 3; /* CURRENT */ 112 this->transmit->ignoreHop2State = 3; /* IDLE */ 113 this->edge->ignoreHop2State = 0; /* DISABLED; */ 114 #endif 115 116 #if 0 117 this->info->debug = 1; 118 this->pcost->debug = 1; 119 this->p2p->debug = 1; 120 this->edge->debug = 1; 121 this->migrate->debug = 1; 122 this->sttrans->debug = 1; 123 this->topoch->debug = 1; 124 this->roletrns->debug = 1; 125 #endif 126 this->sttrans->debug = 1; 127 128 #endif 129 return this; 130 } 131 132 void 133 STP_port_init (PORT_T* this, STPM_T* stpm, Bool check_link) 134 { 135 if (check_link) { 136 this->adminEnable = STP_OUT_get_port_link_status (this->port_index); 137 STP_VECT_create (&this->designPrio, 138 &stpm->BrId, 139 0, 140 &stpm->BrId, 141 this->port_id, 142 this->port_id); 143 STP_copy_times (&this->designTimes, &stpm->rootTimes); 144 } 145 146 /* reset timers */ 147 this->fdWhile = 148 this->helloWhen = 149 this->mdelayWhile = 150 this->rbWhile = 151 this->rcvdInfoWhile = 152 this->rrWhile = 153 this->tcWhile = 154 this->txCount = 0; 155 156 this->msgPortRole = RSTP_PORT_ROLE_UNKN; 157 this->selectedRole = DisabledPort; 158 this->sendRSTP = True; 159 this->operSpeed = STP_OUT_get_port_oper_speed (this->port_index); 160 this->p2p_recompute = True; 161 } 162 163 void 164 STP_port_delete (PORT_T* this) 165 { 166 STPM_T* stpm; 167 register PORT_T* prev; 168 register PORT_T* tmp; 169 register STATE_MACH_T* stater; 170 register void* pv; 171 172 stpm = this->owner; 173 174 free (this->port_name); 175 for (stater = this->machines; stater; ) { 176 pv = (void*) stater->next; 177 STP_state_mach_delete (stater); 178 stater = (STATE_MACH_T*) pv; 179 } 180 181 prev = NULL; 182 for (tmp = stpm->ports; tmp; tmp = tmp->next) { 183 if (tmp->port_index == this->port_index) { 184 if (prev) { 185 prev->next = this->next; 186 } else { 187 stpm->ports = this->next; 188 } 189 STP_FREE(this, "stp instance"); 190 break; 191 } 192 prev = tmp; 193 } 194 } 195 196 int 197 STP_port_rx_bpdu (PORT_T* this, BPDU_T* bpdu, size_t len) 198 { 199 STP_info_rx_bpdu (this, bpdu, len); 200 201 return 0; 202 } 203 204 #ifdef STP_DBG 205 int STP_port_trace_state_machine (PORT_T* this, char* mach_name, int enadis) 206 { 207 STATE_MACH_T *stater; 208 int nmatch = 0; 209 210 for (stater = this->machines; stater; stater = stater->next) { 211 if (! strcmp (mach_name, "all") || ! strcmp (mach_name, stater->name)) { 212 if (stater->debug != enadis) 213 { 214 stp_trace ("port %s on %s trace %-8s (was %s) now %s", 215 this->port_name, this->owner->name, 216 stater->name, 217 stater->debug ? " enabled" :"disabled", 218 enadis ? " enabled" :"disabled"); 219 } 220 stater->debug = enadis; 221 nmatch++; 222 } 223 } 224 225 if (nmatch == 0) { 226 stp_trace("port %s no such state machine as '%s'", this->port_name, 227 mach_name); 228 return STP_No_Such_State_Machine; 229 } 230 231 return 0; 232 } 233 234 void STP_port_trace_flags (char* title, PORT_T* this) 235 { 236 unsigned long flag = 0L; 237 238 if (!port_trace_flags) return; 239 240 if (this->reRoot) flag |= 0x000001L; 241 if (this->sync) flag |= 0x000002L; 242 if (this->synced) flag |= 0x000004L; 243 244 if (this->proposed) flag |= 0x000010L; 245 if (this->proposing) flag |= 0x000020L; 246 if (this->agreed) flag |= 0x000040L; 247 if (this->updtInfo) flag |= 0x000080L; 248 249 if (this->operEdge) flag |= 0x000100L; 250 stp_trace (" %-12s: flags=0x%04lx fdWhile=%d port=%s", title, flag, this->fdWhile, this->port_name); 251 } 252 253 #endif 254