xref: /freebsd/sys/net/bridgestp.c (revision 84ee9401a3fc8d3c22424266f421a928989cd692)
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  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  *
28  * OpenBSD: bridgestp.c,v 1.5 2001/03/22 03:48:29 jason Exp
29  */
30 
31 /*
32  * Implementation of the spanning tree protocol as defined in
33  * ISO/IEC Final DIS 15802-3 (IEEE P802.1D/D17), May 25, 1998.
34  * (In English: IEEE 802.1D, Draft 17, 1998)
35  */
36 
37 #include <sys/cdefs.h>
38 __FBSDID("$FreeBSD$");
39 
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/mbuf.h>
43 #include <sys/socket.h>
44 #include <sys/sockio.h>
45 #include <sys/kernel.h>
46 #include <sys/callout.h>
47 #include <sys/module.h>
48 #include <sys/proc.h>
49 #include <sys/lock.h>
50 #include <sys/mutex.h>
51 #include <sys/taskqueue.h>
52 
53 #include <net/if.h>
54 #include <net/if_dl.h>
55 #include <net/if_types.h>
56 #include <net/if_llc.h>
57 #include <net/if_media.h>
58 
59 #include <netinet/in.h>
60 #include <netinet/in_systm.h>
61 #include <netinet/in_var.h>
62 #include <netinet/if_ether.h>
63 #include <net/bridgestp.h>
64 
65 const uint8_t bstp_etheraddr[] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
66 
67 LIST_HEAD(, bstp_state) bstp_list;
68 static struct mtx	bstp_list_mtx;
69 
70 static void	bstp_initialize_port(struct bstp_state *,
71 		    struct bstp_port *);
72 static void	bstp_ifupdstatus(struct bstp_state *, struct bstp_port *);
73 static void	bstp_enable_port(struct bstp_state *, struct bstp_port *);
74 static void	bstp_disable_port(struct bstp_state *,
75 		    struct bstp_port *);
76 #ifdef notused
77 static void	bstp_enable_change_detection(struct bstp_port *);
78 static void	bstp_disable_change_detection(struct bstp_port *);
79 #endif /* notused */
80 static int	bstp_root_bridge(struct bstp_state *bs);
81 static int	bstp_supersedes_port_info(struct bstp_state *,
82 		    struct bstp_port *, struct bstp_config_unit *);
83 static int	bstp_designated_port(struct bstp_state *,
84 		    struct bstp_port *);
85 static int	bstp_designated_for_some_port(struct bstp_state *);
86 static void	bstp_transmit_config(struct bstp_state *,
87 		    struct bstp_port *);
88 static void	bstp_transmit_tcn(struct bstp_state *);
89 static void	bstp_received_config_bpdu(struct bstp_state *,
90 		    struct bstp_port *, struct bstp_config_unit *);
91 static void	bstp_received_tcn_bpdu(struct bstp_state *,
92 		    struct bstp_port *, struct bstp_tcn_unit *);
93 static void	bstp_record_config_information(struct bstp_state *,
94 		    struct bstp_port *, struct bstp_config_unit *);
95 static void	bstp_record_config_timeout_values(struct bstp_state *,
96 		    struct bstp_config_unit *);
97 static void	bstp_config_bpdu_generation(struct bstp_state *);
98 static void	bstp_send_config_bpdu(struct bstp_state *,
99 		    struct bstp_port *, struct bstp_config_unit *);
100 static void	bstp_configuration_update(struct bstp_state *);
101 static void	bstp_root_selection(struct bstp_state *);
102 static void	bstp_designated_port_selection(struct bstp_state *);
103 static void	bstp_become_designated_port(struct bstp_state *,
104 		    struct bstp_port *);
105 static void	bstp_port_state_selection(struct bstp_state *);
106 static void	bstp_make_forwarding(struct bstp_state *,
107 		    struct bstp_port *);
108 static void	bstp_make_blocking(struct bstp_state *,
109 		    struct bstp_port *);
110 static void	bstp_set_port_state(struct bstp_port *, uint8_t);
111 static void	bstp_state_change(void *, int);
112 static void	bstp_update_forward_transitions(struct bstp_port *);
113 #ifdef notused
114 static void	bstp_set_bridge_priority(struct bstp_state *, uint64_t);
115 static void	bstp_set_port_priority(struct bstp_state *,
116 		    struct bstp_port *, uint16_t);
117 static void	bstp_set_path_cost(struct bstp_state *,
118 		    struct bstp_port *, uint32_t);
119 #endif /* notused */
120 static void	bstp_topology_change_detection(struct bstp_state *);
121 static void	bstp_topology_change_acknowledged(struct bstp_state *);
122 static void	bstp_acknowledge_topology_change(struct bstp_state *,
123 		    struct bstp_port *);
124 
125 static void	bstp_enqueue(struct ifnet *, struct mbuf *);
126 static void	bstp_tick(void *);
127 static void	bstp_timer_start(struct bstp_timer *, uint16_t);
128 static void	bstp_timer_stop(struct bstp_timer *);
129 static int	bstp_timer_expired(struct bstp_timer *, uint16_t);
130 
131 static void	bstp_hold_timer_expiry(struct bstp_state *,
132 		    struct bstp_port *);
133 static void	bstp_message_age_timer_expiry(struct bstp_state *,
134 		    struct bstp_port *);
135 static void	bstp_forward_delay_timer_expiry(struct bstp_state *,
136 		    struct bstp_port *);
137 static void	bstp_topology_change_timer_expiry(struct bstp_state *);
138 static void	bstp_tcn_timer_expiry(struct bstp_state *);
139 static void	bstp_hello_timer_expiry(struct bstp_state *);
140 static int	bstp_addr_cmp(const uint8_t *, const uint8_t *);
141 
142 static void
143 bstp_transmit_config(struct bstp_state *bs, struct bstp_port *bp)
144 {
145 	BSTP_LOCK_ASSERT(bs);
146 
147 	if (bp->bp_hold_timer.active) {
148 		bp->bp_config_pending = 1;
149 		return;
150 	}
151 
152 	bp->bp_config_bpdu.cu_message_type = BSTP_MSGTYPE_CFG;
153 	bp->bp_config_bpdu.cu_rootid = bs->bs_designated_root;
154 	bp->bp_config_bpdu.cu_root_path_cost = bs->bs_root_path_cost;
155 	bp->bp_config_bpdu.cu_bridge_id = bs->bs_bridge_id;
156 	bp->bp_config_bpdu.cu_port_id = bp->bp_port_id;
157 
158 	if (bstp_root_bridge(bs))
159 		bp->bp_config_bpdu.cu_message_age = 0;
160 	else
161 		bp->bp_config_bpdu.cu_message_age =
162 		    bs->bs_root_port->bp_message_age_timer.value +
163 		    BSTP_MESSAGE_AGE_INCR;
164 
165 	bp->bp_config_bpdu.cu_max_age = bs->bs_max_age;
166 	bp->bp_config_bpdu.cu_hello_time = bs->bs_hello_time;
167 	bp->bp_config_bpdu.cu_forward_delay = bs->bs_forward_delay;
168 	bp->bp_config_bpdu.cu_topology_change_acknowledgment
169 	    = bp->bp_topology_change_acknowledge;
170 	bp->bp_config_bpdu.cu_topology_change = bs->bs_topology_change;
171 
172 	if (bp->bp_config_bpdu.cu_message_age < bs->bs_max_age) {
173 		bp->bp_topology_change_acknowledge = 0;
174 		bp->bp_config_pending = 0;
175 		bstp_send_config_bpdu(bs, bp, &bp->bp_config_bpdu);
176 		bstp_timer_start(&bp->bp_hold_timer, 0);
177 	}
178 }
179 
180 static void
181 bstp_send_config_bpdu(struct bstp_state *bs, struct bstp_port *bp,
182     struct bstp_config_unit *cu)
183 {
184 	struct ifnet *ifp;
185 	struct mbuf *m;
186 	struct ether_header *eh;
187 	struct bstp_cbpdu bpdu;
188 
189 	BSTP_LOCK_ASSERT(bs);
190 
191 	ifp = bp->bp_ifp;
192 
193 	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
194 		return;
195 
196 	MGETHDR(m, M_DONTWAIT, MT_DATA);
197 	if (m == NULL)
198 		return;
199 
200 	eh = mtod(m, struct ether_header *);
201 
202 	m->m_pkthdr.rcvif = ifp;
203 	m->m_pkthdr.len = sizeof(*eh) + sizeof(bpdu);
204 	m->m_len = m->m_pkthdr.len;
205 
206 	bpdu.cbu_ssap = bpdu.cbu_dsap = LLC_8021D_LSAP;
207 	bpdu.cbu_ctl = LLC_UI;
208 	bpdu.cbu_protoid = htons(0);
209 	bpdu.cbu_protover = 0;
210 	bpdu.cbu_bpdutype = cu->cu_message_type;
211 	bpdu.cbu_flags = (cu->cu_topology_change ? BSTP_FLAG_TC : 0) |
212 	    (cu->cu_topology_change_acknowledgment ? BSTP_FLAG_TCA : 0);
213 
214 	bpdu.cbu_rootpri = htons(cu->cu_rootid >> 48);
215 	bpdu.cbu_rootaddr[0] = cu->cu_rootid >> 40;
216 	bpdu.cbu_rootaddr[1] = cu->cu_rootid >> 32;
217 	bpdu.cbu_rootaddr[2] = cu->cu_rootid >> 24;
218 	bpdu.cbu_rootaddr[3] = cu->cu_rootid >> 16;
219 	bpdu.cbu_rootaddr[4] = cu->cu_rootid >> 8;
220 	bpdu.cbu_rootaddr[5] = cu->cu_rootid >> 0;
221 
222 	bpdu.cbu_rootpathcost = htonl(cu->cu_root_path_cost);
223 
224 	bpdu.cbu_bridgepri = htons(cu->cu_bridge_id >> 48);
225 	bpdu.cbu_bridgeaddr[0] = cu->cu_bridge_id >> 40;
226 	bpdu.cbu_bridgeaddr[1] = cu->cu_bridge_id >> 32;
227 	bpdu.cbu_bridgeaddr[2] = cu->cu_bridge_id >> 24;
228 	bpdu.cbu_bridgeaddr[3] = cu->cu_bridge_id >> 16;
229 	bpdu.cbu_bridgeaddr[4] = cu->cu_bridge_id >> 8;
230 	bpdu.cbu_bridgeaddr[5] = cu->cu_bridge_id >> 0;
231 
232 	bpdu.cbu_portid = htons(cu->cu_port_id);
233 	bpdu.cbu_messageage = htons(cu->cu_message_age);
234 	bpdu.cbu_maxage = htons(cu->cu_max_age);
235 	bpdu.cbu_hellotime = htons(cu->cu_hello_time);
236 	bpdu.cbu_forwarddelay = htons(cu->cu_forward_delay);
237 
238 	memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN);
239 	memcpy(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN);
240 	eh->ether_type = htons(sizeof(bpdu));
241 
242 	memcpy(mtod(m, caddr_t) + sizeof(*eh), &bpdu, sizeof(bpdu));
243 
244 	bstp_enqueue(ifp, m);
245 }
246 
247 static int
248 bstp_root_bridge(struct bstp_state *bs)
249 {
250 	return (bs->bs_designated_root == bs->bs_bridge_id);
251 }
252 
253 static int
254 bstp_supersedes_port_info(struct bstp_state *bs, struct bstp_port *bp,
255     struct bstp_config_unit *cu)
256 {
257 	if (cu->cu_rootid < bp->bp_designated_root)
258 		return (1);
259 	if (cu->cu_rootid > bp->bp_designated_root)
260 		return (0);
261 
262 	if (cu->cu_root_path_cost < bp->bp_designated_cost)
263 		return (1);
264 	if (cu->cu_root_path_cost > bp->bp_designated_cost)
265 		return (0);
266 
267 	if (cu->cu_bridge_id < bp->bp_designated_bridge)
268 		return (1);
269 	if (cu->cu_bridge_id > bp->bp_designated_bridge)
270 		return (0);
271 
272 	if (bs->bs_bridge_id != cu->cu_bridge_id)
273 		return (1);
274 	if (cu->cu_port_id <= bp->bp_designated_port)
275 		return (1);
276 	return (0);
277 }
278 
279 static void
280 bstp_record_config_information(struct bstp_state *bs,
281     struct bstp_port *bp, struct bstp_config_unit *cu)
282 {
283 	BSTP_LOCK_ASSERT(bs);
284 
285 	bp->bp_designated_root = cu->cu_rootid;
286 	bp->bp_designated_cost = cu->cu_root_path_cost;
287 	bp->bp_designated_bridge = cu->cu_bridge_id;
288 	bp->bp_designated_port = cu->cu_port_id;
289 	bstp_timer_start(&bp->bp_message_age_timer, cu->cu_message_age);
290 }
291 
292 static void
293 bstp_record_config_timeout_values(struct bstp_state *bs,
294     struct bstp_config_unit *config)
295 {
296 	BSTP_LOCK_ASSERT(bs);
297 
298 	bs->bs_max_age = config->cu_max_age;
299 	bs->bs_hello_time = config->cu_hello_time;
300 	bs->bs_forward_delay = config->cu_forward_delay;
301 	bs->bs_topology_change = config->cu_topology_change;
302 }
303 
304 static void
305 bstp_config_bpdu_generation(struct bstp_state *bs)
306 {
307 	struct bstp_port *bp;
308 
309 	BSTP_LOCK_ASSERT(bs);
310 
311 	LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
312 		if (bstp_designated_port(bs, bp) &&
313 		    (bp->bp_state != BSTP_IFSTATE_DISABLED))
314 			bstp_transmit_config(bs, bp);
315 	}
316 }
317 
318 static int
319 bstp_designated_port(struct bstp_state *bs, struct bstp_port *bp)
320 {
321 	return ((bp->bp_designated_bridge == bs->bs_bridge_id)
322 	    && (bp->bp_designated_port == bp->bp_port_id));
323 }
324 
325 static void
326 bstp_transmit_tcn(struct bstp_state *bs)
327 {
328 	struct bstp_tbpdu bpdu;
329 	struct bstp_port *bp = bs->bs_root_port;
330 	struct ifnet *ifp = bp->bp_ifp;
331 	struct ether_header *eh;
332 	struct mbuf *m;
333 
334 	BSTP_LOCK_ASSERT(bs);
335 
336 	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
337 		return;
338 
339 	MGETHDR(m, M_DONTWAIT, MT_DATA);
340 	if (m == NULL)
341 		return;
342 
343 	m->m_pkthdr.rcvif = ifp;
344 	m->m_pkthdr.len = sizeof(*eh) + sizeof(bpdu);
345 	m->m_len = m->m_pkthdr.len;
346 
347 	eh = mtod(m, struct ether_header *);
348 
349 	memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN);
350 	memcpy(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN);
351 	eh->ether_type = htons(sizeof(bpdu));
352 
353 	bpdu.tbu_ssap = bpdu.tbu_dsap = LLC_8021D_LSAP;
354 	bpdu.tbu_ctl = LLC_UI;
355 	bpdu.tbu_protoid = 0;
356 	bpdu.tbu_protover = 0;
357 	bpdu.tbu_bpdutype = BSTP_MSGTYPE_TCN;
358 
359 	memcpy(mtod(m, caddr_t) + sizeof(*eh), &bpdu, sizeof(bpdu));
360 
361 	bstp_enqueue(ifp, m);
362 }
363 
364 static void
365 bstp_configuration_update(struct bstp_state *bs)
366 {
367 	BSTP_LOCK_ASSERT(bs);
368 
369 	bstp_root_selection(bs);
370 	bstp_designated_port_selection(bs);
371 }
372 
373 static void
374 bstp_root_selection(struct bstp_state *bs)
375 {
376 	struct bstp_port *root_port = NULL, *bp;
377 
378 	BSTP_LOCK_ASSERT(bs);
379 
380 	LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
381 		if (bstp_designated_port(bs, bp))
382 			continue;
383 		if (bp->bp_state == BSTP_IFSTATE_DISABLED)
384 			continue;
385 		if (bp->bp_designated_root >= bs->bs_bridge_id)
386 			continue;
387 		if (root_port == NULL)
388 			goto set_port;
389 
390 		if (bp->bp_designated_root < root_port->bp_designated_root)
391 			goto set_port;
392 		if (bp->bp_designated_root > root_port->bp_designated_root)
393 			continue;
394 
395 		if ((bp->bp_designated_cost + bp->bp_path_cost) <
396 		    (root_port->bp_designated_cost + root_port->bp_path_cost))
397 			goto set_port;
398 		if ((bp->bp_designated_cost + bp->bp_path_cost) >
399 		    (root_port->bp_designated_cost + root_port->bp_path_cost))
400 			continue;
401 
402 		if (bp->bp_designated_bridge <
403 		    root_port->bp_designated_bridge)
404 			goto set_port;
405 		if (bp->bp_designated_bridge >
406 		    root_port->bp_designated_bridge)
407 			continue;
408 
409 		if (bp->bp_designated_port < root_port->bp_designated_port)
410 			goto set_port;
411 		if (bp->bp_designated_port > root_port->bp_designated_port)
412 			continue;
413 
414 		if (bp->bp_port_id >= root_port->bp_port_id)
415 			continue;
416 set_port:
417 		root_port = bp;
418 	}
419 
420 	bs->bs_root_port = root_port;
421 	if (root_port == NULL) {
422 		bs->bs_designated_root = bs->bs_bridge_id;
423 		bs->bs_root_path_cost = 0;
424 	} else {
425 		bs->bs_designated_root = root_port->bp_designated_root;
426 		bs->bs_root_path_cost = root_port->bp_designated_cost +
427 		    root_port->bp_path_cost;
428 	}
429 }
430 
431 static void
432 bstp_designated_port_selection(struct bstp_state *bs)
433 {
434 	struct bstp_port *bp;
435 
436 	BSTP_LOCK_ASSERT(bs);
437 
438 	LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
439 		if (bstp_designated_port(bs, bp))
440 			goto designated;
441 		if (bp->bp_designated_root != bs->bs_designated_root)
442 			goto designated;
443 
444 		if (bs->bs_root_path_cost < bp->bp_designated_cost)
445 			goto designated;
446 		if (bs->bs_root_path_cost > bp->bp_designated_cost)
447 			continue;
448 
449 		if (bs->bs_bridge_id < bp->bp_designated_bridge)
450 			goto designated;
451 		if (bs->bs_bridge_id > bp->bp_designated_bridge)
452 			continue;
453 
454 		if (bp->bp_port_id > bp->bp_designated_port)
455 			continue;
456 designated:
457 		bstp_become_designated_port(bs, bp);
458 	}
459 }
460 
461 static void
462 bstp_become_designated_port(struct bstp_state *bs, struct bstp_port *bp)
463 {
464 	BSTP_LOCK_ASSERT(bs);
465 
466 	bp->bp_designated_root = bs->bs_designated_root;
467 	bp->bp_designated_cost = bs->bs_root_path_cost;
468 	bp->bp_designated_bridge = bs->bs_bridge_id;
469 	bp->bp_designated_port = bp->bp_port_id;
470 }
471 
472 static void
473 bstp_port_state_selection(struct bstp_state *bs)
474 {
475 	struct bstp_port *bp;
476 
477 	BSTP_LOCK_ASSERT(bs);
478 
479 	LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
480 		if (bp == bs->bs_root_port) {
481 			bp->bp_config_pending = 0;
482 			bp->bp_topology_change_acknowledge = 0;
483 			bstp_make_forwarding(bs, bp);
484 		} else if (bstp_designated_port(bs, bp)) {
485 			bstp_timer_stop(&bp->bp_message_age_timer);
486 			bstp_make_forwarding(bs, bp);
487 		} else {
488 			bp->bp_config_pending = 0;
489 			bp->bp_topology_change_acknowledge = 0;
490 			bstp_make_blocking(bs, bp);
491 		}
492 	}
493 }
494 
495 static void
496 bstp_make_forwarding(struct bstp_state *bs, struct bstp_port *bp)
497 {
498 	BSTP_LOCK_ASSERT(bs);
499 
500 	if (bp->bp_state == BSTP_IFSTATE_BLOCKING) {
501 		bstp_set_port_state(bp, BSTP_IFSTATE_LISTENING);
502 		bstp_timer_start(&bp->bp_forward_delay_timer, 0);
503 	}
504 }
505 
506 static void
507 bstp_make_blocking(struct bstp_state *bs, struct bstp_port *bp)
508 {
509 	BSTP_LOCK_ASSERT(bs);
510 
511 	if ((bp->bp_state != BSTP_IFSTATE_DISABLED) &&
512 	    (bp->bp_state != BSTP_IFSTATE_BLOCKING)) {
513 		if ((bp->bp_state == BSTP_IFSTATE_FORWARDING) ||
514 		    (bp->bp_state == BSTP_IFSTATE_LEARNING)) {
515 			if (bp->bp_change_detection_enabled) {
516 				bstp_topology_change_detection(bs);
517 			}
518 		}
519 		bstp_set_port_state(bp, BSTP_IFSTATE_BLOCKING);
520 		bstp_timer_stop(&bp->bp_forward_delay_timer);
521 	}
522 }
523 
524 static void
525 bstp_set_port_state(struct bstp_port *bp, uint8_t state)
526 {
527 	struct bstp_state *bs = bp->bp_bs;
528 
529 	bp->bp_state = state;
530 
531 	/* notify the parent bridge */
532 	if (bs->bs_state_cb != NULL)
533 		taskqueue_enqueue(taskqueue_swi, &bp->bp_statetask);
534 }
535 
536 /*
537  * Notify the bridge that a port state has changed, we need to do this from a
538  * taskqueue to avoid a LOR.
539  */
540 static void
541 bstp_state_change(void *arg, int pending)
542 {
543 	struct bstp_port *bp = (struct bstp_port *)arg;
544 	struct bstp_state *bs = bp->bp_bs;
545 
546 	if (bp->bp_active == 1)
547 		(*bs->bs_state_cb)(bp->bp_ifp, bp->bp_state);
548 }
549 
550 static void
551 bstp_update_forward_transitions(struct bstp_port *bp)
552 {
553 	bp->bp_forward_transitions++;
554 }
555 
556 static void
557 bstp_topology_change_detection(struct bstp_state *bs)
558 {
559 	BSTP_LOCK_ASSERT(bs);
560 
561 	if (bstp_root_bridge(bs)) {
562 		bs->bs_topology_change = 1;
563 		bstp_timer_start(&bs->bs_topology_change_timer, 0);
564 	} else if (!bs->bs_topology_change_detected) {
565 		bstp_transmit_tcn(bs);
566 		bstp_timer_start(&bs->bs_tcn_timer, 0);
567 	}
568 	bs->bs_topology_change_detected = 1;
569 	getmicrotime(&bs->bs_last_tc_time);
570 }
571 
572 static void
573 bstp_topology_change_acknowledged(struct bstp_state *bs)
574 {
575 	BSTP_LOCK_ASSERT(bs);
576 
577 	bs->bs_topology_change_detected = 0;
578 	bstp_timer_stop(&bs->bs_tcn_timer);
579 }
580 
581 static void
582 bstp_acknowledge_topology_change(struct bstp_state *bs,
583     struct bstp_port *bp)
584 {
585 	BSTP_LOCK_ASSERT(bs);
586 
587 	bp->bp_topology_change_acknowledge = 1;
588 	bstp_transmit_config(bs, bp);
589 }
590 
591 struct mbuf *
592 bstp_input(struct bstp_port *bp, struct ifnet *ifp, struct mbuf *m)
593 {
594 	struct bstp_state *bs = bp->bp_bs;
595 	struct ether_header *eh;
596 	struct bstp_tbpdu tpdu;
597 	struct bstp_cbpdu cpdu;
598 	struct bstp_config_unit cu;
599 	struct bstp_tcn_unit tu;
600 	uint16_t len;
601 
602 	if (bp->bp_active == 0) {
603 		m_freem(m);
604 		return (NULL);
605 	}
606 
607 	BSTP_LOCK(bs);
608 
609 	eh = mtod(m, struct ether_header *);
610 
611 	len = ntohs(eh->ether_type);
612 	if (len < sizeof(tpdu))
613 		goto out;
614 
615 	m_adj(m, ETHER_HDR_LEN);
616 
617 	if (m->m_pkthdr.len > len)
618 		m_adj(m, len - m->m_pkthdr.len);
619 	if (m->m_len < sizeof(tpdu) &&
620 	    (m = m_pullup(m, sizeof(tpdu))) == NULL)
621 		goto out;
622 
623 	memcpy(&tpdu, mtod(m, caddr_t), sizeof(tpdu));
624 
625 	if (tpdu.tbu_dsap != LLC_8021D_LSAP ||
626 	    tpdu.tbu_ssap != LLC_8021D_LSAP ||
627 	    tpdu.tbu_ctl != LLC_UI)
628 		goto out;
629 	if (tpdu.tbu_protoid != 0 || tpdu.tbu_protover != 0)
630 		goto out;
631 
632 	switch (tpdu.tbu_bpdutype) {
633 	case BSTP_MSGTYPE_TCN:
634 		tu.tu_message_type = tpdu.tbu_bpdutype;
635 		bstp_received_tcn_bpdu(bs, bp, &tu);
636 		break;
637 	case BSTP_MSGTYPE_CFG:
638 		if (m->m_len < sizeof(cpdu) &&
639 		    (m = m_pullup(m, sizeof(cpdu))) == NULL)
640 			goto out;
641 		memcpy(&cpdu, mtod(m, caddr_t), sizeof(cpdu));
642 
643 		cu.cu_rootid =
644 		    (((uint64_t)ntohs(cpdu.cbu_rootpri)) << 48) |
645 		    (((uint64_t)cpdu.cbu_rootaddr[0]) << 40) |
646 		    (((uint64_t)cpdu.cbu_rootaddr[1]) << 32) |
647 		    (((uint64_t)cpdu.cbu_rootaddr[2]) << 24) |
648 		    (((uint64_t)cpdu.cbu_rootaddr[3]) << 16) |
649 		    (((uint64_t)cpdu.cbu_rootaddr[4]) << 8) |
650 		    (((uint64_t)cpdu.cbu_rootaddr[5]) << 0);
651 
652 		cu.cu_bridge_id =
653 		    (((uint64_t)ntohs(cpdu.cbu_bridgepri)) << 48) |
654 		    (((uint64_t)cpdu.cbu_bridgeaddr[0]) << 40) |
655 		    (((uint64_t)cpdu.cbu_bridgeaddr[1]) << 32) |
656 		    (((uint64_t)cpdu.cbu_bridgeaddr[2]) << 24) |
657 		    (((uint64_t)cpdu.cbu_bridgeaddr[3]) << 16) |
658 		    (((uint64_t)cpdu.cbu_bridgeaddr[4]) << 8) |
659 		    (((uint64_t)cpdu.cbu_bridgeaddr[5]) << 0);
660 
661 		cu.cu_root_path_cost = ntohl(cpdu.cbu_rootpathcost);
662 		cu.cu_message_age = ntohs(cpdu.cbu_messageage);
663 		cu.cu_max_age = ntohs(cpdu.cbu_maxage);
664 		cu.cu_hello_time = ntohs(cpdu.cbu_hellotime);
665 		cu.cu_forward_delay = ntohs(cpdu.cbu_forwarddelay);
666 		cu.cu_port_id = ntohs(cpdu.cbu_portid);
667 		cu.cu_message_type = cpdu.cbu_bpdutype;
668 		cu.cu_topology_change_acknowledgment =
669 		    (cpdu.cbu_flags & BSTP_FLAG_TCA) ? 1 : 0;
670 		cu.cu_topology_change =
671 		    (cpdu.cbu_flags & BSTP_FLAG_TC) ? 1 : 0;
672 		bstp_received_config_bpdu(bs, bp, &cu);
673 		break;
674 	default:
675 		goto out;
676 	}
677 
678 out:
679 	BSTP_UNLOCK(bs);
680 	if (m)
681 		m_freem(m);
682 	return (NULL);
683 }
684 
685 static void
686 bstp_received_config_bpdu(struct bstp_state *bs, struct bstp_port *bp,
687     struct bstp_config_unit *cu)
688 {
689 	int root;
690 
691 	BSTP_LOCK_ASSERT(bs);
692 
693 	root = bstp_root_bridge(bs);
694 
695 	if (bp->bp_state != BSTP_IFSTATE_DISABLED) {
696 		if (bstp_supersedes_port_info(bs, bp, cu)) {
697 			bstp_record_config_information(bs, bp, cu);
698 			bstp_configuration_update(bs);
699 			bstp_port_state_selection(bs);
700 
701 			if ((bstp_root_bridge(bs) == 0) && root) {
702 				bstp_timer_stop(&bs->bs_hello_timer);
703 
704 				if (bs->bs_topology_change_detected) {
705 					bstp_timer_stop(
706 					    &bs->bs_topology_change_timer);
707 					bstp_transmit_tcn(bs);
708 					bstp_timer_start(&bs->bs_tcn_timer, 0);
709 				}
710 			}
711 
712 			if (bp == bs->bs_root_port) {
713 				bstp_record_config_timeout_values(bs, cu);
714 				bstp_config_bpdu_generation(bs);
715 
716 				if (cu->cu_topology_change_acknowledgment)
717 					bstp_topology_change_acknowledged(bs);
718 			}
719 		} else if (bstp_designated_port(bs, bp))
720 			bstp_transmit_config(bs, bp);
721 	}
722 }
723 
724 static void
725 bstp_received_tcn_bpdu(struct bstp_state *bs, struct bstp_port *bp,
726     struct bstp_tcn_unit *tcn)
727 {
728 	if (bp->bp_state != BSTP_IFSTATE_DISABLED &&
729 	    bstp_designated_port(bs, bp)) {
730 		bstp_topology_change_detection(bs);
731 		bstp_acknowledge_topology_change(bs, bp);
732 	}
733 }
734 
735 static void
736 bstp_hello_timer_expiry(struct bstp_state *bs)
737 {
738 	bstp_config_bpdu_generation(bs);
739 	bstp_timer_start(&bs->bs_hello_timer, 0);
740 }
741 
742 static void
743 bstp_message_age_timer_expiry(struct bstp_state *bs,
744     struct bstp_port *bp)
745 {
746 	int root;
747 
748 	BSTP_LOCK_ASSERT(bs);
749 
750 	root = bstp_root_bridge(bs);
751 	bstp_become_designated_port(bs, bp);
752 	bstp_configuration_update(bs);
753 	bstp_port_state_selection(bs);
754 
755 	if ((bstp_root_bridge(bs)) && (root == 0)) {
756 		bs->bs_max_age = bs->bs_bridge_max_age;
757 		bs->bs_hello_time = bs->bs_bridge_hello_time;
758 		bs->bs_forward_delay = bs->bs_bridge_forward_delay;
759 
760 		bstp_topology_change_detection(bs);
761 		bstp_timer_stop(&bs->bs_tcn_timer);
762 		bstp_config_bpdu_generation(bs);
763 		bstp_timer_start(&bs->bs_hello_timer, 0);
764 	}
765 }
766 
767 static void
768 bstp_forward_delay_timer_expiry(struct bstp_state *bs,
769     struct bstp_port *bp)
770 {
771 	if (bp->bp_state == BSTP_IFSTATE_LISTENING) {
772 		bstp_set_port_state(bp, BSTP_IFSTATE_LEARNING);
773 		bstp_timer_start(&bp->bp_forward_delay_timer, 0);
774 	} else if (bp->bp_state == BSTP_IFSTATE_LEARNING) {
775 		bstp_set_port_state(bp, BSTP_IFSTATE_FORWARDING);
776 		bstp_update_forward_transitions(bp);
777 		if (bstp_designated_for_some_port(bs) &&
778 		    bp->bp_change_detection_enabled)
779 			bstp_topology_change_detection(bs);
780 	}
781 }
782 
783 static int
784 bstp_designated_for_some_port(struct bstp_state *bs)
785 {
786 
787 	struct bstp_port *bp;
788 
789 	BSTP_LOCK_ASSERT(bs);
790 
791 	LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
792 		if (bp->bp_designated_bridge == bs->bs_bridge_id)
793 			return (1);
794 	}
795 	return (0);
796 }
797 
798 static void
799 bstp_tcn_timer_expiry(struct bstp_state *bs)
800 {
801 	BSTP_LOCK_ASSERT(bs);
802 
803 	bstp_transmit_tcn(bs);
804 	bstp_timer_start(&bs->bs_tcn_timer, 0);
805 }
806 
807 static void
808 bstp_topology_change_timer_expiry(struct bstp_state *bs)
809 {
810 	BSTP_LOCK_ASSERT(bs);
811 
812 	bs->bs_topology_change_detected = 0;
813 	bs->bs_topology_change = 0;
814 }
815 
816 static void
817 bstp_hold_timer_expiry(struct bstp_state *bs, struct bstp_port *bp)
818 {
819 	if (bp->bp_config_pending)
820 		bstp_transmit_config(bs, bp);
821 }
822 
823 static int
824 bstp_addr_cmp(const uint8_t *a, const uint8_t *b)
825 {
826 	int i, d;
827 
828 	for (i = 0, d = 0; i < ETHER_ADDR_LEN && d == 0; i++) {
829 		d = ((int)a[i]) - ((int)b[i]);
830 	}
831 
832 	return (d);
833 }
834 
835 void
836 bstp_reinit(struct bstp_state *bs)
837 {
838 	struct bstp_port *bp, *mbp;
839 	u_char *e_addr;
840 
841 	BSTP_LOCK(bs);
842 
843 	mbp = NULL;
844 	LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
845 		bp->bp_port_id = (bp->bp_priority << 8) |
846 		    (bp->bp_ifp->if_index & 0xff);
847 
848 		if (mbp == NULL) {
849 			mbp = bp;
850 			continue;
851 		}
852 		if (bstp_addr_cmp(IF_LLADDR(bp->bp_ifp),
853 		    IF_LLADDR(mbp->bp_ifp)) < 0) {
854 			mbp = bp;
855 			continue;
856 		}
857 	}
858 	if (mbp == NULL) {
859 		BSTP_UNLOCK(bs);
860 		bstp_stop(bs);
861 		return;
862 	}
863 
864 	e_addr = IF_LLADDR(mbp->bp_ifp);
865 	bs->bs_bridge_id =
866 	    (((uint64_t)bs->bs_bridge_priority) << 48) |
867 	    (((uint64_t)e_addr[0]) << 40) |
868 	    (((uint64_t)e_addr[1]) << 32) |
869 	    (((uint64_t)e_addr[2]) << 24) |
870 	    (((uint64_t)e_addr[3]) << 16) |
871 	    (((uint64_t)e_addr[4]) << 8) |
872 	    (((uint64_t)e_addr[5]));
873 
874 	bs->bs_designated_root = bs->bs_bridge_id;
875 	bs->bs_root_path_cost = 0;
876 	bs->bs_root_port = NULL;
877 
878 	bs->bs_max_age = bs->bs_bridge_max_age;
879 	bs->bs_hello_time = bs->bs_bridge_hello_time;
880 	bs->bs_forward_delay = bs->bs_bridge_forward_delay;
881 	bs->bs_topology_change_detected = 0;
882 	bs->bs_topology_change = 0;
883 	bstp_timer_stop(&bs->bs_tcn_timer);
884 	bstp_timer_stop(&bs->bs_topology_change_timer);
885 
886 	if (callout_pending(&bs->bs_bstpcallout) == 0)
887 		callout_reset(&bs->bs_bstpcallout, hz,
888 		    bstp_tick, bs);
889 
890 	LIST_FOREACH(bp, &bs->bs_bplist, bp_next)
891 		bstp_ifupdstatus(bs, bp);
892 
893 	getmicrotime(&bs->bs_last_tc_time);
894 	bstp_port_state_selection(bs);
895 	bstp_config_bpdu_generation(bs);
896 	bstp_timer_start(&bs->bs_hello_timer, 0);
897 	bstp_timer_start(&bs->bs_link_timer, 0);
898 	BSTP_UNLOCK(bs);
899 }
900 
901 static int
902 bstp_modevent(module_t mod, int type, void *data)
903 {
904 
905 	switch (type) {
906 	case MOD_LOAD:
907 		mtx_init(&bstp_list_mtx, "bridgestp list", NULL, MTX_DEF);
908 		LIST_INIT(&bstp_list);
909 		bstp_linkstate_p = bstp_linkstate;
910 		break;
911 	case MOD_UNLOAD:
912 		mtx_destroy(&bstp_list_mtx);
913 		break;
914 	default:
915 		return (EOPNOTSUPP);
916 	}
917 	return (0);
918 }
919 
920 static moduledata_t bstp_mod = {
921 	"bridgestp",
922 	bstp_modevent,
923 	0
924 };
925 
926 DECLARE_MODULE(bridgestp, bstp_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
927 MODULE_VERSION(bridgestp, 1);
928 
929 void
930 bstp_attach(struct bstp_state *bs, bstp_state_cb_t state_callback)
931 {
932 	BSTP_LOCK_INIT(bs);
933 	callout_init_mtx(&bs->bs_bstpcallout, &bs->bs_mtx, 0);
934 	LIST_INIT(&bs->bs_bplist);
935 
936 	bs->bs_bridge_max_age = BSTP_DEFAULT_MAX_AGE;
937 	bs->bs_bridge_hello_time = BSTP_DEFAULT_HELLO_TIME;
938 	bs->bs_bridge_forward_delay = BSTP_DEFAULT_FORWARD_DELAY;
939 	bs->bs_bridge_priority = BSTP_DEFAULT_BRIDGE_PRIORITY;
940 	bs->bs_hold_time = BSTP_DEFAULT_HOLD_TIME;
941 	bs->bs_state_cb = state_callback;
942 
943 	mtx_lock(&bstp_list_mtx);
944 	LIST_INSERT_HEAD(&bstp_list, bs, bs_list);
945 	mtx_unlock(&bstp_list_mtx);
946 }
947 
948 void
949 bstp_detach(struct bstp_state *bs)
950 {
951 	KASSERT(LIST_EMPTY(&bs->bs_bplist), ("bstp still active"));
952 
953 	mtx_lock(&bstp_list_mtx);
954 	LIST_REMOVE(bs, bs_list);
955 	mtx_unlock(&bstp_list_mtx);
956 	BSTP_LOCK_DESTROY(bs);
957 }
958 
959 void
960 bstp_init(struct bstp_state *bs)
961 {
962 	callout_reset(&bs->bs_bstpcallout, hz, bstp_tick, bs);
963 	bstp_reinit(bs);
964 }
965 
966 void
967 bstp_stop(struct bstp_state *bs)
968 {
969 	struct bstp_port *bp;
970 
971 	BSTP_LOCK(bs);
972 
973 	LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
974 		bstp_set_port_state(bp, BSTP_IFSTATE_DISABLED);
975 		bstp_timer_stop(&bp->bp_hold_timer);
976 		bstp_timer_stop(&bp->bp_message_age_timer);
977 		bstp_timer_stop(&bp->bp_forward_delay_timer);
978 	}
979 
980 	callout_drain(&bs->bs_bstpcallout);
981 	callout_stop(&bs->bs_bstpcallout);
982 
983 	bstp_timer_stop(&bs->bs_topology_change_timer);
984 	bstp_timer_stop(&bs->bs_tcn_timer);
985 	bstp_timer_stop(&bs->bs_hello_timer);
986 
987 	BSTP_UNLOCK(bs);
988 }
989 
990 static void
991 bstp_initialize_port(struct bstp_state *bs, struct bstp_port *bp)
992 {
993 	BSTP_LOCK_ASSERT(bs);
994 
995 	bstp_become_designated_port(bs, bp);
996 	bstp_set_port_state(bp, BSTP_IFSTATE_BLOCKING);
997 	bp->bp_topology_change_acknowledge = 0;
998 	bp->bp_config_pending = 0;
999 	bp->bp_change_detection_enabled = 1;
1000 	bstp_timer_stop(&bp->bp_message_age_timer);
1001 	bstp_timer_stop(&bp->bp_forward_delay_timer);
1002 	bstp_timer_stop(&bp->bp_hold_timer);
1003 }
1004 
1005 static void
1006 bstp_enable_port(struct bstp_state *bs, struct bstp_port *bp)
1007 {
1008 	bstp_initialize_port(bs, bp);
1009 	bstp_port_state_selection(bs);
1010 }
1011 
1012 static void
1013 bstp_disable_port(struct bstp_state *bs, struct bstp_port *bp)
1014 {
1015 	int root;
1016 
1017 	BSTP_LOCK_ASSERT(bs);
1018 
1019 	root = bstp_root_bridge(bs);
1020 	bstp_become_designated_port(bs, bp);
1021 	bstp_set_port_state(bp, BSTP_IFSTATE_DISABLED);
1022 	bp->bp_topology_change_acknowledge = 0;
1023 	bp->bp_config_pending = 0;
1024 	bstp_timer_stop(&bp->bp_message_age_timer);
1025 	bstp_timer_stop(&bp->bp_forward_delay_timer);
1026 	bstp_configuration_update(bs);
1027 	bstp_port_state_selection(bs);
1028 
1029 	if (bstp_root_bridge(bs) && (root == 0)) {
1030 		bs->bs_max_age = bs->bs_bridge_max_age;
1031 		bs->bs_hello_time = bs->bs_bridge_hello_time;
1032 		bs->bs_forward_delay = bs->bs_bridge_forward_delay;
1033 
1034 		bstp_topology_change_detection(bs);
1035 		bstp_timer_stop(&bs->bs_tcn_timer);
1036 		bstp_config_bpdu_generation(bs);
1037 		bstp_timer_start(&bs->bs_hello_timer, 0);
1038 	}
1039 }
1040 
1041 #ifdef notused
1042 static void
1043 bstp_set_bridge_priority(struct bstp_state *bs, uint64_t new_bridge_id)
1044 {
1045 	struct bstp_port *bp;
1046 	int root;
1047 
1048 	BSTP_LOCK_ASSERT(bs);
1049 
1050 	root = bstp_root_bridge(bs);
1051 
1052 	LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
1053 		if (bstp_designated_port(bs, bp))
1054 			bp->bp_designated_bridge = new_bridge_id;
1055 	}
1056 
1057 	bs->bs_bridge_id = new_bridge_id;
1058 
1059 	bstp_configuration_update(bs);
1060 	bstp_port_state_selection(bs);
1061 
1062 	if (bstp_root_bridge(bs) && (root == 0)) {
1063 		bs->bs_max_age = bs->bs_bridge_max_age;
1064 		bs->bs_hello_time = bs->bs_bridge_hello_time;
1065 		bs->bs_forward_delay = bs->bs_bridge_forward_delay;
1066 
1067 		bstp_topology_change_detection(bs);
1068 		bstp_timer_stop(&bs->bs_tcn_timer);
1069 		bstp_config_bpdu_generation(bs);
1070 		bstp_timer_start(&bs->bs_hello_timer, 0);
1071 	}
1072 }
1073 
1074 static void
1075 bstp_set_port_priority(struct bstp_state *bs, struct bstp_port *bp,
1076     uint16_t new_port_id)
1077 {
1078 	if (bstp_designated_port(bs, bp))
1079 		bp->bp_designated_port = new_port_id;
1080 
1081 	bp->bp_port_id = new_port_id;
1082 
1083 	if ((bs->bs_bridge_id == bp->bp_designated_bridge) &&
1084 	    (bp->bp_port_id < bp->bp_designated_port)) {
1085 		bstp_become_designated_port(bs, bp);
1086 		bstp_port_state_selection(bs);
1087 	}
1088 }
1089 
1090 static void
1091 bstp_set_path_cost(struct bstp_state *bs, struct bstp_port *bp,
1092     uint32_t path_cost)
1093 {
1094 	bp->bp_path_cost = path_cost;
1095 	bstp_configuration_update(bs);
1096 	bstp_port_state_selection(bs);
1097 }
1098 
1099 static void
1100 bstp_enable_change_detection(struct bstp_port *bp)
1101 {
1102 	bp->bp_change_detection_enabled = 1;
1103 }
1104 
1105 static void
1106 bstp_disable_change_detection(struct bstp_port *bp)
1107 {
1108 	bp->bp_change_detection_enabled = 0;
1109 }
1110 #endif /* notused */
1111 
1112 static void
1113 bstp_enqueue(struct ifnet *dst_ifp, struct mbuf *m)
1114 {
1115 	int err = 0;
1116 
1117 	IFQ_ENQUEUE(&dst_ifp->if_snd, m, err);
1118 
1119 	if ((dst_ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0)
1120 		(*dst_ifp->if_start)(dst_ifp);
1121 }
1122 
1123 void
1124 bstp_linkstate(struct ifnet *ifp, int state)
1125 {
1126 	struct bstp_state *bs;
1127 	struct bstp_port *bp;
1128 
1129 	/*
1130 	 * It would be nice if the ifnet had a pointer to the bstp_port so we
1131 	 * didnt need to search for it, but that may be an overkill. In reality
1132 	 * this is fast and doesnt get called often.
1133 	 */
1134 	mtx_lock(&bstp_list_mtx);
1135 	LIST_FOREACH(bs, &bstp_list, bs_list) {
1136 		BSTP_LOCK(bs);
1137 		LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
1138 			if (bp->bp_ifp == ifp) {
1139 				bstp_ifupdstatus(bs, bp);
1140 				/* it only exists once so return */
1141 				BSTP_UNLOCK(bs);
1142 				mtx_unlock(&bstp_list_mtx);
1143 				return;
1144 			}
1145 		}
1146 		BSTP_UNLOCK(bs);
1147 	}
1148 	mtx_unlock(&bstp_list_mtx);
1149 }
1150 
1151 static void
1152 bstp_ifupdstatus(struct bstp_state *bs, struct bstp_port *bp)
1153 {
1154 	struct ifnet *ifp = bp->bp_ifp;
1155 	struct ifmediareq ifmr;
1156 	int error = 0;
1157 
1158 	BSTP_LOCK_ASSERT(bs);
1159 
1160 	bzero((char *)&ifmr, sizeof(ifmr));
1161 	error = (*ifp->if_ioctl)(ifp, SIOCGIFMEDIA, (caddr_t)&ifmr);
1162 
1163 	if ((error == 0) && (ifp->if_flags & IFF_UP)) {
1164 		if (ifmr.ifm_status & IFM_ACTIVE) {
1165 			if (bp->bp_state == BSTP_IFSTATE_DISABLED)
1166 				bstp_enable_port(bs, bp);
1167 
1168 		} else {
1169 			if (bp->bp_state != BSTP_IFSTATE_DISABLED)
1170 				bstp_disable_port(bs, bp);
1171 		}
1172 		return;
1173 	}
1174 
1175 	if (bp->bp_state != BSTP_IFSTATE_DISABLED)
1176 		bstp_disable_port(bs, bp);
1177 }
1178 
1179 static void
1180 bstp_tick(void *arg)
1181 {
1182 	struct bstp_state *bs = arg;
1183 	struct bstp_port *bp;
1184 
1185 	BSTP_LOCK_ASSERT(bs);
1186 
1187 	/* slow timer to catch missed link events */
1188 	if (bstp_timer_expired(&bs->bs_link_timer, BSTP_LINK_TIMER)) {
1189 		LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
1190 			bstp_ifupdstatus(bs, bp);
1191 		}
1192 		bstp_timer_start(&bs->bs_link_timer, 0);
1193 	}
1194 
1195 	if (bstp_timer_expired(&bs->bs_hello_timer, bs->bs_hello_time))
1196 		bstp_hello_timer_expiry(bs);
1197 
1198 	if (bstp_timer_expired(&bs->bs_tcn_timer, bs->bs_bridge_hello_time))
1199 		bstp_tcn_timer_expiry(bs);
1200 
1201 	if (bstp_timer_expired(&bs->bs_topology_change_timer,
1202 	    bs->bs_topology_change_time))
1203 		bstp_topology_change_timer_expiry(bs);
1204 
1205 	LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
1206 		if (bstp_timer_expired(&bp->bp_message_age_timer,
1207 		    bs->bs_max_age))
1208 			bstp_message_age_timer_expiry(bs, bp);
1209 	}
1210 
1211 	LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
1212 		if (bstp_timer_expired(&bp->bp_forward_delay_timer,
1213 		    bs->bs_forward_delay))
1214 			bstp_forward_delay_timer_expiry(bs, bp);
1215 
1216 		if (bstp_timer_expired(&bp->bp_hold_timer,
1217 		    bs->bs_hold_time))
1218 			bstp_hold_timer_expiry(bs, bp);
1219 	}
1220 
1221 	callout_reset(&bs->bs_bstpcallout, hz, bstp_tick, bs);
1222 }
1223 
1224 static void
1225 bstp_timer_start(struct bstp_timer *t, uint16_t v)
1226 {
1227 	t->value = v;
1228 	t->active = 1;
1229 }
1230 
1231 static void
1232 bstp_timer_stop(struct bstp_timer *t)
1233 {
1234 	t->value = 0;
1235 	t->active = 0;
1236 }
1237 
1238 static int
1239 bstp_timer_expired(struct bstp_timer *t, uint16_t v)
1240 {
1241 	if (t->active == 0)
1242 		return (0);
1243 	t->value += BSTP_TICK_VAL;
1244 	if (t->value >= v) {
1245 		bstp_timer_stop(t);
1246 		return (1);
1247 	}
1248 	return (0);
1249 
1250 }
1251 
1252 int
1253 bstp_add(struct bstp_state *bs, struct bstp_port *bp, struct ifnet *ifp)
1254 {
1255 	KASSERT(bp->bp_active == 0, ("already a bstp member"));
1256 
1257 	switch (ifp->if_type) {
1258 		case IFT_ETHER:	/* These can do spanning tree. */
1259 			break;
1260 		default:
1261 			/* Nothing else can. */
1262 			return (EINVAL);
1263 	}
1264 
1265 	BSTP_LOCK(bs);
1266 	bp->bp_ifp = ifp;
1267 	bp->bp_bs = bs;
1268 	bp->bp_active = 1;
1269 	bp->bp_priority = BSTP_DEFAULT_PORT_PRIORITY;
1270 	bp->bp_path_cost = BSTP_DEFAULT_PATH_COST;
1271 
1272 	LIST_INSERT_HEAD(&bs->bs_bplist, bp, bp_next);
1273 	TASK_INIT(&bp->bp_statetask, 0, bstp_state_change, bp);
1274 	BSTP_UNLOCK(bs);
1275 	bstp_reinit(bs);
1276 
1277 	return (0);
1278 }
1279 
1280 void
1281 bstp_delete(struct bstp_port *bp)
1282 {
1283 	struct bstp_state *bs = bp->bp_bs;
1284 
1285 	KASSERT(bp->bp_active == 1, ("not a bstp member"));
1286 
1287 	BSTP_LOCK(bs);
1288 	if (bp->bp_state != BSTP_IFSTATE_DISABLED)
1289 		bstp_disable_port(bs, bp);
1290 	LIST_REMOVE(bp, bp_next);
1291 	BSTP_UNLOCK(bs);
1292 	bp->bp_bs = NULL;
1293 	bp->bp_active = 0;
1294 
1295 	bstp_reinit(bs);
1296 }
1297 
1298 /*
1299  * The bstp_port structure is about to be freed by the parent bridge.
1300  */
1301 void
1302 bstp_drain(struct bstp_port *bp)
1303 {
1304 	KASSERT(bp->bp_active == 0, ("port is still attached"));
1305 	taskqueue_drain(taskqueue_swi, &bp->bp_statetask);
1306 }
1307