xref: /onnv-gate/usr/src/lib/librstp/common/topoch.c (revision 10491:8893b747ecdf)
1*10491SRishi.Srivatsavai@Sun.COM /************************************************************************
2*10491SRishi.Srivatsavai@Sun.COM  * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
3*10491SRishi.Srivatsavai@Sun.COM  * Copyright (C) 2001-2003 Optical Access
4*10491SRishi.Srivatsavai@Sun.COM  * Author: Alex Rozin
5*10491SRishi.Srivatsavai@Sun.COM  *
6*10491SRishi.Srivatsavai@Sun.COM  * This file is part of RSTP library.
7*10491SRishi.Srivatsavai@Sun.COM  *
8*10491SRishi.Srivatsavai@Sun.COM  * RSTP library is free software; you can redistribute it and/or modify it
9*10491SRishi.Srivatsavai@Sun.COM  * under the terms of the GNU Lesser General Public License as published by the
10*10491SRishi.Srivatsavai@Sun.COM  * Free Software Foundation; version 2.1
11*10491SRishi.Srivatsavai@Sun.COM  *
12*10491SRishi.Srivatsavai@Sun.COM  * RSTP library is distributed in the hope that it will be useful, but
13*10491SRishi.Srivatsavai@Sun.COM  * WITHOUT ANY WARRANTY; without even the implied warranty of
14*10491SRishi.Srivatsavai@Sun.COM  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
15*10491SRishi.Srivatsavai@Sun.COM  * General Public License for more details.
16*10491SRishi.Srivatsavai@Sun.COM  *
17*10491SRishi.Srivatsavai@Sun.COM  * You should have received a copy of the GNU Lesser General Public License
18*10491SRishi.Srivatsavai@Sun.COM  * along with RSTP library; see the file COPYING.  If not, write to the Free
19*10491SRishi.Srivatsavai@Sun.COM  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20*10491SRishi.Srivatsavai@Sun.COM  * 02111-1307, USA.
21*10491SRishi.Srivatsavai@Sun.COM  **********************************************************************/
22*10491SRishi.Srivatsavai@Sun.COM 
23*10491SRishi.Srivatsavai@Sun.COM /* Topolgy Change state machine : 17.25 */
24*10491SRishi.Srivatsavai@Sun.COM 
25*10491SRishi.Srivatsavai@Sun.COM #include "base.h"
26*10491SRishi.Srivatsavai@Sun.COM #include "stpm.h"
27*10491SRishi.Srivatsavai@Sun.COM #include "stp_to.h" /* for STP_OUT_flush_lt */
28*10491SRishi.Srivatsavai@Sun.COM 
29*10491SRishi.Srivatsavai@Sun.COM #define STATES { \
30*10491SRishi.Srivatsavai@Sun.COM   CHOOSE(INIT),             \
31*10491SRishi.Srivatsavai@Sun.COM   CHOOSE(INACTIVE),         \
32*10491SRishi.Srivatsavai@Sun.COM   CHOOSE(TCACTIVE),         \
33*10491SRishi.Srivatsavai@Sun.COM   CHOOSE(DETECTED),         \
34*10491SRishi.Srivatsavai@Sun.COM   CHOOSE(NOTIFIED_TC),          \
35*10491SRishi.Srivatsavai@Sun.COM   CHOOSE(PROPAGATING),          \
36*10491SRishi.Srivatsavai@Sun.COM   CHOOSE(ACKNOWLEDGED),         \
37*10491SRishi.Srivatsavai@Sun.COM   CHOOSE(NOTIFIED_TCN)         \
38*10491SRishi.Srivatsavai@Sun.COM }
39*10491SRishi.Srivatsavai@Sun.COM 
40*10491SRishi.Srivatsavai@Sun.COM #define GET_STATE_NAME STP_topoch_get_state_name
41*10491SRishi.Srivatsavai@Sun.COM #include "choose.h"
42*10491SRishi.Srivatsavai@Sun.COM 
43*10491SRishi.Srivatsavai@Sun.COM #ifndef STRONGLY_SPEC_802_1W
44*10491SRishi.Srivatsavai@Sun.COM /*
45*10491SRishi.Srivatsavai@Sun.COM  * In many kinds of hardware the function
46*10491SRishi.Srivatsavai@Sun.COM  * STP_OUT_flush_lt is a) is very hard and b) cannot
47*10491SRishi.Srivatsavai@Sun.COM  * delete learning emtries per port. The alternate
48*10491SRishi.Srivatsavai@Sun.COM  * method may be used: we don't care operEdge flag here,
49*10491SRishi.Srivatsavai@Sun.COM  * but clean learning table once for TopologyChange
50*10491SRishi.Srivatsavai@Sun.COM  * for all ports, except the received port. I am ready to discuss :(
51*10491SRishi.Srivatsavai@Sun.COM  * See below word STRONGLY_SPEC_802_1W
52*10491SRishi.Srivatsavai@Sun.COM  */
53*10491SRishi.Srivatsavai@Sun.COM #else
54*10491SRishi.Srivatsavai@Sun.COM static Bool
flush(STATE_MACH_T * this,char * reason)55*10491SRishi.Srivatsavai@Sun.COM flush (STATE_MACH_T *this, char* reason) /* 17.19.9 */
56*10491SRishi.Srivatsavai@Sun.COM {
57*10491SRishi.Srivatsavai@Sun.COM   register PORT_T* port = this->owner.port;
58*10491SRishi.Srivatsavai@Sun.COM   Bool bret;
59*10491SRishi.Srivatsavai@Sun.COM 
60*10491SRishi.Srivatsavai@Sun.COM   if (port->operEdge) return True;
61*10491SRishi.Srivatsavai@Sun.COM   if (this->debug) {
62*10491SRishi.Srivatsavai@Sun.COM     stp_trace("%s (%s, %s, %s, '%s')",
63*10491SRishi.Srivatsavai@Sun.COM         "flush", port->port_name, port->owner->name,
64*10491SRishi.Srivatsavai@Sun.COM         LT_FLASH_ONLY_THE_PORT == type ? "this port" : "other ports",
65*10491SRishi.Srivatsavai@Sun.COM         reason);
66*10491SRishi.Srivatsavai@Sun.COM   }
67*10491SRishi.Srivatsavai@Sun.COM 
68*10491SRishi.Srivatsavai@Sun.COM   bret = STP_OUT_flush_lt (port->port_index, port->owner->vlan_id,
69*10491SRishi.Srivatsavai@Sun.COM                            LT_FLASH_ONLY_THE_PORT, reason);
70*10491SRishi.Srivatsavai@Sun.COM }
71*10491SRishi.Srivatsavai@Sun.COM #endif
72*10491SRishi.Srivatsavai@Sun.COM 
73*10491SRishi.Srivatsavai@Sun.COM static void
setTcPropBridge(STATE_MACH_T * this,char * reason)74*10491SRishi.Srivatsavai@Sun.COM setTcPropBridge (STATE_MACH_T* this, char* reason) /* 17.19.14 */
75*10491SRishi.Srivatsavai@Sun.COM {
76*10491SRishi.Srivatsavai@Sun.COM   register PORT_T* port = this->owner.port;
77*10491SRishi.Srivatsavai@Sun.COM   register PORT_T* tmp;
78*10491SRishi.Srivatsavai@Sun.COM 
79*10491SRishi.Srivatsavai@Sun.COM   for (tmp = port->owner->ports; tmp; tmp = tmp->next) {
80*10491SRishi.Srivatsavai@Sun.COM     if (tmp->port_index != port->port_index)
81*10491SRishi.Srivatsavai@Sun.COM       tmp->tcProp = True;
82*10491SRishi.Srivatsavai@Sun.COM   }
83*10491SRishi.Srivatsavai@Sun.COM 
84*10491SRishi.Srivatsavai@Sun.COM #ifndef STRONGLY_SPEC_802_1W
85*10491SRishi.Srivatsavai@Sun.COM #ifdef STP_DBG
86*10491SRishi.Srivatsavai@Sun.COM   if (this->debug) {
87*10491SRishi.Srivatsavai@Sun.COM     stp_trace("%s (%s, %s, %s, '%s')",
88*10491SRishi.Srivatsavai@Sun.COM         "clearFDB", port->port_name, port->owner->name,
89*10491SRishi.Srivatsavai@Sun.COM         "other ports", reason);
90*10491SRishi.Srivatsavai@Sun.COM   }
91*10491SRishi.Srivatsavai@Sun.COM #endif
92*10491SRishi.Srivatsavai@Sun.COM 
93*10491SRishi.Srivatsavai@Sun.COM   STP_OUT_flush_lt (port->port_index, port->owner->vlan_id,
94*10491SRishi.Srivatsavai@Sun.COM                     LT_FLASH_ALL_PORTS_EXCLUDE_THIS, reason);
95*10491SRishi.Srivatsavai@Sun.COM #endif
96*10491SRishi.Srivatsavai@Sun.COM }
97*10491SRishi.Srivatsavai@Sun.COM 
98*10491SRishi.Srivatsavai@Sun.COM static unsigned int
newTcWhile(STATE_MACH_T * this)99*10491SRishi.Srivatsavai@Sun.COM newTcWhile (STATE_MACH_T* this) /* 17.19.7 */
100*10491SRishi.Srivatsavai@Sun.COM {
101*10491SRishi.Srivatsavai@Sun.COM   register PORT_T* port = this->owner.port;
102*10491SRishi.Srivatsavai@Sun.COM 
103*10491SRishi.Srivatsavai@Sun.COM   if (port->sendRSTP && port->operPointToPointMac) {
104*10491SRishi.Srivatsavai@Sun.COM     return 2 * port->owner->rootTimes.HelloTime;
105*10491SRishi.Srivatsavai@Sun.COM   }
106*10491SRishi.Srivatsavai@Sun.COM   return port->owner->rootTimes.MaxAge;
107*10491SRishi.Srivatsavai@Sun.COM }
108*10491SRishi.Srivatsavai@Sun.COM 
109*10491SRishi.Srivatsavai@Sun.COM void
STP_topoch_enter_state(STATE_MACH_T * this)110*10491SRishi.Srivatsavai@Sun.COM STP_topoch_enter_state (STATE_MACH_T* this)
111*10491SRishi.Srivatsavai@Sun.COM {
112*10491SRishi.Srivatsavai@Sun.COM   register PORT_T*      port = this->owner.port;
113*10491SRishi.Srivatsavai@Sun.COM 
114*10491SRishi.Srivatsavai@Sun.COM   switch (this->State) {
115*10491SRishi.Srivatsavai@Sun.COM     case BEGIN:
116*10491SRishi.Srivatsavai@Sun.COM     case INIT:
117*10491SRishi.Srivatsavai@Sun.COM #ifdef STRONGLY_SPEC_802_1W
118*10491SRishi.Srivatsavai@Sun.COM       flush (this, "topoch INIT");
119*10491SRishi.Srivatsavai@Sun.COM #endif
120*10491SRishi.Srivatsavai@Sun.COM       port->tcWhile = 0;
121*10491SRishi.Srivatsavai@Sun.COM       port->tc =
122*10491SRishi.Srivatsavai@Sun.COM       port->tcProp =
123*10491SRishi.Srivatsavai@Sun.COM       port->tcAck = False;
124*10491SRishi.Srivatsavai@Sun.COM       break;
125*10491SRishi.Srivatsavai@Sun.COM     case INACTIVE:
126*10491SRishi.Srivatsavai@Sun.COM       port->rcvdTc =
127*10491SRishi.Srivatsavai@Sun.COM       port->rcvdTcn =
128*10491SRishi.Srivatsavai@Sun.COM       port->rcvdTcAck = port->tc = port->tcProp = False;
129*10491SRishi.Srivatsavai@Sun.COM       break;
130*10491SRishi.Srivatsavai@Sun.COM     case TCACTIVE:
131*10491SRishi.Srivatsavai@Sun.COM       break;
132*10491SRishi.Srivatsavai@Sun.COM     case DETECTED:
133*10491SRishi.Srivatsavai@Sun.COM       port->tcWhile = newTcWhile (this);
134*10491SRishi.Srivatsavai@Sun.COM #ifdef STP_DBG
135*10491SRishi.Srivatsavai@Sun.COM   if (this->debug)
136*10491SRishi.Srivatsavai@Sun.COM     stp_trace("DETECTED: tcWhile=%d on port %s",
137*10491SRishi.Srivatsavai@Sun.COM         port->tcWhile, port->port_name);
138*10491SRishi.Srivatsavai@Sun.COM #endif
139*10491SRishi.Srivatsavai@Sun.COM       setTcPropBridge (this, "DETECTED");
140*10491SRishi.Srivatsavai@Sun.COM       port->tc = False;
141*10491SRishi.Srivatsavai@Sun.COM       break;
142*10491SRishi.Srivatsavai@Sun.COM     case NOTIFIED_TC:
143*10491SRishi.Srivatsavai@Sun.COM       port->rcvdTcn = port->rcvdTc = False;
144*10491SRishi.Srivatsavai@Sun.COM       if (port->role == DesignatedPort) {
145*10491SRishi.Srivatsavai@Sun.COM         port->tcAck = True;
146*10491SRishi.Srivatsavai@Sun.COM       }
147*10491SRishi.Srivatsavai@Sun.COM       setTcPropBridge (this, "NOTIFIED_TC");
148*10491SRishi.Srivatsavai@Sun.COM       break;
149*10491SRishi.Srivatsavai@Sun.COM     case PROPAGATING:
150*10491SRishi.Srivatsavai@Sun.COM       port->tcWhile = newTcWhile (this);
151*10491SRishi.Srivatsavai@Sun.COM #ifdef STP_DBG
152*10491SRishi.Srivatsavai@Sun.COM   if (this->debug)
153*10491SRishi.Srivatsavai@Sun.COM     stp_trace("PROPAGATING: tcWhile=%d on port %s",
154*10491SRishi.Srivatsavai@Sun.COM         port->tcWhile, port->port_name);
155*10491SRishi.Srivatsavai@Sun.COM #endif
156*10491SRishi.Srivatsavai@Sun.COM #ifdef STRONGLY_SPEC_802_1W
157*10491SRishi.Srivatsavai@Sun.COM       flush (this, "topoch PROPAGATING");
158*10491SRishi.Srivatsavai@Sun.COM #endif
159*10491SRishi.Srivatsavai@Sun.COM       port->tcProp = False;
160*10491SRishi.Srivatsavai@Sun.COM       break;
161*10491SRishi.Srivatsavai@Sun.COM     case ACKNOWLEDGED:
162*10491SRishi.Srivatsavai@Sun.COM       port->tcWhile = 0;
163*10491SRishi.Srivatsavai@Sun.COM #ifdef STP_DBG
164*10491SRishi.Srivatsavai@Sun.COM   if (this->debug)
165*10491SRishi.Srivatsavai@Sun.COM     stp_trace("ACKNOWLEDGED: tcWhile=%d on port %s",
166*10491SRishi.Srivatsavai@Sun.COM         port->tcWhile, port->port_name);
167*10491SRishi.Srivatsavai@Sun.COM #endif
168*10491SRishi.Srivatsavai@Sun.COM       port->rcvdTcAck = False;
169*10491SRishi.Srivatsavai@Sun.COM       break;
170*10491SRishi.Srivatsavai@Sun.COM     case NOTIFIED_TCN:
171*10491SRishi.Srivatsavai@Sun.COM       port->tcWhile = newTcWhile (this);
172*10491SRishi.Srivatsavai@Sun.COM #ifdef STP_DBG
173*10491SRishi.Srivatsavai@Sun.COM   if (this->debug)
174*10491SRishi.Srivatsavai@Sun.COM     stp_trace("NOTIFIED_TCN: tcWhile=%d on port %s",
175*10491SRishi.Srivatsavai@Sun.COM         port->tcWhile, port->port_name);
176*10491SRishi.Srivatsavai@Sun.COM #endif
177*10491SRishi.Srivatsavai@Sun.COM       break;
178*10491SRishi.Srivatsavai@Sun.COM   };
179*10491SRishi.Srivatsavai@Sun.COM }
180*10491SRishi.Srivatsavai@Sun.COM 
181*10491SRishi.Srivatsavai@Sun.COM Bool
STP_topoch_check_conditions(STATE_MACH_T * this)182*10491SRishi.Srivatsavai@Sun.COM STP_topoch_check_conditions (STATE_MACH_T* this)
183*10491SRishi.Srivatsavai@Sun.COM {
184*10491SRishi.Srivatsavai@Sun.COM   register PORT_T*      port = this->owner.port;
185*10491SRishi.Srivatsavai@Sun.COM 
186*10491SRishi.Srivatsavai@Sun.COM   if (BEGIN == this->State) {
187*10491SRishi.Srivatsavai@Sun.COM     return STP_hop_2_state (this, INIT);
188*10491SRishi.Srivatsavai@Sun.COM   }
189*10491SRishi.Srivatsavai@Sun.COM 
190*10491SRishi.Srivatsavai@Sun.COM   switch (this->State) {
191*10491SRishi.Srivatsavai@Sun.COM     case INIT:
192*10491SRishi.Srivatsavai@Sun.COM       return STP_hop_2_state (this, INACTIVE);
193*10491SRishi.Srivatsavai@Sun.COM     case INACTIVE:
194*10491SRishi.Srivatsavai@Sun.COM       if (port->role == RootPort || port->role == DesignatedPort)
195*10491SRishi.Srivatsavai@Sun.COM         return STP_hop_2_state (this, TCACTIVE);
196*10491SRishi.Srivatsavai@Sun.COM       if (port->rcvdTc || port->rcvdTcn || port->rcvdTcAck ||
197*10491SRishi.Srivatsavai@Sun.COM           port->tc || port->tcProp)
198*10491SRishi.Srivatsavai@Sun.COM         return STP_hop_2_state (this, INACTIVE);
199*10491SRishi.Srivatsavai@Sun.COM       break;
200*10491SRishi.Srivatsavai@Sun.COM     case TCACTIVE:
201*10491SRishi.Srivatsavai@Sun.COM       if (port->role != RootPort && (port->role != DesignatedPort))
202*10491SRishi.Srivatsavai@Sun.COM         return STP_hop_2_state (this, INIT);
203*10491SRishi.Srivatsavai@Sun.COM       if (port->tc)
204*10491SRishi.Srivatsavai@Sun.COM         return STP_hop_2_state (this, DETECTED);
205*10491SRishi.Srivatsavai@Sun.COM       if (port->rcvdTcn)
206*10491SRishi.Srivatsavai@Sun.COM         return STP_hop_2_state (this, NOTIFIED_TCN);
207*10491SRishi.Srivatsavai@Sun.COM       if (port->rcvdTc)
208*10491SRishi.Srivatsavai@Sun.COM         return STP_hop_2_state (this, NOTIFIED_TC);
209*10491SRishi.Srivatsavai@Sun.COM       if (port->tcProp && !port->operEdge)
210*10491SRishi.Srivatsavai@Sun.COM         return STP_hop_2_state (this, PROPAGATING);
211*10491SRishi.Srivatsavai@Sun.COM       if (port->rcvdTcAck)
212*10491SRishi.Srivatsavai@Sun.COM         return STP_hop_2_state (this, ACKNOWLEDGED);
213*10491SRishi.Srivatsavai@Sun.COM       break;
214*10491SRishi.Srivatsavai@Sun.COM     case DETECTED:
215*10491SRishi.Srivatsavai@Sun.COM       return STP_hop_2_state (this, TCACTIVE);
216*10491SRishi.Srivatsavai@Sun.COM     case NOTIFIED_TC:
217*10491SRishi.Srivatsavai@Sun.COM       return STP_hop_2_state (this, TCACTIVE);
218*10491SRishi.Srivatsavai@Sun.COM     case PROPAGATING:
219*10491SRishi.Srivatsavai@Sun.COM       return STP_hop_2_state (this, TCACTIVE);
220*10491SRishi.Srivatsavai@Sun.COM     case ACKNOWLEDGED:
221*10491SRishi.Srivatsavai@Sun.COM       return STP_hop_2_state (this, TCACTIVE);
222*10491SRishi.Srivatsavai@Sun.COM     case NOTIFIED_TCN:
223*10491SRishi.Srivatsavai@Sun.COM       return STP_hop_2_state (this, NOTIFIED_TC);
224*10491SRishi.Srivatsavai@Sun.COM   };
225*10491SRishi.Srivatsavai@Sun.COM   return False;
226*10491SRishi.Srivatsavai@Sun.COM }
227*10491SRishi.Srivatsavai@Sun.COM 
228