FreeBSD/Linux Kernel Cross Reference
sys/net/bridgestp.c
1 /* $NetBSD: bridgestp.c,v 1.5 2003/11/28 08:56:48 keihan Exp $ */
2
3 /*
4 * Copyright (c) 2000 Jason L. Wright (jason@thought.net)
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Jason L. Wright
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *
33 * OpenBSD: bridgestp.c,v 1.5 2001/03/22 03:48:29 jason Exp
34 */
35
36 /*
37 * Implementation of the spanning tree protocol as defined in
38 * ISO/IEC Final DIS 15802-3 (IEEE P802.1D/D17), May 25, 1998.
39 * (In English: IEEE 802.1D, Draft 17, 1998)
40 */
41
42 #include <sys/cdefs.h>
43 __FBSDID("$FreeBSD: releng/6.0/sys/net/bridgestp.c 151571 2005-10-23 02:37:28Z thompsa $");
44
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/mbuf.h>
48 #include <sys/socket.h>
49 #include <sys/sockio.h>
50 #include <sys/kernel.h>
51 #include <sys/callout.h>
52 #include <sys/proc.h>
53 #include <sys/lock.h>
54 #include <sys/mutex.h>
55
56 #include <net/if.h>
57 #include <net/if_dl.h>
58 #include <net/if_types.h>
59 #include <net/if_llc.h>
60 #include <net/if_media.h>
61
62 #include <netinet/in.h>
63 #include <netinet/in_systm.h>
64 #include <netinet/in_var.h>
65 #include <netinet/if_ether.h>
66 #include <net/if_bridgevar.h>
67
68 /* BPDU message types */
69 #define BSTP_MSGTYPE_CFG 0x00 /* Configuration */
70 #define BSTP_MSGTYPE_TCN 0x80 /* Topology chg notification */
71
72 /* BPDU flags */
73 #define BSTP_FLAG_TC 0x01 /* Topology change */
74 #define BSTP_FLAG_TCA 0x80 /* Topology change ack */
75
76 #define BSTP_MESSAGE_AGE_INCR (1 * 256) /* in 256ths of a second */
77 #define BSTP_TICK_VAL (1 * 256) /* in 256ths of a second */
78
79 /*
80 * Because BPDU's do not make nicely aligned structures, two different
81 * declarations are used: bstp_?bpdu (wire representation, packed) and
82 * bstp_*_unit (internal, nicely aligned version).
83 */
84
85 /* configuration bridge protocol data unit */
86 struct bstp_cbpdu {
87 uint8_t cbu_dsap; /* LLC: destination sap */
88 uint8_t cbu_ssap; /* LLC: source sap */
89 uint8_t cbu_ctl; /* LLC: control */
90 uint16_t cbu_protoid; /* protocol id */
91 uint8_t cbu_protover; /* protocol version */
92 uint8_t cbu_bpdutype; /* message type */
93 uint8_t cbu_flags; /* flags (below) */
94
95 /* root id */
96 uint16_t cbu_rootpri; /* root priority */
97 uint8_t cbu_rootaddr[6]; /* root address */
98
99 uint32_t cbu_rootpathcost; /* root path cost */
100
101 /* bridge id */
102 uint16_t cbu_bridgepri; /* bridge priority */
103 uint8_t cbu_bridgeaddr[6]; /* bridge address */
104
105 uint16_t cbu_portid; /* port id */
106 uint16_t cbu_messageage; /* current message age */
107 uint16_t cbu_maxage; /* maximum age */
108 uint16_t cbu_hellotime; /* hello time */
109 uint16_t cbu_forwarddelay; /* forwarding delay */
110 } __attribute__((__packed__));
111
112 /* topology change notification bridge protocol data unit */
113 struct bstp_tbpdu {
114 uint8_t tbu_dsap; /* LLC: destination sap */
115 uint8_t tbu_ssap; /* LLC: source sap */
116 uint8_t tbu_ctl; /* LLC: control */
117 uint16_t tbu_protoid; /* protocol id */
118 uint8_t tbu_protover; /* protocol version */
119 uint8_t tbu_bpdutype; /* message type */
120 } __attribute__((__packed__));
121
122 const uint8_t bstp_etheraddr[] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
123
124 void bstp_initialize_port(struct bridge_softc *, struct bridge_iflist *);
125 void bstp_ifupdstatus(struct bridge_softc *, struct bridge_iflist *);
126 void bstp_enable_port(struct bridge_softc *, struct bridge_iflist *);
127 void bstp_disable_port(struct bridge_softc *, struct bridge_iflist *);
128 void bstp_enable_change_detection(struct bridge_iflist *);
129 void bstp_disable_change_detection(struct bridge_iflist *);
130 int bstp_root_bridge(struct bridge_softc *sc);
131 int bstp_supersedes_port_info(struct bridge_softc *,
132 struct bridge_iflist *, struct bstp_config_unit *);
133 int bstp_designated_port(struct bridge_softc *, struct bridge_iflist *);
134 int bstp_designated_for_some_port(struct bridge_softc *);
135 void bstp_transmit_config(struct bridge_softc *, struct bridge_iflist *);
136 void bstp_transmit_tcn(struct bridge_softc *);
137 void bstp_received_config_bpdu(struct bridge_softc *,
138 struct bridge_iflist *, struct bstp_config_unit *);
139 void bstp_received_tcn_bpdu(struct bridge_softc *, struct bridge_iflist *,
140 struct bstp_tcn_unit *);
141 void bstp_record_config_information(struct bridge_softc *,
142 struct bridge_iflist *, struct bstp_config_unit *);
143 void bstp_record_config_timeout_values(struct bridge_softc *,
144 struct bstp_config_unit *);
145 void bstp_config_bpdu_generation(struct bridge_softc *);
146 void bstp_send_config_bpdu(struct bridge_softc *, struct bridge_iflist *,
147 struct bstp_config_unit *);
148 void bstp_configuration_update(struct bridge_softc *);
149 void bstp_root_selection(struct bridge_softc *);
150 void bstp_designated_port_selection(struct bridge_softc *);
151 void bstp_become_designated_port(struct bridge_softc *,
152 struct bridge_iflist *);
153 void bstp_port_state_selection(struct bridge_softc *);
154 void bstp_make_forwarding(struct bridge_softc *, struct bridge_iflist *);
155 void bstp_make_blocking(struct bridge_softc *, struct bridge_iflist *);
156 void bstp_set_port_state(struct bridge_iflist *, uint8_t);
157 void bstp_set_bridge_priority(struct bridge_softc *, uint64_t);
158 void bstp_set_port_priority(struct bridge_softc *, struct bridge_iflist *,
159 uint16_t);
160 void bstp_set_path_cost(struct bridge_softc *, struct bridge_iflist *,
161 uint32_t);
162 void bstp_topology_change_detection(struct bridge_softc *);
163 void bstp_topology_change_acknowledged(struct bridge_softc *);
164 void bstp_acknowledge_topology_change(struct bridge_softc *,
165 struct bridge_iflist *);
166
167 void bstp_tick(void *);
168 void bstp_timer_start(struct bridge_timer *, uint16_t);
169 void bstp_timer_stop(struct bridge_timer *);
170 int bstp_timer_expired(struct bridge_timer *, uint16_t);
171
172 void bstp_hold_timer_expiry(struct bridge_softc *, struct bridge_iflist *);
173 void bstp_message_age_timer_expiry(struct bridge_softc *,
174 struct bridge_iflist *);
175 void bstp_forward_delay_timer_expiry(struct bridge_softc *,
176 struct bridge_iflist *);
177 void bstp_topology_change_timer_expiry(struct bridge_softc *);
178 void bstp_tcn_timer_expiry(struct bridge_softc *);
179 void bstp_hello_timer_expiry(struct bridge_softc *);
180
181 void
182 bstp_transmit_config(struct bridge_softc *sc, struct bridge_iflist *bif)
183 {
184 if (bif->bif_hold_timer.active) {
185 bif->bif_config_pending = 1;
186 return;
187 }
188
189 bif->bif_config_bpdu.cu_message_type = BSTP_MSGTYPE_CFG;
190 bif->bif_config_bpdu.cu_rootid = sc->sc_designated_root;
191 bif->bif_config_bpdu.cu_root_path_cost = sc->sc_root_path_cost;
192 bif->bif_config_bpdu.cu_bridge_id = sc->sc_bridge_id;
193 bif->bif_config_bpdu.cu_port_id = bif->bif_port_id;
194
195 if (bstp_root_bridge(sc))
196 bif->bif_config_bpdu.cu_message_age = 0;
197 else
198 bif->bif_config_bpdu.cu_message_age =
199 sc->sc_root_port->bif_message_age_timer.value +
200 BSTP_MESSAGE_AGE_INCR;
201
202 bif->bif_config_bpdu.cu_max_age = sc->sc_max_age;
203 bif->bif_config_bpdu.cu_hello_time = sc->sc_hello_time;
204 bif->bif_config_bpdu.cu_forward_delay = sc->sc_forward_delay;
205 bif->bif_config_bpdu.cu_topology_change_acknowledgment
206 = bif->bif_topology_change_acknowledge;
207 bif->bif_config_bpdu.cu_topology_change = sc->sc_topology_change;
208
209 if (bif->bif_config_bpdu.cu_message_age < sc->sc_max_age) {
210 bif->bif_topology_change_acknowledge = 0;
211 bif->bif_config_pending = 0;
212 bstp_send_config_bpdu(sc, bif, &bif->bif_config_bpdu);
213 bstp_timer_start(&bif->bif_hold_timer, 0);
214 }
215 }
216
217 void
218 bstp_send_config_bpdu(struct bridge_softc *sc, struct bridge_iflist *bif,
219 struct bstp_config_unit *cu)
220 {
221 struct ifnet *ifp;
222 struct mbuf *m;
223 struct ether_header *eh;
224 struct bstp_cbpdu bpdu;
225
226 BRIDGE_LOCK_ASSERT(sc);
227
228 ifp = bif->bif_ifp;
229
230 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
231 return;
232
233 MGETHDR(m, M_DONTWAIT, MT_DATA);
234 if (m == NULL)
235 return;
236
237 eh = mtod(m, struct ether_header *);
238
239 m->m_pkthdr.rcvif = ifp;
240 m->m_pkthdr.len = sizeof(*eh) + sizeof(bpdu);
241 m->m_len = m->m_pkthdr.len;
242
243 bpdu.cbu_ssap = bpdu.cbu_dsap = LLC_8021D_LSAP;
244 bpdu.cbu_ctl = LLC_UI;
245 bpdu.cbu_protoid = htons(0);
246 bpdu.cbu_protover = 0;
247 bpdu.cbu_bpdutype = cu->cu_message_type;
248 bpdu.cbu_flags = (cu->cu_topology_change ? BSTP_FLAG_TC : 0) |
249 (cu->cu_topology_change_acknowledgment ? BSTP_FLAG_TCA : 0);
250
251 bpdu.cbu_rootpri = htons(cu->cu_rootid >> 48);
252 bpdu.cbu_rootaddr[0] = cu->cu_rootid >> 40;
253 bpdu.cbu_rootaddr[1] = cu->cu_rootid >> 32;
254 bpdu.cbu_rootaddr[2] = cu->cu_rootid >> 24;
255 bpdu.cbu_rootaddr[3] = cu->cu_rootid >> 16;
256 bpdu.cbu_rootaddr[4] = cu->cu_rootid >> 8;
257 bpdu.cbu_rootaddr[5] = cu->cu_rootid >> 0;
258
259 bpdu.cbu_rootpathcost = htonl(cu->cu_root_path_cost);
260
261 bpdu.cbu_bridgepri = htons(cu->cu_rootid >> 48);
262 bpdu.cbu_bridgeaddr[0] = cu->cu_rootid >> 40;
263 bpdu.cbu_bridgeaddr[1] = cu->cu_rootid >> 32;
264 bpdu.cbu_bridgeaddr[2] = cu->cu_rootid >> 24;
265 bpdu.cbu_bridgeaddr[3] = cu->cu_rootid >> 16;
266 bpdu.cbu_bridgeaddr[4] = cu->cu_rootid >> 8;
267 bpdu.cbu_bridgeaddr[5] = cu->cu_rootid >> 0;
268
269 bpdu.cbu_portid = htons(cu->cu_port_id);
270 bpdu.cbu_messageage = htons(cu->cu_message_age);
271 bpdu.cbu_maxage = htons(cu->cu_max_age);
272 bpdu.cbu_hellotime = htons(cu->cu_hello_time);
273 bpdu.cbu_forwarddelay = htons(cu->cu_forward_delay);
274
275 memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN);
276 memcpy(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN);
277 eh->ether_type = htons(sizeof(bpdu));
278
279 memcpy(mtod(m, caddr_t) + sizeof(*eh), &bpdu, sizeof(bpdu));
280
281 /* XXX: safe here?!? */
282 BRIDGE_UNLOCK(sc);
283 bridge_enqueue(sc, ifp, m);
284 BRIDGE_LOCK(sc);
285 }
286
287 int
288 bstp_root_bridge(struct bridge_softc *sc)
289 {
290 return (sc->sc_designated_root == sc->sc_bridge_id);
291 }
292
293 int
294 bstp_supersedes_port_info(struct bridge_softc *sc, struct bridge_iflist *bif,
295 struct bstp_config_unit *cu)
296 {
297 if (cu->cu_rootid < bif->bif_designated_root)
298 return (1);
299 if (cu->cu_rootid > bif->bif_designated_root)
300 return (0);
301
302 if (cu->cu_root_path_cost < bif->bif_designated_cost)
303 return (1);
304 if (cu->cu_root_path_cost > bif->bif_designated_cost)
305 return (0);
306
307 if (cu->cu_bridge_id < bif->bif_designated_bridge)
308 return (1);
309 if (cu->cu_bridge_id > bif->bif_designated_bridge)
310 return (0);
311
312 if (sc->sc_bridge_id != cu->cu_bridge_id)
313 return (1);
314 if (cu->cu_port_id <= bif->bif_designated_port)
315 return (1);
316 return (0);
317 }
318
319 void
320 bstp_record_config_information(struct bridge_softc *sc,
321 struct bridge_iflist *bif, struct bstp_config_unit *cu)
322 {
323 bif->bif_designated_root = cu->cu_rootid;
324 bif->bif_designated_cost = cu->cu_root_path_cost;
325 bif->bif_designated_bridge = cu->cu_bridge_id;
326 bif->bif_designated_port = cu->cu_port_id;
327 bstp_timer_start(&bif->bif_message_age_timer, cu->cu_message_age);
328 }
329
330 void
331 bstp_record_config_timeout_values(struct bridge_softc *sc,
332 struct bstp_config_unit *config)
333 {
334 sc->sc_max_age = config->cu_max_age;
335 sc->sc_hello_time = config->cu_hello_time;
336 sc->sc_forward_delay = config->cu_forward_delay;
337 sc->sc_topology_change = config->cu_topology_change;
338 }
339
340 void
341 bstp_config_bpdu_generation(struct bridge_softc *sc)
342 {
343 struct bridge_iflist *bif;
344
345 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
346 if ((bif->bif_flags & IFBIF_STP) == 0)
347 continue;
348 if (bstp_designated_port(sc, bif) &&
349 (bif->bif_state != BSTP_IFSTATE_DISABLED))
350 bstp_transmit_config(sc, bif);
351 }
352 }
353
354 int
355 bstp_designated_port(struct bridge_softc *sc, struct bridge_iflist *bif)
356 {
357 return ((bif->bif_designated_bridge == sc->sc_bridge_id)
358 && (bif->bif_designated_port == bif->bif_port_id));
359 }
360
361 void
362 bstp_transmit_tcn(struct bridge_softc *sc)
363 {
364 struct bstp_tbpdu bpdu;
365 struct bridge_iflist *bif = sc->sc_root_port;
366 struct ifnet *ifp = bif->bif_ifp;
367 struct ether_header *eh;
368 struct mbuf *m;
369
370 BRIDGE_LOCK_ASSERT(sc);
371
372 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
373 return;
374
375 MGETHDR(m, M_DONTWAIT, MT_DATA);
376 if (m == NULL)
377 return;
378
379 m->m_pkthdr.rcvif = ifp;
380 m->m_pkthdr.len = sizeof(*eh) + sizeof(bpdu);
381 m->m_len = m->m_pkthdr.len;
382
383 eh = mtod(m, struct ether_header *);
384
385 memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN);
386 memcpy(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN);
387 eh->ether_type = htons(sizeof(bpdu));
388
389 bpdu.tbu_ssap = bpdu.tbu_dsap = LLC_8021D_LSAP;
390 bpdu.tbu_ctl = LLC_UI;
391 bpdu.tbu_protoid = 0;
392 bpdu.tbu_protover = 0;
393 bpdu.tbu_bpdutype = BSTP_MSGTYPE_TCN;
394
395 memcpy(mtod(m, caddr_t) + sizeof(*eh), &bpdu, sizeof(bpdu));
396
397 /* XXX: safe here?!? */
398 BRIDGE_UNLOCK(sc);
399 bridge_enqueue(sc, ifp, m);
400 BRIDGE_LOCK(sc);
401 }
402
403 void
404 bstp_configuration_update(struct bridge_softc *sc)
405 {
406 BRIDGE_LOCK_ASSERT(sc);
407
408 bstp_root_selection(sc);
409 bstp_designated_port_selection(sc);
410 }
411
412 void
413 bstp_root_selection(struct bridge_softc *sc)
414 {
415 struct bridge_iflist *root_port = NULL, *bif;
416
417 BRIDGE_LOCK_ASSERT(sc);
418
419 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
420 if ((bif->bif_flags & IFBIF_STP) == 0)
421 continue;
422 if (bstp_designated_port(sc, bif))
423 continue;
424 if (bif->bif_state == BSTP_IFSTATE_DISABLED)
425 continue;
426 if (bif->bif_designated_root >= sc->sc_bridge_id)
427 continue;
428 if (root_port == NULL)
429 goto set_port;
430
431 if (bif->bif_designated_root < root_port->bif_designated_root)
432 goto set_port;
433 if (bif->bif_designated_root > root_port->bif_designated_root)
434 continue;
435
436 if ((bif->bif_designated_cost + bif->bif_path_cost) <
437 (root_port->bif_designated_cost + root_port->bif_path_cost))
438 goto set_port;
439 if ((bif->bif_designated_cost + bif->bif_path_cost) >
440 (root_port->bif_designated_cost + root_port->bif_path_cost))
441 continue;
442
443 if (bif->bif_designated_bridge <
444 root_port->bif_designated_bridge)
445 goto set_port;
446 if (bif->bif_designated_bridge >
447 root_port->bif_designated_bridge)
448 continue;
449
450 if (bif->bif_designated_port < root_port->bif_designated_port)
451 goto set_port;
452 if (bif->bif_designated_port > root_port->bif_designated_port)
453 continue;
454
455 if (bif->bif_port_id >= root_port->bif_port_id)
456 continue;
457 set_port:
458 root_port = bif;
459 }
460
461 sc->sc_root_port = root_port;
462 if (root_port == NULL) {
463 sc->sc_designated_root = sc->sc_bridge_id;
464 sc->sc_root_path_cost = 0;
465 } else {
466 sc->sc_designated_root = root_port->bif_designated_root;
467 sc->sc_root_path_cost = root_port->bif_designated_cost +
468 root_port->bif_path_cost;
469 }
470 }
471
472 void
473 bstp_designated_port_selection(struct bridge_softc *sc)
474 {
475 struct bridge_iflist *bif;
476
477 BRIDGE_LOCK_ASSERT(sc);
478
479 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
480 if ((bif->bif_flags & IFBIF_STP) == 0)
481 continue;
482 if (bstp_designated_port(sc, bif))
483 goto designated;
484 if (bif->bif_designated_root != sc->sc_designated_root)
485 goto designated;
486
487 if (sc->sc_root_path_cost < bif->bif_designated_cost)
488 goto designated;
489 if (sc->sc_root_path_cost > bif->bif_designated_cost)
490 continue;
491
492 if (sc->sc_bridge_id < bif->bif_designated_bridge)
493 goto designated;
494 if (sc->sc_bridge_id > bif->bif_designated_bridge)
495 continue;
496
497 if (bif->bif_port_id > bif->bif_designated_port)
498 continue;
499 designated:
500 bstp_become_designated_port(sc, bif);
501 }
502 }
503
504 void
505 bstp_become_designated_port(struct bridge_softc *sc, struct bridge_iflist *bif)
506 {
507 bif->bif_designated_root = sc->sc_designated_root;
508 bif->bif_designated_cost = sc->sc_root_path_cost;
509 bif->bif_designated_bridge = sc->sc_bridge_id;
510 bif->bif_designated_port = bif->bif_port_id;
511 }
512
513 void
514 bstp_port_state_selection(struct bridge_softc *sc)
515 {
516 struct bridge_iflist *bif;
517
518 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
519 if ((bif->bif_flags & IFBIF_STP) == 0)
520 continue;
521 if (bif == sc->sc_root_port) {
522 bif->bif_config_pending = 0;
523 bif->bif_topology_change_acknowledge = 0;
524 bstp_make_forwarding(sc, bif);
525 } else if (bstp_designated_port(sc, bif)) {
526 bstp_timer_stop(&bif->bif_message_age_timer);
527 bstp_make_forwarding(sc, bif);
528 } else {
529 bif->bif_config_pending = 0;
530 bif->bif_topology_change_acknowledge = 0;
531 bstp_make_blocking(sc, bif);
532 }
533 }
534 }
535
536 void
537 bstp_make_forwarding(struct bridge_softc *sc, struct bridge_iflist *bif)
538 {
539 if (bif->bif_state == BSTP_IFSTATE_BLOCKING) {
540 bstp_set_port_state(bif, BSTP_IFSTATE_LISTENING);
541 bstp_timer_start(&bif->bif_forward_delay_timer, 0);
542 }
543 }
544
545 void
546 bstp_make_blocking(struct bridge_softc *sc, struct bridge_iflist *bif)
547 {
548 BRIDGE_LOCK_ASSERT(sc);
549
550 if ((bif->bif_state != BSTP_IFSTATE_DISABLED) &&
551 (bif->bif_state != BSTP_IFSTATE_BLOCKING)) {
552 if ((bif->bif_state == BSTP_IFSTATE_FORWARDING) ||
553 (bif->bif_state == BSTP_IFSTATE_LEARNING)) {
554 if (bif->bif_change_detection_enabled) {
555 bstp_topology_change_detection(sc);
556 }
557 }
558 bstp_set_port_state(bif, BSTP_IFSTATE_BLOCKING);
559 bridge_rtdelete(sc, bif->bif_ifp, IFBF_FLUSHDYN);
560 bstp_timer_stop(&bif->bif_forward_delay_timer);
561 }
562 }
563
564 void
565 bstp_set_port_state(struct bridge_iflist *bif, uint8_t state)
566 {
567 bif->bif_state = state;
568 }
569
570 void
571 bstp_topology_change_detection(struct bridge_softc *sc)
572 {
573 if (bstp_root_bridge(sc)) {
574 sc->sc_topology_change = 1;
575 bstp_timer_start(&sc->sc_topology_change_timer, 0);
576 } else if (!sc->sc_topology_change_detected) {
577 bstp_transmit_tcn(sc);
578 bstp_timer_start(&sc->sc_tcn_timer, 0);
579 }
580 sc->sc_topology_change_detected = 1;
581 }
582
583 void
584 bstp_topology_change_acknowledged(struct bridge_softc *sc)
585 {
586 sc->sc_topology_change_detected = 0;
587 bstp_timer_stop(&sc->sc_tcn_timer);
588 }
589
590 void
591 bstp_acknowledge_topology_change(struct bridge_softc *sc,
592 struct bridge_iflist *bif)
593 {
594 bif->bif_topology_change_acknowledge = 1;
595 bstp_transmit_config(sc, bif);
596 }
597
598 struct mbuf *
599 bstp_input(struct ifnet *ifp, struct mbuf *m)
600 {
601 struct bridge_softc *sc = ifp->if_bridge;
602 struct bridge_iflist *bif = NULL;
603 struct ether_header *eh;
604 struct bstp_tbpdu tpdu;
605 struct bstp_cbpdu cpdu;
606 struct bstp_config_unit cu;
607 struct bstp_tcn_unit tu;
608 uint16_t len;
609
610 BRIDGE_LOCK_ASSERT(sc);
611
612 eh = mtod(m, struct ether_header *);
613
614 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
615 if ((bif->bif_flags & IFBIF_STP) == 0)
616 continue;
617 if (bif->bif_ifp == ifp)
618 break;
619 }
620 if (bif == NULL)
621 goto out;
622
623 len = ntohs(eh->ether_type);
624 if (len < sizeof(tpdu))
625 goto out;
626
627 m_adj(m, ETHER_HDR_LEN);
628
629 if (m->m_pkthdr.len > len)
630 m_adj(m, len - m->m_pkthdr.len);
631 if (m->m_len < sizeof(tpdu) &&
632 (m = m_pullup(m, sizeof(tpdu))) == NULL)
633 goto out;
634
635 memcpy(&tpdu, mtod(m, caddr_t), sizeof(tpdu));
636
637 if (tpdu.tbu_dsap != LLC_8021D_LSAP ||
638 tpdu.tbu_ssap != LLC_8021D_LSAP ||
639 tpdu.tbu_ctl != LLC_UI)
640 goto out;
641 if (tpdu.tbu_protoid != 0 || tpdu.tbu_protover != 0)
642 goto out;
643
644 switch (tpdu.tbu_bpdutype) {
645 case BSTP_MSGTYPE_TCN:
646 tu.tu_message_type = tpdu.tbu_bpdutype;
647 bstp_received_tcn_bpdu(sc, bif, &tu);
648 break;
649 case BSTP_MSGTYPE_CFG:
650 if (m->m_len < sizeof(cpdu) &&
651 (m = m_pullup(m, sizeof(cpdu))) == NULL)
652 goto out;
653 memcpy(&cpdu, mtod(m, caddr_t), sizeof(cpdu));
654
655 cu.cu_rootid =
656 (((uint64_t)ntohs(cpdu.cbu_rootpri)) << 48) |
657 (((uint64_t)cpdu.cbu_rootaddr[0]) << 40) |
658 (((uint64_t)cpdu.cbu_rootaddr[1]) << 32) |
659 (((uint64_t)cpdu.cbu_rootaddr[2]) << 24) |
660 (((uint64_t)cpdu.cbu_rootaddr[3]) << 16) |
661 (((uint64_t)cpdu.cbu_rootaddr[4]) << 8) |
662 (((uint64_t)cpdu.cbu_rootaddr[5]) << 0);
663
664 cu.cu_bridge_id =
665 (((uint64_t)ntohs(cpdu.cbu_bridgepri)) << 48) |
666 (((uint64_t)cpdu.cbu_bridgeaddr[0]) << 40) |
667 (((uint64_t)cpdu.cbu_bridgeaddr[1]) << 32) |
668 (((uint64_t)cpdu.cbu_bridgeaddr[2]) << 24) |
669 (((uint64_t)cpdu.cbu_bridgeaddr[3]) << 16) |
670 (((uint64_t)cpdu.cbu_bridgeaddr[4]) << 8) |
671 (((uint64_t)cpdu.cbu_bridgeaddr[5]) << 0);
672
673 cu.cu_root_path_cost = ntohl(cpdu.cbu_rootpathcost);
674 cu.cu_message_age = ntohs(cpdu.cbu_messageage);
675 cu.cu_max_age = ntohs(cpdu.cbu_maxage);
676 cu.cu_hello_time = ntohs(cpdu.cbu_hellotime);
677 cu.cu_forward_delay = ntohs(cpdu.cbu_forwarddelay);
678 cu.cu_port_id = ntohs(cpdu.cbu_portid);
679 cu.cu_message_type = cpdu.cbu_bpdutype;
680 cu.cu_topology_change_acknowledgment =
681 (cpdu.cbu_flags & BSTP_FLAG_TCA) ? 1 : 0;
682 cu.cu_topology_change =
683 (cpdu.cbu_flags & BSTP_FLAG_TC) ? 1 : 0;
684 bstp_received_config_bpdu(sc, bif, &cu);
685 break;
686 default:
687 goto out;
688 }
689
690 out:
691 if (m)
692 m_freem(m);
693 return (NULL);
694 }
695
696 void
697 bstp_received_config_bpdu(struct bridge_softc *sc, struct bridge_iflist *bif,
698 struct bstp_config_unit *cu)
699 {
700 int root;
701
702 BRIDGE_LOCK_ASSERT(sc);
703
704 root = bstp_root_bridge(sc);
705
706 if (bif->bif_state != BSTP_IFSTATE_DISABLED) {
707 if (bstp_supersedes_port_info(sc, bif, cu)) {
708 bstp_record_config_information(sc, bif, cu);
709 bstp_configuration_update(sc);
710 bstp_port_state_selection(sc);
711
712 if ((bstp_root_bridge(sc) == 0) && root) {
713 bstp_timer_stop(&sc->sc_hello_timer);
714
715 if (sc->sc_topology_change_detected) {
716 bstp_timer_stop(
717 &sc->sc_topology_change_timer);
718 bstp_transmit_tcn(sc);
719 bstp_timer_start(&sc->sc_tcn_timer, 0);
720 }
721 }
722
723 if (bif == sc->sc_root_port) {
724 bstp_record_config_timeout_values(sc, cu);
725 bstp_config_bpdu_generation(sc);
726
727 if (cu->cu_topology_change_acknowledgment)
728 bstp_topology_change_acknowledged(sc);
729 }
730 } else if (bstp_designated_port(sc, bif))
731 bstp_transmit_config(sc, bif);
732 }
733 }
734
735 void
736 bstp_received_tcn_bpdu(struct bridge_softc *sc, struct bridge_iflist *bif,
737 struct bstp_tcn_unit *tcn)
738 {
739 if (bif->bif_state != BSTP_IFSTATE_DISABLED &&
740 bstp_designated_port(sc, bif)) {
741 bstp_topology_change_detection(sc);
742 bstp_acknowledge_topology_change(sc, bif);
743 }
744 }
745
746 void
747 bstp_hello_timer_expiry(struct bridge_softc *sc)
748 {
749 bstp_config_bpdu_generation(sc);
750 bstp_timer_start(&sc->sc_hello_timer, 0);
751 }
752
753 void
754 bstp_message_age_timer_expiry(struct bridge_softc *sc,
755 struct bridge_iflist *bif)
756 {
757 int root;
758
759 root = bstp_root_bridge(sc);
760 bstp_become_designated_port(sc, bif);
761 bstp_configuration_update(sc);
762 bstp_port_state_selection(sc);
763
764 if ((bstp_root_bridge(sc)) && (root == 0)) {
765 sc->sc_max_age = sc->sc_bridge_max_age;
766 sc->sc_hello_time = sc->sc_bridge_hello_time;
767 sc->sc_forward_delay = sc->sc_bridge_forward_delay;
768
769 bstp_topology_change_detection(sc);
770 bstp_timer_stop(&sc->sc_tcn_timer);
771 bstp_config_bpdu_generation(sc);
772 bstp_timer_start(&sc->sc_hello_timer, 0);
773 }
774 }
775
776 void
777 bstp_forward_delay_timer_expiry(struct bridge_softc *sc,
778 struct bridge_iflist *bif)
779 {
780 if (bif->bif_state == BSTP_IFSTATE_LISTENING) {
781 bstp_set_port_state(bif, BSTP_IFSTATE_LEARNING);
782 bstp_timer_start(&bif->bif_forward_delay_timer, 0);
783 } else if (bif->bif_state == BSTP_IFSTATE_LEARNING) {
784 bstp_set_port_state(bif, BSTP_IFSTATE_FORWARDING);
785 if (bstp_designated_for_some_port(sc) &&
786 bif->bif_change_detection_enabled)
787 bstp_topology_change_detection(sc);
788 }
789 }
790
791 int
792 bstp_designated_for_some_port(struct bridge_softc *sc)
793 {
794
795 struct bridge_iflist *bif;
796
797 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
798 if ((bif->bif_flags & IFBIF_STP) == 0)
799 continue;
800 if (bif->bif_designated_bridge == sc->sc_bridge_id)
801 return (1);
802 }
803 return (0);
804 }
805
806 void
807 bstp_tcn_timer_expiry(struct bridge_softc *sc)
808 {
809 bstp_transmit_tcn(sc);
810 bstp_timer_start(&sc->sc_tcn_timer, 0);
811 }
812
813 void
814 bstp_topology_change_timer_expiry(struct bridge_softc *sc)
815 {
816 sc->sc_topology_change_detected = 0;
817 sc->sc_topology_change = 0;
818 }
819
820 void
821 bstp_hold_timer_expiry(struct bridge_softc *sc, struct bridge_iflist *bif)
822 {
823 if (bif->bif_config_pending)
824 bstp_transmit_config(sc, bif);
825 }
826
827 void
828 bstp_initialization(struct bridge_softc *sc)
829 {
830 struct bridge_iflist *bif, *mif;
831
832 BRIDGE_LOCK_ASSERT(sc);
833
834 mif = NULL;
835 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
836 if ((bif->bif_flags & IFBIF_STP) == 0)
837 continue;
838 if (bif->bif_ifp->if_type != IFT_ETHER)
839 continue;
840 bif->bif_port_id = (bif->bif_priority << 8) |
841 (bif->bif_ifp->if_index & 0xff);
842
843 if (mif == NULL) {
844 mif = bif;
845 continue;
846 }
847 if (memcmp(IF_LLADDR(bif->bif_ifp),
848 IF_LLADDR(mif->bif_ifp), ETHER_ADDR_LEN) < 0) {
849 mif = bif;
850 continue;
851 }
852 }
853 if (mif == NULL) {
854 bstp_stop(sc);
855 return;
856 }
857
858 sc->sc_bridge_id =
859 (((uint64_t)sc->sc_bridge_priority) << 48) |
860 (((uint64_t)IF_LLADDR(mif->bif_ifp)[0]) << 40) |
861 (((uint64_t)IF_LLADDR(mif->bif_ifp)[1]) << 32) |
862 (IF_LLADDR(mif->bif_ifp)[2] << 24) |
863 (IF_LLADDR(mif->bif_ifp)[3] << 16) |
864 (IF_LLADDR(mif->bif_ifp)[4] << 8) |
865 (IF_LLADDR(mif->bif_ifp)[5]);
866
867 sc->sc_designated_root = sc->sc_bridge_id;
868 sc->sc_root_path_cost = 0;
869 sc->sc_root_port = NULL;
870
871 sc->sc_max_age = sc->sc_bridge_max_age;
872 sc->sc_hello_time = sc->sc_bridge_hello_time;
873 sc->sc_forward_delay = sc->sc_bridge_forward_delay;
874 sc->sc_topology_change_detected = 0;
875 sc->sc_topology_change = 0;
876 bstp_timer_stop(&sc->sc_tcn_timer);
877 bstp_timer_stop(&sc->sc_topology_change_timer);
878
879 if (callout_pending(&sc->sc_bstpcallout) == 0)
880 callout_reset(&sc->sc_bstpcallout, hz,
881 bstp_tick, sc);
882
883 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
884 if (bif->bif_flags & IFBIF_STP)
885 bstp_enable_port(sc, bif);
886 else
887 bstp_disable_port(sc, bif);
888 }
889
890 bstp_port_state_selection(sc);
891 bstp_config_bpdu_generation(sc);
892 bstp_timer_start(&sc->sc_hello_timer, 0);
893 }
894
895 void
896 bstp_stop(struct bridge_softc *sc)
897 {
898 struct bridge_iflist *bif;
899
900 BRIDGE_LOCK_ASSERT(sc);
901
902 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
903 bstp_set_port_state(bif, BSTP_IFSTATE_DISABLED);
904 bstp_timer_stop(&bif->bif_hold_timer);
905 bstp_timer_stop(&bif->bif_message_age_timer);
906 bstp_timer_stop(&bif->bif_forward_delay_timer);
907 }
908
909 callout_stop(&sc->sc_bstpcallout);
910
911 bstp_timer_stop(&sc->sc_topology_change_timer);
912 bstp_timer_stop(&sc->sc_tcn_timer);
913 bstp_timer_stop(&sc->sc_hello_timer);
914
915 }
916
917 void
918 bstp_initialize_port(struct bridge_softc *sc, struct bridge_iflist *bif)
919 {
920 bstp_become_designated_port(sc, bif);
921 bstp_set_port_state(bif, BSTP_IFSTATE_BLOCKING);
922 bif->bif_topology_change_acknowledge = 0;
923 bif->bif_config_pending = 0;
924 bif->bif_change_detection_enabled = 1;
925 bstp_timer_stop(&bif->bif_message_age_timer);
926 bstp_timer_stop(&bif->bif_forward_delay_timer);
927 bstp_timer_stop(&bif->bif_hold_timer);
928 }
929
930 void
931 bstp_enable_port(struct bridge_softc *sc, struct bridge_iflist *bif)
932 {
933 bstp_initialize_port(sc, bif);
934 bstp_port_state_selection(sc);
935 }
936
937 void
938 bstp_disable_port(struct bridge_softc *sc, struct bridge_iflist *bif)
939 {
940 int root;
941
942 BRIDGE_LOCK_ASSERT(sc);
943
944 root = bstp_root_bridge(sc);
945 bstp_become_designated_port(sc, bif);
946 bstp_set_port_state(bif, BSTP_IFSTATE_DISABLED);
947 bif->bif_topology_change_acknowledge = 0;
948 bif->bif_config_pending = 0;
949 bstp_timer_stop(&bif->bif_message_age_timer);
950 bstp_timer_stop(&bif->bif_forward_delay_timer);
951 bstp_configuration_update(sc);
952 bstp_port_state_selection(sc);
953 bridge_rtdelete(sc, bif->bif_ifp, IFBF_FLUSHDYN);
954
955 if (bstp_root_bridge(sc) && (root == 0)) {
956 sc->sc_max_age = sc->sc_bridge_max_age;
957 sc->sc_hello_time = sc->sc_bridge_hello_time;
958 sc->sc_forward_delay = sc->sc_bridge_forward_delay;
959
960 bstp_topology_change_detection(sc);
961 bstp_timer_stop(&sc->sc_tcn_timer);
962 bstp_config_bpdu_generation(sc);
963 bstp_timer_start(&sc->sc_hello_timer, 0);
964 }
965 }
966
967 void
968 bstp_set_bridge_priority(struct bridge_softc *sc, uint64_t new_bridge_id)
969 {
970 struct bridge_iflist *bif;
971 int root;
972
973 BRIDGE_LOCK_ASSERT(sc);
974
975 root = bstp_root_bridge(sc);
976
977 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
978 if ((bif->bif_flags & IFBIF_STP) == 0)
979 continue;
980 if (bstp_designated_port(sc, bif))
981 bif->bif_designated_bridge = new_bridge_id;
982 }
983
984 sc->sc_bridge_id = new_bridge_id;
985
986 bstp_configuration_update(sc);
987 bstp_port_state_selection(sc);
988
989 if (bstp_root_bridge(sc) && (root == 0)) {
990 sc->sc_max_age = sc->sc_bridge_max_age;
991 sc->sc_hello_time = sc->sc_bridge_hello_time;
992 sc->sc_forward_delay = sc->sc_bridge_forward_delay;
993
994 bstp_topology_change_detection(sc);
995 bstp_timer_stop(&sc->sc_tcn_timer);
996 bstp_config_bpdu_generation(sc);
997 bstp_timer_start(&sc->sc_hello_timer, 0);
998 }
999 }
1000
1001 void
1002 bstp_set_port_priority(struct bridge_softc *sc, struct bridge_iflist *bif,
1003 uint16_t new_port_id)
1004 {
1005 if (bstp_designated_port(sc, bif))
1006 bif->bif_designated_port = new_port_id;
1007
1008 bif->bif_port_id = new_port_id;
1009
1010 if ((sc->sc_bridge_id == bif->bif_designated_bridge) &&
1011 (bif->bif_port_id < bif->bif_designated_port)) {
1012 bstp_become_designated_port(sc, bif);
1013 bstp_port_state_selection(sc);
1014 }
1015 }
1016
1017 void
1018 bstp_set_path_cost(struct bridge_softc *sc, struct bridge_iflist *bif,
1019 uint32_t path_cost)
1020 {
1021 bif->bif_path_cost = path_cost;
1022 bstp_configuration_update(sc);
1023 bstp_port_state_selection(sc);
1024 }
1025
1026 void
1027 bstp_enable_change_detection(struct bridge_iflist *bif)
1028 {
1029 bif->bif_change_detection_enabled = 1;
1030 }
1031
1032 void
1033 bstp_disable_change_detection(struct bridge_iflist *bif)
1034 {
1035 bif->bif_change_detection_enabled = 0;
1036 }
1037
1038 void
1039 bstp_linkstate(struct ifnet *ifp, int state)
1040 {
1041 struct bridge_softc *sc;
1042 struct bridge_iflist *bif;
1043
1044 sc = ifp->if_bridge;
1045 BRIDGE_LOCK(sc);
1046
1047 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
1048 if ((bif->bif_flags & IFBIF_STP) == 0)
1049 continue;
1050
1051 if (bif->bif_ifp == ifp) {
1052 bstp_ifupdstatus(sc, bif);
1053 break;
1054 }
1055 }
1056
1057 BRIDGE_UNLOCK(sc);
1058 }
1059
1060 void
1061 bstp_ifupdstatus(struct bridge_softc *sc, struct bridge_iflist *bif)
1062 {
1063 struct ifnet *ifp = bif->bif_ifp;
1064 struct ifmediareq ifmr;
1065 int error = 0;
1066
1067 BRIDGE_LOCK_ASSERT(sc);
1068
1069 bzero((char *)&ifmr, sizeof(ifmr));
1070 error = (*ifp->if_ioctl)(ifp, SIOCGIFMEDIA, (caddr_t)&ifmr);
1071
1072 if ((error == 0) && (ifp->if_flags & IFF_UP)) {
1073 if (ifmr.ifm_status & IFM_ACTIVE) {
1074 if (bif->bif_state == BSTP_IFSTATE_DISABLED)
1075 bstp_enable_port(sc, bif);
1076
1077 } else {
1078 if (bif->bif_state != BSTP_IFSTATE_DISABLED)
1079 bstp_disable_port(sc, bif);
1080 }
1081 return;
1082 }
1083
1084 if (bif->bif_state != BSTP_IFSTATE_DISABLED)
1085 bstp_disable_port(sc, bif);
1086 }
1087
1088 void
1089 bstp_tick(void *arg)
1090 {
1091 struct bridge_softc *sc = arg;
1092 struct bridge_iflist *bif;
1093
1094 BRIDGE_LOCK_ASSERT(sc);
1095
1096 #if 0
1097 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
1098 if ((bif->bif_flags & IFBIF_STP) == 0)
1099 continue;
1100 /*
1101 * XXX This can cause a lag in "link does away"
1102 * XXX and "spanning tree gets updated". We need
1103 * XXX come sort of callback from the link state
1104 * XXX update code to kick spanning tree.
1105 * XXX --thorpej@NetBSD.org
1106 */
1107 bstp_ifupdstatus(sc, bif);
1108 }
1109 #endif
1110
1111 if (bstp_timer_expired(&sc->sc_hello_timer, sc->sc_hello_time))
1112 bstp_hello_timer_expiry(sc);
1113
1114 if (bstp_timer_expired(&sc->sc_tcn_timer, sc->sc_bridge_hello_time))
1115 bstp_tcn_timer_expiry(sc);
1116
1117 if (bstp_timer_expired(&sc->sc_topology_change_timer,
1118 sc->sc_topology_change_time))
1119 bstp_topology_change_timer_expiry(sc);
1120
1121 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
1122 if ((bif->bif_flags & IFBIF_STP) == 0)
1123 continue;
1124 if (bstp_timer_expired(&bif->bif_message_age_timer,
1125 sc->sc_max_age))
1126 bstp_message_age_timer_expiry(sc, bif);
1127 }
1128
1129 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
1130 if ((bif->bif_flags & IFBIF_STP) == 0)
1131 continue;
1132 if (bstp_timer_expired(&bif->bif_forward_delay_timer,
1133 sc->sc_forward_delay))
1134 bstp_forward_delay_timer_expiry(sc, bif);
1135
1136 if (bstp_timer_expired(&bif->bif_hold_timer,
1137 sc->sc_hold_time))
1138 bstp_hold_timer_expiry(sc, bif);
1139 }
1140
1141 if (sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING)
1142 callout_reset(&sc->sc_bstpcallout, hz, bstp_tick, sc);
1143 }
1144
1145 void
1146 bstp_timer_start(struct bridge_timer *t, uint16_t v)
1147 {
1148 t->value = v;
1149 t->active = 1;
1150 }
1151
1152 void
1153 bstp_timer_stop(struct bridge_timer *t)
1154 {
1155 t->value = 0;
1156 t->active = 0;
1157 }
1158
1159 int
1160 bstp_timer_expired(struct bridge_timer *t, uint16_t v)
1161 {
1162 if (t->active == 0)
1163 return (0);
1164 t->value += BSTP_TICK_VAL;
1165 if (t->value >= v) {
1166 bstp_timer_stop(t);
1167 return (1);
1168 }
1169 return (0);
1170
1171 }
Cache object: ffd3d73bf0f20fb3af23db2f9808c25e
|