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