2 * Copyright (c) 2000 Jason L. Wright (jason@thought.net)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Jason L. Wright
16 * 4. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
31 * $OpenBSD: bridgestp.c,v 1.5 2001/03/22 03:48:29 jason Exp $
32 * $NetBSD: bridgestp.c,v 1.5 2003/11/28 08:56:48 keihan Exp $
33 * $FreeBSD: src/sys/net/bridgestp.c,v 1.7 2005/10/11 02:58:32 thompsa 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/param.h>
43 #include <sys/systm.h>
45 #include <sys/socket.h>
46 #include <sys/sockio.h>
47 #include <sys/kernel.h>
48 #include <sys/callout.h>
51 #include <sys/thread.h>
52 #include <sys/thread2.h>
53 #include <sys/msgport2.h>
56 #include <net/if_dl.h>
57 #include <net/if_types.h>
58 #include <net/if_llc.h>
59 #include <net/if_media.h>
61 #include <netinet/in.h>
62 #include <netinet/in_systm.h>
63 #include <netinet/in_var.h>
64 #include <netinet/if_ether.h>
65 #include <net/bridge/if_bridgevar.h>
67 /* BPDU message types */
68 #define BSTP_MSGTYPE_CFG 0x00 /* Configuration */
69 #define BSTP_MSGTYPE_TCN 0x80 /* Topology chg notification */
72 #define BSTP_FLAG_TC 0x01 /* Topology change */
73 #define BSTP_FLAG_TCA 0x80 /* Topology change ack */
75 #define BSTP_MESSAGE_AGE_INCR (1 * 256) /* in 256ths of a second */
76 #define BSTP_TICK_VAL (1 * 256) /* in 256ths of a second */
79 * Because BPDU's do not make nicely aligned structures, two different
80 * declarations are used: bstp_?bpdu (wire representation, packed) and
81 * bstp_*_unit (internal, nicely aligned version).
84 /* configuration bridge protocol data unit */
86 uint8_t cbu_dsap; /* LLC: destination sap */
87 uint8_t cbu_ssap; /* LLC: source sap */
88 uint8_t cbu_ctl; /* LLC: control */
89 uint16_t cbu_protoid; /* protocol id */
90 uint8_t cbu_protover; /* protocol version */
91 uint8_t cbu_bpdutype; /* message type */
92 uint8_t cbu_flags; /* flags (below) */
95 uint16_t cbu_rootpri; /* root priority */
96 uint8_t cbu_rootaddr[6]; /* root address */
98 uint32_t cbu_rootpathcost; /* root path cost */
101 uint16_t cbu_bridgepri; /* bridge priority */
102 uint8_t cbu_bridgeaddr[6]; /* bridge address */
104 uint16_t cbu_portid; /* port id */
105 uint16_t cbu_messageage; /* current message age */
106 uint16_t cbu_maxage; /* maximum age */
107 uint16_t cbu_hellotime; /* hello time */
108 uint16_t cbu_forwarddelay; /* forwarding delay */
109 } __attribute__((__packed__));
111 /* topology change notification bridge protocol data unit */
113 uint8_t tbu_dsap; /* LLC: destination sap */
114 uint8_t tbu_ssap; /* LLC: source sap */
115 uint8_t tbu_ctl; /* LLC: control */
116 uint16_t tbu_protoid; /* protocol id */
117 uint8_t tbu_protover; /* protocol version */
118 uint8_t tbu_bpdutype; /* message type */
119 } __attribute__((__packed__));
121 const uint8_t bstp_etheraddr[] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
123 static void bstp_initialize_port(struct bridge_softc *,
124 struct bridge_iflist *);
125 static void bstp_ifupdstatus(struct bridge_softc *, struct bridge_iflist *);
126 static void bstp_enable_port(struct bridge_softc *, struct bridge_iflist *);
127 static void bstp_disable_port(struct bridge_softc *,
128 struct bridge_iflist *);
130 static void bstp_enable_change_detection(struct bridge_iflist *);
131 static void bstp_disable_change_detection(struct bridge_iflist *);
133 static int bstp_root_bridge(struct bridge_softc *sc);
134 static int bstp_supersedes_port_info(struct bridge_softc *,
135 struct bridge_iflist *, struct bstp_config_unit *);
136 static int bstp_designated_port(struct bridge_softc *,
137 struct bridge_iflist *);
138 static int bstp_designated_for_some_port(struct bridge_softc *);
139 static void bstp_transmit_config(struct bridge_softc *,
140 struct bridge_iflist *);
141 static void bstp_transmit_tcn(struct bridge_softc *);
142 static void bstp_received_config_bpdu(struct bridge_softc *,
143 struct bridge_iflist *, struct bstp_config_unit *);
144 static void bstp_received_tcn_bpdu(struct bridge_softc *,
145 struct bridge_iflist *, struct bstp_tcn_unit *);
146 static void bstp_record_config_information(struct bridge_softc *,
147 struct bridge_iflist *, struct bstp_config_unit *);
148 static void bstp_record_config_timeout_values(struct bridge_softc *,
149 struct bstp_config_unit *);
150 static void bstp_config_bpdu_generation(struct bridge_softc *);
151 static void bstp_send_config_bpdu(struct bridge_softc *,
152 struct bridge_iflist *, struct bstp_config_unit *);
153 static void bstp_configuration_update(struct bridge_softc *);
154 static void bstp_root_selection(struct bridge_softc *);
155 static void bstp_designated_port_selection(struct bridge_softc *);
156 static void bstp_become_designated_port(struct bridge_softc *,
157 struct bridge_iflist *);
158 static void bstp_port_state_selection(struct bridge_softc *);
159 static void bstp_make_forwarding(struct bridge_softc *,
160 struct bridge_iflist *);
161 static void bstp_make_blocking(struct bridge_softc *,
162 struct bridge_iflist *);
163 static void bstp_set_port_state(struct bridge_iflist *, uint8_t);
165 static void bstp_set_bridge_priority(struct bridge_softc *, uint64_t);
166 static void bstp_set_port_priority(struct bridge_softc *,
167 struct bridge_iflist *, uint16_t);
168 static void bstp_set_path_cost(struct bridge_softc *,
169 struct bridge_iflist *, uint32_t);
171 static void bstp_topology_change_detection(struct bridge_softc *);
172 static void bstp_topology_change_acknowledged(struct bridge_softc *);
173 static void bstp_acknowledge_topology_change(struct bridge_softc *,
174 struct bridge_iflist *);
176 static void bstp_tick(void *);
177 static void bstp_timer_start(struct bridge_timer *, uint16_t);
178 static void bstp_timer_stop(struct bridge_timer *);
179 static int bstp_timer_expired(struct bridge_timer *, uint16_t);
181 static void bstp_hold_timer_expiry(struct bridge_softc *,
182 struct bridge_iflist *);
183 static void bstp_message_age_timer_expiry(struct bridge_softc *,
184 struct bridge_iflist *);
185 static void bstp_forward_delay_timer_expiry(struct bridge_softc *,
186 struct bridge_iflist *);
187 static void bstp_topology_change_timer_expiry(struct bridge_softc *);
188 static void bstp_tcn_timer_expiry(struct bridge_softc *);
189 static void bstp_hello_timer_expiry(struct bridge_softc *);
190 static int bstp_addr_cmp(const uint8_t *, const uint8_t *);
193 bstp_transmit_config(struct bridge_softc *sc, struct bridge_iflist *bif)
195 if (bif->bif_hold_timer.active) {
196 bif->bif_config_pending = 1;
200 bif->bif_config_bpdu.cu_message_type = BSTP_MSGTYPE_CFG;
201 bif->bif_config_bpdu.cu_rootid = sc->sc_designated_root;
202 bif->bif_config_bpdu.cu_root_path_cost = sc->sc_root_path_cost;
203 bif->bif_config_bpdu.cu_bridge_id = sc->sc_bridge_id;
204 bif->bif_config_bpdu.cu_port_id = bif->bif_port_id;
206 if (bstp_root_bridge(sc)) {
207 bif->bif_config_bpdu.cu_message_age = 0;
209 bif->bif_config_bpdu.cu_message_age =
210 sc->sc_root_port->bifi_message_age_timer.value +
211 BSTP_MESSAGE_AGE_INCR;
214 bif->bif_config_bpdu.cu_max_age = sc->sc_max_age;
215 bif->bif_config_bpdu.cu_hello_time = sc->sc_hello_time;
216 bif->bif_config_bpdu.cu_forward_delay = sc->sc_forward_delay;
217 bif->bif_config_bpdu.cu_topology_change_acknowledgment
218 = bif->bif_topology_change_acknowledge;
219 bif->bif_config_bpdu.cu_topology_change = sc->sc_topology_change;
221 if (bif->bif_config_bpdu.cu_message_age < sc->sc_max_age) {
222 bif->bif_topology_change_acknowledge = 0;
223 bif->bif_config_pending = 0;
224 bstp_send_config_bpdu(sc, bif, &bif->bif_config_bpdu);
225 bstp_timer_start(&bif->bif_hold_timer, 0);
230 bstp_send_config_bpdu(struct bridge_softc *sc, struct bridge_iflist *bif,
231 struct bstp_config_unit *cu)
235 struct ether_header *eh;
236 struct bstp_cbpdu bpdu;
240 if ((ifp->if_flags & IFF_RUNNING) == 0)
243 MGETHDR(m, MB_DONTWAIT, MT_DATA);
247 eh = mtod(m, struct ether_header *);
249 m->m_pkthdr.rcvif = ifp;
250 m->m_pkthdr.len = sizeof(*eh) + sizeof(bpdu);
251 m->m_len = m->m_pkthdr.len;
253 bpdu.cbu_ssap = bpdu.cbu_dsap = LLC_8021D_LSAP;
254 bpdu.cbu_ctl = LLC_UI;
255 bpdu.cbu_protoid = htons(0);
256 bpdu.cbu_protover = 0;
257 bpdu.cbu_bpdutype = cu->cu_message_type;
258 bpdu.cbu_flags = (cu->cu_topology_change ? BSTP_FLAG_TC : 0) |
259 (cu->cu_topology_change_acknowledgment ? BSTP_FLAG_TCA : 0);
261 bpdu.cbu_rootpri = htons(cu->cu_rootid >> 48);
262 bpdu.cbu_rootaddr[0] = cu->cu_rootid >> 40;
263 bpdu.cbu_rootaddr[1] = cu->cu_rootid >> 32;
264 bpdu.cbu_rootaddr[2] = cu->cu_rootid >> 24;
265 bpdu.cbu_rootaddr[3] = cu->cu_rootid >> 16;
266 bpdu.cbu_rootaddr[4] = cu->cu_rootid >> 8;
267 bpdu.cbu_rootaddr[5] = cu->cu_rootid >> 0;
269 bpdu.cbu_rootpathcost = htonl(cu->cu_root_path_cost);
271 bpdu.cbu_bridgepri = htons(cu->cu_bridge_id >> 48);
272 bpdu.cbu_bridgeaddr[0] = cu->cu_bridge_id >> 40;
273 bpdu.cbu_bridgeaddr[1] = cu->cu_bridge_id >> 32;
274 bpdu.cbu_bridgeaddr[2] = cu->cu_bridge_id >> 24;
275 bpdu.cbu_bridgeaddr[3] = cu->cu_bridge_id >> 16;
276 bpdu.cbu_bridgeaddr[4] = cu->cu_bridge_id >> 8;
277 bpdu.cbu_bridgeaddr[5] = cu->cu_bridge_id >> 0;
279 bpdu.cbu_portid = htons(cu->cu_port_id);
280 bpdu.cbu_messageage = htons(cu->cu_message_age);
281 bpdu.cbu_maxage = htons(cu->cu_max_age);
282 bpdu.cbu_hellotime = htons(cu->cu_hello_time);
283 bpdu.cbu_forwarddelay = htons(cu->cu_forward_delay);
285 memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN);
286 memcpy(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN);
287 eh->ether_type = htons(sizeof(bpdu));
289 memcpy(mtod(m, caddr_t) + sizeof(*eh), &bpdu, sizeof(bpdu));
291 bridge_enqueue(ifp, m);
295 bstp_root_bridge(struct bridge_softc *sc)
297 return (sc->sc_designated_root == sc->sc_bridge_id);
301 bstp_supersedes_port_info(struct bridge_softc *sc, struct bridge_iflist *bif,
302 struct bstp_config_unit *cu)
304 if (cu->cu_rootid < bif->bif_designated_root)
306 if (cu->cu_rootid > bif->bif_designated_root)
309 if (cu->cu_root_path_cost < bif->bif_designated_cost)
311 if (cu->cu_root_path_cost > bif->bif_designated_cost)
314 if (cu->cu_bridge_id < bif->bif_designated_bridge)
316 if (cu->cu_bridge_id > bif->bif_designated_bridge)
319 if (sc->sc_bridge_id != cu->cu_bridge_id)
321 if (cu->cu_port_id <= bif->bif_designated_port)
327 bstp_record_config_information(struct bridge_softc *sc,
328 struct bridge_iflist *bif, struct bstp_config_unit *cu)
330 bif->bif_designated_root = cu->cu_rootid;
331 bif->bif_designated_cost = cu->cu_root_path_cost;
332 bif->bif_designated_bridge = cu->cu_bridge_id;
333 bif->bif_designated_port = cu->cu_port_id;
334 bstp_timer_start(&bif->bif_message_age_timer, cu->cu_message_age);
338 bstp_record_config_timeout_values(struct bridge_softc *sc,
339 struct bstp_config_unit *config)
341 sc->sc_max_age = config->cu_max_age;
342 sc->sc_hello_time = config->cu_hello_time;
343 sc->sc_forward_delay = config->cu_forward_delay;
344 sc->sc_topology_change = config->cu_topology_change;
348 bstp_config_bpdu_generation(struct bridge_softc *sc)
350 struct bridge_iflist *bif, *nbif;
352 LIST_FOREACH_MUTABLE(bif, &sc->sc_iflists[mycpuid], bif_next, nbif) {
353 if ((bif->bif_flags & IFBIF_STP) == 0)
355 if (bstp_designated_port(sc, bif) &&
356 (bif->bif_state != BSTP_IFSTATE_DISABLED))
357 bstp_transmit_config(sc, bif);
359 if (nbif != NULL && !nbif->bif_onlist) {
360 KKASSERT(bif->bif_onlist);
361 nbif = LIST_NEXT(bif, bif_next);
367 bstp_designated_port(struct bridge_softc *sc, struct bridge_iflist *bif)
369 return ((bif->bif_designated_bridge == sc->sc_bridge_id)
370 && (bif->bif_designated_port == bif->bif_port_id));
374 bstp_transmit_tcn(struct bridge_softc *sc)
376 struct bstp_tbpdu bpdu;
377 struct ifnet *ifp = sc->sc_root_port->bifi_ifp;
378 struct ether_header *eh;
381 if ((ifp->if_flags & IFF_RUNNING) == 0)
384 MGETHDR(m, MB_DONTWAIT, MT_DATA);
388 m->m_pkthdr.rcvif = ifp;
389 m->m_pkthdr.len = sizeof(*eh) + sizeof(bpdu);
390 m->m_len = m->m_pkthdr.len;
392 eh = mtod(m, struct ether_header *);
394 memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN);
395 memcpy(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN);
396 eh->ether_type = htons(sizeof(bpdu));
398 bpdu.tbu_ssap = bpdu.tbu_dsap = LLC_8021D_LSAP;
399 bpdu.tbu_ctl = LLC_UI;
400 bpdu.tbu_protoid = 0;
401 bpdu.tbu_protover = 0;
402 bpdu.tbu_bpdutype = BSTP_MSGTYPE_TCN;
404 memcpy(mtod(m, caddr_t) + sizeof(*eh), &bpdu, sizeof(bpdu));
406 bridge_enqueue(ifp, m);
410 bstp_configuration_update(struct bridge_softc *sc)
412 bstp_root_selection(sc);
413 bstp_designated_port_selection(sc);
417 bstp_root_selection(struct bridge_softc *sc)
419 struct bridge_iflist *root_port = NULL, *bif;
421 LIST_FOREACH(bif, &sc->sc_iflists[mycpuid], bif_next) {
422 if ((bif->bif_flags & IFBIF_STP) == 0)
424 if (bstp_designated_port(sc, bif))
426 if (bif->bif_state == BSTP_IFSTATE_DISABLED)
428 if (bif->bif_designated_root >= sc->sc_bridge_id)
430 if (root_port == NULL)
433 if (bif->bif_designated_root < root_port->bif_designated_root)
435 if (bif->bif_designated_root > root_port->bif_designated_root)
438 if ((bif->bif_designated_cost + bif->bif_path_cost) <
439 (root_port->bif_designated_cost + root_port->bif_path_cost))
441 if ((bif->bif_designated_cost + bif->bif_path_cost) >
442 (root_port->bif_designated_cost + root_port->bif_path_cost))
445 if (bif->bif_designated_bridge <
446 root_port->bif_designated_bridge)
448 if (bif->bif_designated_bridge >
449 root_port->bif_designated_bridge)
452 if (bif->bif_designated_port < root_port->bif_designated_port)
454 if (bif->bif_designated_port > root_port->bif_designated_port)
457 if (bif->bif_port_id >= root_port->bif_port_id)
463 if (root_port == NULL) {
464 sc->sc_root_port = NULL;
465 sc->sc_designated_root = sc->sc_bridge_id;
466 sc->sc_root_path_cost = 0;
468 sc->sc_root_port = root_port->bif_info;
469 sc->sc_designated_root = root_port->bif_designated_root;
470 sc->sc_root_path_cost = root_port->bif_designated_cost +
471 root_port->bif_path_cost;
476 bstp_designated_port_selection(struct bridge_softc *sc)
478 struct bridge_iflist *bif;
480 LIST_FOREACH(bif, &sc->sc_iflists[mycpuid], bif_next) {
481 if ((bif->bif_flags & IFBIF_STP) == 0)
483 if (bstp_designated_port(sc, bif))
485 if (bif->bif_designated_root != sc->sc_designated_root)
488 if (sc->sc_root_path_cost < bif->bif_designated_cost)
490 if (sc->sc_root_path_cost > bif->bif_designated_cost)
493 if (sc->sc_bridge_id < bif->bif_designated_bridge)
495 if (sc->sc_bridge_id > bif->bif_designated_bridge)
498 if (bif->bif_port_id > bif->bif_designated_port)
501 bstp_become_designated_port(sc, bif);
506 bstp_become_designated_port(struct bridge_softc *sc, struct bridge_iflist *bif)
508 bif->bif_designated_root = sc->sc_designated_root;
509 bif->bif_designated_cost = sc->sc_root_path_cost;
510 bif->bif_designated_bridge = sc->sc_bridge_id;
511 bif->bif_designated_port = bif->bif_port_id;
515 bstp_port_state_selection(struct bridge_softc *sc)
517 struct bridge_iflist *bif, *nbif;
519 LIST_FOREACH_MUTABLE(bif, &sc->sc_iflists[mycpuid], bif_next, nbif) {
520 if ((bif->bif_flags & IFBIF_STP) == 0)
522 if (bif->bif_info == sc->sc_root_port) {
523 bif->bif_config_pending = 0;
524 bif->bif_topology_change_acknowledge = 0;
525 bstp_make_forwarding(sc, bif);
526 } else if (bstp_designated_port(sc, bif)) {
527 bstp_timer_stop(&bif->bif_message_age_timer);
528 bstp_make_forwarding(sc, bif);
530 bif->bif_config_pending = 0;
531 bif->bif_topology_change_acknowledge = 0;
532 bstp_make_blocking(sc, bif);
535 if (nbif != NULL && !nbif->bif_onlist) {
536 KKASSERT(bif->bif_onlist);
537 nbif = LIST_NEXT(bif, bif_next);
543 bstp_make_forwarding(struct bridge_softc *sc, struct bridge_iflist *bif)
545 if (bif->bif_state == BSTP_IFSTATE_BLOCKING) {
546 bstp_set_port_state(bif, BSTP_IFSTATE_LISTENING);
547 bstp_timer_start(&bif->bif_forward_delay_timer, 0);
552 bstp_make_blocking(struct bridge_softc *sc, struct bridge_iflist *bif)
554 if ((bif->bif_state != BSTP_IFSTATE_DISABLED) &&
555 (bif->bif_state != BSTP_IFSTATE_BLOCKING)) {
556 if ((bif->bif_state == BSTP_IFSTATE_FORWARDING) ||
557 (bif->bif_state == BSTP_IFSTATE_LEARNING)) {
558 if (bif->bif_change_detection_enabled) {
559 bstp_topology_change_detection(sc);
562 bstp_set_port_state(bif, BSTP_IFSTATE_BLOCKING);
563 bridge_rtdelete(sc, bif->bif_ifp, IFBF_FLUSHDYN);
564 bstp_timer_stop(&bif->bif_forward_delay_timer);
569 bstp_set_port_state(struct bridge_iflist *bif, uint8_t state)
571 bif->bif_state = state;
575 bstp_topology_change_detection(struct bridge_softc *sc)
577 if (bstp_root_bridge(sc)) {
578 sc->sc_topology_change = 1;
579 bstp_timer_start(&sc->sc_topology_change_timer, 0);
580 } else if (!sc->sc_topology_change_detected) {
581 bstp_transmit_tcn(sc);
582 bstp_timer_start(&sc->sc_tcn_timer, 0);
584 sc->sc_topology_change_detected = 1;
588 bstp_topology_change_acknowledged(struct bridge_softc *sc)
590 sc->sc_topology_change_detected = 0;
591 bstp_timer_stop(&sc->sc_tcn_timer);
595 bstp_acknowledge_topology_change(struct bridge_softc *sc,
596 struct bridge_iflist *bif)
598 bif->bif_topology_change_acknowledge = 1;
599 bstp_transmit_config(sc, bif);
603 bstp_input(struct bridge_softc *sc, struct bridge_iflist *bif, struct mbuf *m)
605 struct ether_header *eh;
606 struct bstp_tbpdu tpdu;
607 struct bstp_cbpdu cpdu;
608 struct bstp_config_unit cu;
609 struct bstp_tcn_unit tu;
612 if ((bif->bif_flags & IFBIF_STP) == 0)
615 eh = mtod(m, struct ether_header *);
617 len = ntohs(eh->ether_type);
618 if (len < sizeof(tpdu))
621 m_adj(m, ETHER_HDR_LEN);
623 if (m->m_pkthdr.len > len)
624 m_adj(m, len - m->m_pkthdr.len);
625 if (m->m_len < sizeof(tpdu) &&
626 (m = m_pullup(m, sizeof(tpdu))) == NULL)
629 memcpy(&tpdu, mtod(m, caddr_t), sizeof(tpdu));
631 if (tpdu.tbu_dsap != LLC_8021D_LSAP ||
632 tpdu.tbu_ssap != LLC_8021D_LSAP ||
633 tpdu.tbu_ctl != LLC_UI)
635 if (tpdu.tbu_protoid != 0 || tpdu.tbu_protover != 0)
638 switch (tpdu.tbu_bpdutype) {
639 case BSTP_MSGTYPE_TCN:
640 tu.tu_message_type = tpdu.tbu_bpdutype;
641 bstp_received_tcn_bpdu(sc, bif, &tu);
643 case BSTP_MSGTYPE_CFG:
644 if (m->m_len < sizeof(cpdu) &&
645 (m = m_pullup(m, sizeof(cpdu))) == NULL)
647 memcpy(&cpdu, mtod(m, caddr_t), sizeof(cpdu));
650 (((uint64_t)ntohs(cpdu.cbu_rootpri)) << 48) |
651 (((uint64_t)cpdu.cbu_rootaddr[0]) << 40) |
652 (((uint64_t)cpdu.cbu_rootaddr[1]) << 32) |
653 (((uint64_t)cpdu.cbu_rootaddr[2]) << 24) |
654 (((uint64_t)cpdu.cbu_rootaddr[3]) << 16) |
655 (((uint64_t)cpdu.cbu_rootaddr[4]) << 8) |
656 (((uint64_t)cpdu.cbu_rootaddr[5]) << 0);
659 (((uint64_t)ntohs(cpdu.cbu_bridgepri)) << 48) |
660 (((uint64_t)cpdu.cbu_bridgeaddr[0]) << 40) |
661 (((uint64_t)cpdu.cbu_bridgeaddr[1]) << 32) |
662 (((uint64_t)cpdu.cbu_bridgeaddr[2]) << 24) |
663 (((uint64_t)cpdu.cbu_bridgeaddr[3]) << 16) |
664 (((uint64_t)cpdu.cbu_bridgeaddr[4]) << 8) |
665 (((uint64_t)cpdu.cbu_bridgeaddr[5]) << 0);
667 cu.cu_root_path_cost = ntohl(cpdu.cbu_rootpathcost);
668 cu.cu_message_age = ntohs(cpdu.cbu_messageage);
669 cu.cu_max_age = ntohs(cpdu.cbu_maxage);
670 cu.cu_hello_time = ntohs(cpdu.cbu_hellotime);
671 cu.cu_forward_delay = ntohs(cpdu.cbu_forwarddelay);
672 cu.cu_port_id = ntohs(cpdu.cbu_portid);
673 cu.cu_message_type = cpdu.cbu_bpdutype;
674 cu.cu_topology_change_acknowledgment =
675 (cpdu.cbu_flags & BSTP_FLAG_TCA) ? 1 : 0;
676 cu.cu_topology_change =
677 (cpdu.cbu_flags & BSTP_FLAG_TC) ? 1 : 0;
678 bstp_received_config_bpdu(sc, bif, &cu);
689 bstp_received_config_bpdu(struct bridge_softc *sc, struct bridge_iflist *bif,
690 struct bstp_config_unit *cu)
694 root = bstp_root_bridge(sc);
696 if (bif->bif_state != BSTP_IFSTATE_DISABLED) {
697 if (bstp_supersedes_port_info(sc, bif, cu)) {
698 bstp_record_config_information(sc, bif, cu);
699 bstp_configuration_update(sc);
700 bstp_port_state_selection(sc);
702 if ((bstp_root_bridge(sc) == 0) && root) {
703 bstp_timer_stop(&sc->sc_hello_timer);
705 if (sc->sc_topology_change_detected) {
707 &sc->sc_topology_change_timer);
708 bstp_transmit_tcn(sc);
709 bstp_timer_start(&sc->sc_tcn_timer, 0);
713 if (bif->bif_info == sc->sc_root_port) {
714 bstp_record_config_timeout_values(sc, cu);
715 bstp_config_bpdu_generation(sc);
717 if (cu->cu_topology_change_acknowledgment)
718 bstp_topology_change_acknowledged(sc);
720 } else if (bstp_designated_port(sc, bif))
721 bstp_transmit_config(sc, bif);
726 bstp_received_tcn_bpdu(struct bridge_softc *sc, struct bridge_iflist *bif,
727 struct bstp_tcn_unit *tcn)
729 if (bif->bif_state != BSTP_IFSTATE_DISABLED &&
730 bstp_designated_port(sc, bif)) {
731 bstp_topology_change_detection(sc);
732 bstp_acknowledge_topology_change(sc, bif);
737 bstp_hello_timer_expiry(struct bridge_softc *sc)
739 bstp_config_bpdu_generation(sc);
740 bstp_timer_start(&sc->sc_hello_timer, 0);
744 bstp_message_age_timer_expiry(struct bridge_softc *sc,
745 struct bridge_iflist *bif)
749 root = bstp_root_bridge(sc);
750 bstp_become_designated_port(sc, bif);
751 bstp_configuration_update(sc);
752 bstp_port_state_selection(sc);
754 if ((bstp_root_bridge(sc)) && (root == 0)) {
755 sc->sc_max_age = sc->sc_bridge_max_age;
756 sc->sc_hello_time = sc->sc_bridge_hello_time;
757 sc->sc_forward_delay = sc->sc_bridge_forward_delay;
759 bstp_topology_change_detection(sc);
760 bstp_timer_stop(&sc->sc_tcn_timer);
761 bstp_config_bpdu_generation(sc);
762 bstp_timer_start(&sc->sc_hello_timer, 0);
767 bstp_forward_delay_timer_expiry(struct bridge_softc *sc,
768 struct bridge_iflist *bif)
770 if (bif->bif_state == BSTP_IFSTATE_LISTENING) {
771 bstp_set_port_state(bif, BSTP_IFSTATE_LEARNING);
772 bstp_timer_start(&bif->bif_forward_delay_timer, 0);
773 } else if (bif->bif_state == BSTP_IFSTATE_LEARNING) {
774 bstp_set_port_state(bif, BSTP_IFSTATE_FORWARDING);
775 if (bstp_designated_for_some_port(sc) &&
776 bif->bif_change_detection_enabled)
777 bstp_topology_change_detection(sc);
782 bstp_designated_for_some_port(struct bridge_softc *sc)
785 struct bridge_iflist *bif;
787 LIST_FOREACH(bif, &sc->sc_iflists[mycpuid], bif_next) {
788 if ((bif->bif_flags & IFBIF_STP) == 0)
790 if (bif->bif_designated_bridge == sc->sc_bridge_id)
797 bstp_tcn_timer_expiry(struct bridge_softc *sc)
799 bstp_transmit_tcn(sc);
800 bstp_timer_start(&sc->sc_tcn_timer, 0);
804 bstp_topology_change_timer_expiry(struct bridge_softc *sc)
806 sc->sc_topology_change_detected = 0;
807 sc->sc_topology_change = 0;
811 bstp_hold_timer_expiry(struct bridge_softc *sc, struct bridge_iflist *bif)
813 if (bif->bif_config_pending)
814 bstp_transmit_config(sc, bif);
818 bstp_addr_cmp(const uint8_t *a, const uint8_t *b)
822 for (i = 0, d = 0; i < ETHER_ADDR_LEN && d == 0; i++) {
823 d = ((int)a[i]) - ((int)b[i]);
830 bstp_initialization(struct bridge_softc *sc)
832 struct bridge_iflist *bif, *mif, *nbif;
835 KKASSERT(&curthread->td_msgport == BRIDGE_CFGPORT);
838 LIST_FOREACH(bif, &sc->sc_iflists[mycpuid], bif_next) {
839 if ((bif->bif_flags & IFBIF_STP) == 0)
841 if (bif->bif_ifp->if_type != IFT_ETHER)
843 bif->bif_port_id = (bif->bif_priority << 8) |
844 (bif->bif_ifp->if_index & 0xff);
850 if (bstp_addr_cmp(IF_LLADDR(bif->bif_ifp),
851 IF_LLADDR(mif->bif_ifp)) < 0) {
861 e_addr = IF_LLADDR(mif->bif_ifp);
863 (((uint64_t)sc->sc_bridge_priority) << 48) |
864 (((uint64_t)e_addr[0]) << 40) |
865 (((uint64_t)e_addr[1]) << 32) |
866 (((uint64_t)e_addr[2]) << 24) |
867 (((uint64_t)e_addr[3]) << 16) |
868 (((uint64_t)e_addr[4]) << 8) |
869 (((uint64_t)e_addr[5]));
871 sc->sc_designated_root = sc->sc_bridge_id;
872 sc->sc_root_path_cost = 0;
873 sc->sc_root_port = NULL;
875 sc->sc_max_age = sc->sc_bridge_max_age;
876 sc->sc_hello_time = sc->sc_bridge_hello_time;
877 sc->sc_forward_delay = sc->sc_bridge_forward_delay;
878 sc->sc_topology_change_detected = 0;
879 sc->sc_topology_change = 0;
880 bstp_timer_stop(&sc->sc_tcn_timer);
881 bstp_timer_stop(&sc->sc_topology_change_timer);
883 if (callout_pending(&sc->sc_bstpcallout) == 0)
884 callout_reset(&sc->sc_bstpcallout, hz,
887 LIST_FOREACH_MUTABLE(bif, &sc->sc_iflists[mycpuid], bif_next, nbif) {
888 if (bif->bif_flags & IFBIF_STP)
889 bstp_ifupdstatus(sc, bif);
891 bstp_disable_port(sc, bif);
893 if (nbif != NULL && !nbif->bif_onlist) {
894 KKASSERT(bif->bif_onlist);
895 nbif = LIST_NEXT(bif, bif_next);
899 bstp_port_state_selection(sc);
900 bstp_config_bpdu_generation(sc);
901 bstp_timer_start(&sc->sc_hello_timer, 0);
905 bstp_stop(struct bridge_softc *sc)
907 struct bridge_iflist *bif;
908 struct lwkt_msg *lmsg;
910 KKASSERT(&curthread->td_msgport == BRIDGE_CFGPORT);
912 LIST_FOREACH(bif, &sc->sc_iflists[mycpuid], bif_next) {
913 bstp_set_port_state(bif, BSTP_IFSTATE_DISABLED);
914 bstp_timer_stop(&bif->bif_hold_timer);
915 bstp_timer_stop(&bif->bif_message_age_timer);
916 bstp_timer_stop(&bif->bif_forward_delay_timer);
919 callout_stop(&sc->sc_bstpcallout);
921 bstp_timer_stop(&sc->sc_topology_change_timer);
922 bstp_timer_stop(&sc->sc_tcn_timer);
923 bstp_timer_stop(&sc->sc_hello_timer);
926 lmsg = &sc->sc_bstptimemsg.lmsg;
927 if ((lmsg->ms_flags & MSGF_DONE) == 0) {
928 /* Pending to be processed; drop it */
935 bstp_initialize_port(struct bridge_softc *sc, struct bridge_iflist *bif)
937 bstp_become_designated_port(sc, bif);
938 bstp_set_port_state(bif, BSTP_IFSTATE_BLOCKING);
939 bif->bif_topology_change_acknowledge = 0;
940 bif->bif_config_pending = 0;
941 bif->bif_change_detection_enabled = 1;
942 bstp_timer_stop(&bif->bif_message_age_timer);
943 bstp_timer_stop(&bif->bif_forward_delay_timer);
944 bstp_timer_stop(&bif->bif_hold_timer);
948 bstp_enable_port(struct bridge_softc *sc, struct bridge_iflist *bif)
950 bstp_initialize_port(sc, bif);
951 bstp_port_state_selection(sc);
955 bstp_disable_port(struct bridge_softc *sc, struct bridge_iflist *bif)
959 root = bstp_root_bridge(sc);
960 bstp_become_designated_port(sc, bif);
961 bstp_set_port_state(bif, BSTP_IFSTATE_DISABLED);
962 bif->bif_topology_change_acknowledge = 0;
963 bif->bif_config_pending = 0;
964 bstp_timer_stop(&bif->bif_message_age_timer);
965 bstp_timer_stop(&bif->bif_forward_delay_timer);
966 bstp_configuration_update(sc);
967 bstp_port_state_selection(sc);
968 bridge_rtdelete(sc, bif->bif_ifp, IFBF_FLUSHDYN);
970 if (bstp_root_bridge(sc) && (root == 0)) {
971 sc->sc_max_age = sc->sc_bridge_max_age;
972 sc->sc_hello_time = sc->sc_bridge_hello_time;
973 sc->sc_forward_delay = sc->sc_bridge_forward_delay;
975 bstp_topology_change_detection(sc);
976 bstp_timer_stop(&sc->sc_tcn_timer);
977 bstp_config_bpdu_generation(sc);
978 bstp_timer_start(&sc->sc_hello_timer, 0);
984 bstp_set_bridge_priority(struct bridge_softc *sc, uint64_t new_bridge_id)
986 struct bridge_iflist *bif;
989 root = bstp_root_bridge(sc);
991 LIST_FOREACH(bif, &sc->sc_iflists[mycpuid], bif_next) {
992 if ((bif->bif_flags & IFBIF_STP) == 0)
994 if (bstp_designated_port(sc, bif))
995 bif->bif_designated_bridge = new_bridge_id;
998 sc->sc_bridge_id = new_bridge_id;
1000 bstp_configuration_update(sc);
1001 bstp_port_state_selection(sc);
1003 if (bstp_root_bridge(sc) && (root == 0)) {
1004 sc->sc_max_age = sc->sc_bridge_max_age;
1005 sc->sc_hello_time = sc->sc_bridge_hello_time;
1006 sc->sc_forward_delay = sc->sc_bridge_forward_delay;
1008 bstp_topology_change_detection(sc);
1009 bstp_timer_stop(&sc->sc_tcn_timer);
1010 bstp_config_bpdu_generation(sc);
1011 bstp_timer_start(&sc->sc_hello_timer, 0);
1016 bstp_set_port_priority(struct bridge_softc *sc, struct bridge_iflist *bif,
1017 uint16_t new_port_id)
1019 if (bstp_designated_port(sc, bif))
1020 bif->bif_designated_port = new_port_id;
1022 bif->bif_port_id = new_port_id;
1024 if ((sc->sc_bridge_id == bif->bif_designated_bridge) &&
1025 (bif->bif_port_id < bif->bif_designated_port)) {
1026 bstp_become_designated_port(sc, bif);
1027 bstp_port_state_selection(sc);
1032 bstp_set_path_cost(struct bridge_softc *sc, struct bridge_iflist *bif,
1035 bif->bif_path_cost = path_cost;
1036 bstp_configuration_update(sc);
1037 bstp_port_state_selection(sc);
1041 bstp_enable_change_detection(struct bridge_iflist *bif)
1043 bif->bif_change_detection_enabled = 1;
1047 bstp_disable_change_detection(struct bridge_iflist *bif)
1049 bif->bif_change_detection_enabled = 0;
1051 #endif /* notused */
1054 bstp_linkstate(struct ifnet *ifp, int state)
1056 struct bridge_softc *sc;
1057 struct bridge_iflist *bif;
1059 sc = ifp->if_bridge;
1060 ifnet_serialize_all(sc->sc_ifp);
1063 * bstp_ifupdstatus() may block, but it is the last
1064 * operation of the member iface iteration, so we
1065 * don't need to use LIST_FOREACH_MUTABLE()+bif_onlist
1068 LIST_FOREACH(bif, &sc->sc_iflists[mycpuid], bif_next) {
1069 if ((bif->bif_flags & IFBIF_STP) == 0)
1072 if (bif->bif_ifp == ifp) {
1073 bstp_ifupdstatus(sc, bif);
1077 ifnet_deserialize_all(sc->sc_ifp);
1081 bstp_ifupdstatus(struct bridge_softc *sc, struct bridge_iflist *bif)
1083 struct ifnet *ifp = bif->bif_ifp;
1084 struct ifmediareq ifmr;
1087 bzero((char *)&ifmr, sizeof(ifmr));
1088 ifnet_serialize_all(ifp);
1089 error = (*ifp->if_ioctl)(ifp, SIOCGIFMEDIA, (caddr_t)&ifmr, NULL);
1090 ifnet_deserialize_all(ifp);
1092 if ((error == 0) && (ifp->if_flags & IFF_UP)) {
1093 if (ifmr.ifm_status & IFM_ACTIVE) {
1094 if (bif->bif_state == BSTP_IFSTATE_DISABLED)
1095 bstp_enable_port(sc, bif);
1098 if (bif->bif_state != BSTP_IFSTATE_DISABLED)
1099 bstp_disable_port(sc, bif);
1104 if (bif->bif_state != BSTP_IFSTATE_DISABLED)
1105 bstp_disable_port(sc, bif);
1109 bstp_tick(void *arg)
1111 struct bridge_softc *sc = arg;
1112 struct lwkt_msg *lmsg;
1114 KKASSERT(mycpuid == BRIDGE_CFGCPU);
1118 if (callout_pending(&sc->sc_bstpcallout) ||
1119 !callout_active(&sc->sc_bstpcallout)) {
1123 callout_deactivate(&sc->sc_bstpcallout);
1125 lmsg = &sc->sc_bstptimemsg.lmsg;
1126 KKASSERT(lmsg->ms_flags & MSGF_DONE);
1127 lwkt_sendmsg(BRIDGE_CFGPORT, lmsg);
1133 bstp_tick_handler(netmsg_t msg)
1135 struct bridge_softc *sc = msg->lmsg.u.ms_resultp;
1136 struct bridge_iflist *bif;
1138 KKASSERT(&curthread->td_msgport == BRIDGE_CFGPORT);
1141 lwkt_replymsg(&msg->lmsg, 0);
1144 ifnet_serialize_all(sc->sc_ifp);
1148 * We don't need to worry that member iface is ripped
1149 * from the per-cpu list during the blocking operation
1150 * in the loop body, since deletion is serialized by
1154 LIST_FOREACH(bif, &sc->sc_iflists[mycpuid], bif_next) {
1155 if ((bif->bif_flags & IFBIF_STP) == 0)
1158 * XXX This can cause a lag in "link does away"
1159 * XXX and "spanning tree gets updated". We need
1160 * XXX come sort of callback from the link state
1161 * XXX update code to kick spanning tree.
1162 * XXX --thorpej@NetBSD.org
1164 bstp_ifupdstatus(sc, bif);
1167 if (bstp_timer_expired(&sc->sc_hello_timer, sc->sc_hello_time))
1168 bstp_hello_timer_expiry(sc);
1170 if (bstp_timer_expired(&sc->sc_tcn_timer, sc->sc_bridge_hello_time))
1171 bstp_tcn_timer_expiry(sc);
1173 if (bstp_timer_expired(&sc->sc_topology_change_timer,
1174 sc->sc_topology_change_time))
1175 bstp_topology_change_timer_expiry(sc);
1177 LIST_FOREACH(bif, &sc->sc_iflists[mycpuid], bif_next) {
1178 if ((bif->bif_flags & IFBIF_STP) == 0)
1180 if (bstp_timer_expired(&bif->bif_message_age_timer,
1182 bstp_message_age_timer_expiry(sc, bif);
1185 LIST_FOREACH(bif, &sc->sc_iflists[mycpuid], bif_next) {
1186 if ((bif->bif_flags & IFBIF_STP) == 0)
1188 if (bstp_timer_expired(&bif->bif_forward_delay_timer,
1189 sc->sc_forward_delay))
1190 bstp_forward_delay_timer_expiry(sc, bif);
1192 if (bstp_timer_expired(&bif->bif_hold_timer,
1194 bstp_hold_timer_expiry(sc, bif);
1197 if (sc->sc_ifp->if_flags & IFF_RUNNING)
1198 callout_reset(&sc->sc_bstpcallout, hz, bstp_tick, sc);
1200 ifnet_deserialize_all(sc->sc_ifp);
1204 bstp_timer_start(struct bridge_timer *t, uint16_t v)
1211 bstp_timer_stop(struct bridge_timer *t)
1218 bstp_timer_expired(struct bridge_timer *t, uint16_t v)
1222 t->value += BSTP_TICK_VAL;
1223 if (t->value >= v) {