removed apps
[luayats.git] / src / rstp / roletrns.c
blobc653c8a47530376b35bb2d11ab2b987f04ccb7a4
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
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
20 * 02111-1307, USA.
21 **********************************************************************/
23 /* Port Role Transitions state machine : 17.24 */
25 /*kd:
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 */
31 #define this _this
32 #include "base.h"
34 #include "stpm.h"
36 /*kd: hinzufügte die neue Funktionen, die im 801.2 benützen*/
37 #define STATES {\
38 CHOOSE(DISABLE_PORT), \
39 CHOOSE(DISABLED_PORT), \
40 CHOOSE(DESIGNATED_DISCARD), \
41 CHOOSE(ALTERNATE_PROPOSED), \
42 CHOOSE(ALTERNATE_AGREED), \
43 CHOOSE(ALTERNATE_PORT), \
44 CHOOSE(BLOCK_PORT), \
45 CHOOSE(INIT_PORT), \
46 CHOOSE(BLOCKED_PORT), \
47 CHOOSE(BACKUP_PORT), \
48 CHOOSE(ROOT_PROPOSED), \
49 CHOOSE(ROOT_AGREED), \
50 CHOOSE(REROOT), \
51 CHOOSE(ROOT_PORT), \
52 CHOOSE(REROOTED), \
53 CHOOSE(ROOT_LEARN), \
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
65 #include "choose.h"
67 #define MigrateTime 3
70 /* 17.21.14 checked: leu */
71 static void
72 setSyncTree (STATE_MACH_T *this)
74 register PORT_T* port;
76 for (port = this->owner.port->owner->ports; port; port = port->next) {
77 port->sync = True;
81 /* 17.21.15 checked: leu */
82 static void
83 setReRootTree (STATE_MACH_T *this)
85 register PORT_T* port;
87 for (port = this->owner.port->owner->ports; port; port = port->next) {
88 port->reRoot = True;
92 #ifdef DELETEME
93 static Bool
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) {
101 return False;
104 return True;
106 #else
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) {
113 #if 0
114 if (port->port_index == this->port_index) continue;
115 #endif
116 if (!port->selected ||
117 (port->role != port->selectedRole) ||
118 (!port->synced && (port->role != RootPort))){
119 return False;
122 return True;
124 #endif
126 /* 17.20.10 checked: leu */
127 static Bool
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;
134 if (port->rrWhile) {
135 return False;
138 return True;
141 /***************************************************************/
142 static unsigned short
143 forward_del (PORT_T* this)
145 register STPM_T* stpm;
146 register unsigned short retval;
147 stpm = this->owner;
148 if (this->sendRSTP == True) {
149 retval = stpm->rootTimes.HelloTime;
150 } else {
151 retval = stpm->rootTimes.ForwardDelay;
153 return retval;
158 /****************************************************************/
159 static Bool
160 edgedel (PORT_T* this)
162 register STPM_T* stpm;
163 register unsigned short EdgeDelay;
164 stpm = this->owner;
165 if (this->operPointToPointMac == True)
167 EdgeDelay = MigrateTime;
169 else
171 EdgeDelay = stpm->rootTimes.ForwardDelay;
173 return EdgeDelay;
178 /*****************************************************************/
179 static Bool
180 rstpVer (STATE_MACH_T* self)
183 STPM_T *stpm = self->owner.stpm;
184 Bool rstpVersion;
185 if (stpm->ForceVersion >= 2)
186 rstpVersion =True;
187 else
188 rstpVersion = False;
189 return rstpVersion;
194 /*****************************************************************/
196 void
197 STP_roletrns_enter_state (STATE_MACH_T* this)
199 register PORT_T* port = this->owner.port;
200 register STPM_T* stpm;
202 stpm = port->owner;
204 switch (this->State) {
205 case BEGIN:
206 case INIT_PORT:
207 #if 1 /* due 802.1y Z.4 */
208 port->role = DisabledPort;
209 #else
210 port->role = port->selectedRole = DisabledPort;
211 port->reselect = True;
212 #endif
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)*/
220 port->rbWhile = 0;
221 #ifdef STP_DBG
222 if (this->debug)
223 STP_port_trace_flags ("after init", port);
224 #endif
225 break;
226 /*case BLOCK_PORT:*/ /*kd: Im neu ZustandMaschine das algoritm ist die andere. s 175. 801.2D*/
227 case DISABLE_PORT:
228 port->role = port->selectedRole;
229 port->learn = False;
230 port->forward = False;
231 break;
232 case DISABLED_PORT: /*kd: s 175 801.2D*/
233 port->fdWhile = stpm->rootTimes.MaxAge;
234 port->synced = True; /* In BLOCKED_PORT */
235 port->rrWhile = 0;
236 port->sync = False;
237 port->reRoot = False; /* BLOCKED_PORT */
238 break;
240 /* 17.23.2 */
241 case ROOT_PROPOSED:
242 /* setSyncBridge (this);*/
243 setSyncTree (this); /*kd: Die Zeile ist aus 802.1D*/
244 port->proposed = False;
245 #ifdef STP_DBG
246 if (this->debug)
247 STP_port_trace_flags ("ROOT_PROPOSED", port);
248 #endif
249 break;
250 case ROOT_AGREED:
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;
255 #ifdef STP_DBG
256 if (this->debug)
257 STP_port_trace_flags ("ROOT_AGREED", port);
258 #endif
259 break;
260 case REROOT:
261 /* setReRootBridge (this);*/
262 setReRootTree (this);
263 #ifdef STP_DBG
264 if (this->debug)
265 STP_port_trace_flags ("REROOT", port);
266 #endif
267 break;
268 case ROOT_PORT:
269 port->role = RootPort;
270 port->rrWhile = stpm->rootTimes.ForwardDelay;
271 #ifdef STP_DBG
272 if (this->debug)
273 STP_port_trace_flags ("ROOT_PORT", port);
274 #endif
275 break;
276 case REROOTED:
277 port->reRoot = False; /* In REROOTED */
278 #ifdef STP_DBG
279 if (this->debug)
280 STP_port_trace_flags ("REROOTED", port);
281 #endif
282 break;
283 case ROOT_LEARN:
284 port->fdWhile = stpm->rootTimes.ForwardDelay;
285 port->learn = True;
286 #ifdef STP_DBG
287 if (this->debug)
288 STP_port_trace_flags ("ROOT_LEARN", port);
289 #endif
290 break;
291 case ROOT_FORWARD:
292 port->fdWhile = 0;
293 port->forward = True;
294 #ifdef STP_DBG
295 if (this->debug)
296 STP_port_trace_flags ("ROOT_FORWARD", port);
297 #endif
298 break;
300 /* 17.23.3 */
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;
305 #ifdef STP_DBG
306 if (this->debug)
307 STP_port_trace_flags ("DESIGNATED_PROPOSE", port);
308 #endif
309 break;
310 case DESIGNATED_SYNCED:
311 port->rrWhile = 0;
312 port->synced = True; /* DESIGNATED_SYNCED */
313 port->sync = False; /* DESIGNATED_SYNCED */
314 #ifdef STP_DBG
315 if (this->debug)
316 STP_port_trace_flags ("DESIGNATED_SYNCED", port);
317 #endif
318 break;
319 case DESIGNATED_RETIRED:
320 port->reRoot = False; /* DESIGNATED_RETIRED */
321 #ifdef STP_DBG
322 if (this->debug)
323 STP_port_trace_flags ("DESIGNATED_RETIRED", port);
324 #endif
325 break;
326 case DESIGNATED_PORT:
327 port->role = DesignatedPort;
328 #ifdef STP_DBG
329 if (this->debug)
330 STP_port_trace_flags ("DESIGNATED_PORT", port);
331 #endif
332 break;
333 /* case DESIGNATED_LISTEN:*/
334 case DESIGNATED_DISCARD: /*kd: 801.2D s 176*/
335 port->learn = False;
336 port->forward = False;
337 port->disputed = False;
338 port->fdWhile = stpm->rootTimes.ForwardDelay;
339 #ifdef STP_DBG
340 if (this->debug)
341 STP_port_trace_flags ("DESIGNATED_DISCARD", port);
342 #endif
343 break;
344 case DESIGNATED_LEARN:
345 port->learn = True;
346 port->fdWhile = stpm->rootTimes.ForwardDelay;
347 #ifdef STP_DBG
348 if (this->debug)
349 STP_port_trace_flags ("DESIGNATED_LEARN", port);
350 #endif
351 break;
352 case DESIGNATED_FORWARD:
353 port->forward = True;
354 port->agreed = port->sendRSTP; /*kd: Die neue Zeile aus 801.2D.*/
355 port->fdWhile = 0;
356 #ifdef STP_DBG
357 if (this->debug)
358 STP_port_trace_flags ("DESIGNATED_FORWARD", port);
359 #endif
360 break;
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;
370 #ifdef STP_DBG
371 if (this->debug)
372 STP_port_trace_flags ("ALTERNATE_PROPOSED", port);
373 #endif
374 break;
375 case ALTERNATE_AGREED:
376 port->proposed = False;
377 port->agree = True;
378 port->newInfo = True;
379 #ifdef STP_DBG
380 if (this->debug)
381 STP_port_trace_flags ("ALTERNATE_AGREED", port);
382 #endif
383 break;
384 case ALTERNATE_PORT:
385 port->fdWhile = forward_del(port);
386 port->synced = True;
387 port->rrWhile = 0;
388 port->sync = False;
389 port->reRoot = False;
390 #ifdef STP_DBG
391 if(this->debug)
392 STP_port_trace_flags ("ALTERNATE_PORT", port);
393 #endif
394 break;
395 case BLOCK_PORT:
396 port->role = port->selectedRole;
397 port->learn = False;
398 port->forward = False;
399 #ifdef STP_DBG
400 if (this->debug)
401 STP_port_trace_flags ("BLOCK_PORT", port);
402 #endif
403 break;
405 case BACKUP_PORT:
406 port->rbWhile = 2 * stpm->rootTimes.HelloTime;
407 #ifdef STP_DBG
408 if (this->debug)
409 STP_port_trace_flags ("BACKUP_PORT", port);
410 #endif
411 break;
415 Bool
416 STP_roletrns_check_conditions (STATE_MACH_T* this)
418 register PORT_T *port = this->owner.port;
419 register STPM_T *stpm;
420 Bool allSynced;
421 Bool reRooted;
423 stpm = port->owner;
425 if (BEGIN == this->State) {
426 return STP_hop_2_state (this, INIT_PORT);
429 if (port->role != port->selectedRole &&
430 port->selected &&
431 ! port->updtInfo) {
432 switch (port->selectedRole) {
433 case AlternatePort:
434 case BackupPort:
435 #ifdef STP_DBG
436 if (this->debug) {
437 stp_trace ("hop to BLOCK_PORT role=%d selectedRole=%d",
438 (int) port->role, (int) port->selectedRole);
440 #endif
441 return STP_hop_2_state (this, BLOCK_PORT);
442 case DisabledPort:
443 return STP_hop_2_state (this, DISABLE_PORT); /*kd: sehe die 17.20, 17.21, 17.22, 17.23 figuren aus 801.2D*/
444 case RootPort:
445 return STP_hop_2_state (this, ROOT_PORT);
446 case DesignatedPort:
447 return STP_hop_2_state (this, DESIGNATED_PORT);
449 default:
450 return False;
454 allSynced = compute_allSynced (port);
456 switch (this->State) {
457 /* 17.23.1 */
458 case INIT_PORT:
459 return STP_hop_2_state (this, DISABLE_PORT); /*kd: die Änderung aus 802.1D*/
460 case DISABLE_PORT:
461 if (!port->selected || port->updtInfo) break;
462 if (!port->learning && !port->forwarding) {
463 return STP_hop_2_state (this, DISABLED_PORT);
465 break;
466 case DISABLED_PORT:
467 if (!port->selected || port->updtInfo) break;
468 if (port->fdWhile != stpm->rootTimes.MaxAge ||
469 port->sync ||
470 port->reRoot ||
471 !port->synced) {
472 return STP_hop_2_state (this, DISABLED_PORT);
474 break;
475 /* 17.23.2 */
476 case ROOT_PROPOSED: /**/
477 return STP_hop_2_state (this, ROOT_PORT);
478 case ROOT_AGREED:
479 return STP_hop_2_state (this, ROOT_PORT);
480 case REROOT:
481 return STP_hop_2_state (this, ROOT_PORT);
482 case 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"*/
503 !port->learn) {
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);
513 break;
514 case REROOTED:
515 return STP_hop_2_state (this, ROOT_PORT);
516 case ROOT_LEARN:
517 return STP_hop_2_state (this, ROOT_PORT);
518 case ROOT_FORWARD:
519 return STP_hop_2_state (this, ROOT_PORT);
520 /* 17.29.3 */ /**/
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)
529 break;
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) &&
555 !port->sync &&
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*/
569 break;
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);
583 case BLOCK_PORT:
584 return STP_hop_2_state (this, ALTERNATE_PORT);
585 case BACKUP_PORT:
586 return STP_hop_2_state (this, ALTERNATE_PORT);
588 case ALTERNATE_PORT:
589 if (!port->selected || port->updtInfo)
590 break;
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)) ||
605 port->sync ||
606 port->reRoot ||
607 !port->synced) {
608 return STP_hop_2_state (this, ALTERNATE_PORT);
610 break;
613 return False;