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