xref: /titanic_50/usr/src/lib/librstp/common/transmit.c (revision 4eaa471005973e11a6110b69fe990530b3b95a38)
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 /* Port Transmit state machine : 17.27 */
24*4eaa4710SRishi Srivatsavai 
25*4eaa4710SRishi Srivatsavai #include "base.h"
26*4eaa4710SRishi Srivatsavai #include "stpm.h"
27*4eaa4710SRishi Srivatsavai #include "stp_to.h" /* for STP_OUT_get_port_mac & STP_OUT_tx_bpdu */
28*4eaa4710SRishi Srivatsavai 
29*4eaa4710SRishi Srivatsavai #define BPDU_LEN8023_OFF    12
30*4eaa4710SRishi Srivatsavai 
31*4eaa4710SRishi Srivatsavai #define STATES {        \
32*4eaa4710SRishi Srivatsavai   CHOOSE(TRANSMIT_INIT),    \
33*4eaa4710SRishi Srivatsavai   CHOOSE(TRANSMIT_PERIODIC),    \
34*4eaa4710SRishi Srivatsavai   CHOOSE(IDLE),         \
35*4eaa4710SRishi Srivatsavai   CHOOSE(TRANSMIT_CONFIG),  \
36*4eaa4710SRishi Srivatsavai   CHOOSE(TRANSMIT_TCN),     \
37*4eaa4710SRishi Srivatsavai   CHOOSE(TRANSMIT_RSTP)    \
38*4eaa4710SRishi Srivatsavai }
39*4eaa4710SRishi Srivatsavai 
40*4eaa4710SRishi Srivatsavai #define GET_STATE_NAME STP_transmit_get_state_name
41*4eaa4710SRishi Srivatsavai #include "choose.h"
42*4eaa4710SRishi Srivatsavai 
43*4eaa4710SRishi Srivatsavai #define MIN_FRAME_LENGTH    64
44*4eaa4710SRishi Srivatsavai 
45*4eaa4710SRishi Srivatsavai 
46*4eaa4710SRishi Srivatsavai typedef struct tx_tcn_bpdu_t {
47*4eaa4710SRishi Srivatsavai   MAC_HEADER_T  mac;
48*4eaa4710SRishi Srivatsavai   ETH_HEADER_T  eth;
49*4eaa4710SRishi Srivatsavai   BPDU_HEADER_T hdr;
50*4eaa4710SRishi Srivatsavai } TCN_BPDU_T;
51*4eaa4710SRishi Srivatsavai 
52*4eaa4710SRishi Srivatsavai typedef struct tx_stp_bpdu_t {
53*4eaa4710SRishi Srivatsavai   MAC_HEADER_T  mac;
54*4eaa4710SRishi Srivatsavai   ETH_HEADER_T  eth;
55*4eaa4710SRishi Srivatsavai   BPDU_HEADER_T hdr;
56*4eaa4710SRishi Srivatsavai   BPDU_BODY_T   body;
57*4eaa4710SRishi Srivatsavai } CONFIG_BPDU_T;
58*4eaa4710SRishi Srivatsavai 
59*4eaa4710SRishi Srivatsavai typedef struct tx_rstp_bpdu_t {
60*4eaa4710SRishi Srivatsavai   MAC_HEADER_T  mac;
61*4eaa4710SRishi Srivatsavai   ETH_HEADER_T  eth;
62*4eaa4710SRishi Srivatsavai   BPDU_HEADER_T hdr;
63*4eaa4710SRishi Srivatsavai   BPDU_BODY_T   body;
64*4eaa4710SRishi Srivatsavai   unsigned char ver_1_length[2];
65*4eaa4710SRishi Srivatsavai } RSTP_BPDU_T;
66*4eaa4710SRishi Srivatsavai 
67*4eaa4710SRishi Srivatsavai 
68*4eaa4710SRishi Srivatsavai static RSTP_BPDU_T bpdu_packet  = {
69*4eaa4710SRishi Srivatsavai   {/* MAC_HEADER_T */
70*4eaa4710SRishi Srivatsavai     {0x01, 0x80, 0xc2, 0x00, 0x00, 0x00},   /* dst_mac */
71*4eaa4710SRishi Srivatsavai     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}    /* src_mac */
72*4eaa4710SRishi Srivatsavai   },
73*4eaa4710SRishi Srivatsavai   { /* ETH_HEADER_T */
74*4eaa4710SRishi Srivatsavai     {0x00, 0x00},               /* len8023 */
75*4eaa4710SRishi Srivatsavai     BPDU_L_SAP, BPDU_L_SAP, LLC_UI      /* dsap, ssap, llc */
76*4eaa4710SRishi Srivatsavai   },
77*4eaa4710SRishi Srivatsavai   {/* BPDU_HEADER_T */
78*4eaa4710SRishi Srivatsavai     {0x00, 0x00},               /* protocol */
79*4eaa4710SRishi Srivatsavai     BPDU_VERSION_ID, 0x00           /* version, bpdu_type */
80*4eaa4710SRishi Srivatsavai   },
81*4eaa4710SRishi Srivatsavai   {
82*4eaa4710SRishi Srivatsavai     0x00,                   /*  flags; */
83*4eaa4710SRishi Srivatsavai     {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},  /*  root_id[8]; */
84*4eaa4710SRishi Srivatsavai     {0x00,0x00,0x00,0x00},          /*  root_path_cost[4]; */
85*4eaa4710SRishi Srivatsavai     {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},  /*  bridge_id[8]; */
86*4eaa4710SRishi Srivatsavai     {0x00,0x00},                /*  port_id[2]; */
87*4eaa4710SRishi Srivatsavai     {0x00,0x00},                /*  message_age[2]; */
88*4eaa4710SRishi Srivatsavai     {0x00,0x00},                /*  max_age[2]; */
89*4eaa4710SRishi Srivatsavai     {0x00,0x00},                /*  hello_time[2]; */
90*4eaa4710SRishi Srivatsavai     {0x00,0x00},                /*  forward_delay[2]; */
91*4eaa4710SRishi Srivatsavai   },
92*4eaa4710SRishi Srivatsavai    {0x00,0x00},                 /*  ver_1_length[2]; */
93*4eaa4710SRishi Srivatsavai };
94*4eaa4710SRishi Srivatsavai 
95*4eaa4710SRishi Srivatsavai static size_t
build_bpdu_header(int port_index,unsigned char bpdu_type,unsigned short pkt_len)96*4eaa4710SRishi Srivatsavai build_bpdu_header (int port_index,
97*4eaa4710SRishi Srivatsavai                    unsigned char bpdu_type,
98*4eaa4710SRishi Srivatsavai                    unsigned short pkt_len)
99*4eaa4710SRishi Srivatsavai {
100*4eaa4710SRishi Srivatsavai   unsigned short len8023;
101*4eaa4710SRishi Srivatsavai 
102*4eaa4710SRishi Srivatsavai   STP_OUT_get_port_mac (port_index, bpdu_packet.mac.src_mac);
103*4eaa4710SRishi Srivatsavai 
104*4eaa4710SRishi Srivatsavai   bpdu_packet.hdr.bpdu_type = bpdu_type;
105*4eaa4710SRishi Srivatsavai   bpdu_packet.hdr.version = (BPDU_RSTP == bpdu_type) ?
106*4eaa4710SRishi Srivatsavai                             BPDU_VERSION_RAPID_ID    :
107*4eaa4710SRishi Srivatsavai                             BPDU_VERSION_ID;
108*4eaa4710SRishi Srivatsavai 
109*4eaa4710SRishi Srivatsavai   /* NOTE: I suppose, that sizeof(unsigned short)=2 ! */
110*4eaa4710SRishi Srivatsavai   len8023 = htons ((unsigned short) (pkt_len + 3));
111*4eaa4710SRishi Srivatsavai   (void) memcpy (&bpdu_packet.eth.len8023, &len8023, 2);
112*4eaa4710SRishi Srivatsavai 
113*4eaa4710SRishi Srivatsavai   if (pkt_len < MIN_FRAME_LENGTH) pkt_len = MIN_FRAME_LENGTH;
114*4eaa4710SRishi Srivatsavai   return pkt_len;
115*4eaa4710SRishi Srivatsavai }
116*4eaa4710SRishi Srivatsavai 
117*4eaa4710SRishi Srivatsavai static int
txTcn(STATE_MACH_T * this)118*4eaa4710SRishi Srivatsavai txTcn (STATE_MACH_T* this)
119*4eaa4710SRishi Srivatsavai { /* 17.19.17 (page 68) & 9.3.2 (page 25) */
120*4eaa4710SRishi Srivatsavai   register size_t       pkt_len;
121*4eaa4710SRishi Srivatsavai   register int          port_index, vlan_id;
122*4eaa4710SRishi Srivatsavai 
123*4eaa4710SRishi Srivatsavai #ifdef STP_DBG
124*4eaa4710SRishi Srivatsavai   if (this->owner.port->skip_tx > 0) {
125*4eaa4710SRishi Srivatsavai     if (1 == this->owner.port->skip_tx)
126*4eaa4710SRishi Srivatsavai       stp_trace ("port %s stop tx skipping",
127*4eaa4710SRishi Srivatsavai                  this->owner.port->port_name);
128*4eaa4710SRishi Srivatsavai     this->owner.port->skip_tx--;
129*4eaa4710SRishi Srivatsavai     return STP_Nothing_To_Do;
130*4eaa4710SRishi Srivatsavai   }
131*4eaa4710SRishi Srivatsavai #endif
132*4eaa4710SRishi Srivatsavai 
133*4eaa4710SRishi Srivatsavai   if (this->owner.port->admin_non_stp) return 1;
134*4eaa4710SRishi Srivatsavai   port_index = this->owner.port->port_index;
135*4eaa4710SRishi Srivatsavai   vlan_id = this->owner.port->owner->vlan_id;
136*4eaa4710SRishi Srivatsavai 
137*4eaa4710SRishi Srivatsavai   pkt_len = build_bpdu_header (port_index,
138*4eaa4710SRishi Srivatsavai                                BPDU_TOPO_CHANGE_TYPE,
139*4eaa4710SRishi Srivatsavai                                sizeof (BPDU_HEADER_T));
140*4eaa4710SRishi Srivatsavai 
141*4eaa4710SRishi Srivatsavai #ifdef STP_DBG
142*4eaa4710SRishi Srivatsavai   if (this->debug)
143*4eaa4710SRishi Srivatsavai     stp_trace ("port %s txTcn", this->owner.port->port_name);
144*4eaa4710SRishi Srivatsavai #endif
145*4eaa4710SRishi Srivatsavai   return STP_OUT_tx_bpdu (port_index, vlan_id,
146*4eaa4710SRishi Srivatsavai                           (unsigned char *) &bpdu_packet,
147*4eaa4710SRishi Srivatsavai                           pkt_len);
148*4eaa4710SRishi Srivatsavai }
149*4eaa4710SRishi Srivatsavai 
150*4eaa4710SRishi Srivatsavai static void
build_config_bpdu(PORT_T * port,Bool set_topo_ack_flag)151*4eaa4710SRishi Srivatsavai build_config_bpdu (PORT_T* port, Bool set_topo_ack_flag)
152*4eaa4710SRishi Srivatsavai {
153*4eaa4710SRishi Srivatsavai   bpdu_packet.body.flags = 0;
154*4eaa4710SRishi Srivatsavai   if (port->tcWhile) {
155*4eaa4710SRishi Srivatsavai #ifdef STP_DBG
156*4eaa4710SRishi Srivatsavai     if (port->topoch->debug)
157*4eaa4710SRishi Srivatsavai       stp_trace ("tcWhile=%d =>tx TOPOLOGY_CHANGE_BIT to port %s",
158*4eaa4710SRishi Srivatsavai                  (int) port->tcWhile, port->port_name);
159*4eaa4710SRishi Srivatsavai #endif
160*4eaa4710SRishi Srivatsavai     bpdu_packet.body.flags |= TOPOLOGY_CHANGE_BIT;
161*4eaa4710SRishi Srivatsavai   }
162*4eaa4710SRishi Srivatsavai 
163*4eaa4710SRishi Srivatsavai   if (set_topo_ack_flag && port->tcAck) {
164*4eaa4710SRishi Srivatsavai     bpdu_packet.body.flags |= TOPOLOGY_CHANGE_ACK_BIT;
165*4eaa4710SRishi Srivatsavai   }
166*4eaa4710SRishi Srivatsavai 
167*4eaa4710SRishi Srivatsavai   STP_VECT_set_vector (&port->portPrio, &bpdu_packet.body);
168*4eaa4710SRishi Srivatsavai   STP_set_times (&port->portTimes, &bpdu_packet.body);
169*4eaa4710SRishi Srivatsavai }
170*4eaa4710SRishi Srivatsavai 
171*4eaa4710SRishi Srivatsavai static int
txConfig(STATE_MACH_T * this)172*4eaa4710SRishi Srivatsavai txConfig (STATE_MACH_T* this)
173*4eaa4710SRishi Srivatsavai {/* 17.19.15 (page 67) & 9.3.1 (page 23) */
174*4eaa4710SRishi Srivatsavai   register size_t   pkt_len;
175*4eaa4710SRishi Srivatsavai   register PORT_T*  port = NULL;
176*4eaa4710SRishi Srivatsavai   register int      port_index, vlan_id;
177*4eaa4710SRishi Srivatsavai 
178*4eaa4710SRishi Srivatsavai #ifdef STP_DBG
179*4eaa4710SRishi Srivatsavai   if (this->owner.port->skip_tx > 0) {
180*4eaa4710SRishi Srivatsavai     if (1 == this->owner.port->skip_tx)
181*4eaa4710SRishi Srivatsavai       stp_trace ("port %s stop tx skipping",
182*4eaa4710SRishi Srivatsavai                  this->owner.port->port_name);
183*4eaa4710SRishi Srivatsavai     this->owner.port->skip_tx--;
184*4eaa4710SRishi Srivatsavai     return STP_Nothing_To_Do;
185*4eaa4710SRishi Srivatsavai   }
186*4eaa4710SRishi Srivatsavai #endif
187*4eaa4710SRishi Srivatsavai 
188*4eaa4710SRishi Srivatsavai   port = this->owner.port;
189*4eaa4710SRishi Srivatsavai   if (port->admin_non_stp) return 1;
190*4eaa4710SRishi Srivatsavai   port_index = port->port_index;
191*4eaa4710SRishi Srivatsavai   vlan_id = port->owner->vlan_id;
192*4eaa4710SRishi Srivatsavai 
193*4eaa4710SRishi Srivatsavai   pkt_len = build_bpdu_header (port->port_index,
194*4eaa4710SRishi Srivatsavai                                BPDU_CONFIG_TYPE,
195*4eaa4710SRishi Srivatsavai                                sizeof (BPDU_HEADER_T) + sizeof (BPDU_BODY_T));
196*4eaa4710SRishi Srivatsavai   build_config_bpdu (port, True);
197*4eaa4710SRishi Srivatsavai 
198*4eaa4710SRishi Srivatsavai #ifdef STP_DBG
199*4eaa4710SRishi Srivatsavai   if (this->debug)
200*4eaa4710SRishi Srivatsavai     stp_trace ("port %s txConfig flags=0X%lx",
201*4eaa4710SRishi Srivatsavai         port->port_name,
202*4eaa4710SRishi Srivatsavai         (unsigned long) bpdu_packet.body.flags);
203*4eaa4710SRishi Srivatsavai #endif
204*4eaa4710SRishi Srivatsavai   return STP_OUT_tx_bpdu (port_index, vlan_id,
205*4eaa4710SRishi Srivatsavai                           (unsigned char *) &bpdu_packet,
206*4eaa4710SRishi Srivatsavai                           pkt_len);
207*4eaa4710SRishi Srivatsavai }
208*4eaa4710SRishi Srivatsavai 
209*4eaa4710SRishi Srivatsavai static int
txRstp(STATE_MACH_T * this)210*4eaa4710SRishi Srivatsavai txRstp (STATE_MACH_T* this)
211*4eaa4710SRishi Srivatsavai {/* 17.19.16 (page 68) & 9.3.3 (page 25) */
212*4eaa4710SRishi Srivatsavai   register size_t       pkt_len;
213*4eaa4710SRishi Srivatsavai   register PORT_T*      port = NULL;
214*4eaa4710SRishi Srivatsavai   register int          port_index, vlan_id;
215*4eaa4710SRishi Srivatsavai   unsigned char         role;
216*4eaa4710SRishi Srivatsavai 
217*4eaa4710SRishi Srivatsavai #ifdef STP_DBG
218*4eaa4710SRishi Srivatsavai   if (this->owner.port->skip_tx > 0) {
219*4eaa4710SRishi Srivatsavai     if (1 == this->owner.port->skip_tx)
220*4eaa4710SRishi Srivatsavai       stp_trace ("port %s stop tx skipping",
221*4eaa4710SRishi Srivatsavai                  this->owner.port->port_name);
222*4eaa4710SRishi Srivatsavai     else
223*4eaa4710SRishi Srivatsavai       stp_trace ("port %s skip tx %d",
224*4eaa4710SRishi Srivatsavai                  this->owner.port->port_name, this->owner.port->skip_tx);
225*4eaa4710SRishi Srivatsavai 
226*4eaa4710SRishi Srivatsavai     this->owner.port->skip_tx--;
227*4eaa4710SRishi Srivatsavai     return STP_Nothing_To_Do;
228*4eaa4710SRishi Srivatsavai   }
229*4eaa4710SRishi Srivatsavai #endif
230*4eaa4710SRishi Srivatsavai 
231*4eaa4710SRishi Srivatsavai   port = this->owner.port;
232*4eaa4710SRishi Srivatsavai   if (port->admin_non_stp) return 1;
233*4eaa4710SRishi Srivatsavai   port_index = port->port_index;
234*4eaa4710SRishi Srivatsavai   vlan_id = port->owner->vlan_id;
235*4eaa4710SRishi Srivatsavai 
236*4eaa4710SRishi Srivatsavai   pkt_len = build_bpdu_header (port->port_index,
237*4eaa4710SRishi Srivatsavai                                BPDU_RSTP,
238*4eaa4710SRishi Srivatsavai                                sizeof (BPDU_HEADER_T) + sizeof (BPDU_BODY_T) + 2);
239*4eaa4710SRishi Srivatsavai   build_config_bpdu (port, False);
240*4eaa4710SRishi Srivatsavai 
241*4eaa4710SRishi Srivatsavai   switch (port->selectedRole) {
242*4eaa4710SRishi Srivatsavai     default:
243*4eaa4710SRishi Srivatsavai     case DisabledPort:
244*4eaa4710SRishi Srivatsavai       role = RSTP_PORT_ROLE_UNKN;
245*4eaa4710SRishi Srivatsavai       break;
246*4eaa4710SRishi Srivatsavai     case AlternatePort:
247*4eaa4710SRishi Srivatsavai       role = RSTP_PORT_ROLE_ALTBACK;
248*4eaa4710SRishi Srivatsavai       break;
249*4eaa4710SRishi Srivatsavai     case BackupPort:
250*4eaa4710SRishi Srivatsavai       role = RSTP_PORT_ROLE_ALTBACK;
251*4eaa4710SRishi Srivatsavai       break;
252*4eaa4710SRishi Srivatsavai     case RootPort:
253*4eaa4710SRishi Srivatsavai       role = RSTP_PORT_ROLE_ROOT;
254*4eaa4710SRishi Srivatsavai       break;
255*4eaa4710SRishi Srivatsavai     case DesignatedPort:
256*4eaa4710SRishi Srivatsavai       role = RSTP_PORT_ROLE_DESGN;
257*4eaa4710SRishi Srivatsavai       break;
258*4eaa4710SRishi Srivatsavai   }
259*4eaa4710SRishi Srivatsavai 
260*4eaa4710SRishi Srivatsavai   bpdu_packet.body.flags |= (role << PORT_ROLE_OFFS);
261*4eaa4710SRishi Srivatsavai 
262*4eaa4710SRishi Srivatsavai   if (port->synced) {
263*4eaa4710SRishi Srivatsavai #if 0 /* def STP_DBG */
264*4eaa4710SRishi Srivatsavai     if (port->roletrns->debug)
265*4eaa4710SRishi Srivatsavai       stp_trace ("tx AGREEMENT_BIT to port %s", port->port_name);
266*4eaa4710SRishi Srivatsavai #endif
267*4eaa4710SRishi Srivatsavai     bpdu_packet.body.flags |= AGREEMENT_BIT;
268*4eaa4710SRishi Srivatsavai   }
269*4eaa4710SRishi Srivatsavai 
270*4eaa4710SRishi Srivatsavai   if (port->proposing) {
271*4eaa4710SRishi Srivatsavai #if 0 /* def STP_DBG */
272*4eaa4710SRishi Srivatsavai     if (port->roletrns->debug)
273*4eaa4710SRishi Srivatsavai       stp_trace ("tx PROPOSAL_BIT to port %s", port->port_name);
274*4eaa4710SRishi Srivatsavai #endif
275*4eaa4710SRishi Srivatsavai     bpdu_packet.body.flags |= PROPOSAL_BIT;
276*4eaa4710SRishi Srivatsavai   }
277*4eaa4710SRishi Srivatsavai 
278*4eaa4710SRishi Srivatsavai #ifdef STP_DBG
279*4eaa4710SRishi Srivatsavai   if (this->debug)
280*4eaa4710SRishi Srivatsavai     stp_trace ("port %s txRstp flags=0X%lx",
281*4eaa4710SRishi Srivatsavai         port->port_name,
282*4eaa4710SRishi Srivatsavai         (unsigned long) bpdu_packet.body.flags);
283*4eaa4710SRishi Srivatsavai #endif
284*4eaa4710SRishi Srivatsavai 
285*4eaa4710SRishi Srivatsavai   return STP_OUT_tx_bpdu (port_index, vlan_id,
286*4eaa4710SRishi Srivatsavai                           (unsigned char *) &bpdu_packet,
287*4eaa4710SRishi Srivatsavai                           pkt_len);
288*4eaa4710SRishi Srivatsavai }
289*4eaa4710SRishi Srivatsavai 
290*4eaa4710SRishi Srivatsavai void
STP_transmit_enter_state(STATE_MACH_T * this)291*4eaa4710SRishi Srivatsavai STP_transmit_enter_state (STATE_MACH_T* this)
292*4eaa4710SRishi Srivatsavai {
293*4eaa4710SRishi Srivatsavai   register PORT_T*     port = this->owner.port;
294*4eaa4710SRishi Srivatsavai 
295*4eaa4710SRishi Srivatsavai   switch (this->State) {
296*4eaa4710SRishi Srivatsavai     case BEGIN:
297*4eaa4710SRishi Srivatsavai     case TRANSMIT_INIT:
298*4eaa4710SRishi Srivatsavai       port->newInfo = False;
299*4eaa4710SRishi Srivatsavai       port->helloWhen = 0;
300*4eaa4710SRishi Srivatsavai       port->txCount = 0;
301*4eaa4710SRishi Srivatsavai       break;
302*4eaa4710SRishi Srivatsavai     case TRANSMIT_PERIODIC:
303*4eaa4710SRishi Srivatsavai       port->newInfo = port->newInfo ||
304*4eaa4710SRishi Srivatsavai                             ((port->role == DesignatedPort) ||
305*4eaa4710SRishi Srivatsavai                              ((port->role == RootPort) && port->tcWhile));
306*4eaa4710SRishi Srivatsavai       port->helloWhen = port->owner->rootTimes.HelloTime;
307*4eaa4710SRishi Srivatsavai       break;
308*4eaa4710SRishi Srivatsavai     case IDLE:
309*4eaa4710SRishi Srivatsavai       break;
310*4eaa4710SRishi Srivatsavai     case TRANSMIT_CONFIG:
311*4eaa4710SRishi Srivatsavai       port->newInfo = False;
312*4eaa4710SRishi Srivatsavai       (void) txConfig (this);
313*4eaa4710SRishi Srivatsavai       port->txCount++;
314*4eaa4710SRishi Srivatsavai       port->tcAck = False;
315*4eaa4710SRishi Srivatsavai       break;
316*4eaa4710SRishi Srivatsavai     case TRANSMIT_TCN:
317*4eaa4710SRishi Srivatsavai       port->newInfo = False;
318*4eaa4710SRishi Srivatsavai       (void) txTcn (this);
319*4eaa4710SRishi Srivatsavai       port->txCount++;
320*4eaa4710SRishi Srivatsavai       break;
321*4eaa4710SRishi Srivatsavai     case TRANSMIT_RSTP:
322*4eaa4710SRishi Srivatsavai       port->newInfo = False;
323*4eaa4710SRishi Srivatsavai       (void) txRstp (this);
324*4eaa4710SRishi Srivatsavai       port->txCount++;
325*4eaa4710SRishi Srivatsavai       port->tcAck = False;
326*4eaa4710SRishi Srivatsavai       break;
327*4eaa4710SRishi Srivatsavai   };
328*4eaa4710SRishi Srivatsavai }
329*4eaa4710SRishi Srivatsavai 
330*4eaa4710SRishi Srivatsavai Bool
STP_transmit_check_conditions(STATE_MACH_T * this)331*4eaa4710SRishi Srivatsavai STP_transmit_check_conditions (STATE_MACH_T* this)
332*4eaa4710SRishi Srivatsavai {
333*4eaa4710SRishi Srivatsavai   register PORT_T*     port = this->owner.port;
334*4eaa4710SRishi Srivatsavai 
335*4eaa4710SRishi Srivatsavai   switch (this->State) {
336*4eaa4710SRishi Srivatsavai     case BEGIN:
337*4eaa4710SRishi Srivatsavai       return STP_hop_2_state (this, TRANSMIT_INIT);
338*4eaa4710SRishi Srivatsavai     case TRANSMIT_INIT:
339*4eaa4710SRishi Srivatsavai       return STP_hop_2_state (this, IDLE);
340*4eaa4710SRishi Srivatsavai     case TRANSMIT_PERIODIC:
341*4eaa4710SRishi Srivatsavai       return STP_hop_2_state (this, IDLE);
342*4eaa4710SRishi Srivatsavai     case IDLE:
343*4eaa4710SRishi Srivatsavai       if (!port->helloWhen) return STP_hop_2_state (this, TRANSMIT_PERIODIC);
344*4eaa4710SRishi Srivatsavai       if (!port->sendRSTP && port->newInfo &&
345*4eaa4710SRishi Srivatsavai           (port->txCount < TxHoldCount) &&
346*4eaa4710SRishi Srivatsavai           (port->role == DesignatedPort) &&
347*4eaa4710SRishi Srivatsavai           port->helloWhen)
348*4eaa4710SRishi Srivatsavai         return STP_hop_2_state (this, TRANSMIT_CONFIG);
349*4eaa4710SRishi Srivatsavai       if (!port->sendRSTP && port->newInfo &&
350*4eaa4710SRishi Srivatsavai           (port->txCount < TxHoldCount) &&
351*4eaa4710SRishi Srivatsavai           (port->role == RootPort) &&
352*4eaa4710SRishi Srivatsavai           port->helloWhen)
353*4eaa4710SRishi Srivatsavai         return STP_hop_2_state (this, TRANSMIT_TCN);
354*4eaa4710SRishi Srivatsavai       if (port->sendRSTP && port->newInfo &&
355*4eaa4710SRishi Srivatsavai           (port->txCount < TxHoldCount) &&
356*4eaa4710SRishi Srivatsavai           ((port->role == RootPort) ||
357*4eaa4710SRishi Srivatsavai            (port->role == DesignatedPort)))
358*4eaa4710SRishi Srivatsavai         return STP_hop_2_state (this, TRANSMIT_RSTP);
359*4eaa4710SRishi Srivatsavai       break;
360*4eaa4710SRishi Srivatsavai     case TRANSMIT_CONFIG:
361*4eaa4710SRishi Srivatsavai       return STP_hop_2_state (this, IDLE);
362*4eaa4710SRishi Srivatsavai     case TRANSMIT_TCN:
363*4eaa4710SRishi Srivatsavai       return STP_hop_2_state (this, IDLE);
364*4eaa4710SRishi Srivatsavai     case TRANSMIT_RSTP:
365*4eaa4710SRishi Srivatsavai       return STP_hop_2_state (this, IDLE);
366*4eaa4710SRishi Srivatsavai   };
367*4eaa4710SRishi Srivatsavai   return False;
368*4eaa4710SRishi Srivatsavai }
369