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 /* Port Protocol Migration state machine : 17.26 */
24
25 #include "base.h"
26 #include "stpm.h"
27
28 #define STATES { \
29 CHOOSE(INIT), \
30 CHOOSE(SEND_RSTP), \
31 CHOOSE(SENDING_RSTP), \
32 CHOOSE(SEND_STP), \
33 CHOOSE(SENDING_STP) \
34 }
35
36 #define GET_STATE_NAME STP_migrate_get_state_name
37 #include "choose.h"
38
39 #define MigrateTime 3 /* 17,16.4 */
40
41 void
STP_migrate_enter_state(STATE_MACH_T * this)42 STP_migrate_enter_state (STATE_MACH_T* this)
43 {
44 register PORT_T* port = this->owner.port;
45
46 switch (this->State) {
47 case BEGIN:
48 case INIT:
49 port->initPm = True;
50 port->mcheck = False;
51 break;
52 case SEND_RSTP:
53 port->mdelayWhile = MigrateTime;
54 port->mcheck = port->initPm = False;
55 port->sendRSTP = True;
56 break;
57 case SENDING_RSTP:
58 port->rcvdRSTP = port->rcvdSTP = False;
59 break;
60 case SEND_STP:
61 port->mdelayWhile = MigrateTime;
62 port->sendRSTP = False;
63 port->initPm = False;
64 break;
65 case SENDING_STP:
66 port->rcvdRSTP = port->rcvdSTP = False;
67 break;
68 }
69 }
70
71 Bool
STP_migrate_check_conditions(STATE_MACH_T * this)72 STP_migrate_check_conditions (STATE_MACH_T* this)
73 {
74 register PORT_T* port = this->owner.port;
75
76 if ((!port->portEnabled && !port->initPm) || BEGIN == this->State)
77 return STP_hop_2_state (this, INIT);
78
79 switch (this->State) {
80 case INIT:
81 if (port->portEnabled) {
82 return STP_hop_2_state (this, (port->owner->ForceVersion >= 2) ?
83 SEND_RSTP : SEND_STP);
84 }
85 break;
86 case SEND_RSTP:
87 return STP_hop_2_state (this, SENDING_RSTP);
88 case SENDING_RSTP:
89 if (port->mcheck)
90 return STP_hop_2_state (this, SEND_RSTP);
91 if (port->mdelayWhile &&
92 (port->rcvdSTP || port->rcvdRSTP)) {
93 return STP_hop_2_state (this, SENDING_RSTP);
94 }
95
96 if (!port->mdelayWhile && port->rcvdSTP) {
97 return STP_hop_2_state (this, SEND_STP);
98 }
99
100 if (port->owner->ForceVersion < 2) {
101 return STP_hop_2_state (this, SEND_STP);
102 }
103
104 break;
105 case SEND_STP:
106 return STP_hop_2_state (this, SENDING_STP);
107 case SENDING_STP:
108 if (port->mcheck)
109 return STP_hop_2_state (this, SEND_RSTP);
110 if (port->mdelayWhile &&
111 (port->rcvdSTP || port->rcvdRSTP))
112 return STP_hop_2_state (this, SENDING_STP);
113 if (!port->mdelayWhile && port->rcvdRSTP)
114 return STP_hop_2_state (this, SEND_RSTP);
115 break;
116 }
117 return False;
118 }
119
120