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