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