1 /************************************************************************
2 * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
3 * Copyright (C) 2001-2003 Optical Access
6 * This file is part of RSTP library.
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
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.
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
21 **********************************************************************/
23 /* Port Role Transitions state machine : 17.24 */
26 Diese Teil impliziert die "Port Role Transitions state machine".
27 Der Unterscied zwischen alten und neuen Standert impliziert die verschiedene Realisierung "Alternate and Backup ports.
28 Andere VerschiedenHeiten sind nicht so wichtig */
36 /*kd: hinzufügte die neue Funktionen, die im 801.2 benützen*/
38 CHOOSE(DISABLE_PORT), \
39 CHOOSE(DISABLED_PORT), \
40 CHOOSE(DESIGNATED_DISCARD), \
41 CHOOSE(ALTERNATE_PROPOSED), \
42 CHOOSE(ALTERNATE_AGREED), \
43 CHOOSE(ALTERNATE_PORT), \
46 CHOOSE(BLOCKED_PORT), \
47 CHOOSE(BACKUP_PORT), \
48 CHOOSE(ROOT_PROPOSED), \
49 CHOOSE(ROOT_AGREED), \
54 CHOOSE(ROOT_FORWARD), \
55 CHOOSE(DESIGNATED_PROPOSE), \
56 CHOOSE(DESIGNATED_SYNCED), \
57 CHOOSE(DESIGNATED_RETIRED), \
58 CHOOSE(DESIGNATED_PORT), \
59 CHOOSE(DESIGNATED_LISTEN), \
60 CHOOSE(DESIGNATED_LEARN), \
61 CHOOSE(DESIGNATED_FORWARD), \
64 #define GET_STATE_NAME STP_roletrns_get_state_name
70 /* 17.21.14 checked: leu */
72 setSyncTree (STATE_MACH_T
*this)
74 register PORT_T
* port
;
76 for (port
= this->owner
.port
->owner
->ports
; port
; port
= port
->next
) {
81 /* 17.21.15 checked: leu */
83 setReRootTree (STATE_MACH_T
*this)
85 register PORT_T
* port
;
87 for (port
= this->owner
.port
->owner
->ports
; port
; port
= port
->next
) {
94 compute_all_synced (PORT_T
* this)
96 register PORT_T
* port
;
98 for (port
= this->owner
->ports
; port
; port
= port
->next
) {
99 if (port
->port_index
== this->port_index
) continue;
100 if (! port
->synced
) {
107 /* 17.20.3 checked: leu */
108 static Bool
compute_allSynced (PORT_T
* this)
110 register PORT_T
* port
;
112 for (port
= this->owner
->ports
; port
; port
= port
->next
) {
114 if (port
->port_index
== this->port_index
) continue;
116 if (!port
->selected
||
117 (port
->role
!= port
->selectedRole
) ||
118 (!port
->synced
&& (port
->role
!= RootPort
))){
126 /* 17.20.10 checked: leu */
128 compute_reRooted (PORT_T
* this)
130 register PORT_T
* port
;
132 for (port
= this->owner
->ports
; port
; port
= port
->next
) {
133 if (port
->port_index
== this->port_index
) continue;
141 /***************************************************************/
142 static unsigned short
143 forward_del (PORT_T
* this)
145 register STPM_T
* stpm
;
146 register unsigned short retval
;
148 if (this->sendRSTP
== True
) {
149 retval
= stpm
->rootTimes
.HelloTime
;
151 retval
= stpm
->rootTimes
.ForwardDelay
;
158 /****************************************************************/
160 edgedel (PORT_T
* this)
162 register STPM_T
* stpm
;
163 register unsigned short EdgeDelay
;
165 if (this->operPointToPointMac
== True
)
167 EdgeDelay
= MigrateTime
;
171 EdgeDelay
= stpm
->rootTimes
.ForwardDelay
;
178 /*****************************************************************/
180 rstpVer (STATE_MACH_T
* self
)
183 STPM_T
*stpm
= self
->owner
.stpm
;
185 if (stpm
->ForceVersion
>= 2)
194 /*****************************************************************/
197 STP_roletrns_enter_state (STATE_MACH_T
* this)
199 register PORT_T
* port
= this->owner
.port
;
200 register STPM_T
* stpm
;
204 switch (this->State
) {
207 #if 1 /* due 802.1y Z.4 */
208 port
->role
= DisabledPort
;
210 port
->role
= port
->selectedRole
= DisabledPort
;
211 port
->reselect
= True
;
213 port
->learn
= False
;/*v INIT_PORT 802.1D */
214 port
->forward
= False
; /*v INIT_PORT 802.1D */
215 port
->synced
= False
; /* in INIT */
216 port
->sync
= True
; /* in INIT */
217 port
->reRoot
= True
; /* in INIT_PORT */
218 port
->rrWhile
= stpm
->rootTimes
.ForwardDelay
;
219 port
->fdWhile
= stpm
->rootTimes
.MaxAge
; /*kd: Zeile ist geändert. s.175 (Disabled Port Role)*/
223 STP_port_trace_flags ("after init", port
);
226 /*case BLOCK_PORT:*/ /*kd: Im neu ZustandMaschine das algoritm ist die andere. s 175. 801.2D*/
228 port
->role
= port
->selectedRole
;
230 port
->forward
= False
;
232 case DISABLED_PORT
: /*kd: s 175 801.2D*/
233 port
->fdWhile
= stpm
->rootTimes
.MaxAge
;
234 port
->synced
= True
; /* In BLOCKED_PORT */
237 port
->reRoot
= False
; /* BLOCKED_PORT */
242 /* setSyncBridge (this);*/
243 setSyncTree (this); /*kd: Die Zeile ist aus 802.1D*/
244 port
->proposed
= False
;
247 STP_port_trace_flags ("ROOT_PROPOSED", port
);
251 port
->proposed
= False
;
252 port
->sync
= False
; /* in ROOT_AGREED */
253 port
->agree
= True
; /* In ROOT_AGREED */ /*kd: aus 801.2D*/
254 port
->newInfo
= True
;
257 STP_port_trace_flags ("ROOT_AGREED", port
);
261 /* setReRootBridge (this);*/
262 setReRootTree (this);
265 STP_port_trace_flags ("REROOT", port
);
269 port
->role
= RootPort
;
270 port
->rrWhile
= stpm
->rootTimes
.ForwardDelay
;
273 STP_port_trace_flags ("ROOT_PORT", port
);
277 port
->reRoot
= False
; /* In REROOTED */
280 STP_port_trace_flags ("REROOTED", port
);
284 port
->fdWhile
= stpm
->rootTimes
.ForwardDelay
;
288 STP_port_trace_flags ("ROOT_LEARN", port
);
293 port
->forward
= True
;
296 STP_port_trace_flags ("ROOT_FORWARD", port
);
301 case DESIGNATED_PROPOSE
:
302 port
->proposing
= True
; /* in DESIGNATED_PROPOSE */
303 port
->edgeDelayWhile
= edgedel(port
);/*Die neue Zeile aus 801.2D*/
304 port
->newInfo
= True
;
307 STP_port_trace_flags ("DESIGNATED_PROPOSE", port
);
310 case DESIGNATED_SYNCED
:
312 port
->synced
= True
; /* DESIGNATED_SYNCED */
313 port
->sync
= False
; /* DESIGNATED_SYNCED */
316 STP_port_trace_flags ("DESIGNATED_SYNCED", port
);
319 case DESIGNATED_RETIRED
:
320 port
->reRoot
= False
; /* DESIGNATED_RETIRED */
323 STP_port_trace_flags ("DESIGNATED_RETIRED", port
);
326 case DESIGNATED_PORT
:
327 port
->role
= DesignatedPort
;
330 STP_port_trace_flags ("DESIGNATED_PORT", port
);
333 /* case DESIGNATED_LISTEN:*/
334 case DESIGNATED_DISCARD
: /*kd: 801.2D s 176*/
336 port
->forward
= False
;
337 port
->disputed
= False
;
338 port
->fdWhile
= stpm
->rootTimes
.ForwardDelay
;
341 STP_port_trace_flags ("DESIGNATED_DISCARD", port
);
344 case DESIGNATED_LEARN
:
346 port
->fdWhile
= stpm
->rootTimes
.ForwardDelay
;
349 STP_port_trace_flags ("DESIGNATED_LEARN", port
);
352 case DESIGNATED_FORWARD
:
353 port
->forward
= True
;
354 port
->agreed
= port
->sendRSTP
; /*kd: Die neue Zeile aus 801.2D.*/
358 STP_port_trace_flags ("DESIGNATED_FORWARD", port
);
363 /*kd: Die neue Teil für Alternate und Backup Port roles*/
364 /**********************************************/
367 case ALTERNATE_PROPOSED
:
368 setSyncTree (this); /*kd: 801.2D s 177 Alternate and Backup Port roles*/
369 port
->proposed
= False
;
372 STP_port_trace_flags ("ALTERNATE_PROPOSED", port
);
375 case ALTERNATE_AGREED
:
376 port
->proposed
= False
;
378 port
->newInfo
= True
;
381 STP_port_trace_flags ("ALTERNATE_AGREED", port
);
385 port
->fdWhile
= forward_del(port
);
389 port
->reRoot
= False
;
392 STP_port_trace_flags ("ALTERNATE_PORT", port
);
396 port
->role
= port
->selectedRole
;
398 port
->forward
= False
;
401 STP_port_trace_flags ("BLOCK_PORT", port
);
406 port
->rbWhile
= 2 * stpm
->rootTimes
.HelloTime
;
409 STP_port_trace_flags ("BACKUP_PORT", port
);
416 STP_roletrns_check_conditions (STATE_MACH_T
* this)
418 register PORT_T
*port
= this->owner
.port
;
419 register STPM_T
*stpm
;
425 if (BEGIN
== this->State
) {
426 return STP_hop_2_state (this, INIT_PORT
);
429 if (port
->role
!= port
->selectedRole
&&
432 switch (port
->selectedRole
) {
437 stp_trace ("hop to BLOCK_PORT role=%d selectedRole=%d",
438 (int) port
->role
, (int) port
->selectedRole
);
441 return STP_hop_2_state (this, BLOCK_PORT
);
443 return STP_hop_2_state (this, DISABLE_PORT
); /*kd: sehe die 17.20, 17.21, 17.22, 17.23 figuren aus 801.2D*/
445 return STP_hop_2_state (this, ROOT_PORT
);
447 return STP_hop_2_state (this, DESIGNATED_PORT
);
454 allSynced
= compute_allSynced (port
);
456 switch (this->State
) {
459 return STP_hop_2_state (this, DISABLE_PORT
); /*kd: die Änderung aus 802.1D*/
461 if (!port
->selected
|| port
->updtInfo
) break;
462 if (!port
->learning
&& !port
->forwarding
) {
463 return STP_hop_2_state (this, DISABLED_PORT
);
467 if (!port
->selected
|| port
->updtInfo
) break;
468 if (port
->fdWhile
!= stpm
->rootTimes
.MaxAge
||
472 return STP_hop_2_state (this, DISABLED_PORT
);
476 case ROOT_PROPOSED
: /**/
477 return STP_hop_2_state (this, ROOT_PORT
);
479 return STP_hop_2_state (this, ROOT_PORT
);
481 return STP_hop_2_state (this, ROOT_PORT
);
483 if (!port
->selected
|| port
->updtInfo
) break;
484 if (!port
->forward
&& !port
->reRoot
) {
485 return STP_hop_2_state (this, REROOT
);
487 if ((allSynced
&& !port
->agree
) || (port
->proposed
&& port
->agree
)) {
488 return STP_hop_2_state (this, ROOT_AGREED
);
490 if (port
->proposed
&& !port
->agree
) {
491 return STP_hop_2_state (this, ROOT_PROPOSED
);
494 reRooted
= compute_reRooted (port
);
495 if (((!port
->fdWhile
||
496 ((reRooted
&& port
->rbWhile
==0))) && rstpVer(this)) &&
497 /*kd: "rstpVersion" True if Protocol Version is greater than or equal to 2*/
498 port
->learn
&& !port
->forward
) {
499 return STP_hop_2_state (this, ROOT_FORWARD
);
501 if ((!port
->fdWhile
||
502 ((reRooted
&& !port
->rbWhile
) && rstpVer(this))) && /*kd: Jetz steht die alter parametr "ForceVersion>=2, aber die neu rstpVerson stehen muss. Beide haben die gleichen Bedeutung, und Ich lasse die alte"*/
504 return STP_hop_2_state (this, ROOT_LEARN
);
507 if (port
->reRoot
&& port
->forward
) {
508 return STP_hop_2_state (this, REROOTED
);
510 if (port
->rrWhile
!= stpm
->rootTimes
.ForwardDelay
) {
511 return STP_hop_2_state (this, ROOT_PORT
);
515 return STP_hop_2_state (this, ROOT_PORT
);
517 return STP_hop_2_state (this, ROOT_PORT
);
519 return STP_hop_2_state (this, ROOT_PORT
);
521 case DESIGNATED_PROPOSE
:
522 return STP_hop_2_state (this, DESIGNATED_PORT
);
523 case DESIGNATED_SYNCED
:
524 return STP_hop_2_state (this, DESIGNATED_PORT
);
525 case DESIGNATED_RETIRED
:
526 return STP_hop_2_state (this, DESIGNATED_PORT
);
527 case DESIGNATED_PORT
:
528 if (!port
->selected
|| port
->updtInfo
)
531 if (!port
->forward
&& !port
->agreed
&& !port
->proposing
&& !port
->operEdge
) {
532 return STP_hop_2_state (this, DESIGNATED_PROPOSE
);
535 if (port
->rrWhile
==0 && port
->reRoot
) {
536 return STP_hop_2_state (this, DESIGNATED_RETIRED
);
539 if (!port
->learning
&& !port
->forwarding
&& !port
->synced
) {
540 return STP_hop_2_state (this, DESIGNATED_SYNCED
);
543 if (port
->agreed
&& !port
->synced
) {
544 return STP_hop_2_state (this, DESIGNATED_SYNCED
);
546 if (port
->operEdge
&& !port
->synced
) {
547 return STP_hop_2_state (this, DESIGNATED_SYNCED
);
549 if (port
->sync
&& port
->synced
) {
550 return STP_hop_2_state (this, DESIGNATED_SYNCED
);
553 if ((port
->fdWhile
==0 || port
->agreed
|| port
->operEdge
) &&
554 (port
->rrWhile
==0 || !port
->reRoot
) &&
556 (port
->learn
&& !port
->forward
)) {
557 return STP_hop_2_state (this, DESIGNATED_FORWARD
);
559 if ((port
->fdWhile
==0 || port
->agreed
|| port
->operEdge
) &&
560 (port
->rrWhile
==0 || !port
->reRoot
) &&
561 !port
->sync
&& !port
->learn
) {
562 return STP_hop_2_state (this, DESIGNATED_LEARN
);
564 if (((port
->sync
&& !port
->synced
) ||
565 (port
->reRoot
&& port
->rrWhile
!=0) || port
->disputed
) &&
566 !port
->operEdge
&& (port
->learn
|| port
->forward
)) {
567 return STP_hop_2_state (this, DESIGNATED_DISCARD
);/*izmeneno*/
570 case DESIGNATED_DISCARD
:
571 return STP_hop_2_state (this, DESIGNATED_PORT
);
572 case DESIGNATED_LEARN
:
573 return STP_hop_2_state (this, DESIGNATED_PORT
);
574 case DESIGNATED_FORWARD
:
575 return STP_hop_2_state (this, DESIGNATED_PORT
);
577 /*kd: Für Alternate and Backup port teil*/
578 /****************************************/
579 case ALTERNATE_PROPOSED
:
580 return STP_hop_2_state (this, ALTERNATE_PORT
);
581 case ALTERNATE_AGREED
:
582 return STP_hop_2_state (this, ALTERNATE_PORT
);
584 return STP_hop_2_state (this, ALTERNATE_PORT
);
586 return STP_hop_2_state (this, ALTERNATE_PORT
);
589 if (!port
->selected
|| port
->updtInfo
)
592 if (!port
->agree
&& port
->proposed
) {
593 return STP_hop_2_state (this, ALTERNATE_PROPOSED
);
595 if ((allSynced
&& !port
->agree
) || (port
->proposed
&& port
->agree
)) {
596 return STP_hop_2_state (this, ALTERNATE_AGREED
);
598 if (port
->rbWhile
!= 2 * (unsigned int) stpm
->rootTimes
.HelloTime
&&
599 port
->role
== BackupPort
) {
600 return STP_hop_2_state (this, BACKUP_PORT
);
604 if ((port
->fdWhile
!= forward_del(port
)) ||
608 return STP_hop_2_state (this, ALTERNATE_PORT
);