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