xref: /openbsd-src/sys/net/bridgestp.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: bridgestp.c,v 1.7 2001/06/27 06:07:37 kjc 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 
34 /*
35  * Implementation of the spanning tree protocol as defined in
36  * ISO/IEC Final DIS 15802-3 (IEEE P802.1D/D17), May 25, 1998.
37  * (In English: IEEE 802.1D, Draft 17, 1998)
38  */
39 
40 #include "bridge.h"
41 
42 #if NBRIDGE > 0
43 
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/mbuf.h>
47 #include <sys/socket.h>
48 #include <sys/ioctl.h>
49 #include <sys/device.h>
50 #include <sys/kernel.h>
51 #include <sys/timeout.h>
52 
53 #include <net/if.h>
54 #include <net/if_types.h>
55 #include <net/if_llc.h>
56 #include <net/if_media.h>
57 #include <net/route.h>
58 #include <net/netisr.h>
59 
60 #ifdef INET
61 #include <netinet/in.h>
62 #include <netinet/in_systm.h>
63 #include <netinet/in_var.h>
64 #include <netinet/ip.h>
65 #include <netinet/if_ether.h>
66 #endif
67 
68 #if NBPFILTER > 0
69 #include <net/bpf.h>
70 #endif
71 
72 #include <net/if_bridge.h>
73 
74 /* BPDU message types */
75 #define	BSTP_MSGTYPE_CFG	0x00		/* Configuration */
76 #define	BSTP_MSGTYPE_TCN	0x80		/* Topology chg notification */
77 
78 /* BPDU flags */
79 #define	BSTP_FLAG_TC		0x01		/* Topology change */
80 #define	BSTP_FLAG_TCA		0x80		/* Topology change ack */
81 
82 #define	BSTP_MESSAGE_AGE_INCR	(1 * 256)	/* in 256ths of a second */
83 #define	BSTP_TICK_VAL		(1 * 256)	/* in 256ths of a second */
84 
85 /*
86  * Because BPDU's do not make nicely aligned structures, two different
87  * declarations are used: bstp_?bpdu (wire representation, packed) and
88  * bstp_*_unit (internal, nicely aligned version).
89  */
90 
91 /* configuration bridge protocol data unit */
92 struct bstp_cbpdu {
93 	u_int8_t	cbu_dsap;		/* LLC: destination sap */
94 	u_int8_t	cbu_ssap;		/* LLC: source sap */
95 	u_int8_t	cbu_ctl;		/* LLC: control */
96 	u_int16_t	cbu_protoid;		/* protocol id */
97 	u_int8_t	cbu_protover;		/* protocol version */
98 	u_int8_t	cbu_bpdutype;		/* message type */
99 	u_int8_t	cbu_flags;		/* flags (below) */
100 
101 	/* root id */
102 	u_int16_t	cbu_rootpri;		/* root priority */
103 	u_int8_t	cbu_rootaddr[6];	/* root address */
104 
105 	u_int32_t	cbu_rootpathcost;	/* root path cost */
106 
107 	/* bridge id */
108 	u_int16_t	cbu_bridgepri;		/* bridge priority */
109 	u_int8_t	cbu_bridgeaddr[6];	/* bridge address */
110 
111 	u_int16_t	cbu_portid;		/* port id */
112 	u_int16_t	cbu_messageage;		/* current message age */
113 	u_int16_t	cbu_maxage;		/* maximum age */
114 	u_int16_t	cbu_hellotime;		/* hello time */
115 	u_int16_t	cbu_forwarddelay;	/* forwarding delay */
116 } __attribute__((__packed__));
117 
118 /* topology change notification bridge protocol data unit */
119 struct bstp_tbpdu {
120 	u_int8_t	tbu_dsap;		/* LLC: destination sap */
121 	u_int8_t	tbu_ssap;		/* LLC: source sap */
122 	u_int8_t	tbu_ctl;		/* LLC: control */
123 	u_int16_t	tbu_protoid;		/* protocol id */
124 	u_int8_t	tbu_protover;		/* protocol version */
125 	u_int8_t	tbu_bpdutype;		/* message type */
126 } __attribute__((__packed__));
127 
128 u_int8_t bstp_etheraddr[] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
129 
130 void bstp_initialization __P((struct bridge_softc *));
131 void bstp_stop __P((struct bridge_softc *));
132 void bstp_initialize_port __P((struct bridge_softc *, struct bridge_iflist *));
133 void bstp_ifupdstatus __P((struct bridge_softc *, struct bridge_iflist *));
134 void bstp_enable_port __P((struct bridge_softc *, struct bridge_iflist *));
135 void bstp_disable_port __P((struct bridge_softc *, struct bridge_iflist *));
136 void bstp_enable_change_detection __P((struct bridge_iflist *));
137 void bstp_disable_change_detection __P((struct bridge_iflist *));
138 int bstp_root_bridge __P((struct bridge_softc *sc));
139 int bstp_supersedes_port_info __P((struct bridge_softc *, struct bridge_iflist *, struct bstp_config_unit *));
140 int bstp_designated_port __P((struct bridge_softc *, struct bridge_iflist *));
141 int bstp_designated_for_some_port __P((struct bridge_softc *));
142 void bstp_transmit_config __P((struct bridge_softc *, struct bridge_iflist *));
143 void bstp_transmit_tcn __P((struct bridge_softc *));
144 struct mbuf *bstp_input __P((struct bridge_softc *, struct ifnet *,
145     struct ether_header *, struct mbuf *));
146 void bstp_received_config_bpdu __P((struct bridge_softc *, struct bridge_iflist *, struct bstp_config_unit *));
147 void bstp_received_tcn_bpdu __P((struct bridge_softc *, struct bridge_iflist *, struct bstp_tcn_unit *));
148 void bstp_record_config_information __P((struct bridge_softc *, struct bridge_iflist *, struct bstp_config_unit *));
149 void bstp_record_config_timeout_values __P((struct bridge_softc *, struct bstp_config_unit *));
150 void bstp_config_bpdu_generation __P((struct bridge_softc *));
151 void bstp_send_config_bpdu __P((struct bridge_iflist *, struct bstp_config_unit *));
152 void bstp_configuration_update __P((struct bridge_softc *));
153 void bstp_root_selection __P((struct bridge_softc *));
154 void bstp_designated_port_selection __P((struct bridge_softc *));
155 void bstp_become_designated_port __P((struct bridge_softc *, struct bridge_iflist *));
156 void bstp_port_state_selection __P((struct bridge_softc *));
157 void bstp_make_forwarding __P((struct bridge_softc *, struct bridge_iflist *));
158 void bstp_make_blocking __P((struct bridge_softc *, struct bridge_iflist *));
159 void bstp_set_port_state __P((struct bridge_iflist *, u_int8_t));
160 void bstp_set_bridge_priority __P((struct bridge_softc *, u_int64_t));
161 void bstp_set_port_priority __P((struct bridge_softc *, struct bridge_iflist *, u_int16_t));
162 void bstp_set_path_cost __P((struct bridge_softc *, struct bridge_iflist *, u_int32_t));
163 void bstp_topology_change_detection __P((struct bridge_softc *));
164 void bstp_topology_change_acknowledged __P((struct bridge_softc *));
165 void bstp_acknowledge_topology_change __P((struct bridge_softc *, struct bridge_iflist *));
166 
167 void bstp_tick __P((void *));
168 void bstp_timer_start __P((struct bridge_timer *, u_int16_t));
169 void bstp_timer_stop __P((struct bridge_timer *));
170 int bstp_timer_expired __P((struct bridge_timer *, u_int16_t));
171 
172 void bstp_hold_timer_expiry __P((struct bridge_softc *, struct bridge_iflist *));
173 void bstp_message_age_timer_expiry __P((struct bridge_softc *, struct bridge_iflist *));
174 void bstp_forward_delay_timer_expiry __P((struct bridge_softc *, struct bridge_iflist *));
175 void bstp_topology_change_timer_expiry __P((struct bridge_softc *));
176 void bstp_tcn_timer_expiry __P((struct bridge_softc *));
177 void bstp_hello_timer_expiry __P((struct bridge_softc *));
178 
179 void
180 bstp_transmit_config(sc, bif)
181 	struct bridge_softc *sc;
182 	struct bridge_iflist *bif;
183 {
184 	if (bif->bif_hold_timer.active) {
185 		bif->bif_config_pending = 1;
186 		return;
187 	}
188 
189 	bif->bif_config_bpdu.cu_message_type = BSTP_MSGTYPE_CFG;
190 	bif->bif_config_bpdu.cu_rootid = sc->sc_designated_root;
191 	bif->bif_config_bpdu.cu_root_path_cost = sc->sc_root_path_cost;
192 	bif->bif_config_bpdu.cu_bridge_id = sc->sc_bridge_id;
193 	bif->bif_config_bpdu.cu_port_id = bif->bif_port_id;
194 
195 	if (bstp_root_bridge(sc))
196 		bif->bif_config_bpdu.cu_message_age = 0;
197 	else
198 		bif->bif_config_bpdu.cu_message_age =
199 		    sc->sc_root_port->bif_message_age_timer.value +
200 		    BSTP_MESSAGE_AGE_INCR;
201 
202 	bif->bif_config_bpdu.cu_max_age = sc->sc_max_age;
203 	bif->bif_config_bpdu.cu_hello_time = sc->sc_hello_time;
204 	bif->bif_config_bpdu.cu_forward_delay = sc->sc_forward_delay;
205 	bif->bif_config_bpdu.cu_topology_change_acknowledgment
206 	    = bif->bif_topology_change_acknowledge;
207 	bif->bif_config_bpdu.cu_topology_change = sc->sc_topology_change;
208 
209 	if (bif->bif_config_bpdu.cu_message_age < sc->sc_max_age) {
210 		bif->bif_topology_change_acknowledge = 0;
211 		bif->bif_config_pending = 0;
212 		bstp_send_config_bpdu(bif, &bif->bif_config_bpdu);
213 		bstp_timer_start(&bif->bif_hold_timer, 0);
214 	}
215 }
216 
217 void
218 bstp_send_config_bpdu(bif, cu)
219 	struct bridge_iflist *bif;
220 	struct bstp_config_unit *cu;
221 {
222 	struct arpcom *arp;
223 	struct ifnet *ifp;
224 	struct mbuf *m;
225 	struct ether_header eh;
226 	struct bstp_cbpdu bpdu;
227 	int s, error;
228 
229 	s = splimp();
230 	ifp = bif->ifp;
231 	arp = (struct arpcom *)ifp;
232 
233 	if ((ifp->if_flags & IFF_RUNNING) == 0) {
234 		splx(s);
235 		return;
236 	}
237 #ifdef ALTQ
238 	if (!ALTQ_IS_ENABLED(&ifp->if_snd))
239 #endif
240 	if (IF_QFULL(&ifp->if_snd)) {
241 		splx(s);
242 		return;
243 	}
244 
245 	MGETHDR(m, M_DONTWAIT, MT_DATA);
246 	if (m == NULL) {
247 		splx(s);
248 		return;
249 	}
250 	m->m_pkthdr.rcvif = ifp;
251 	m->m_pkthdr.len = sizeof(eh) + sizeof(bpdu);
252 	m->m_len = m->m_pkthdr.len;
253 
254 	bpdu.cbu_ssap = bpdu.cbu_dsap = LLC_8021D_LSAP;
255 	bpdu.cbu_ctl = LLC_UI;
256 	bpdu.cbu_protoid = htons(0);
257 	bpdu.cbu_protover = 0;
258 	bpdu.cbu_bpdutype = cu->cu_message_type;
259 	bpdu.cbu_flags = (cu->cu_topology_change ? BSTP_FLAG_TC : 0) |
260 	    (cu->cu_topology_change_acknowledgment ? BSTP_FLAG_TCA : 0);
261 
262 	bpdu.cbu_rootpri = htons(cu->cu_rootid >> 48);
263 	bpdu.cbu_rootaddr[0] = cu->cu_rootid >> 40;
264 	bpdu.cbu_rootaddr[1] = cu->cu_rootid >> 32;
265 	bpdu.cbu_rootaddr[2] = cu->cu_rootid >> 24;
266 	bpdu.cbu_rootaddr[3] = cu->cu_rootid >> 16;
267 	bpdu.cbu_rootaddr[4] = cu->cu_rootid >> 8;
268 	bpdu.cbu_rootaddr[5] = cu->cu_rootid >> 0;
269 
270 	bpdu.cbu_rootpathcost = htonl(cu->cu_root_path_cost);
271 
272 	bpdu.cbu_bridgepri = htons(cu->cu_rootid >> 48);
273 	bpdu.cbu_bridgeaddr[0] = cu->cu_rootid >> 40;
274 	bpdu.cbu_bridgeaddr[1] = cu->cu_rootid >> 32;
275 	bpdu.cbu_bridgeaddr[2] = cu->cu_rootid >> 24;
276 	bpdu.cbu_bridgeaddr[3] = cu->cu_rootid >> 16;
277 	bpdu.cbu_bridgeaddr[4] = cu->cu_rootid >> 8;
278 	bpdu.cbu_bridgeaddr[5] = cu->cu_rootid >> 0;
279 
280 	bpdu.cbu_portid = htons(cu->cu_port_id);
281 	bpdu.cbu_messageage = htons(cu->cu_message_age);
282 	bpdu.cbu_maxage = htons(cu->cu_max_age);
283 	bpdu.cbu_hellotime = htons(cu->cu_hello_time);
284 	bpdu.cbu_forwarddelay = htons(cu->cu_forward_delay);
285 
286 	bcopy(arp->ac_enaddr, eh.ether_shost, ETHER_ADDR_LEN);
287 	bcopy(bstp_etheraddr, eh.ether_dhost, ETHER_ADDR_LEN);
288 	eh.ether_type = htons(sizeof(bpdu));
289 
290 	bcopy(&eh, m->m_data, sizeof(eh));
291 	bcopy(&bpdu, m->m_data + sizeof(eh), sizeof(bpdu));
292 
293 	IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
294 	if (error == 0 && (ifp->if_flags & IFF_OACTIVE) == 0)
295 		(*ifp->if_start)(ifp);
296 	splx(s);
297 }
298 
299 int
300 bstp_root_bridge(sc)
301 	struct bridge_softc *sc;
302 {
303 	return (sc->sc_designated_root == sc->sc_bridge_id);
304 }
305 
306 int
307 bstp_supersedes_port_info(sc, bif, cu)
308 	struct bridge_softc *sc;
309 	struct bridge_iflist *bif;
310 	struct bstp_config_unit *cu;
311 {
312 	if (cu->cu_rootid < bif->bif_designated_root)
313 		return (1);
314 	if (cu->cu_rootid > bif->bif_designated_root)
315 		return (0);
316 
317 	if (cu->cu_root_path_cost < bif->bif_designated_cost)
318 		return (1);
319 	if (cu->cu_root_path_cost > bif->bif_designated_cost)
320 		return (0);
321 
322 	if (cu->cu_bridge_id < bif->bif_designated_bridge)
323 		return (1);
324 	if (cu->cu_bridge_id > bif->bif_designated_bridge)
325 		return (0);
326 
327 	if (sc->sc_bridge_id != cu->cu_bridge_id)
328 		return (1);
329 	if (cu->cu_port_id <= bif->bif_designated_port)
330 		return (1);
331 	return (0);
332 }
333 
334 void
335 bstp_record_config_information(sc, bif, cu)
336 	struct bridge_softc *sc;
337 	struct bridge_iflist *bif;
338 	struct bstp_config_unit *cu;
339 {
340 	bif->bif_designated_root = cu->cu_rootid;
341 	bif->bif_designated_cost = cu->cu_root_path_cost;
342 	bif->bif_designated_bridge = cu->cu_bridge_id;
343 	bif->bif_designated_port = cu->cu_port_id;
344 	bstp_timer_start(&bif->bif_message_age_timer, cu->cu_message_age);
345 }
346 
347 void
348 bstp_record_config_timeout_values(sc, config)
349 	struct bridge_softc *sc;
350 	struct bstp_config_unit *config;
351 {
352 	sc->sc_max_age = config->cu_max_age;
353 	sc->sc_hello_time = config->cu_hello_time;
354 	sc->sc_forward_delay = config->cu_forward_delay;
355 	sc->sc_topology_change = config->cu_topology_change;
356 }
357 
358 void
359 bstp_config_bpdu_generation(sc)
360 	struct bridge_softc *sc;
361 {
362 	struct bridge_iflist *bif;
363 
364 	LIST_FOREACH(bif, &sc->sc_iflist, next) {
365 		if (!(bif->bif_flags & IFBIF_STP))
366 			continue;
367 		if (bstp_designated_port(sc, bif) &&
368 		    (bif->bif_state != BSTP_IFSTATE_DISABLED))
369 			bstp_transmit_config(sc, bif);
370 	}
371 }
372 
373 int
374 bstp_designated_port(sc, bif)
375 	struct bridge_softc *sc;
376 	struct bridge_iflist *bif;
377 {
378 	return ((bif->bif_designated_bridge == sc->sc_bridge_id)
379 	    && (bif->bif_designated_port == bif->bif_port_id));
380 }
381 
382 void
383 bstp_transmit_tcn(sc)
384 	struct bridge_softc *sc;
385 {
386 	struct bstp_tbpdu bpdu;
387 	struct bridge_iflist *bif = sc->sc_root_port;
388 	struct ifnet *ifp = bif->ifp;
389 	struct arpcom *arp = (struct arpcom *)ifp;
390 	struct ether_header *eh;
391 	struct mbuf *m;
392 	int s, error;
393 
394 	MGETHDR(m, M_DONTWAIT, MT_DATA);
395 	if (m == NULL)
396 		return;
397 	m->m_pkthdr.rcvif = ifp;
398 	m->m_pkthdr.len = sizeof(eh) + sizeof(bpdu);
399 	m->m_len = m->m_pkthdr.len;
400 
401 	eh = mtod(m, struct ether_header *);
402 	bcopy(arp->ac_enaddr, eh->ether_shost, ETHER_ADDR_LEN);
403 	bcopy(bstp_etheraddr, eh->ether_dhost, ETHER_ADDR_LEN);
404 	eh->ether_type = htons(sizeof(bpdu));
405 
406 	bpdu.tbu_ssap = bpdu.tbu_dsap = LLC_8021D_LSAP;
407 	bpdu.tbu_ctl = LLC_UI;
408 	bpdu.tbu_protoid = 0;
409 	bpdu.tbu_protover = 0;
410 	bpdu.tbu_bpdutype = BSTP_MSGTYPE_TCN;
411 	bcopy(&bpdu, m->m_data + sizeof(eh), sizeof(bpdu));
412 
413 	s = splimp();
414 	if ((ifp->if_flags & IFF_RUNNING) == 0)
415 		goto out;
416 	IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
417 	if (error == 0 && (ifp->if_flags & IFF_OACTIVE) == 0)
418 		(*ifp->if_start)(ifp);
419 	m = NULL;
420 
421 out:
422 	splx(s);
423 	if (m != NULL)
424 		m_freem(m);
425 }
426 
427 void
428 bstp_configuration_update(sc)
429 	struct bridge_softc *sc;
430 {
431 	bstp_root_selection(sc);
432 	bstp_designated_port_selection(sc);
433 }
434 
435 void
436 bstp_root_selection(sc)
437 	struct bridge_softc *sc;
438 {
439 	struct bridge_iflist *root_port = NULL, *bif;
440 
441 	LIST_FOREACH(bif, &sc->sc_iflist, next) {
442 		if (!(bif->bif_flags & IFBIF_STP))
443 			continue;
444 		if (bstp_designated_port(sc, bif))
445 			continue;
446 		if (bif->bif_state == BSTP_IFSTATE_DISABLED)
447 			continue;
448 		if (bif->bif_designated_root >= sc->sc_bridge_id)
449 			continue;
450 		if (root_port == NULL)
451 			goto set_port;
452 
453 		if (bif->bif_designated_root < root_port->bif_designated_root)
454 			goto set_port;
455 		if (bif->bif_designated_root > root_port->bif_designated_root)
456 			continue;
457 
458 		if ((bif->bif_designated_cost + bif->bif_path_cost) <
459 		    (root_port->bif_designated_cost + root_port->bif_path_cost))
460 			goto set_port;
461 		if ((bif->bif_designated_cost + bif->bif_path_cost) >
462 		    (root_port->bif_designated_cost + root_port->bif_path_cost))
463 			continue;
464 
465 		if (bif->bif_designated_bridge < root_port->bif_designated_bridge)
466 			goto set_port;
467 		if (bif->bif_designated_bridge > root_port->bif_designated_bridge)
468 			continue;
469 
470 		if (bif->bif_designated_port < root_port->bif_designated_port)
471 			goto set_port;
472 		if (bif->bif_designated_port > root_port->bif_designated_port)
473 			continue;
474 
475 		if (bif->bif_port_id >= root_port->bif_port_id)
476 			continue;
477 set_port:
478 		root_port = bif;
479 	}
480 
481 	sc->sc_root_port = root_port;
482 	if (root_port == NULL) {
483 		sc->sc_designated_root = sc->sc_bridge_id;
484 		sc->sc_root_path_cost = 0;
485 	} else {
486 		sc->sc_designated_root = root_port->bif_designated_root;
487 		sc->sc_root_path_cost = root_port->bif_designated_cost +
488 		    root_port->bif_path_cost;
489 	}
490 }
491 
492 void
493 bstp_designated_port_selection(sc)
494 	struct bridge_softc *sc;
495 {
496 	struct bridge_iflist *bif;
497 
498 	LIST_FOREACH(bif, &sc->sc_iflist, next) {
499 		if (!(bif->bif_flags & IFBIF_STP))
500 			continue;
501 		if (bstp_designated_port(sc, bif))
502 			goto designated;
503 		if (bif->bif_designated_root != sc->sc_designated_root)
504 			goto designated;
505 
506 		if (sc->sc_root_path_cost < bif->bif_designated_cost)
507 			goto designated;
508 		if (sc->sc_root_path_cost > bif->bif_designated_cost)
509 			continue;
510 
511 		if (sc->sc_bridge_id < bif->bif_designated_bridge)
512 			goto designated;
513 		if (sc->sc_bridge_id > bif->bif_designated_bridge)
514 			continue;
515 
516 		if (bif->bif_port_id > bif->bif_designated_port)
517 			continue;
518 designated:
519 		bstp_become_designated_port(sc, bif);
520 	}
521 }
522 
523 void
524 bstp_become_designated_port(sc, bif)
525 	struct bridge_softc *sc;
526 	struct bridge_iflist *bif;
527 {
528 	bif->bif_designated_root = sc->sc_designated_root;
529 	bif->bif_designated_cost = sc->sc_root_path_cost;
530 	bif->bif_designated_bridge = sc->sc_bridge_id;
531 	bif->bif_designated_port = bif->bif_port_id;
532 }
533 
534 void
535 bstp_port_state_selection(sc)
536 	struct bridge_softc *sc;
537 {
538 	struct bridge_iflist *bif;
539 
540 	LIST_FOREACH(bif, &sc->sc_iflist, next) {
541 		if (!(bif->bif_flags & IFBIF_STP))
542 			continue;
543 		if (bif == sc->sc_root_port) {
544 			bif->bif_config_pending = 0;
545 			bif->bif_topology_change_acknowledge = 0;
546 			bstp_make_forwarding(sc, bif);
547 		} else if (bstp_designated_port(sc, bif)) {
548 			bstp_timer_stop(&bif->bif_message_age_timer);
549 			bstp_make_forwarding(sc, bif);
550 		} else {
551 			bif->bif_config_pending = 0;
552 			bif->bif_topology_change_acknowledge = 0;
553 			bstp_make_blocking(sc, bif);
554 		}
555 	}
556 }
557 
558 void
559 bstp_make_forwarding(sc, bif)
560 	struct bridge_softc *sc;
561 	struct bridge_iflist *bif;
562 {
563 	if (bif->bif_state == BSTP_IFSTATE_BLOCKING) {
564 		bstp_set_port_state(bif, BSTP_IFSTATE_LISTENING);
565 		bstp_timer_start(&bif->bif_forward_delay_timer, 0);
566 	}
567 }
568 
569 void
570 bstp_make_blocking(sc, bif)
571 	struct bridge_softc *sc;
572 	struct bridge_iflist *bif;
573 {
574 	if ((bif->bif_state != BSTP_IFSTATE_DISABLED) &&
575 	    (bif->bif_state != BSTP_IFSTATE_BLOCKING)) {
576 		if ((bif->bif_state == BSTP_IFSTATE_FORWARDING) ||
577 		    (bif->bif_state == BSTP_IFSTATE_LEARNING)) {
578 			if (bif->bif_change_detection_enabled) {
579 				bstp_topology_change_detection(sc);
580 			}
581 		}
582 		bstp_set_port_state(bif, BSTP_IFSTATE_BLOCKING);
583 		bstp_timer_stop(&bif->bif_forward_delay_timer);
584 	}
585 }
586 
587 void
588 bstp_set_port_state(bif, state)
589 	struct bridge_iflist *bif;
590 	u_int8_t state;
591 {
592 	bif->bif_state = state;
593 }
594 
595 void
596 bstp_topology_change_detection(sc)
597 	struct bridge_softc *sc;
598 {
599 	if (bstp_root_bridge(sc)) {
600 		sc->sc_topology_change = 1;
601 		bstp_timer_start(&sc->sc_topology_change_timer, 0);
602 	} else if (!sc->sc_topology_change_detected) {
603 		bstp_transmit_tcn(sc);
604 		bstp_timer_start(&sc->sc_tcn_timer, 0);
605 	}
606 	sc->sc_topology_change_detected = 1;
607 }
608 
609 void
610 bstp_topology_change_acknowledged(sc)
611 	struct bridge_softc *sc;
612 {
613 	sc->sc_topology_change_detected = 0;
614 	bstp_timer_stop(&sc->sc_tcn_timer);
615 }
616 
617 void
618 bstp_acknowledge_topology_change(sc, bif)
619 	struct bridge_softc *sc;
620 	struct bridge_iflist *bif;
621 {
622 	bif->bif_topology_change_acknowledge = 1;
623 	bstp_transmit_config(sc, bif);
624 }
625 
626 struct mbuf *
627 bstp_input(sc, ifp, eh, m)
628 	struct bridge_softc *sc;
629 	struct ifnet *ifp;
630 	struct ether_header *eh;
631 	struct mbuf *m;
632 {
633 	struct bridge_iflist *bif = NULL;
634 	struct bstp_tbpdu tpdu;
635 	struct bstp_cbpdu cpdu;
636 	struct bstp_config_unit cu;
637 	struct bstp_tcn_unit tu;
638 	u_int16_t len;
639 
640 	LIST_FOREACH(bif, &sc->sc_iflist, next) {
641 		if (!(bif->bif_flags & IFBIF_STP))
642 			continue;
643 		if (bif->ifp == ifp)
644 			break;
645 	}
646 	if (bif == NULL)
647 		goto out;
648 
649 	len = ntohs(eh->ether_type);
650 	if (len < sizeof(tpdu))
651 		goto out;
652 	if (m->m_pkthdr.len > len)
653 		m_adj(m, len - m->m_pkthdr.len);
654 	if ((m = m_pullup(m, sizeof(tpdu))) == NULL)
655 		goto out;
656 	bcopy(mtod(m, struct tpdu *), &tpdu, sizeof(tpdu));
657 
658 	if (tpdu.tbu_dsap != LLC_8021D_LSAP ||
659 	    tpdu.tbu_ssap != LLC_8021D_LSAP ||
660 	    tpdu.tbu_ctl != LLC_UI)
661 		goto out;
662 	if (tpdu.tbu_protoid != 0 || tpdu.tbu_protover != 0)
663 		goto out;
664 
665 	switch (tpdu.tbu_bpdutype) {
666 	case BSTP_MSGTYPE_TCN:
667 		tu.tu_message_type = tpdu.tbu_bpdutype;
668 		bstp_received_tcn_bpdu(sc, bif, &tu);
669 		break;
670 	case BSTP_MSGTYPE_CFG:
671 		if ((m = m_pullup(m, sizeof(cpdu))) == NULL)
672 			goto out;
673 		bcopy(mtod(m, struct bstp_cpdu *), &cpdu, sizeof(cpdu));
674 
675 		cu.cu_rootid =
676 		    (((u_int64_t)ntohs(cpdu.cbu_rootpri)) << 48) |
677 		    (((u_int64_t)cpdu.cbu_rootaddr[0]) << 40) |
678 		    (((u_int64_t)cpdu.cbu_rootaddr[1]) << 32) |
679 		    (((u_int64_t)cpdu.cbu_rootaddr[2]) << 24) |
680 		    (((u_int64_t)cpdu.cbu_rootaddr[3]) << 16) |
681 		    (((u_int64_t)cpdu.cbu_rootaddr[4]) << 8) |
682 		    (((u_int64_t)cpdu.cbu_rootaddr[5]) << 0);
683 
684 		cu.cu_bridge_id =
685 		    (((u_int64_t)ntohs(cpdu.cbu_bridgepri)) << 48) |
686 		    (((u_int64_t)cpdu.cbu_bridgeaddr[0]) << 40) |
687 		    (((u_int64_t)cpdu.cbu_bridgeaddr[1]) << 32) |
688 		    (((u_int64_t)cpdu.cbu_bridgeaddr[2]) << 24) |
689 		    (((u_int64_t)cpdu.cbu_bridgeaddr[3]) << 16) |
690 		    (((u_int64_t)cpdu.cbu_bridgeaddr[4]) << 8) |
691 		    (((u_int64_t)cpdu.cbu_bridgeaddr[5]) << 0);
692 
693 		cu.cu_root_path_cost = ntohl(cpdu.cbu_rootpathcost);
694 		cu.cu_message_age = ntohs(cpdu.cbu_messageage);
695 		cu.cu_max_age = ntohs(cpdu.cbu_maxage);
696 		cu.cu_hello_time = ntohs(cpdu.cbu_hellotime);
697 		cu.cu_forward_delay = ntohs(cpdu.cbu_forwarddelay);
698 		cu.cu_port_id = ntohs(cpdu.cbu_portid);
699 		cu.cu_message_type = cpdu.cbu_bpdutype;
700 		cu.cu_topology_change_acknowledgment =
701 		    (cpdu.cbu_flags & BSTP_FLAG_TCA) ? 1 : 0;
702 		cu.cu_topology_change =
703 		    (cpdu.cbu_flags & BSTP_FLAG_TC) ? 1 : 0;
704 		bstp_received_config_bpdu(sc, bif, &cu);
705 		break;
706 	default:
707 		goto out;
708 	}
709 
710 out:
711 	if (m)
712 		m_freem(m);
713 	return (NULL);
714 }
715 
716 void
717 bstp_received_config_bpdu(sc, bif, cu)
718 	struct bridge_softc *sc;
719 	struct bridge_iflist *bif;
720 	struct bstp_config_unit *cu;
721 {
722 	int root;
723 
724 	root = bstp_root_bridge(sc);
725 
726 	if (bif->bif_state != BSTP_IFSTATE_DISABLED) {
727 		if (bstp_supersedes_port_info(sc, bif, cu)) {
728 			bstp_record_config_information(sc, bif, cu);
729 			bstp_configuration_update(sc);
730 			bstp_port_state_selection(sc);
731 
732 			if ((!bstp_root_bridge(sc)) && root) {
733 				bstp_timer_stop(&sc->sc_hello_timer);
734 
735 				if (sc->sc_topology_change_detected) {
736 					bstp_timer_stop(&sc->sc_topology_change_timer);
737 					bstp_transmit_tcn(sc);
738 					bstp_timer_start(&sc->sc_tcn_timer, 0);
739 				}
740 			}
741 
742 			if (bif == sc->sc_root_port) {
743 				bstp_record_config_timeout_values(sc, cu);
744 				bstp_config_bpdu_generation(sc);
745 
746 				if (cu->cu_topology_change_acknowledgment)
747 					bstp_topology_change_acknowledged(sc);
748 			}
749 		}
750 		else if (bstp_designated_port(sc, bif))
751 			bstp_transmit_config(sc, bif);
752 	}
753 }
754 
755 void
756 bstp_received_tcn_bpdu(sc, bif, tcn)
757 	struct bridge_softc *sc;
758 	struct bridge_iflist *bif;
759 	struct bstp_tcn_unit *tcn;
760 {
761 	if (bif->bif_state != BSTP_IFSTATE_DISABLED &&
762 	    bstp_designated_port(sc, bif)) {
763 			bstp_topology_change_detection(sc);
764 			bstp_acknowledge_topology_change(sc, bif);
765 	}
766 }
767 
768 void
769 bstp_hello_timer_expiry(sc)
770 	struct bridge_softc *sc;
771 {
772 	bstp_config_bpdu_generation(sc);
773 	bstp_timer_start(&sc->sc_hello_timer, 0);
774 }
775 
776 void
777 bstp_message_age_timer_expiry(sc, bif)
778 	struct bridge_softc *sc;
779 	struct bridge_iflist *bif;
780 {
781 	int root;
782 
783 	root = bstp_root_bridge(sc);
784 	bstp_become_designated_port(sc, bif);
785 	bstp_configuration_update(sc);
786 	bstp_port_state_selection(sc);
787 
788 	if ((bstp_root_bridge(sc)) && (!root)) {
789 		sc->sc_max_age = sc->sc_bridge_max_age;
790 		sc->sc_hello_time = sc->sc_bridge_hello_time;
791 		sc->sc_forward_delay = sc->sc_bridge_forward_delay;
792 
793 		bstp_topology_change_detection(sc);
794 		bstp_timer_stop(&sc->sc_tcn_timer);
795 		bstp_config_bpdu_generation(sc);
796 		bstp_timer_start(&sc->sc_hello_timer, 0);
797 	}
798 }
799 
800 void
801 bstp_forward_delay_timer_expiry(sc, bif)
802 	struct bridge_softc *sc;
803 	struct bridge_iflist *bif;
804 {
805 	if (bif->bif_state == BSTP_IFSTATE_LISTENING) {
806 		bstp_set_port_state(bif, BSTP_IFSTATE_LEARNING);
807 		bstp_timer_start(&bif->bif_forward_delay_timer, 0);
808 	} else if (bif->bif_state == BSTP_IFSTATE_LEARNING) {
809 		bstp_set_port_state(bif, BSTP_IFSTATE_FORWARDING);
810 		if (bstp_designated_for_some_port(sc) &&
811 		    bif->bif_change_detection_enabled)
812 			bstp_topology_change_detection(sc);
813 	}
814 }
815 
816 int
817 bstp_designated_for_some_port(sc)
818 	struct bridge_softc *sc;
819 {
820 
821 	struct bridge_iflist *bif;
822 
823 	LIST_FOREACH(bif, &sc->sc_iflist, next) {
824 		if (!(bif->bif_flags & IFBIF_STP))
825 			continue;
826 		if (bif->bif_designated_bridge == sc->sc_bridge_id)
827 			return (1);
828 	}
829 	return (0);
830 }
831 
832 void
833 bstp_tcn_timer_expiry(sc)
834 	struct bridge_softc *sc;
835 {
836 	bstp_transmit_tcn(sc);
837 	bstp_timer_start(&sc->sc_tcn_timer, 0);
838 }
839 
840 void
841 bstp_topology_change_timer_expiry(sc)
842 	struct bridge_softc *sc;
843 {
844 	sc->sc_topology_change_detected = 0;
845 	sc->sc_topology_change = 0;
846 }
847 
848 void
849 bstp_hold_timer_expiry(sc, bif)
850 	struct bridge_softc *sc;
851 	struct bridge_iflist *bif;
852 {
853 	if (bif->bif_config_pending)
854 		bstp_transmit_config(sc, bif);
855 }
856 
857 void
858 bstp_initialization(sc)
859 	struct bridge_softc *sc;
860 {
861 	struct bridge_iflist *bif, *mif;
862 	struct arpcom *ac, *mac;
863 
864 	mif = NULL; mac = NULL;
865 	LIST_FOREACH(bif, &sc->sc_iflist, next) {
866 		if (!(bif->bif_flags & IFBIF_STP))
867 			continue;
868 		if (bif->ifp->if_type != IFT_ETHER)
869 			continue;
870 		bif->bif_port_id = (bif->bif_priority << 8) |
871 		    (bif->ifp->if_index & 0xff);
872 
873 		if (mif == NULL) {
874 			mif = bif;
875 			mac = (struct arpcom *)bif->ifp;
876 			continue;
877 		}
878 		ac = (struct arpcom *)bif->ifp;
879 		if (memcmp(ac->ac_enaddr, mac->ac_enaddr, ETHER_ADDR_LEN) < 0) {
880 			mif = bif;
881 			mac = (struct arpcom *)bif->ifp;
882 			continue;
883 		}
884 	}
885 	if (mif == NULL) {
886 		bstp_stop(sc);
887 		return;
888 	}
889 
890 	sc->sc_bridge_id =
891 	    (((u_int64_t)sc->sc_bridge_priority) << 48) |
892 	    (((u_int64_t)mac->ac_enaddr[0]) << 40) |
893 	    (((u_int64_t)mac->ac_enaddr[1]) << 32) |
894 	    (mac->ac_enaddr[2] << 24) | (mac->ac_enaddr[3] << 16) |
895 	    (mac->ac_enaddr[4] << 8) | (mac->ac_enaddr[5]);
896 
897 	sc->sc_designated_root = sc->sc_bridge_id;
898 	sc->sc_root_path_cost = 0;
899 	sc->sc_root_port = NULL;
900 
901 	sc->sc_max_age = sc->sc_bridge_max_age;
902 	sc->sc_hello_time = sc->sc_bridge_hello_time;
903 	sc->sc_forward_delay = sc->sc_bridge_forward_delay;
904 	sc->sc_topology_change_detected = 0;
905 	sc->sc_topology_change = 0;
906 	bstp_timer_stop(&sc->sc_tcn_timer);
907 	bstp_timer_stop(&sc->sc_topology_change_timer);
908 
909 	if (!timeout_initialized(&sc->sc_bstptimeout))
910 		timeout_set(&sc->sc_bstptimeout, bstp_tick, sc);
911 	if (!timeout_pending(&sc->sc_bstptimeout))
912 		timeout_add(&sc->sc_bstptimeout, hz);
913 
914 	LIST_FOREACH(bif, &sc->sc_iflist, next) {
915 		if (bif->bif_flags & IFBIF_STP)
916 			bstp_enable_port(sc, bif);
917 		else
918 			bstp_disable_port(sc, bif);
919 	}
920 
921 	bstp_port_state_selection(sc);
922 	bstp_config_bpdu_generation(sc);
923 	bstp_timer_start(&sc->sc_hello_timer, 0);
924 }
925 
926 void
927 bstp_stop(sc)
928 	struct bridge_softc *sc;
929 {
930 
931 	struct bridge_iflist *bif;
932 
933 	LIST_FOREACH(bif, &sc->sc_iflist, next) {
934 		bstp_set_port_state(bif, BSTP_IFSTATE_DISABLED);
935 		bstp_timer_stop(&bif->bif_hold_timer);
936 		bstp_timer_stop(&bif->bif_message_age_timer);
937 		bstp_timer_stop(&bif->bif_forward_delay_timer);
938 	}
939 
940 	if (timeout_initialized(&sc->sc_bstptimeout) &&
941 	    timeout_pending(&sc->sc_bstptimeout))
942 		timeout_del(&sc->sc_bstptimeout);
943 
944 	bstp_timer_stop(&sc->sc_topology_change_timer);
945 	bstp_timer_stop(&sc->sc_tcn_timer);
946 	bstp_timer_stop(&sc->sc_hello_timer);
947 
948 }
949 
950 void
951 bstp_initialize_port(sc, bif)
952 	struct bridge_softc *sc;
953 	struct bridge_iflist *bif;
954 {
955 	bstp_become_designated_port(sc, bif);
956 	bstp_set_port_state(bif, BSTP_IFSTATE_BLOCKING);
957 	bif->bif_topology_change_acknowledge = 0;
958 	bif->bif_config_pending = 0;
959 	bif->bif_change_detection_enabled = 1;
960 	bstp_timer_stop(&bif->bif_message_age_timer);
961 	bstp_timer_stop(&bif->bif_forward_delay_timer);
962 	bstp_timer_stop(&bif->bif_hold_timer);
963 }
964 
965 void
966 bstp_enable_port(sc, bif)
967 	struct bridge_softc *sc;
968 	struct bridge_iflist *bif;
969 {
970 	bstp_initialize_port(sc, bif);
971 	bstp_port_state_selection(sc);
972 }
973 
974 void
975 bstp_disable_port(sc, bif)
976 	struct bridge_softc *sc;
977 	struct bridge_iflist *bif;
978 {
979 	int root;
980 
981 	root = bstp_root_bridge(sc);
982 	bstp_become_designated_port(sc, bif);
983 	bstp_set_port_state(bif, BSTP_IFSTATE_DISABLED);
984 	bif->bif_topology_change_acknowledge = 0;
985 	bif->bif_config_pending = 0;
986 	bstp_timer_stop(&bif->bif_message_age_timer);
987 	bstp_timer_stop(&bif->bif_forward_delay_timer);
988 	bstp_configuration_update(sc);
989 	bstp_port_state_selection(sc);
990 
991 	if (bstp_root_bridge(sc) && (!root))	{
992 		sc->sc_max_age = sc->sc_bridge_max_age;
993 		sc->sc_hello_time = sc->sc_bridge_hello_time;
994 		sc->sc_forward_delay = sc->sc_bridge_forward_delay;
995 
996 		bstp_topology_change_detection(sc);
997 		bstp_timer_stop(&sc->sc_tcn_timer);
998 		bstp_config_bpdu_generation(sc);
999 		bstp_timer_start(&sc->sc_hello_timer, 0);
1000 	}
1001 }
1002 
1003 void
1004 bstp_set_bridge_priority(sc, new_bridge_id)
1005 	struct bridge_softc *sc;
1006 	u_int64_t new_bridge_id;
1007 {
1008 	int root;
1009 	struct bridge_iflist *bif;
1010 
1011 	root = bstp_root_bridge(sc);
1012 
1013 	LIST_FOREACH(bif, &sc->sc_iflist, next) {
1014 		if (!(bif->bif_flags & IFBIF_STP))
1015 			continue;
1016 		if (bstp_designated_port(sc, bif))
1017 			bif->bif_designated_bridge = new_bridge_id;
1018 	}
1019 
1020 	sc->sc_bridge_id = new_bridge_id;
1021 
1022 	bstp_configuration_update(sc);
1023 	bstp_port_state_selection(sc);
1024 
1025 	if (bstp_root_bridge(sc) && (!root)) {
1026 		sc->sc_max_age = sc->sc_bridge_max_age;
1027 		sc->sc_hello_time = sc->sc_bridge_hello_time;
1028 		sc->sc_forward_delay = sc->sc_bridge_forward_delay;
1029 
1030 		bstp_topology_change_detection(sc);
1031 		bstp_timer_stop(&sc->sc_tcn_timer);
1032 		bstp_config_bpdu_generation(sc);
1033 		bstp_timer_start(&sc->sc_hello_timer, 0);
1034 	}
1035 }
1036 
1037 void
1038 bstp_set_port_priority(sc, bif, new_port_id)
1039 	struct bridge_softc *sc;
1040 	struct bridge_iflist *bif;
1041 	u_int16_t new_port_id;
1042 {
1043 	if (bstp_designated_port(sc, bif))
1044 		bif->bif_designated_port = new_port_id;
1045 
1046 	bif->bif_port_id = new_port_id;
1047 
1048 	if ((sc->sc_bridge_id == bif->bif_designated_bridge) &&
1049 	    (bif->bif_port_id < bif->bif_designated_port)) {
1050 		bstp_become_designated_port(sc, bif);
1051 		bstp_port_state_selection(sc);
1052 	}
1053 }
1054 
1055 void
1056 bstp_set_path_cost(sc, bif, path_cost)
1057 	struct bridge_softc *sc;
1058 	struct bridge_iflist *bif;
1059 	u_int32_t path_cost;
1060 {
1061 	bif->bif_path_cost = path_cost;
1062 	bstp_configuration_update(sc);
1063 	bstp_port_state_selection(sc);
1064 }
1065 
1066 void
1067 bstp_enable_change_detection(bif)
1068 	struct bridge_iflist *bif;
1069 {
1070 	bif->bif_change_detection_enabled = 1;
1071 }
1072 
1073 void
1074 bstp_disable_change_detection(bif)
1075 	struct bridge_iflist *bif;
1076 {
1077 	bif->bif_change_detection_enabled = 0;
1078 }
1079 
1080 void
1081 bstp_ifupdstatus(sc, bif)
1082 	struct bridge_softc *sc;
1083 	struct bridge_iflist *bif;
1084 {
1085 	struct ifnet *ifp = bif->ifp;
1086 	struct ifmediareq ifmr;
1087 	int err;
1088 
1089 	if (ifp->if_flags & IFF_UP) {
1090 		ifmr.ifm_count = 0;
1091 		err = (*ifp->if_ioctl)(ifp, SIOCGIFMEDIA, (caddr_t)&ifmr);
1092 		if (err) {
1093 			if (bif->bif_state == BSTP_IFSTATE_DISABLED)
1094 				bstp_enable_port(sc, bif);
1095 			return;
1096 		}
1097 
1098 		if (!(ifmr.ifm_status & IFM_AVALID)) {
1099 			if (bif->bif_state == BSTP_IFSTATE_DISABLED)
1100 				bstp_enable_port(sc, bif);
1101 			return;
1102 		}
1103 
1104 		if (ifmr.ifm_status & IFM_ACTIVE) {
1105 			if (bif->bif_state == BSTP_IFSTATE_DISABLED)
1106 				bstp_enable_port(sc, bif);
1107 			return;
1108 		}
1109 
1110 		if (bif->bif_state != BSTP_IFSTATE_DISABLED)
1111 			bstp_disable_port(sc, bif);
1112 
1113 		return;
1114 	}
1115 
1116 	if (bif->bif_state != BSTP_IFSTATE_DISABLED)
1117 		bstp_disable_port(sc, bif);
1118 }
1119 
1120 void
1121 bstp_tick(vsc)
1122 	void *vsc;
1123 {
1124 	struct bridge_softc *sc = vsc;
1125 	struct bridge_iflist *bif;
1126 	int s;
1127 
1128 	s = splnet();
1129 
1130 	LIST_FOREACH(bif, &sc->sc_iflist, next) {
1131 		if (!(bif->bif_flags & IFBIF_STP))
1132 			continue;
1133 		bstp_ifupdstatus(sc, bif);
1134 	}
1135 
1136 	if (bstp_timer_expired(&sc->sc_hello_timer, sc->sc_hello_time))
1137 		bstp_hello_timer_expiry(sc);
1138 
1139 	if (bstp_timer_expired(&sc->sc_tcn_timer, sc->sc_bridge_hello_time))
1140 		bstp_tcn_timer_expiry(sc);
1141 
1142 	if (bstp_timer_expired(&sc->sc_topology_change_timer,
1143 	    sc->sc_topology_change_time))
1144 		bstp_topology_change_timer_expiry(sc);
1145 
1146 	LIST_FOREACH(bif, &sc->sc_iflist, next) {
1147 		if (!(bif->bif_flags & IFBIF_STP))
1148 			continue;
1149 		if (bstp_timer_expired(&bif->bif_message_age_timer,
1150 		    sc->sc_max_age))
1151 			bstp_message_age_timer_expiry(sc, bif);
1152 	}
1153 
1154 	LIST_FOREACH(bif, &sc->sc_iflist, next) {
1155 		if (!(bif->bif_flags & IFBIF_STP))
1156 			continue;
1157 		if (bstp_timer_expired(&bif->bif_forward_delay_timer,
1158 		    sc->sc_forward_delay))
1159 			bstp_forward_delay_timer_expiry(sc, bif);
1160 
1161 		if (bstp_timer_expired(&bif->bif_hold_timer,
1162 		    sc->sc_hold_time))
1163 			bstp_hold_timer_expiry(sc, bif);
1164 	}
1165 
1166 	if (sc->sc_if.if_flags & IFF_RUNNING)
1167 		timeout_add(&sc->sc_bstptimeout, hz);
1168 
1169 	splx(s);
1170 }
1171 
1172 void
1173 bstp_timer_start(t, v)
1174 	struct bridge_timer *t;
1175 	u_int16_t v;
1176 {
1177 	t->value = v;
1178 	t->active = 1;
1179 }
1180 
1181 void
1182 bstp_timer_stop(t)
1183 	struct bridge_timer *t;
1184 {
1185 	t->value = 0;
1186 	t->active = 0;
1187 }
1188 
1189 int
1190 bstp_timer_expired(t, v)
1191 	struct bridge_timer *t;
1192 	u_int16_t v;
1193 {
1194 	if (!t->active)
1195 		return (0);
1196 	t->value += BSTP_TICK_VAL;
1197 	if (t->value >= v) {
1198 		bstp_timer_stop(t);
1199 		return (1);
1200 	}
1201 	return (0);
1202 
1203 }
1204 
1205 int
1206 bstp_ioctl(ifp, cmd, data)
1207 	struct ifnet *ifp;
1208 	u_long cmd;
1209 	caddr_t	data;
1210 {
1211 	struct bridge_softc *sc = (struct bridge_softc *)ifp;
1212 	struct ifbrparam *bp = (struct ifbrparam *)data;
1213 	int r = 0, err = 0;
1214 
1215 	switch (cmd) {
1216 	case SIOCBRDGGPRI:
1217 		bp->ifbrp_prio = sc->sc_bridge_priority;
1218 		break;
1219 	case SIOCBRDGGMA:
1220 		bp->ifbrp_maxage = sc->sc_bridge_max_age >> 8;
1221 		break;
1222 	case SIOCBRDGGHT:
1223 		bp->ifbrp_hellotime = sc->sc_bridge_hello_time >> 8;
1224 		break;
1225 	case SIOCBRDGGFD:
1226 		bp->ifbrp_fwddelay = sc->sc_bridge_forward_delay >> 8;
1227 		break;
1228 	case SIOCBRDGSPRI:
1229 		sc->sc_bridge_priority = bp->ifbrp_prio;
1230 		r = 1;
1231 		break;
1232 	case SIOCBRDGSMA:
1233 		if (bp->ifbrp_maxage == 0) {
1234 			err = EINVAL;
1235 			break;
1236 		}
1237 		sc->sc_bridge_max_age = bp->ifbrp_maxage << 8;
1238 		r = 1;
1239 		break;
1240 	case SIOCBRDGSHT:
1241 		if (bp->ifbrp_hellotime == 0) {
1242 			err = EINVAL;
1243 			break;
1244 		}
1245 		sc->sc_bridge_hello_time = bp->ifbrp_hellotime << 8;
1246 		r = 1;
1247 		break;
1248 	case SIOCBRDGSFD:
1249 		if (bp->ifbrp_fwddelay == 0) {
1250 			err = EINVAL;
1251 			break;
1252 		}
1253 		sc->sc_bridge_forward_delay = bp->ifbrp_fwddelay << 8;
1254 		r = 1;
1255 		break;
1256 	case SIOCBRDGADD:
1257 	case SIOCBRDGDEL:
1258 	case SIOCBRDGSIFFLGS:
1259 	case SIOCBRDGSIFPRIO:
1260 		r = 1;
1261 		break;
1262 	default:
1263 		break;
1264 	}
1265 
1266 	if (r)
1267 		bstp_initialization(sc);
1268 
1269 	return (err);
1270 }
1271 
1272 #endif /* NBRIDGE */
1273