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