1 /* $NetBSD: bridgestp.c,v 1.5 2003/11/28 08:56:48 keihan Exp $ */
4 * Copyright (c) 2000 Jason L. Wright (jason@thought.net)
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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.
33 * OpenBSD: bridgestp.c,v 1.5 2001/03/22 03:48:29 jason Exp
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)
42 #include <sys/cdefs.h>
43 __FBSDID("$FreeBSD$");
45 #include <sys/param.h>
46 #include <sys/systm.h>
48 #include <sys/socket.h>
49 #include <sys/sockio.h>
50 #include <sys/kernel.h>
51 #include <sys/callout.h>
52 #include <sys/module.h>
55 #include <sys/mutex.h>
56 #include <sys/taskqueue.h>
59 #include <net/if_dl.h>
60 #include <net/if_types.h>
61 #include <net/if_llc.h>
62 #include <net/if_media.h>
64 #include <netinet/in.h>
65 #include <netinet/in_systm.h>
66 #include <netinet/in_var.h>
67 #include <netinet/if_ether.h>
68 #include <net/bridgestp.h>
70 const uint8_t bstp_etheraddr[] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
72 LIST_HEAD(, bstp_state) bstp_list;
73 static struct mtx bstp_list_mtx;
75 static void bstp_initialize_port(struct bstp_state *,
77 static void bstp_ifupdstatus(struct bstp_state *, struct bstp_port *);
78 static void bstp_enable_port(struct bstp_state *, struct bstp_port *);
79 static void bstp_disable_port(struct bstp_state *,
82 static void bstp_enable_change_detection(struct bstp_port *);
83 static void bstp_disable_change_detection(struct bstp_port *);
85 static int bstp_root_bridge(struct bstp_state *bs);
86 static int bstp_supersedes_port_info(struct bstp_state *,
87 struct bstp_port *, struct bstp_config_unit *);
88 static int bstp_designated_port(struct bstp_state *,
90 static int bstp_designated_for_some_port(struct bstp_state *);
91 static void bstp_transmit_config(struct bstp_state *,
93 static void bstp_transmit_tcn(struct bstp_state *);
94 static void bstp_received_config_bpdu(struct bstp_state *,
95 struct bstp_port *, struct bstp_config_unit *);
96 static void bstp_received_tcn_bpdu(struct bstp_state *,
97 struct bstp_port *, struct bstp_tcn_unit *);
98 static void bstp_record_config_information(struct bstp_state *,
99 struct bstp_port *, struct bstp_config_unit *);
100 static void bstp_record_config_timeout_values(struct bstp_state *,
101 struct bstp_config_unit *);
102 static void bstp_config_bpdu_generation(struct bstp_state *);
103 static void bstp_send_config_bpdu(struct bstp_state *,
104 struct bstp_port *, struct bstp_config_unit *);
105 static void bstp_configuration_update(struct bstp_state *);
106 static void bstp_root_selection(struct bstp_state *);
107 static void bstp_designated_port_selection(struct bstp_state *);
108 static void bstp_become_designated_port(struct bstp_state *,
110 static void bstp_port_state_selection(struct bstp_state *);
111 static void bstp_make_forwarding(struct bstp_state *,
113 static void bstp_make_blocking(struct bstp_state *,
115 static void bstp_set_port_state(struct bstp_port *, uint8_t);
116 static void bstp_state_change(void *, int);
117 static void bstp_update_forward_transitions(struct bstp_port *);
119 static void bstp_set_bridge_priority(struct bstp_state *, uint64_t);
120 static void bstp_set_port_priority(struct bstp_state *,
121 struct bstp_port *, uint16_t);
122 static void bstp_set_path_cost(struct bstp_state *,
123 struct bstp_port *, uint32_t);
125 static void bstp_topology_change_detection(struct bstp_state *);
126 static void bstp_topology_change_acknowledged(struct bstp_state *);
127 static void bstp_acknowledge_topology_change(struct bstp_state *,
130 static void bstp_enqueue(struct ifnet *, struct mbuf *);
131 static void bstp_tick(void *);
132 static void bstp_timer_start(struct bstp_timer *, uint16_t);
133 static void bstp_timer_stop(struct bstp_timer *);
134 static int bstp_timer_expired(struct bstp_timer *, uint16_t);
136 static void bstp_hold_timer_expiry(struct bstp_state *,
138 static void bstp_message_age_timer_expiry(struct bstp_state *,
140 static void bstp_forward_delay_timer_expiry(struct bstp_state *,
142 static void bstp_topology_change_timer_expiry(struct bstp_state *);
143 static void bstp_tcn_timer_expiry(struct bstp_state *);
144 static void bstp_hello_timer_expiry(struct bstp_state *);
145 static int bstp_addr_cmp(const uint8_t *, const uint8_t *);
148 bstp_transmit_config(struct bstp_state *bs, struct bstp_port *bp)
150 BSTP_LOCK_ASSERT(bs);
152 if (bp->bp_hold_timer.active) {
153 bp->bp_config_pending = 1;
157 bp->bp_config_bpdu.cu_message_type = BSTP_MSGTYPE_CFG;
158 bp->bp_config_bpdu.cu_rootid = bs->bs_designated_root;
159 bp->bp_config_bpdu.cu_root_path_cost = bs->bs_root_path_cost;
160 bp->bp_config_bpdu.cu_bridge_id = bs->bs_bridge_id;
161 bp->bp_config_bpdu.cu_port_id = bp->bp_port_id;
163 if (bstp_root_bridge(bs))
164 bp->bp_config_bpdu.cu_message_age = 0;
166 bp->bp_config_bpdu.cu_message_age =
167 bs->bs_root_port->bp_message_age_timer.value +
168 BSTP_MESSAGE_AGE_INCR;
170 bp->bp_config_bpdu.cu_max_age = bs->bs_max_age;
171 bp->bp_config_bpdu.cu_hello_time = bs->bs_hello_time;
172 bp->bp_config_bpdu.cu_forward_delay = bs->bs_forward_delay;
173 bp->bp_config_bpdu.cu_topology_change_acknowledgment
174 = bp->bp_topology_change_acknowledge;
175 bp->bp_config_bpdu.cu_topology_change = bs->bs_topology_change;
177 if (bp->bp_config_bpdu.cu_message_age < bs->bs_max_age) {
178 bp->bp_topology_change_acknowledge = 0;
179 bp->bp_config_pending = 0;
180 bstp_send_config_bpdu(bs, bp, &bp->bp_config_bpdu);
181 bstp_timer_start(&bp->bp_hold_timer, 0);
186 bstp_send_config_bpdu(struct bstp_state *bs, struct bstp_port *bp,
187 struct bstp_config_unit *cu)
191 struct ether_header *eh;
192 struct bstp_cbpdu bpdu;
194 BSTP_LOCK_ASSERT(bs);
198 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
201 MGETHDR(m, M_DONTWAIT, MT_DATA);
205 eh = mtod(m, struct ether_header *);
207 m->m_pkthdr.rcvif = ifp;
208 m->m_pkthdr.len = sizeof(*eh) + sizeof(bpdu);
209 m->m_len = m->m_pkthdr.len;
211 bpdu.cbu_ssap = bpdu.cbu_dsap = LLC_8021D_LSAP;
212 bpdu.cbu_ctl = LLC_UI;
213 bpdu.cbu_protoid = htons(0);
214 bpdu.cbu_protover = 0;
215 bpdu.cbu_bpdutype = cu->cu_message_type;
216 bpdu.cbu_flags = (cu->cu_topology_change ? BSTP_FLAG_TC : 0) |
217 (cu->cu_topology_change_acknowledgment ? BSTP_FLAG_TCA : 0);
219 bpdu.cbu_rootpri = htons(cu->cu_rootid >> 48);
220 bpdu.cbu_rootaddr[0] = cu->cu_rootid >> 40;
221 bpdu.cbu_rootaddr[1] = cu->cu_rootid >> 32;
222 bpdu.cbu_rootaddr[2] = cu->cu_rootid >> 24;
223 bpdu.cbu_rootaddr[3] = cu->cu_rootid >> 16;
224 bpdu.cbu_rootaddr[4] = cu->cu_rootid >> 8;
225 bpdu.cbu_rootaddr[5] = cu->cu_rootid >> 0;
227 bpdu.cbu_rootpathcost = htonl(cu->cu_root_path_cost);
229 bpdu.cbu_bridgepri = htons(cu->cu_bridge_id >> 48);
230 bpdu.cbu_bridgeaddr[0] = cu->cu_bridge_id >> 40;
231 bpdu.cbu_bridgeaddr[1] = cu->cu_bridge_id >> 32;
232 bpdu.cbu_bridgeaddr[2] = cu->cu_bridge_id >> 24;
233 bpdu.cbu_bridgeaddr[3] = cu->cu_bridge_id >> 16;
234 bpdu.cbu_bridgeaddr[4] = cu->cu_bridge_id >> 8;
235 bpdu.cbu_bridgeaddr[5] = cu->cu_bridge_id >> 0;
237 bpdu.cbu_portid = htons(cu->cu_port_id);
238 bpdu.cbu_messageage = htons(cu->cu_message_age);
239 bpdu.cbu_maxage = htons(cu->cu_max_age);
240 bpdu.cbu_hellotime = htons(cu->cu_hello_time);
241 bpdu.cbu_forwarddelay = htons(cu->cu_forward_delay);
243 memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN);
244 memcpy(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN);
245 eh->ether_type = htons(sizeof(bpdu));
247 memcpy(mtod(m, caddr_t) + sizeof(*eh), &bpdu, sizeof(bpdu));
249 bstp_enqueue(ifp, m);
253 bstp_root_bridge(struct bstp_state *bs)
255 return (bs->bs_designated_root == bs->bs_bridge_id);
259 bstp_supersedes_port_info(struct bstp_state *bs, struct bstp_port *bp,
260 struct bstp_config_unit *cu)
262 if (cu->cu_rootid < bp->bp_designated_root)
264 if (cu->cu_rootid > bp->bp_designated_root)
267 if (cu->cu_root_path_cost < bp->bp_designated_cost)
269 if (cu->cu_root_path_cost > bp->bp_designated_cost)
272 if (cu->cu_bridge_id < bp->bp_designated_bridge)
274 if (cu->cu_bridge_id > bp->bp_designated_bridge)
277 if (bs->bs_bridge_id != cu->cu_bridge_id)
279 if (cu->cu_port_id <= bp->bp_designated_port)
285 bstp_record_config_information(struct bstp_state *bs,
286 struct bstp_port *bp, struct bstp_config_unit *cu)
288 BSTP_LOCK_ASSERT(bs);
290 bp->bp_designated_root = cu->cu_rootid;
291 bp->bp_designated_cost = cu->cu_root_path_cost;
292 bp->bp_designated_bridge = cu->cu_bridge_id;
293 bp->bp_designated_port = cu->cu_port_id;
294 bstp_timer_start(&bp->bp_message_age_timer, cu->cu_message_age);
298 bstp_record_config_timeout_values(struct bstp_state *bs,
299 struct bstp_config_unit *config)
301 BSTP_LOCK_ASSERT(bs);
303 bs->bs_max_age = config->cu_max_age;
304 bs->bs_hello_time = config->cu_hello_time;
305 bs->bs_forward_delay = config->cu_forward_delay;
306 bs->bs_topology_change = config->cu_topology_change;
310 bstp_config_bpdu_generation(struct bstp_state *bs)
312 struct bstp_port *bp;
314 BSTP_LOCK_ASSERT(bs);
316 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
317 if (bstp_designated_port(bs, bp) &&
318 (bp->bp_state != BSTP_IFSTATE_DISABLED))
319 bstp_transmit_config(bs, bp);
324 bstp_designated_port(struct bstp_state *bs, struct bstp_port *bp)
326 return ((bp->bp_designated_bridge == bs->bs_bridge_id)
327 && (bp->bp_designated_port == bp->bp_port_id));
331 bstp_transmit_tcn(struct bstp_state *bs)
333 struct bstp_tbpdu bpdu;
334 struct bstp_port *bp = bs->bs_root_port;
335 struct ifnet *ifp = bp->bp_ifp;
336 struct ether_header *eh;
339 BSTP_LOCK_ASSERT(bs);
341 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
344 MGETHDR(m, M_DONTWAIT, MT_DATA);
348 m->m_pkthdr.rcvif = ifp;
349 m->m_pkthdr.len = sizeof(*eh) + sizeof(bpdu);
350 m->m_len = m->m_pkthdr.len;
352 eh = mtod(m, struct ether_header *);
354 memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN);
355 memcpy(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN);
356 eh->ether_type = htons(sizeof(bpdu));
358 bpdu.tbu_ssap = bpdu.tbu_dsap = LLC_8021D_LSAP;
359 bpdu.tbu_ctl = LLC_UI;
360 bpdu.tbu_protoid = 0;
361 bpdu.tbu_protover = 0;
362 bpdu.tbu_bpdutype = BSTP_MSGTYPE_TCN;
364 memcpy(mtod(m, caddr_t) + sizeof(*eh), &bpdu, sizeof(bpdu));
366 bstp_enqueue(ifp, m);
370 bstp_configuration_update(struct bstp_state *bs)
372 BSTP_LOCK_ASSERT(bs);
374 bstp_root_selection(bs);
375 bstp_designated_port_selection(bs);
379 bstp_root_selection(struct bstp_state *bs)
381 struct bstp_port *root_port = NULL, *bp;
383 BSTP_LOCK_ASSERT(bs);
385 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
386 if (bstp_designated_port(bs, bp))
388 if (bp->bp_state == BSTP_IFSTATE_DISABLED)
390 if (bp->bp_designated_root >= bs->bs_bridge_id)
392 if (root_port == NULL)
395 if (bp->bp_designated_root < root_port->bp_designated_root)
397 if (bp->bp_designated_root > root_port->bp_designated_root)
400 if ((bp->bp_designated_cost + bp->bp_path_cost) <
401 (root_port->bp_designated_cost + root_port->bp_path_cost))
403 if ((bp->bp_designated_cost + bp->bp_path_cost) >
404 (root_port->bp_designated_cost + root_port->bp_path_cost))
407 if (bp->bp_designated_bridge <
408 root_port->bp_designated_bridge)
410 if (bp->bp_designated_bridge >
411 root_port->bp_designated_bridge)
414 if (bp->bp_designated_port < root_port->bp_designated_port)
416 if (bp->bp_designated_port > root_port->bp_designated_port)
419 if (bp->bp_port_id >= root_port->bp_port_id)
425 bs->bs_root_port = root_port;
426 if (root_port == NULL) {
427 bs->bs_designated_root = bs->bs_bridge_id;
428 bs->bs_root_path_cost = 0;
430 bs->bs_designated_root = root_port->bp_designated_root;
431 bs->bs_root_path_cost = root_port->bp_designated_cost +
432 root_port->bp_path_cost;
437 bstp_designated_port_selection(struct bstp_state *bs)
439 struct bstp_port *bp;
441 BSTP_LOCK_ASSERT(bs);
443 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
444 if (bstp_designated_port(bs, bp))
446 if (bp->bp_designated_root != bs->bs_designated_root)
449 if (bs->bs_root_path_cost < bp->bp_designated_cost)
451 if (bs->bs_root_path_cost > bp->bp_designated_cost)
454 if (bs->bs_bridge_id < bp->bp_designated_bridge)
456 if (bs->bs_bridge_id > bp->bp_designated_bridge)
459 if (bp->bp_port_id > bp->bp_designated_port)
462 bstp_become_designated_port(bs, bp);
467 bstp_become_designated_port(struct bstp_state *bs, struct bstp_port *bp)
469 BSTP_LOCK_ASSERT(bs);
471 bp->bp_designated_root = bs->bs_designated_root;
472 bp->bp_designated_cost = bs->bs_root_path_cost;
473 bp->bp_designated_bridge = bs->bs_bridge_id;
474 bp->bp_designated_port = bp->bp_port_id;
478 bstp_port_state_selection(struct bstp_state *bs)
480 struct bstp_port *bp;
482 BSTP_LOCK_ASSERT(bs);
484 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
485 if (bp == bs->bs_root_port) {
486 bp->bp_config_pending = 0;
487 bp->bp_topology_change_acknowledge = 0;
488 bstp_make_forwarding(bs, bp);
489 } else if (bstp_designated_port(bs, bp)) {
490 bstp_timer_stop(&bp->bp_message_age_timer);
491 bstp_make_forwarding(bs, bp);
493 bp->bp_config_pending = 0;
494 bp->bp_topology_change_acknowledge = 0;
495 bstp_make_blocking(bs, bp);
501 bstp_make_forwarding(struct bstp_state *bs, struct bstp_port *bp)
503 BSTP_LOCK_ASSERT(bs);
505 if (bp->bp_state == BSTP_IFSTATE_BLOCKING) {
506 bstp_set_port_state(bp, BSTP_IFSTATE_LISTENING);
507 bstp_timer_start(&bp->bp_forward_delay_timer, 0);
512 bstp_make_blocking(struct bstp_state *bs, struct bstp_port *bp)
514 BSTP_LOCK_ASSERT(bs);
516 if ((bp->bp_state != BSTP_IFSTATE_DISABLED) &&
517 (bp->bp_state != BSTP_IFSTATE_BLOCKING)) {
518 if ((bp->bp_state == BSTP_IFSTATE_FORWARDING) ||
519 (bp->bp_state == BSTP_IFSTATE_LEARNING)) {
520 if (bp->bp_change_detection_enabled) {
521 bstp_topology_change_detection(bs);
524 bstp_set_port_state(bp, BSTP_IFSTATE_BLOCKING);
525 bstp_timer_stop(&bp->bp_forward_delay_timer);
530 bstp_set_port_state(struct bstp_port *bp, uint8_t state)
532 struct bstp_state *bs = bp->bp_bs;
534 bp->bp_state = state;
536 /* notify the parent bridge */
537 if (bs->bs_state_cb != NULL)
538 taskqueue_enqueue(taskqueue_swi, &bp->bp_statetask);
542 * Notify the bridge that a port state has changed, we need to do this from a
543 * taskqueue to avoid a LOR.
546 bstp_state_change(void *arg, int pending)
548 struct bstp_port *bp = (struct bstp_port *)arg;
549 struct bstp_state *bs = bp->bp_bs;
551 if (bp->bp_active == 1)
552 (*bs->bs_state_cb)(bp->bp_ifp, bp->bp_state);
556 bstp_update_forward_transitions(struct bstp_port *bp)
558 bp->bp_forward_transitions++;
562 bstp_topology_change_detection(struct bstp_state *bs)
564 BSTP_LOCK_ASSERT(bs);
566 if (bstp_root_bridge(bs)) {
567 bs->bs_topology_change = 1;
568 bstp_timer_start(&bs->bs_topology_change_timer, 0);
569 } else if (!bs->bs_topology_change_detected) {
570 bstp_transmit_tcn(bs);
571 bstp_timer_start(&bs->bs_tcn_timer, 0);
573 bs->bs_topology_change_detected = 1;
574 getmicrotime(&bs->bs_last_tc_time);
578 bstp_topology_change_acknowledged(struct bstp_state *bs)
580 BSTP_LOCK_ASSERT(bs);
582 bs->bs_topology_change_detected = 0;
583 bstp_timer_stop(&bs->bs_tcn_timer);
587 bstp_acknowledge_topology_change(struct bstp_state *bs,
588 struct bstp_port *bp)
590 BSTP_LOCK_ASSERT(bs);
592 bp->bp_topology_change_acknowledge = 1;
593 bstp_transmit_config(bs, bp);
597 bstp_input(struct bstp_port *bp, struct ifnet *ifp, struct mbuf *m)
599 struct bstp_state *bs = bp->bp_bs;
600 struct ether_header *eh;
601 struct bstp_tbpdu tpdu;
602 struct bstp_cbpdu cpdu;
603 struct bstp_config_unit cu;
604 struct bstp_tcn_unit tu;
607 if (bp->bp_active == 0) {
614 eh = mtod(m, struct ether_header *);
616 len = ntohs(eh->ether_type);
617 if (len < sizeof(tpdu))
620 m_adj(m, ETHER_HDR_LEN);
622 if (m->m_pkthdr.len > len)
623 m_adj(m, len - m->m_pkthdr.len);
624 if (m->m_len < sizeof(tpdu) &&
625 (m = m_pullup(m, sizeof(tpdu))) == NULL)
628 memcpy(&tpdu, mtod(m, caddr_t), sizeof(tpdu));
630 if (tpdu.tbu_dsap != LLC_8021D_LSAP ||
631 tpdu.tbu_ssap != LLC_8021D_LSAP ||
632 tpdu.tbu_ctl != LLC_UI)
634 if (tpdu.tbu_protoid != 0 || tpdu.tbu_protover != 0)
637 switch (tpdu.tbu_bpdutype) {
638 case BSTP_MSGTYPE_TCN:
639 tu.tu_message_type = tpdu.tbu_bpdutype;
640 bstp_received_tcn_bpdu(bs, bp, &tu);
642 case BSTP_MSGTYPE_CFG:
643 if (m->m_len < sizeof(cpdu) &&
644 (m = m_pullup(m, sizeof(cpdu))) == NULL)
646 memcpy(&cpdu, mtod(m, caddr_t), sizeof(cpdu));
649 (((uint64_t)ntohs(cpdu.cbu_rootpri)) << 48) |
650 (((uint64_t)cpdu.cbu_rootaddr[0]) << 40) |
651 (((uint64_t)cpdu.cbu_rootaddr[1]) << 32) |
652 (((uint64_t)cpdu.cbu_rootaddr[2]) << 24) |
653 (((uint64_t)cpdu.cbu_rootaddr[3]) << 16) |
654 (((uint64_t)cpdu.cbu_rootaddr[4]) << 8) |
655 (((uint64_t)cpdu.cbu_rootaddr[5]) << 0);
658 (((uint64_t)ntohs(cpdu.cbu_bridgepri)) << 48) |
659 (((uint64_t)cpdu.cbu_bridgeaddr[0]) << 40) |
660 (((uint64_t)cpdu.cbu_bridgeaddr[1]) << 32) |
661 (((uint64_t)cpdu.cbu_bridgeaddr[2]) << 24) |
662 (((uint64_t)cpdu.cbu_bridgeaddr[3]) << 16) |
663 (((uint64_t)cpdu.cbu_bridgeaddr[4]) << 8) |
664 (((uint64_t)cpdu.cbu_bridgeaddr[5]) << 0);
666 cu.cu_root_path_cost = ntohl(cpdu.cbu_rootpathcost);
667 cu.cu_message_age = ntohs(cpdu.cbu_messageage);
668 cu.cu_max_age = ntohs(cpdu.cbu_maxage);
669 cu.cu_hello_time = ntohs(cpdu.cbu_hellotime);
670 cu.cu_forward_delay = ntohs(cpdu.cbu_forwarddelay);
671 cu.cu_port_id = ntohs(cpdu.cbu_portid);
672 cu.cu_message_type = cpdu.cbu_bpdutype;
673 cu.cu_topology_change_acknowledgment =
674 (cpdu.cbu_flags & BSTP_FLAG_TCA) ? 1 : 0;
675 cu.cu_topology_change =
676 (cpdu.cbu_flags & BSTP_FLAG_TC) ? 1 : 0;
677 bstp_received_config_bpdu(bs, bp, &cu);
691 bstp_received_config_bpdu(struct bstp_state *bs, struct bstp_port *bp,
692 struct bstp_config_unit *cu)
696 BSTP_LOCK_ASSERT(bs);
698 root = bstp_root_bridge(bs);
700 if (bp->bp_state != BSTP_IFSTATE_DISABLED) {
701 if (bstp_supersedes_port_info(bs, bp, cu)) {
702 bstp_record_config_information(bs, bp, cu);
703 bstp_configuration_update(bs);
704 bstp_port_state_selection(bs);
706 if ((bstp_root_bridge(bs) == 0) && root) {
707 bstp_timer_stop(&bs->bs_hello_timer);
709 if (bs->bs_topology_change_detected) {
711 &bs->bs_topology_change_timer);
712 bstp_transmit_tcn(bs);
713 bstp_timer_start(&bs->bs_tcn_timer, 0);
717 if (bp == bs->bs_root_port) {
718 bstp_record_config_timeout_values(bs, cu);
719 bstp_config_bpdu_generation(bs);
721 if (cu->cu_topology_change_acknowledgment)
722 bstp_topology_change_acknowledged(bs);
724 } else if (bstp_designated_port(bs, bp))
725 bstp_transmit_config(bs, bp);
730 bstp_received_tcn_bpdu(struct bstp_state *bs, struct bstp_port *bp,
731 struct bstp_tcn_unit *tcn)
733 if (bp->bp_state != BSTP_IFSTATE_DISABLED &&
734 bstp_designated_port(bs, bp)) {
735 bstp_topology_change_detection(bs);
736 bstp_acknowledge_topology_change(bs, bp);
741 bstp_hello_timer_expiry(struct bstp_state *bs)
743 bstp_config_bpdu_generation(bs);
744 bstp_timer_start(&bs->bs_hello_timer, 0);
748 bstp_message_age_timer_expiry(struct bstp_state *bs,
749 struct bstp_port *bp)
753 BSTP_LOCK_ASSERT(bs);
755 root = bstp_root_bridge(bs);
756 bstp_become_designated_port(bs, bp);
757 bstp_configuration_update(bs);
758 bstp_port_state_selection(bs);
760 if ((bstp_root_bridge(bs)) && (root == 0)) {
761 bs->bs_max_age = bs->bs_bridge_max_age;
762 bs->bs_hello_time = bs->bs_bridge_hello_time;
763 bs->bs_forward_delay = bs->bs_bridge_forward_delay;
765 bstp_topology_change_detection(bs);
766 bstp_timer_stop(&bs->bs_tcn_timer);
767 bstp_config_bpdu_generation(bs);
768 bstp_timer_start(&bs->bs_hello_timer, 0);
773 bstp_forward_delay_timer_expiry(struct bstp_state *bs,
774 struct bstp_port *bp)
776 if (bp->bp_state == BSTP_IFSTATE_LISTENING) {
777 bstp_set_port_state(bp, BSTP_IFSTATE_LEARNING);
778 bstp_timer_start(&bp->bp_forward_delay_timer, 0);
779 } else if (bp->bp_state == BSTP_IFSTATE_LEARNING) {
780 bstp_set_port_state(bp, BSTP_IFSTATE_FORWARDING);
781 bstp_update_forward_transitions(bp);
782 if (bstp_designated_for_some_port(bs) &&
783 bp->bp_change_detection_enabled)
784 bstp_topology_change_detection(bs);
789 bstp_designated_for_some_port(struct bstp_state *bs)
792 struct bstp_port *bp;
794 BSTP_LOCK_ASSERT(bs);
796 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
797 if (bp->bp_designated_bridge == bs->bs_bridge_id)
804 bstp_tcn_timer_expiry(struct bstp_state *bs)
806 BSTP_LOCK_ASSERT(bs);
808 bstp_transmit_tcn(bs);
809 bstp_timer_start(&bs->bs_tcn_timer, 0);
813 bstp_topology_change_timer_expiry(struct bstp_state *bs)
815 BSTP_LOCK_ASSERT(bs);
817 bs->bs_topology_change_detected = 0;
818 bs->bs_topology_change = 0;
822 bstp_hold_timer_expiry(struct bstp_state *bs, struct bstp_port *bp)
824 if (bp->bp_config_pending)
825 bstp_transmit_config(bs, bp);
829 bstp_addr_cmp(const uint8_t *a, const uint8_t *b)
833 for (i = 0, d = 0; i < ETHER_ADDR_LEN && d == 0; i++) {
834 d = ((int)a[i]) - ((int)b[i]);
841 bstp_reinit(struct bstp_state *bs)
843 struct bstp_port *bp, *mbp;
849 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
850 bp->bp_port_id = (bp->bp_priority << 8) |
851 (bp->bp_ifp->if_index & 0xff);
857 if (bstp_addr_cmp(IF_LLADDR(bp->bp_ifp),
858 IF_LLADDR(mbp->bp_ifp)) < 0) {
869 e_addr = IF_LLADDR(mbp->bp_ifp);
871 (((uint64_t)bs->bs_bridge_priority) << 48) |
872 (((uint64_t)e_addr[0]) << 40) |
873 (((uint64_t)e_addr[1]) << 32) |
874 (((uint64_t)e_addr[2]) << 24) |
875 (((uint64_t)e_addr[3]) << 16) |
876 (((uint64_t)e_addr[4]) << 8) |
877 (((uint64_t)e_addr[5]));
879 bs->bs_designated_root = bs->bs_bridge_id;
880 bs->bs_root_path_cost = 0;
881 bs->bs_root_port = NULL;
883 bs->bs_max_age = bs->bs_bridge_max_age;
884 bs->bs_hello_time = bs->bs_bridge_hello_time;
885 bs->bs_forward_delay = bs->bs_bridge_forward_delay;
886 bs->bs_topology_change_detected = 0;
887 bs->bs_topology_change = 0;
888 bstp_timer_stop(&bs->bs_tcn_timer);
889 bstp_timer_stop(&bs->bs_topology_change_timer);
891 if (callout_pending(&bs->bs_bstpcallout) == 0)
892 callout_reset(&bs->bs_bstpcallout, hz,
895 LIST_FOREACH(bp, &bs->bs_bplist, bp_next)
896 bstp_ifupdstatus(bs, bp);
898 getmicrotime(&bs->bs_last_tc_time);
899 bstp_port_state_selection(bs);
900 bstp_config_bpdu_generation(bs);
901 bstp_timer_start(&bs->bs_hello_timer, 0);
902 bstp_timer_start(&bs->bs_link_timer, 0);
907 bstp_modevent(module_t mod, int type, void *data)
912 mtx_init(&bstp_list_mtx, "bridgestp list", NULL, MTX_DEF);
913 LIST_INIT(&bstp_list);
914 bstp_linkstate_p = bstp_linkstate;
917 mtx_destroy(&bstp_list_mtx);
925 static moduledata_t bstp_mod = {
931 DECLARE_MODULE(bridgestp, bstp_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
932 MODULE_VERSION(bridgestp, 1);
935 bstp_attach(struct bstp_state *bs, bstp_state_cb_t state_callback)
938 callout_init_mtx(&bs->bs_bstpcallout, &bs->bs_mtx, 0);
939 LIST_INIT(&bs->bs_bplist);
941 bs->bs_bridge_max_age = BSTP_DEFAULT_MAX_AGE;
942 bs->bs_bridge_hello_time = BSTP_DEFAULT_HELLO_TIME;
943 bs->bs_bridge_forward_delay = BSTP_DEFAULT_FORWARD_DELAY;
944 bs->bs_bridge_priority = BSTP_DEFAULT_BRIDGE_PRIORITY;
945 bs->bs_hold_time = BSTP_DEFAULT_HOLD_TIME;
946 bs->bs_state_cb = state_callback;
948 mtx_lock(&bstp_list_mtx);
949 LIST_INSERT_HEAD(&bstp_list, bs, bs_list);
950 mtx_unlock(&bstp_list_mtx);
954 bstp_detach(struct bstp_state *bs)
956 KASSERT(LIST_EMPTY(&bs->bs_bplist), ("bstp still active"));
958 mtx_lock(&bstp_list_mtx);
959 LIST_REMOVE(bs, bs_list);
960 mtx_unlock(&bstp_list_mtx);
961 BSTP_LOCK_DESTROY(bs);
965 bstp_init(struct bstp_state *bs)
967 callout_reset(&bs->bs_bstpcallout, hz, bstp_tick, bs);
972 bstp_stop(struct bstp_state *bs)
974 struct bstp_port *bp;
978 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
979 bstp_set_port_state(bp, BSTP_IFSTATE_DISABLED);
980 bstp_timer_stop(&bp->bp_hold_timer);
981 bstp_timer_stop(&bp->bp_message_age_timer);
982 bstp_timer_stop(&bp->bp_forward_delay_timer);
985 callout_drain(&bs->bs_bstpcallout);
986 callout_stop(&bs->bs_bstpcallout);
988 bstp_timer_stop(&bs->bs_topology_change_timer);
989 bstp_timer_stop(&bs->bs_tcn_timer);
990 bstp_timer_stop(&bs->bs_hello_timer);
996 bstp_initialize_port(struct bstp_state *bs, struct bstp_port *bp)
998 BSTP_LOCK_ASSERT(bs);
1000 bstp_become_designated_port(bs, bp);
1001 bstp_set_port_state(bp, BSTP_IFSTATE_BLOCKING);
1002 bp->bp_topology_change_acknowledge = 0;
1003 bp->bp_config_pending = 0;
1004 bp->bp_change_detection_enabled = 1;
1005 bstp_timer_stop(&bp->bp_message_age_timer);
1006 bstp_timer_stop(&bp->bp_forward_delay_timer);
1007 bstp_timer_stop(&bp->bp_hold_timer);
1011 bstp_enable_port(struct bstp_state *bs, struct bstp_port *bp)
1013 bstp_initialize_port(bs, bp);
1014 bstp_port_state_selection(bs);
1018 bstp_disable_port(struct bstp_state *bs, struct bstp_port *bp)
1022 BSTP_LOCK_ASSERT(bs);
1024 root = bstp_root_bridge(bs);
1025 bstp_become_designated_port(bs, bp);
1026 bstp_set_port_state(bp, BSTP_IFSTATE_DISABLED);
1027 bp->bp_topology_change_acknowledge = 0;
1028 bp->bp_config_pending = 0;
1029 bstp_timer_stop(&bp->bp_message_age_timer);
1030 bstp_timer_stop(&bp->bp_forward_delay_timer);
1031 bstp_configuration_update(bs);
1032 bstp_port_state_selection(bs);
1034 if (bstp_root_bridge(bs) && (root == 0)) {
1035 bs->bs_max_age = bs->bs_bridge_max_age;
1036 bs->bs_hello_time = bs->bs_bridge_hello_time;
1037 bs->bs_forward_delay = bs->bs_bridge_forward_delay;
1039 bstp_topology_change_detection(bs);
1040 bstp_timer_stop(&bs->bs_tcn_timer);
1041 bstp_config_bpdu_generation(bs);
1042 bstp_timer_start(&bs->bs_hello_timer, 0);
1048 bstp_set_bridge_priority(struct bstp_state *bs, uint64_t new_bridge_id)
1050 struct bstp_port *bp;
1053 BSTP_LOCK_ASSERT(bs);
1055 root = bstp_root_bridge(bs);
1057 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
1058 if (bstp_designated_port(bs, bp))
1059 bp->bp_designated_bridge = new_bridge_id;
1062 bs->bs_bridge_id = new_bridge_id;
1064 bstp_configuration_update(bs);
1065 bstp_port_state_selection(bs);
1067 if (bstp_root_bridge(bs) && (root == 0)) {
1068 bs->bs_max_age = bs->bs_bridge_max_age;
1069 bs->bs_hello_time = bs->bs_bridge_hello_time;
1070 bs->bs_forward_delay = bs->bs_bridge_forward_delay;
1072 bstp_topology_change_detection(bs);
1073 bstp_timer_stop(&bs->bs_tcn_timer);
1074 bstp_config_bpdu_generation(bs);
1075 bstp_timer_start(&bs->bs_hello_timer, 0);
1080 bstp_set_port_priority(struct bstp_state *bs, struct bstp_port *bp,
1081 uint16_t new_port_id)
1083 if (bstp_designated_port(bs, bp))
1084 bp->bp_designated_port = new_port_id;
1086 bp->bp_port_id = new_port_id;
1088 if ((bs->bs_bridge_id == bp->bp_designated_bridge) &&
1089 (bp->bp_port_id < bp->bp_designated_port)) {
1090 bstp_become_designated_port(bs, bp);
1091 bstp_port_state_selection(bs);
1096 bstp_set_path_cost(struct bstp_state *bs, struct bstp_port *bp,
1099 bp->bp_path_cost = path_cost;
1100 bstp_configuration_update(bs);
1101 bstp_port_state_selection(bs);
1105 bstp_enable_change_detection(struct bstp_port *bp)
1107 bp->bp_change_detection_enabled = 1;
1111 bstp_disable_change_detection(struct bstp_port *bp)
1113 bp->bp_change_detection_enabled = 0;
1115 #endif /* notused */
1118 bstp_enqueue(struct ifnet *dst_ifp, struct mbuf *m)
1122 IFQ_ENQUEUE(&dst_ifp->if_snd, m, err);
1124 if ((dst_ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0)
1125 (*dst_ifp->if_start)(dst_ifp);
1129 bstp_linkstate(struct ifnet *ifp, int state)
1131 struct bstp_state *bs;
1132 struct bstp_port *bp;
1135 * It would be nice if the ifnet had a pointer to the bstp_port so we
1136 * didnt need to search for it, but that may be an overkill. In reality
1137 * this is fast and doesnt get called often.
1139 mtx_lock(&bstp_list_mtx);
1140 LIST_FOREACH(bs, &bstp_list, bs_list) {
1142 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
1143 if (bp->bp_ifp == ifp) {
1144 bstp_ifupdstatus(bs, bp);
1145 /* it only exists once so return */
1147 mtx_unlock(&bstp_list_mtx);
1153 mtx_unlock(&bstp_list_mtx);
1157 bstp_ifupdstatus(struct bstp_state *bs, struct bstp_port *bp)
1159 struct ifnet *ifp = bp->bp_ifp;
1160 struct ifmediareq ifmr;
1163 BSTP_LOCK_ASSERT(bs);
1165 bzero((char *)&ifmr, sizeof(ifmr));
1166 error = (*ifp->if_ioctl)(ifp, SIOCGIFMEDIA, (caddr_t)&ifmr);
1168 if ((error == 0) && (ifp->if_flags & IFF_UP)) {
1169 if (ifmr.ifm_status & IFM_ACTIVE) {
1170 if (bp->bp_state == BSTP_IFSTATE_DISABLED)
1171 bstp_enable_port(bs, bp);
1174 if (bp->bp_state != BSTP_IFSTATE_DISABLED)
1175 bstp_disable_port(bs, bp);
1180 if (bp->bp_state != BSTP_IFSTATE_DISABLED)
1181 bstp_disable_port(bs, bp);
1185 bstp_tick(void *arg)
1187 struct bstp_state *bs = arg;
1188 struct bstp_port *bp;
1190 BSTP_LOCK_ASSERT(bs);
1192 /* slow timer to catch missed link events */
1193 if (bstp_timer_expired(&bs->bs_link_timer, BSTP_LINK_TIMER)) {
1194 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
1195 bstp_ifupdstatus(bs, bp);
1197 bstp_timer_start(&bs->bs_link_timer, 0);
1200 if (bstp_timer_expired(&bs->bs_hello_timer, bs->bs_hello_time))
1201 bstp_hello_timer_expiry(bs);
1203 if (bstp_timer_expired(&bs->bs_tcn_timer, bs->bs_bridge_hello_time))
1204 bstp_tcn_timer_expiry(bs);
1206 if (bstp_timer_expired(&bs->bs_topology_change_timer,
1207 bs->bs_topology_change_time))
1208 bstp_topology_change_timer_expiry(bs);
1210 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
1211 if (bstp_timer_expired(&bp->bp_message_age_timer,
1213 bstp_message_age_timer_expiry(bs, bp);
1216 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
1217 if (bstp_timer_expired(&bp->bp_forward_delay_timer,
1218 bs->bs_forward_delay))
1219 bstp_forward_delay_timer_expiry(bs, bp);
1221 if (bstp_timer_expired(&bp->bp_hold_timer,
1223 bstp_hold_timer_expiry(bs, bp);
1226 callout_reset(&bs->bs_bstpcallout, hz, bstp_tick, bs);
1230 bstp_timer_start(struct bstp_timer *t, uint16_t v)
1237 bstp_timer_stop(struct bstp_timer *t)
1244 bstp_timer_expired(struct bstp_timer *t, uint16_t v)
1248 t->value += BSTP_TICK_VAL;
1249 if (t->value >= v) {
1258 bstp_add(struct bstp_state *bs, struct bstp_port *bp, struct ifnet *ifp)
1260 KASSERT(bp->bp_active == 0, ("already a bstp member"));
1262 switch (ifp->if_type) {
1263 case IFT_ETHER: /* These can do spanning tree. */
1266 /* Nothing else can. */
1274 bp->bp_priority = BSTP_DEFAULT_PORT_PRIORITY;
1275 bp->bp_path_cost = BSTP_DEFAULT_PATH_COST;
1277 LIST_INSERT_HEAD(&bs->bs_bplist, bp, bp_next);
1278 TASK_INIT(&bp->bp_statetask, 0, bstp_state_change, bp);
1286 bstp_delete(struct bstp_port *bp)
1288 struct bstp_state *bs = bp->bp_bs;
1290 KASSERT(bp->bp_active == 1, ("not a bstp member"));
1293 if (bp->bp_state != BSTP_IFSTATE_DISABLED)
1294 bstp_disable_port(bs, bp);
1295 LIST_REMOVE(bp, bp_next);
1304 * The bstp_port structure is about to be freed by the parent bridge.
1307 bstp_drain(struct bstp_port *bp)
1309 KASSERT(bp->bp_active == 0, ("port is still attached"));
1310 taskqueue_drain(taskqueue_swi, &bp->bp_statetask);