1 /* $NetBSD: bridgestp.c,v 1.13 2007/12/25 18:33:44 perry Exp $ */
4 * Copyright (c) 2000 Jason L. Wright (jason@thought.net)
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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.
33 * OpenBSD: bridgestp.c,v 1.5 2001/03/22 03:48:29 jason Exp
37 * Implementation of the spanning tree protocol as defined in
38 * ISO/IEC Final DIS 15802-3 (IEEE P802.1D/D17), May 25, 1998.
39 * (In English: IEEE 802.1D, Draft 17, 1998)
42 #include <sys/cdefs.h>
43 __KERNEL_RCSID(0, "$NetBSD: bridgestp.c,v 1.13 2007/12/25 18:33:44 perry Exp $");
45 #include <sys/param.h>
46 #include <sys/systm.h>
48 #include <sys/socket.h>
49 #include <sys/ioctl.h>
50 #include <sys/device.h>
51 #include <sys/kernel.h>
52 #include <sys/callout.h>
55 #include <net/if_dl.h>
56 #include <net/if_types.h>
57 #include <net/if_llc.h>
59 #include <net/if_ether.h>
60 #include <net/if_bridgevar.h>
62 /* BPDU message types */
63 #define BSTP_MSGTYPE_CFG 0x00 /* Configuration */
64 #define BSTP_MSGTYPE_TCN 0x80 /* Topology chg notification */
67 #define BSTP_FLAG_TC 0x01 /* Topology change */
68 #define BSTP_FLAG_TCA 0x80 /* Topology change ack */
70 #define BSTP_MESSAGE_AGE_INCR (1 * 256) /* in 256ths of a second */
71 #define BSTP_TICK_VAL (1 * 256) /* in 256ths of a second */
74 * Because BPDU's do not make nicely aligned structures, two different
75 * declarations are used: bstp_?bpdu (wire representation, packed) and
76 * bstp_*_unit (internal, nicely aligned version).
79 /* configuration bridge protocol data unit */
81 uint8_t cbu_dsap
; /* LLC: destination sap */
82 uint8_t cbu_ssap
; /* LLC: source sap */
83 uint8_t cbu_ctl
; /* LLC: control */
84 uint16_t cbu_protoid
; /* protocol id */
85 uint8_t cbu_protover
; /* protocol version */
86 uint8_t cbu_bpdutype
; /* message type */
87 uint8_t cbu_flags
; /* flags (below) */
90 uint16_t cbu_rootpri
; /* root priority */
91 uint8_t cbu_rootaddr
[6]; /* root address */
93 uint32_t cbu_rootpathcost
; /* root path cost */
96 uint16_t cbu_bridgepri
; /* bridge priority */
97 uint8_t cbu_bridgeaddr
[6]; /* bridge address */
99 uint16_t cbu_portid
; /* port id */
100 uint16_t cbu_messageage
; /* current message age */
101 uint16_t cbu_maxage
; /* maximum age */
102 uint16_t cbu_hellotime
; /* hello time */
103 uint16_t cbu_forwarddelay
; /* forwarding delay */
106 /* topology change notification bridge protocol data unit */
108 uint8_t tbu_dsap
; /* LLC: destination sap */
109 uint8_t tbu_ssap
; /* LLC: source sap */
110 uint8_t tbu_ctl
; /* LLC: control */
111 uint16_t tbu_protoid
; /* protocol id */
112 uint8_t tbu_protover
; /* protocol version */
113 uint8_t tbu_bpdutype
; /* message type */
116 const uint8_t bstp_etheraddr
[] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
118 void bstp_initialize_port(struct bridge_softc
*, struct bridge_iflist
*);
119 void bstp_ifupdstatus(struct bridge_softc
*, struct bridge_iflist
*);
120 void bstp_enable_port(struct bridge_softc
*, struct bridge_iflist
*);
121 void bstp_disable_port(struct bridge_softc
*, struct bridge_iflist
*);
122 void bstp_enable_change_detection(struct bridge_iflist
*);
123 void bstp_disable_change_detection(struct bridge_iflist
*);
124 int bstp_root_bridge(struct bridge_softc
*sc
);
125 int bstp_supersedes_port_info(struct bridge_softc
*,
126 struct bridge_iflist
*, struct bstp_config_unit
*);
127 int bstp_designated_port(struct bridge_softc
*, struct bridge_iflist
*);
128 int bstp_designated_for_some_port(struct bridge_softc
*);
129 void bstp_transmit_config(struct bridge_softc
*, struct bridge_iflist
*);
130 void bstp_transmit_tcn(struct bridge_softc
*);
131 void bstp_received_config_bpdu(struct bridge_softc
*,
132 struct bridge_iflist
*, struct bstp_config_unit
*);
133 void bstp_received_tcn_bpdu(struct bridge_softc
*, struct bridge_iflist
*,
134 struct bstp_tcn_unit
*);
135 void bstp_record_config_information(struct bridge_softc
*,
136 struct bridge_iflist
*, struct bstp_config_unit
*);
137 void bstp_record_config_timeout_values(struct bridge_softc
*,
138 struct bstp_config_unit
*);
139 void bstp_config_bpdu_generation(struct bridge_softc
*);
140 void bstp_send_config_bpdu(struct bridge_softc
*, struct bridge_iflist
*,
141 struct bstp_config_unit
*);
142 void bstp_configuration_update(struct bridge_softc
*);
143 void bstp_root_selection(struct bridge_softc
*);
144 void bstp_designated_port_selection(struct bridge_softc
*);
145 void bstp_become_designated_port(struct bridge_softc
*,
146 struct bridge_iflist
*);
147 void bstp_port_state_selection(struct bridge_softc
*);
148 void bstp_make_forwarding(struct bridge_softc
*, struct bridge_iflist
*);
149 void bstp_make_blocking(struct bridge_softc
*, struct bridge_iflist
*);
150 void bstp_set_port_state(struct bridge_iflist
*, uint8_t);
151 void bstp_set_bridge_priority(struct bridge_softc
*, uint64_t);
152 void bstp_set_port_priority(struct bridge_softc
*, struct bridge_iflist
*,
154 void bstp_set_path_cost(struct bridge_softc
*, struct bridge_iflist
*,
156 void bstp_topology_change_detection(struct bridge_softc
*);
157 void bstp_topology_change_acknowledged(struct bridge_softc
*);
158 void bstp_acknowledge_topology_change(struct bridge_softc
*,
159 struct bridge_iflist
*);
161 void bstp_tick(void *);
162 void bstp_timer_start(struct bridge_timer
*, uint16_t);
163 void bstp_timer_stop(struct bridge_timer
*);
164 int bstp_timer_expired(struct bridge_timer
*, uint16_t);
166 void bstp_hold_timer_expiry(struct bridge_softc
*, struct bridge_iflist
*);
167 void bstp_message_age_timer_expiry(struct bridge_softc
*,
168 struct bridge_iflist
*);
169 void bstp_forward_delay_timer_expiry(struct bridge_softc
*,
170 struct bridge_iflist
*);
171 void bstp_topology_change_timer_expiry(struct bridge_softc
*);
172 void bstp_tcn_timer_expiry(struct bridge_softc
*);
173 void bstp_hello_timer_expiry(struct bridge_softc
*);
176 bstp_transmit_config(struct bridge_softc
*sc
, struct bridge_iflist
*bif
)
178 if (bif
->bif_hold_timer
.active
) {
179 bif
->bif_config_pending
= 1;
183 bif
->bif_config_bpdu
.cu_message_type
= BSTP_MSGTYPE_CFG
;
184 bif
->bif_config_bpdu
.cu_rootid
= sc
->sc_designated_root
;
185 bif
->bif_config_bpdu
.cu_root_path_cost
= sc
->sc_root_path_cost
;
186 bif
->bif_config_bpdu
.cu_bridge_id
= sc
->sc_bridge_id
;
187 bif
->bif_config_bpdu
.cu_port_id
= bif
->bif_port_id
;
189 if (bstp_root_bridge(sc
))
190 bif
->bif_config_bpdu
.cu_message_age
= 0;
192 bif
->bif_config_bpdu
.cu_message_age
=
193 sc
->sc_root_port
->bif_message_age_timer
.value
+
194 BSTP_MESSAGE_AGE_INCR
;
196 bif
->bif_config_bpdu
.cu_max_age
= sc
->sc_max_age
;
197 bif
->bif_config_bpdu
.cu_hello_time
= sc
->sc_hello_time
;
198 bif
->bif_config_bpdu
.cu_forward_delay
= sc
->sc_forward_delay
;
199 bif
->bif_config_bpdu
.cu_topology_change_acknowledgment
200 = bif
->bif_topology_change_acknowledge
;
201 bif
->bif_config_bpdu
.cu_topology_change
= sc
->sc_topology_change
;
203 if (bif
->bif_config_bpdu
.cu_message_age
< sc
->sc_max_age
) {
204 bif
->bif_topology_change_acknowledge
= 0;
205 bif
->bif_config_pending
= 0;
206 bstp_send_config_bpdu(sc
, bif
, &bif
->bif_config_bpdu
);
207 bstp_timer_start(&bif
->bif_hold_timer
, 0);
212 bstp_send_config_bpdu(struct bridge_softc
*sc
, struct bridge_iflist
*bif
,
213 struct bstp_config_unit
*cu
)
217 struct ether_header
*eh
;
218 struct bstp_cbpdu bpdu
;
223 if ((ifp
->if_flags
& IFF_RUNNING
) == 0)
226 MGETHDR(m
, M_DONTWAIT
, MT_DATA
);
230 eh
= mtod(m
, struct ether_header
*);
232 m
->m_pkthdr
.rcvif
= ifp
;
233 m
->m_pkthdr
.len
= sizeof(*eh
) + sizeof(bpdu
);
234 m
->m_len
= m
->m_pkthdr
.len
;
236 bpdu
.cbu_ssap
= bpdu
.cbu_dsap
= LLC_8021D_LSAP
;
237 bpdu
.cbu_ctl
= LLC_UI
;
238 bpdu
.cbu_protoid
= htons(0);
239 bpdu
.cbu_protover
= 0;
240 bpdu
.cbu_bpdutype
= cu
->cu_message_type
;
241 bpdu
.cbu_flags
= (cu
->cu_topology_change
? BSTP_FLAG_TC
: 0) |
242 (cu
->cu_topology_change_acknowledgment
? BSTP_FLAG_TCA
: 0);
244 bpdu
.cbu_rootpri
= htons(cu
->cu_rootid
>> 48);
245 bpdu
.cbu_rootaddr
[0] = cu
->cu_rootid
>> 40;
246 bpdu
.cbu_rootaddr
[1] = cu
->cu_rootid
>> 32;
247 bpdu
.cbu_rootaddr
[2] = cu
->cu_rootid
>> 24;
248 bpdu
.cbu_rootaddr
[3] = cu
->cu_rootid
>> 16;
249 bpdu
.cbu_rootaddr
[4] = cu
->cu_rootid
>> 8;
250 bpdu
.cbu_rootaddr
[5] = cu
->cu_rootid
>> 0;
252 bpdu
.cbu_rootpathcost
= htonl(cu
->cu_root_path_cost
);
254 bpdu
.cbu_bridgepri
= htons(cu
->cu_rootid
>> 48);
255 bpdu
.cbu_bridgeaddr
[0] = cu
->cu_rootid
>> 40;
256 bpdu
.cbu_bridgeaddr
[1] = cu
->cu_rootid
>> 32;
257 bpdu
.cbu_bridgeaddr
[2] = cu
->cu_rootid
>> 24;
258 bpdu
.cbu_bridgeaddr
[3] = cu
->cu_rootid
>> 16;
259 bpdu
.cbu_bridgeaddr
[4] = cu
->cu_rootid
>> 8;
260 bpdu
.cbu_bridgeaddr
[5] = cu
->cu_rootid
>> 0;
262 bpdu
.cbu_portid
= htons(cu
->cu_port_id
);
263 bpdu
.cbu_messageage
= htons(cu
->cu_message_age
);
264 bpdu
.cbu_maxage
= htons(cu
->cu_max_age
);
265 bpdu
.cbu_hellotime
= htons(cu
->cu_hello_time
);
266 bpdu
.cbu_forwarddelay
= htons(cu
->cu_forward_delay
);
268 memcpy(eh
->ether_shost
, CLLADDR(ifp
->if_sadl
), ETHER_ADDR_LEN
);
269 memcpy(eh
->ether_dhost
, bstp_etheraddr
, ETHER_ADDR_LEN
);
270 eh
->ether_type
= htons(sizeof(bpdu
));
272 memcpy(mtod(m
, char *) + sizeof(*eh
), &bpdu
, sizeof(bpdu
));
275 bridge_enqueue(sc
, ifp
, m
, 0);
280 bstp_root_bridge(struct bridge_softc
*sc
)
282 return (sc
->sc_designated_root
== sc
->sc_bridge_id
);
286 bstp_supersedes_port_info(struct bridge_softc
*sc
, struct bridge_iflist
*bif
,
287 struct bstp_config_unit
*cu
)
289 if (cu
->cu_rootid
< bif
->bif_designated_root
)
291 if (cu
->cu_rootid
> bif
->bif_designated_root
)
294 if (cu
->cu_root_path_cost
< bif
->bif_designated_cost
)
296 if (cu
->cu_root_path_cost
> bif
->bif_designated_cost
)
299 if (cu
->cu_bridge_id
< bif
->bif_designated_bridge
)
301 if (cu
->cu_bridge_id
> bif
->bif_designated_bridge
)
304 if (sc
->sc_bridge_id
!= cu
->cu_bridge_id
)
306 if (cu
->cu_port_id
<= bif
->bif_designated_port
)
312 bstp_record_config_information(struct bridge_softc
*sc
,
313 struct bridge_iflist
*bif
, struct bstp_config_unit
*cu
)
315 bif
->bif_designated_root
= cu
->cu_rootid
;
316 bif
->bif_designated_cost
= cu
->cu_root_path_cost
;
317 bif
->bif_designated_bridge
= cu
->cu_bridge_id
;
318 bif
->bif_designated_port
= cu
->cu_port_id
;
319 bstp_timer_start(&bif
->bif_message_age_timer
, cu
->cu_message_age
);
323 bstp_record_config_timeout_values(struct bridge_softc
*sc
,
324 struct bstp_config_unit
*config
)
326 sc
->sc_max_age
= config
->cu_max_age
;
327 sc
->sc_hello_time
= config
->cu_hello_time
;
328 sc
->sc_forward_delay
= config
->cu_forward_delay
;
329 sc
->sc_topology_change
= config
->cu_topology_change
;
333 bstp_config_bpdu_generation(struct bridge_softc
*sc
)
335 struct bridge_iflist
*bif
;
337 LIST_FOREACH(bif
, &sc
->sc_iflist
, bif_next
) {
338 if ((bif
->bif_flags
& IFBIF_STP
) == 0)
340 if (bstp_designated_port(sc
, bif
) &&
341 (bif
->bif_state
!= BSTP_IFSTATE_DISABLED
))
342 bstp_transmit_config(sc
, bif
);
347 bstp_designated_port(struct bridge_softc
*sc
, struct bridge_iflist
*bif
)
349 return ((bif
->bif_designated_bridge
== sc
->sc_bridge_id
)
350 && (bif
->bif_designated_port
== bif
->bif_port_id
));
354 bstp_transmit_tcn(struct bridge_softc
*sc
)
356 struct bstp_tbpdu bpdu
;
357 struct bridge_iflist
*bif
= sc
->sc_root_port
;
359 struct ether_header
*eh
;
363 KASSERT(bif
!= NULL
);
365 if ((ifp
->if_flags
& IFF_RUNNING
) == 0)
368 MGETHDR(m
, M_DONTWAIT
, MT_DATA
);
372 m
->m_pkthdr
.rcvif
= ifp
;
373 m
->m_pkthdr
.len
= sizeof(*eh
) + sizeof(bpdu
);
374 m
->m_len
= m
->m_pkthdr
.len
;
376 eh
= mtod(m
, struct ether_header
*);
378 memcpy(eh
->ether_shost
, CLLADDR(ifp
->if_sadl
), ETHER_ADDR_LEN
);
379 memcpy(eh
->ether_dhost
, bstp_etheraddr
, ETHER_ADDR_LEN
);
380 eh
->ether_type
= htons(sizeof(bpdu
));
382 bpdu
.tbu_ssap
= bpdu
.tbu_dsap
= LLC_8021D_LSAP
;
383 bpdu
.tbu_ctl
= LLC_UI
;
384 bpdu
.tbu_protoid
= 0;
385 bpdu
.tbu_protover
= 0;
386 bpdu
.tbu_bpdutype
= BSTP_MSGTYPE_TCN
;
388 memcpy(mtod(m
, char *) + sizeof(*eh
), &bpdu
, sizeof(bpdu
));
391 bridge_enqueue(sc
, ifp
, m
, 0);
396 bstp_configuration_update(struct bridge_softc
*sc
)
398 bstp_root_selection(sc
);
399 bstp_designated_port_selection(sc
);
403 bstp_root_selection(struct bridge_softc
*sc
)
405 struct bridge_iflist
*root_port
= NULL
, *bif
;
407 LIST_FOREACH(bif
, &sc
->sc_iflist
, bif_next
) {
408 if ((bif
->bif_flags
& IFBIF_STP
) == 0)
410 if (bstp_designated_port(sc
, bif
))
412 if (bif
->bif_state
== BSTP_IFSTATE_DISABLED
)
414 if (bif
->bif_designated_root
>= sc
->sc_bridge_id
)
416 if (root_port
== NULL
)
419 if (bif
->bif_designated_root
< root_port
->bif_designated_root
)
421 if (bif
->bif_designated_root
> root_port
->bif_designated_root
)
424 if ((bif
->bif_designated_cost
+ bif
->bif_path_cost
) <
425 (root_port
->bif_designated_cost
+ root_port
->bif_path_cost
))
427 if ((bif
->bif_designated_cost
+ bif
->bif_path_cost
) >
428 (root_port
->bif_designated_cost
+ root_port
->bif_path_cost
))
431 if (bif
->bif_designated_bridge
<
432 root_port
->bif_designated_bridge
)
434 if (bif
->bif_designated_bridge
>
435 root_port
->bif_designated_bridge
)
438 if (bif
->bif_designated_port
< root_port
->bif_designated_port
)
440 if (bif
->bif_designated_port
> root_port
->bif_designated_port
)
443 if (bif
->bif_port_id
>= root_port
->bif_port_id
)
449 sc
->sc_root_port
= root_port
;
450 if (root_port
== NULL
) {
451 sc
->sc_designated_root
= sc
->sc_bridge_id
;
452 sc
->sc_root_path_cost
= 0;
454 sc
->sc_designated_root
= root_port
->bif_designated_root
;
455 sc
->sc_root_path_cost
= root_port
->bif_designated_cost
+
456 root_port
->bif_path_cost
;
461 bstp_designated_port_selection(struct bridge_softc
*sc
)
463 struct bridge_iflist
*bif
;
465 LIST_FOREACH(bif
, &sc
->sc_iflist
, bif_next
) {
466 if ((bif
->bif_flags
& IFBIF_STP
) == 0)
468 if (bstp_designated_port(sc
, bif
))
470 if (bif
->bif_designated_root
!= sc
->sc_designated_root
)
473 if (sc
->sc_root_path_cost
< bif
->bif_designated_cost
)
475 if (sc
->sc_root_path_cost
> bif
->bif_designated_cost
)
478 if (sc
->sc_bridge_id
< bif
->bif_designated_bridge
)
480 if (sc
->sc_bridge_id
> bif
->bif_designated_bridge
)
483 if (bif
->bif_port_id
> bif
->bif_designated_port
)
486 bstp_become_designated_port(sc
, bif
);
491 bstp_become_designated_port(struct bridge_softc
*sc
, struct bridge_iflist
*bif
)
493 bif
->bif_designated_root
= sc
->sc_designated_root
;
494 bif
->bif_designated_cost
= sc
->sc_root_path_cost
;
495 bif
->bif_designated_bridge
= sc
->sc_bridge_id
;
496 bif
->bif_designated_port
= bif
->bif_port_id
;
500 bstp_port_state_selection(struct bridge_softc
*sc
)
502 struct bridge_iflist
*bif
;
504 LIST_FOREACH(bif
, &sc
->sc_iflist
, bif_next
) {
505 if ((bif
->bif_flags
& IFBIF_STP
) == 0)
507 if (bif
== sc
->sc_root_port
) {
508 bif
->bif_config_pending
= 0;
509 bif
->bif_topology_change_acknowledge
= 0;
510 bstp_make_forwarding(sc
, bif
);
511 } else if (bstp_designated_port(sc
, bif
)) {
512 bstp_timer_stop(&bif
->bif_message_age_timer
);
513 bstp_make_forwarding(sc
, bif
);
515 bif
->bif_config_pending
= 0;
516 bif
->bif_topology_change_acknowledge
= 0;
517 bstp_make_blocking(sc
, bif
);
523 bstp_make_forwarding(struct bridge_softc
*sc
,
524 struct bridge_iflist
*bif
)
526 if (bif
->bif_state
== BSTP_IFSTATE_BLOCKING
) {
527 bstp_set_port_state(bif
, BSTP_IFSTATE_LISTENING
);
528 bstp_timer_start(&bif
->bif_forward_delay_timer
, 0);
533 bstp_make_blocking(struct bridge_softc
*sc
, struct bridge_iflist
*bif
)
535 if ((bif
->bif_state
!= BSTP_IFSTATE_DISABLED
) &&
536 (bif
->bif_state
!= BSTP_IFSTATE_BLOCKING
)) {
537 if ((bif
->bif_state
== BSTP_IFSTATE_FORWARDING
) ||
538 (bif
->bif_state
== BSTP_IFSTATE_LEARNING
)) {
539 if (bif
->bif_change_detection_enabled
) {
540 bstp_topology_change_detection(sc
);
543 bstp_set_port_state(bif
, BSTP_IFSTATE_BLOCKING
);
544 bstp_timer_stop(&bif
->bif_forward_delay_timer
);
549 bstp_set_port_state(struct bridge_iflist
*bif
, uint8_t state
)
551 bif
->bif_state
= state
;
555 bstp_topology_change_detection(struct bridge_softc
*sc
)
557 if (bstp_root_bridge(sc
)) {
558 sc
->sc_topology_change
= 1;
559 bstp_timer_start(&sc
->sc_topology_change_timer
, 0);
560 } else if (!sc
->sc_topology_change_detected
) {
561 bstp_transmit_tcn(sc
);
562 bstp_timer_start(&sc
->sc_tcn_timer
, 0);
564 sc
->sc_topology_change_detected
= 1;
568 bstp_topology_change_acknowledged(struct bridge_softc
*sc
)
570 sc
->sc_topology_change_detected
= 0;
571 bstp_timer_stop(&sc
->sc_tcn_timer
);
575 bstp_acknowledge_topology_change(struct bridge_softc
*sc
,
576 struct bridge_iflist
*bif
)
578 bif
->bif_topology_change_acknowledge
= 1;
579 bstp_transmit_config(sc
, bif
);
583 bstp_input(struct bridge_softc
*sc
, struct bridge_iflist
*bif
, struct mbuf
*m
)
585 struct ether_header
*eh
;
586 struct bstp_tbpdu tpdu
;
587 struct bstp_cbpdu cpdu
;
588 struct bstp_config_unit cu
;
589 struct bstp_tcn_unit tu
;
592 eh
= mtod(m
, struct ether_header
*);
594 if ((bif
->bif_flags
& IFBIF_STP
) == 0)
597 len
= ntohs(eh
->ether_type
);
598 if (len
< sizeof(tpdu
))
601 m_adj(m
, ETHER_HDR_LEN
);
603 if (m
->m_pkthdr
.len
> len
)
604 m_adj(m
, len
- m
->m_pkthdr
.len
);
605 if (m
->m_len
< sizeof(tpdu
) &&
606 (m
= m_pullup(m
, sizeof(tpdu
))) == NULL
)
609 memcpy(&tpdu
, mtod(m
, void *), sizeof(tpdu
));
611 if (tpdu
.tbu_dsap
!= LLC_8021D_LSAP
||
612 tpdu
.tbu_ssap
!= LLC_8021D_LSAP
||
613 tpdu
.tbu_ctl
!= LLC_UI
)
615 if (tpdu
.tbu_protoid
!= 0 || tpdu
.tbu_protover
!= 0)
618 switch (tpdu
.tbu_bpdutype
) {
619 case BSTP_MSGTYPE_TCN
:
620 tu
.tu_message_type
= tpdu
.tbu_bpdutype
;
621 bstp_received_tcn_bpdu(sc
, bif
, &tu
);
623 case BSTP_MSGTYPE_CFG
:
624 if (m
->m_len
< sizeof(cpdu
) &&
625 (m
= m_pullup(m
, sizeof(cpdu
))) == NULL
)
627 memcpy(&cpdu
, mtod(m
, void *), sizeof(cpdu
));
630 (((uint64_t)ntohs(cpdu
.cbu_rootpri
)) << 48) |
631 (((uint64_t)cpdu
.cbu_rootaddr
[0]) << 40) |
632 (((uint64_t)cpdu
.cbu_rootaddr
[1]) << 32) |
633 (((uint64_t)cpdu
.cbu_rootaddr
[2]) << 24) |
634 (((uint64_t)cpdu
.cbu_rootaddr
[3]) << 16) |
635 (((uint64_t)cpdu
.cbu_rootaddr
[4]) << 8) |
636 (((uint64_t)cpdu
.cbu_rootaddr
[5]) << 0);
639 (((uint64_t)ntohs(cpdu
.cbu_bridgepri
)) << 48) |
640 (((uint64_t)cpdu
.cbu_bridgeaddr
[0]) << 40) |
641 (((uint64_t)cpdu
.cbu_bridgeaddr
[1]) << 32) |
642 (((uint64_t)cpdu
.cbu_bridgeaddr
[2]) << 24) |
643 (((uint64_t)cpdu
.cbu_bridgeaddr
[3]) << 16) |
644 (((uint64_t)cpdu
.cbu_bridgeaddr
[4]) << 8) |
645 (((uint64_t)cpdu
.cbu_bridgeaddr
[5]) << 0);
647 cu
.cu_root_path_cost
= ntohl(cpdu
.cbu_rootpathcost
);
648 cu
.cu_message_age
= ntohs(cpdu
.cbu_messageage
);
649 cu
.cu_max_age
= ntohs(cpdu
.cbu_maxage
);
650 cu
.cu_hello_time
= ntohs(cpdu
.cbu_hellotime
);
651 cu
.cu_forward_delay
= ntohs(cpdu
.cbu_forwarddelay
);
652 cu
.cu_port_id
= ntohs(cpdu
.cbu_portid
);
653 cu
.cu_message_type
= cpdu
.cbu_bpdutype
;
654 cu
.cu_topology_change_acknowledgment
=
655 (cpdu
.cbu_flags
& BSTP_FLAG_TCA
) ? 1 : 0;
656 cu
.cu_topology_change
=
657 (cpdu
.cbu_flags
& BSTP_FLAG_TC
) ? 1 : 0;
658 bstp_received_config_bpdu(sc
, bif
, &cu
);
671 bstp_received_config_bpdu(struct bridge_softc
*sc
, struct bridge_iflist
*bif
,
672 struct bstp_config_unit
*cu
)
676 root
= bstp_root_bridge(sc
);
678 if (bif
->bif_state
!= BSTP_IFSTATE_DISABLED
) {
679 if (bstp_supersedes_port_info(sc
, bif
, cu
)) {
680 bstp_record_config_information(sc
, bif
, cu
);
681 bstp_configuration_update(sc
);
682 bstp_port_state_selection(sc
);
684 if ((bstp_root_bridge(sc
) == 0) && root
) {
685 bstp_timer_stop(&sc
->sc_hello_timer
);
687 if (sc
->sc_topology_change_detected
) {
689 &sc
->sc_topology_change_timer
);
690 bstp_transmit_tcn(sc
);
691 bstp_timer_start(&sc
->sc_tcn_timer
, 0);
695 if (bif
== sc
->sc_root_port
) {
696 bstp_record_config_timeout_values(sc
, cu
);
697 bstp_config_bpdu_generation(sc
);
699 if (cu
->cu_topology_change_acknowledgment
)
700 bstp_topology_change_acknowledged(sc
);
702 } else if (bstp_designated_port(sc
, bif
))
703 bstp_transmit_config(sc
, bif
);
708 bstp_received_tcn_bpdu(struct bridge_softc
*sc
, struct bridge_iflist
*bif
,
709 struct bstp_tcn_unit
*tcn
)
711 if (bif
->bif_state
!= BSTP_IFSTATE_DISABLED
&&
712 bstp_designated_port(sc
, bif
)) {
713 bstp_topology_change_detection(sc
);
714 bstp_acknowledge_topology_change(sc
, bif
);
719 bstp_hello_timer_expiry(struct bridge_softc
*sc
)
721 bstp_config_bpdu_generation(sc
);
722 bstp_timer_start(&sc
->sc_hello_timer
, 0);
726 bstp_message_age_timer_expiry(struct bridge_softc
*sc
,
727 struct bridge_iflist
*bif
)
731 root
= bstp_root_bridge(sc
);
732 bstp_become_designated_port(sc
, bif
);
733 bstp_configuration_update(sc
);
734 bstp_port_state_selection(sc
);
736 if ((bstp_root_bridge(sc
)) && (root
== 0)) {
737 sc
->sc_max_age
= sc
->sc_bridge_max_age
;
738 sc
->sc_hello_time
= sc
->sc_bridge_hello_time
;
739 sc
->sc_forward_delay
= sc
->sc_bridge_forward_delay
;
741 bstp_topology_change_detection(sc
);
742 bstp_timer_stop(&sc
->sc_tcn_timer
);
743 bstp_config_bpdu_generation(sc
);
744 bstp_timer_start(&sc
->sc_hello_timer
, 0);
749 bstp_forward_delay_timer_expiry(struct bridge_softc
*sc
,
750 struct bridge_iflist
*bif
)
752 if (bif
->bif_state
== BSTP_IFSTATE_LISTENING
) {
753 bstp_set_port_state(bif
, BSTP_IFSTATE_LEARNING
);
754 bstp_timer_start(&bif
->bif_forward_delay_timer
, 0);
755 } else if (bif
->bif_state
== BSTP_IFSTATE_LEARNING
) {
756 bstp_set_port_state(bif
, BSTP_IFSTATE_FORWARDING
);
757 if (bstp_designated_for_some_port(sc
) &&
758 bif
->bif_change_detection_enabled
)
759 bstp_topology_change_detection(sc
);
764 bstp_designated_for_some_port(struct bridge_softc
*sc
)
767 struct bridge_iflist
*bif
;
769 LIST_FOREACH(bif
, &sc
->sc_iflist
, bif_next
) {
770 if ((bif
->bif_flags
& IFBIF_STP
) == 0)
772 if (bif
->bif_designated_bridge
== sc
->sc_bridge_id
)
779 bstp_tcn_timer_expiry(struct bridge_softc
*sc
)
781 bstp_transmit_tcn(sc
);
782 bstp_timer_start(&sc
->sc_tcn_timer
, 0);
786 bstp_topology_change_timer_expiry(struct bridge_softc
*sc
)
788 sc
->sc_topology_change_detected
= 0;
789 sc
->sc_topology_change
= 0;
793 bstp_hold_timer_expiry(struct bridge_softc
*sc
, struct bridge_iflist
*bif
)
795 if (bif
->bif_config_pending
)
796 bstp_transmit_config(sc
, bif
);
800 bstp_initialization(struct bridge_softc
*sc
)
802 struct bridge_iflist
*bif
, *mif
;
805 LIST_FOREACH(bif
, &sc
->sc_iflist
, bif_next
) {
806 if ((bif
->bif_flags
& IFBIF_STP
) == 0)
808 if (bif
->bif_ifp
->if_type
!= IFT_ETHER
)
810 bif
->bif_port_id
= (bif
->bif_priority
<< 8) |
811 (bif
->bif_ifp
->if_index
& 0xff);
817 if (memcmp(CLLADDR(bif
->bif_ifp
->if_sadl
),
818 CLLADDR(mif
->bif_ifp
->if_sadl
), ETHER_ADDR_LEN
) < 0) {
829 (((uint64_t)sc
->sc_bridge_priority
) << 48) |
830 (((uint64_t)(uint8_t)CLLADDR(mif
->bif_ifp
->if_sadl
)[0]) << 40) |
831 (((uint64_t)(uint8_t)CLLADDR(mif
->bif_ifp
->if_sadl
)[1]) << 32) |
832 (((uint64_t)(uint8_t)CLLADDR(mif
->bif_ifp
->if_sadl
)[2]) << 24) |
833 (((uint64_t)(uint8_t)CLLADDR(mif
->bif_ifp
->if_sadl
)[3]) << 16) |
834 (((uint64_t)(uint8_t)CLLADDR(mif
->bif_ifp
->if_sadl
)[4]) << 8) |
835 (((uint64_t)(uint8_t)CLLADDR(mif
->bif_ifp
->if_sadl
)[5]) << 0);
837 sc
->sc_designated_root
= sc
->sc_bridge_id
;
838 sc
->sc_root_path_cost
= 0;
839 sc
->sc_root_port
= NULL
;
841 sc
->sc_max_age
= sc
->sc_bridge_max_age
;
842 sc
->sc_hello_time
= sc
->sc_bridge_hello_time
;
843 sc
->sc_forward_delay
= sc
->sc_bridge_forward_delay
;
844 sc
->sc_topology_change_detected
= 0;
845 sc
->sc_topology_change
= 0;
846 bstp_timer_stop(&sc
->sc_tcn_timer
);
847 bstp_timer_stop(&sc
->sc_topology_change_timer
);
849 if (callout_pending(&sc
->sc_bstpcallout
) == 0)
850 callout_reset(&sc
->sc_bstpcallout
, hz
,
853 LIST_FOREACH(bif
, &sc
->sc_iflist
, bif_next
) {
854 if (bif
->bif_flags
& IFBIF_STP
)
855 bstp_enable_port(sc
, bif
);
857 bstp_disable_port(sc
, bif
);
860 bstp_port_state_selection(sc
);
861 bstp_config_bpdu_generation(sc
);
862 bstp_timer_start(&sc
->sc_hello_timer
, 0);
866 bstp_stop(struct bridge_softc
*sc
)
868 struct bridge_iflist
*bif
;
870 LIST_FOREACH(bif
, &sc
->sc_iflist
, bif_next
) {
871 bstp_set_port_state(bif
, BSTP_IFSTATE_DISABLED
);
872 bstp_timer_stop(&bif
->bif_hold_timer
);
873 bstp_timer_stop(&bif
->bif_message_age_timer
);
874 bstp_timer_stop(&bif
->bif_forward_delay_timer
);
877 callout_stop(&sc
->sc_bstpcallout
);
879 bstp_timer_stop(&sc
->sc_topology_change_timer
);
880 bstp_timer_stop(&sc
->sc_tcn_timer
);
881 bstp_timer_stop(&sc
->sc_hello_timer
);
886 bstp_initialize_port(struct bridge_softc
*sc
, struct bridge_iflist
*bif
)
888 bstp_become_designated_port(sc
, bif
);
889 bstp_set_port_state(bif
, BSTP_IFSTATE_BLOCKING
);
890 bif
->bif_topology_change_acknowledge
= 0;
891 bif
->bif_config_pending
= 0;
892 bif
->bif_change_detection_enabled
= 1;
893 bstp_timer_stop(&bif
->bif_message_age_timer
);
894 bstp_timer_stop(&bif
->bif_forward_delay_timer
);
895 bstp_timer_stop(&bif
->bif_hold_timer
);
899 bstp_enable_port(struct bridge_softc
*sc
, struct bridge_iflist
*bif
)
901 bstp_initialize_port(sc
, bif
);
902 bstp_port_state_selection(sc
);
906 bstp_disable_port(struct bridge_softc
*sc
, struct bridge_iflist
*bif
)
910 root
= bstp_root_bridge(sc
);
911 bstp_become_designated_port(sc
, bif
);
912 bstp_set_port_state(bif
, BSTP_IFSTATE_DISABLED
);
913 bif
->bif_topology_change_acknowledge
= 0;
914 bif
->bif_config_pending
= 0;
915 bstp_timer_stop(&bif
->bif_message_age_timer
);
916 bstp_timer_stop(&bif
->bif_forward_delay_timer
);
917 bstp_configuration_update(sc
);
918 bstp_port_state_selection(sc
);
920 if (bstp_root_bridge(sc
) && (root
== 0)) {
921 sc
->sc_max_age
= sc
->sc_bridge_max_age
;
922 sc
->sc_hello_time
= sc
->sc_bridge_hello_time
;
923 sc
->sc_forward_delay
= sc
->sc_bridge_forward_delay
;
925 bstp_topology_change_detection(sc
);
926 bstp_timer_stop(&sc
->sc_tcn_timer
);
927 bstp_config_bpdu_generation(sc
);
928 bstp_timer_start(&sc
->sc_hello_timer
, 0);
933 bstp_set_bridge_priority(struct bridge_softc
*sc
, uint64_t new_bridge_id
)
935 struct bridge_iflist
*bif
;
938 root
= bstp_root_bridge(sc
);
940 LIST_FOREACH(bif
, &sc
->sc_iflist
, bif_next
) {
941 if ((bif
->bif_flags
& IFBIF_STP
) == 0)
943 if (bstp_designated_port(sc
, bif
))
944 bif
->bif_designated_bridge
= new_bridge_id
;
947 sc
->sc_bridge_id
= new_bridge_id
;
949 bstp_configuration_update(sc
);
950 bstp_port_state_selection(sc
);
952 if (bstp_root_bridge(sc
) && (root
== 0)) {
953 sc
->sc_max_age
= sc
->sc_bridge_max_age
;
954 sc
->sc_hello_time
= sc
->sc_bridge_hello_time
;
955 sc
->sc_forward_delay
= sc
->sc_bridge_forward_delay
;
957 bstp_topology_change_detection(sc
);
958 bstp_timer_stop(&sc
->sc_tcn_timer
);
959 bstp_config_bpdu_generation(sc
);
960 bstp_timer_start(&sc
->sc_hello_timer
, 0);
965 bstp_set_port_priority(struct bridge_softc
*sc
, struct bridge_iflist
*bif
,
966 uint16_t new_port_id
)
968 if (bstp_designated_port(sc
, bif
))
969 bif
->bif_designated_port
= new_port_id
;
971 bif
->bif_port_id
= new_port_id
;
973 if ((sc
->sc_bridge_id
== bif
->bif_designated_bridge
) &&
974 (bif
->bif_port_id
< bif
->bif_designated_port
)) {
975 bstp_become_designated_port(sc
, bif
);
976 bstp_port_state_selection(sc
);
981 bstp_set_path_cost(struct bridge_softc
*sc
, struct bridge_iflist
*bif
,
984 bif
->bif_path_cost
= path_cost
;
985 bstp_configuration_update(sc
);
986 bstp_port_state_selection(sc
);
990 bstp_enable_change_detection(struct bridge_iflist
*bif
)
992 bif
->bif_change_detection_enabled
= 1;
996 bstp_disable_change_detection(struct bridge_iflist
*bif
)
998 bif
->bif_change_detection_enabled
= 0;
1002 bstp_ifupdstatus(struct bridge_softc
*sc
, struct bridge_iflist
*bif
)
1004 struct ifnet
*ifp
= bif
->bif_ifp
;
1006 if (ifp
->if_flags
& IFF_UP
) {
1007 switch (ifp
->if_link_state
) {
1008 case LINK_STATE_UNKNOWN
:
1010 * Just enable the port if the link state is
1013 if (bif
->bif_state
== BSTP_IFSTATE_DISABLED
)
1014 bstp_enable_port(sc
, bif
);
1018 if (bif
->bif_state
== BSTP_IFSTATE_DISABLED
)
1019 bstp_enable_port(sc
, bif
);
1022 case LINK_STATE_DOWN
:
1023 if (bif
->bif_state
!= BSTP_IFSTATE_DISABLED
)
1024 bstp_disable_port(sc
, bif
);
1030 if (bif
->bif_state
!= BSTP_IFSTATE_DISABLED
)
1031 bstp_disable_port(sc
, bif
);
1035 bstp_tick(void *arg
)
1037 struct bridge_softc
*sc
= arg
;
1038 struct bridge_iflist
*bif
;
1043 LIST_FOREACH(bif
, &sc
->sc_iflist
, bif_next
) {
1044 if ((bif
->bif_flags
& IFBIF_STP
) == 0)
1047 * XXX This can cause a lag in "link does away"
1048 * XXX and "spanning tree gets updated". We need
1049 * XXX come sort of callback from the link state
1050 * XXX update code to kick spanning tree.
1051 * XXX --thorpej@NetBSD.org
1053 bstp_ifupdstatus(sc
, bif
);
1056 if (bstp_timer_expired(&sc
->sc_hello_timer
, sc
->sc_hello_time
))
1057 bstp_hello_timer_expiry(sc
);
1059 if (bstp_timer_expired(&sc
->sc_tcn_timer
, sc
->sc_bridge_hello_time
))
1060 bstp_tcn_timer_expiry(sc
);
1062 if (bstp_timer_expired(&sc
->sc_topology_change_timer
,
1063 sc
->sc_topology_change_time
))
1064 bstp_topology_change_timer_expiry(sc
);
1066 LIST_FOREACH(bif
, &sc
->sc_iflist
, bif_next
) {
1067 if ((bif
->bif_flags
& IFBIF_STP
) == 0)
1069 if (bstp_timer_expired(&bif
->bif_message_age_timer
,
1071 bstp_message_age_timer_expiry(sc
, bif
);
1074 LIST_FOREACH(bif
, &sc
->sc_iflist
, bif_next
) {
1075 if ((bif
->bif_flags
& IFBIF_STP
) == 0)
1077 if (bstp_timer_expired(&bif
->bif_forward_delay_timer
,
1078 sc
->sc_forward_delay
))
1079 bstp_forward_delay_timer_expiry(sc
, bif
);
1081 if (bstp_timer_expired(&bif
->bif_hold_timer
,
1083 bstp_hold_timer_expiry(sc
, bif
);
1086 if (sc
->sc_if
.if_flags
& IFF_RUNNING
)
1087 callout_reset(&sc
->sc_bstpcallout
, hz
, bstp_tick
, sc
);
1093 bstp_timer_start(struct bridge_timer
*t
, uint16_t v
)
1100 bstp_timer_stop(struct bridge_timer
*t
)
1107 bstp_timer_expired(struct bridge_timer
*t
, uint16_t v
)
1111 t
->value
+= BSTP_TICK_VAL
;
1112 if (t
->value
>= v
) {