Remove inclusion of <sys/cdefs.h> from kernel .c files.
[dragonfly.git] / sys / net / bridge / bridgestp.c
1 /*
2  * Copyright (c) 2000 Jason L. Wright (jason@thought.net)
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by Jason L. Wright
16  * 4. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
23  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  * $OpenBSD: bridgestp.c,v 1.5 2001/03/22 03:48:29 jason Exp $
32  * $NetBSD: bridgestp.c,v 1.5 2003/11/28 08:56:48 keihan Exp $
33  * $FreeBSD: src/sys/net/bridgestp.c,v 1.7 2005/10/11 02:58:32 thompsa Exp $
34  */
35
36 /*
37  * Implementation of the spanning tree protocol as defined in
38  * ISO/IEC Final DIS 15802-3 (IEEE P802.1D/D17), May 25, 1998.
39  * (In English: IEEE 802.1D, Draft 17, 1998)
40  */
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/mbuf.h>
45 #include <sys/socket.h>
46 #include <sys/sockio.h>
47 #include <sys/kernel.h>
48 #include <sys/callout.h>
49 #include <sys/proc.h>
50 #include <sys/lock.h>
51 #include <sys/thread.h>
52 #include <sys/thread2.h>
53 #include <sys/msgport2.h>
54
55 #include <net/if.h>
56 #include <net/if_dl.h>
57 #include <net/if_types.h>
58 #include <net/if_llc.h>
59 #include <net/if_media.h>
60
61 #include <netinet/in.h>
62 #include <netinet/in_systm.h>
63 #include <netinet/in_var.h>
64 #include <netinet/if_ether.h>
65 #include <net/bridge/if_bridgevar.h>
66
67 /* BPDU message types */
68 #define BSTP_MSGTYPE_CFG        0x00            /* Configuration */
69 #define BSTP_MSGTYPE_TCN        0x80            /* Topology chg notification */
70
71 /* BPDU flags */
72 #define BSTP_FLAG_TC            0x01            /* Topology change */
73 #define BSTP_FLAG_TCA           0x80            /* Topology change ack */
74
75 #define BSTP_MESSAGE_AGE_INCR   (1 * 256)       /* in 256ths of a second */
76 #define BSTP_TICK_VAL           (1 * 256)       /* in 256ths of a second */
77
78 /*
79  * Because BPDU's do not make nicely aligned structures, two different
80  * declarations are used: bstp_?bpdu (wire representation, packed) and
81  * bstp_*_unit (internal, nicely aligned version).
82  */
83
84 /* configuration bridge protocol data unit */
85 struct bstp_cbpdu {
86         uint8_t         cbu_dsap;               /* LLC: destination sap */
87         uint8_t         cbu_ssap;               /* LLC: source sap */
88         uint8_t         cbu_ctl;                /* LLC: control */
89         uint16_t        cbu_protoid;            /* protocol id */
90         uint8_t         cbu_protover;           /* protocol version */
91         uint8_t         cbu_bpdutype;           /* message type */
92         uint8_t         cbu_flags;              /* flags (below) */
93
94         /* root id */
95         uint16_t        cbu_rootpri;            /* root priority */
96         uint8_t cbu_rootaddr[6];        /* root address */
97
98         uint32_t        cbu_rootpathcost;       /* root path cost */
99
100         /* bridge id */
101         uint16_t        cbu_bridgepri;          /* bridge priority */
102         uint8_t         cbu_bridgeaddr[6];      /* bridge address */
103
104         uint16_t        cbu_portid;             /* port id */
105         uint16_t        cbu_messageage;         /* current message age */
106         uint16_t        cbu_maxage;             /* maximum age */
107         uint16_t        cbu_hellotime;          /* hello time */
108         uint16_t        cbu_forwarddelay;       /* forwarding delay */
109 } __attribute__((__packed__));
110
111 /* topology change notification bridge protocol data unit */
112 struct bstp_tbpdu {
113         uint8_t         tbu_dsap;               /* LLC: destination sap */
114         uint8_t         tbu_ssap;               /* LLC: source sap */
115         uint8_t         tbu_ctl;                /* LLC: control */
116         uint16_t        tbu_protoid;            /* protocol id */
117         uint8_t         tbu_protover;           /* protocol version */
118         uint8_t         tbu_bpdutype;           /* message type */
119 } __attribute__((__packed__));
120
121 const uint8_t bstp_etheraddr[] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
122
123 static void     bstp_initialize_port(struct bridge_softc *,
124                     struct bridge_iflist *);
125 static void     bstp_ifupdstatus(struct bridge_softc *, struct bridge_iflist *);
126 static void     bstp_enable_port(struct bridge_softc *, struct bridge_iflist *);
127 static void     bstp_disable_port(struct bridge_softc *,
128                     struct bridge_iflist *);
129 #ifdef notused
130 static void     bstp_enable_change_detection(struct bridge_iflist *);
131 static void     bstp_disable_change_detection(struct bridge_iflist *);
132 #endif /* notused */
133 static int      bstp_root_bridge(struct bridge_softc *sc);
134 static int      bstp_supersedes_port_info(struct bridge_softc *,
135                     struct bridge_iflist *, struct bstp_config_unit *);
136 static int      bstp_designated_port(struct bridge_softc *,
137                     struct bridge_iflist *);
138 static int      bstp_designated_for_some_port(struct bridge_softc *);
139 static void     bstp_transmit_config(struct bridge_softc *,
140                     struct bridge_iflist *);
141 static void     bstp_transmit_tcn(struct bridge_softc *);
142 static void     bstp_received_config_bpdu(struct bridge_softc *,
143                     struct bridge_iflist *, struct bstp_config_unit *);
144 static void     bstp_received_tcn_bpdu(struct bridge_softc *,
145                     struct bridge_iflist *, struct bstp_tcn_unit *);
146 static void     bstp_record_config_information(struct bridge_softc *,
147                     struct bridge_iflist *, struct bstp_config_unit *);
148 static void     bstp_record_config_timeout_values(struct bridge_softc *,
149                     struct bstp_config_unit *);
150 static void     bstp_config_bpdu_generation(struct bridge_softc *);
151 static void     bstp_send_config_bpdu(struct bridge_softc *,
152                     struct bridge_iflist *, struct bstp_config_unit *);
153 static void     bstp_configuration_update(struct bridge_softc *);
154 static void     bstp_root_selection(struct bridge_softc *);
155 static void     bstp_designated_port_selection(struct bridge_softc *);
156 static void     bstp_become_designated_port(struct bridge_softc *,
157                     struct bridge_iflist *);
158 static void     bstp_port_state_selection(struct bridge_softc *);
159 static void     bstp_make_forwarding(struct bridge_softc *,
160                     struct bridge_iflist *);
161 static void     bstp_make_blocking(struct bridge_softc *,
162                     struct bridge_iflist *);
163 static void     bstp_set_port_state(struct bridge_iflist *, uint8_t);
164 #ifdef notused
165 static void     bstp_set_bridge_priority(struct bridge_softc *, uint64_t);
166 static void     bstp_set_port_priority(struct bridge_softc *,
167                     struct bridge_iflist *, uint16_t);
168 static void     bstp_set_path_cost(struct bridge_softc *,
169                     struct bridge_iflist *, uint32_t);
170 #endif /* notused */
171 static void     bstp_topology_change_detection(struct bridge_softc *);
172 static void     bstp_topology_change_acknowledged(struct bridge_softc *);
173 static void     bstp_acknowledge_topology_change(struct bridge_softc *,
174                     struct bridge_iflist *);
175
176 static void     bstp_tick(void *);
177 static void     bstp_timer_start(struct bridge_timer *, uint16_t);
178 static void     bstp_timer_stop(struct bridge_timer *);
179 static int      bstp_timer_expired(struct bridge_timer *, uint16_t);
180
181 static void     bstp_hold_timer_expiry(struct bridge_softc *,
182                     struct bridge_iflist *);
183 static void     bstp_message_age_timer_expiry(struct bridge_softc *,
184                     struct bridge_iflist *);
185 static void     bstp_forward_delay_timer_expiry(struct bridge_softc *,
186                     struct bridge_iflist *);
187 static void     bstp_topology_change_timer_expiry(struct bridge_softc *);
188 static void     bstp_tcn_timer_expiry(struct bridge_softc *);
189 static void     bstp_hello_timer_expiry(struct bridge_softc *);
190 static int      bstp_addr_cmp(const uint8_t *, const uint8_t *);
191
192 static void
193 bstp_transmit_config(struct bridge_softc *sc, struct bridge_iflist *bif)
194 {
195         if (bif->bif_hold_timer.active) {
196                 bif->bif_config_pending = 1;
197                 return;
198         }
199
200         bif->bif_config_bpdu.cu_message_type = BSTP_MSGTYPE_CFG;
201         bif->bif_config_bpdu.cu_rootid = sc->sc_designated_root;
202         bif->bif_config_bpdu.cu_root_path_cost = sc->sc_root_path_cost;
203         bif->bif_config_bpdu.cu_bridge_id = sc->sc_bridge_id;
204         bif->bif_config_bpdu.cu_port_id = bif->bif_port_id;
205
206         if (bstp_root_bridge(sc)) {
207                 bif->bif_config_bpdu.cu_message_age = 0;
208         } else {
209                 bif->bif_config_bpdu.cu_message_age =
210                     sc->sc_root_port->bifi_message_age_timer.value +
211                     BSTP_MESSAGE_AGE_INCR;
212         }
213
214         bif->bif_config_bpdu.cu_max_age = sc->sc_max_age;
215         bif->bif_config_bpdu.cu_hello_time = sc->sc_hello_time;
216         bif->bif_config_bpdu.cu_forward_delay = sc->sc_forward_delay;
217         bif->bif_config_bpdu.cu_topology_change_acknowledgment
218             = bif->bif_topology_change_acknowledge;
219         bif->bif_config_bpdu.cu_topology_change = sc->sc_topology_change;
220
221         if (bif->bif_config_bpdu.cu_message_age < sc->sc_max_age) {
222                 bif->bif_topology_change_acknowledge = 0;
223                 bif->bif_config_pending = 0;
224                 bstp_send_config_bpdu(sc, bif, &bif->bif_config_bpdu);
225                 bstp_timer_start(&bif->bif_hold_timer, 0);
226         }
227 }
228
229 static void
230 bstp_send_config_bpdu(struct bridge_softc *sc, struct bridge_iflist *bif,
231     struct bstp_config_unit *cu)
232 {
233         struct ifnet *ifp;
234         struct mbuf *m;
235         struct ether_header *eh;
236         struct bstp_cbpdu bpdu;
237
238         ifp = bif->bif_ifp;
239
240         if ((ifp->if_flags & IFF_RUNNING) == 0)
241                 return;
242
243         MGETHDR(m, MB_DONTWAIT, MT_DATA);
244         if (m == NULL)
245                 return;
246
247         eh = mtod(m, struct ether_header *);
248
249         m->m_pkthdr.rcvif = ifp;
250         m->m_pkthdr.len = sizeof(*eh) + sizeof(bpdu);
251         m->m_len = m->m_pkthdr.len;
252
253         bpdu.cbu_ssap = bpdu.cbu_dsap = LLC_8021D_LSAP;
254         bpdu.cbu_ctl = LLC_UI;
255         bpdu.cbu_protoid = htons(0);
256         bpdu.cbu_protover = 0;
257         bpdu.cbu_bpdutype = cu->cu_message_type;
258         bpdu.cbu_flags = (cu->cu_topology_change ? BSTP_FLAG_TC : 0) |
259             (cu->cu_topology_change_acknowledgment ? BSTP_FLAG_TCA : 0);
260
261         bpdu.cbu_rootpri = htons(cu->cu_rootid >> 48);
262         bpdu.cbu_rootaddr[0] = cu->cu_rootid >> 40;
263         bpdu.cbu_rootaddr[1] = cu->cu_rootid >> 32;
264         bpdu.cbu_rootaddr[2] = cu->cu_rootid >> 24;
265         bpdu.cbu_rootaddr[3] = cu->cu_rootid >> 16;
266         bpdu.cbu_rootaddr[4] = cu->cu_rootid >> 8;
267         bpdu.cbu_rootaddr[5] = cu->cu_rootid >> 0;
268
269         bpdu.cbu_rootpathcost = htonl(cu->cu_root_path_cost);
270
271         bpdu.cbu_bridgepri = htons(cu->cu_bridge_id >> 48);
272         bpdu.cbu_bridgeaddr[0] = cu->cu_bridge_id >> 40;
273         bpdu.cbu_bridgeaddr[1] = cu->cu_bridge_id >> 32;
274         bpdu.cbu_bridgeaddr[2] = cu->cu_bridge_id >> 24;
275         bpdu.cbu_bridgeaddr[3] = cu->cu_bridge_id >> 16;
276         bpdu.cbu_bridgeaddr[4] = cu->cu_bridge_id >> 8;
277         bpdu.cbu_bridgeaddr[5] = cu->cu_bridge_id >> 0;
278
279         bpdu.cbu_portid = htons(cu->cu_port_id);
280         bpdu.cbu_messageage = htons(cu->cu_message_age);
281         bpdu.cbu_maxage = htons(cu->cu_max_age);
282         bpdu.cbu_hellotime = htons(cu->cu_hello_time);
283         bpdu.cbu_forwarddelay = htons(cu->cu_forward_delay);
284
285         memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN);
286         memcpy(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN);
287         eh->ether_type = htons(sizeof(bpdu));
288
289         memcpy(mtod(m, caddr_t) + sizeof(*eh), &bpdu, sizeof(bpdu));
290
291         bridge_enqueue(ifp, m);
292 }
293
294 static int
295 bstp_root_bridge(struct bridge_softc *sc)
296 {
297         return (sc->sc_designated_root == sc->sc_bridge_id);
298 }
299
300 static int
301 bstp_supersedes_port_info(struct bridge_softc *sc, struct bridge_iflist *bif,
302     struct bstp_config_unit *cu)
303 {
304         if (cu->cu_rootid < bif->bif_designated_root)
305                 return (1);
306         if (cu->cu_rootid > bif->bif_designated_root)
307                 return (0);
308
309         if (cu->cu_root_path_cost < bif->bif_designated_cost)
310                 return (1);
311         if (cu->cu_root_path_cost > bif->bif_designated_cost)
312                 return (0);
313
314         if (cu->cu_bridge_id < bif->bif_designated_bridge)
315                 return (1);
316         if (cu->cu_bridge_id > bif->bif_designated_bridge)
317                 return (0);
318
319         if (sc->sc_bridge_id != cu->cu_bridge_id)
320                 return (1);
321         if (cu->cu_port_id <= bif->bif_designated_port)
322                 return (1);
323         return (0);
324 }
325
326 static void
327 bstp_record_config_information(struct bridge_softc *sc,
328     struct bridge_iflist *bif, struct bstp_config_unit *cu)
329 {
330         bif->bif_designated_root = cu->cu_rootid;
331         bif->bif_designated_cost = cu->cu_root_path_cost;
332         bif->bif_designated_bridge = cu->cu_bridge_id;
333         bif->bif_designated_port = cu->cu_port_id;
334         bstp_timer_start(&bif->bif_message_age_timer, cu->cu_message_age);
335 }
336
337 static void
338 bstp_record_config_timeout_values(struct bridge_softc *sc,
339     struct bstp_config_unit *config)
340 {
341         sc->sc_max_age = config->cu_max_age;
342         sc->sc_hello_time = config->cu_hello_time;
343         sc->sc_forward_delay = config->cu_forward_delay;
344         sc->sc_topology_change = config->cu_topology_change;
345 }
346
347 static void
348 bstp_config_bpdu_generation(struct bridge_softc *sc)
349 {
350         struct bridge_iflist *bif, *nbif;
351
352         LIST_FOREACH_MUTABLE(bif, &sc->sc_iflists[mycpuid], bif_next, nbif) {
353                 if ((bif->bif_flags & IFBIF_STP) == 0)
354                         continue;
355                 if (bstp_designated_port(sc, bif) &&
356                     (bif->bif_state != BSTP_IFSTATE_DISABLED))
357                         bstp_transmit_config(sc, bif);
358
359                 if (nbif != NULL && !nbif->bif_onlist) {
360                         KKASSERT(bif->bif_onlist);
361                         nbif = LIST_NEXT(bif, bif_next);
362                 }
363         }
364 }
365
366 static int
367 bstp_designated_port(struct bridge_softc *sc, struct bridge_iflist *bif)
368 {
369         return ((bif->bif_designated_bridge == sc->sc_bridge_id)
370             && (bif->bif_designated_port == bif->bif_port_id));
371 }
372
373 static void
374 bstp_transmit_tcn(struct bridge_softc *sc)
375 {
376         struct bstp_tbpdu bpdu;
377         struct ifnet *ifp = sc->sc_root_port->bifi_ifp;
378         struct ether_header *eh;
379         struct mbuf *m;
380
381         if ((ifp->if_flags & IFF_RUNNING) == 0)
382                 return;
383
384         MGETHDR(m, MB_DONTWAIT, MT_DATA);
385         if (m == NULL)
386                 return;
387
388         m->m_pkthdr.rcvif = ifp;
389         m->m_pkthdr.len = sizeof(*eh) + sizeof(bpdu);
390         m->m_len = m->m_pkthdr.len;
391
392         eh = mtod(m, struct ether_header *);
393
394         memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN);
395         memcpy(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN);
396         eh->ether_type = htons(sizeof(bpdu));
397
398         bpdu.tbu_ssap = bpdu.tbu_dsap = LLC_8021D_LSAP;
399         bpdu.tbu_ctl = LLC_UI;
400         bpdu.tbu_protoid = 0;
401         bpdu.tbu_protover = 0;
402         bpdu.tbu_bpdutype = BSTP_MSGTYPE_TCN;
403
404         memcpy(mtod(m, caddr_t) + sizeof(*eh), &bpdu, sizeof(bpdu));
405
406         bridge_enqueue(ifp, m);
407 }
408
409 static void
410 bstp_configuration_update(struct bridge_softc *sc)
411 {
412         bstp_root_selection(sc);
413         bstp_designated_port_selection(sc);
414 }
415
416 static void
417 bstp_root_selection(struct bridge_softc *sc)
418 {
419         struct bridge_iflist *root_port = NULL, *bif;
420
421         LIST_FOREACH(bif, &sc->sc_iflists[mycpuid], bif_next) {
422                 if ((bif->bif_flags & IFBIF_STP) == 0)
423                         continue;
424                 if (bstp_designated_port(sc, bif))
425                         continue;
426                 if (bif->bif_state == BSTP_IFSTATE_DISABLED)
427                         continue;
428                 if (bif->bif_designated_root >= sc->sc_bridge_id)
429                         continue;
430                 if (root_port == NULL)
431                         goto set_port;
432
433                 if (bif->bif_designated_root < root_port->bif_designated_root)
434                         goto set_port;
435                 if (bif->bif_designated_root > root_port->bif_designated_root)
436                         continue;
437
438                 if ((bif->bif_designated_cost + bif->bif_path_cost) <
439                     (root_port->bif_designated_cost + root_port->bif_path_cost))
440                         goto set_port;
441                 if ((bif->bif_designated_cost + bif->bif_path_cost) >
442                     (root_port->bif_designated_cost + root_port->bif_path_cost))
443                         continue;
444
445                 if (bif->bif_designated_bridge <
446                     root_port->bif_designated_bridge)
447                         goto set_port;
448                 if (bif->bif_designated_bridge >
449                     root_port->bif_designated_bridge)
450                         continue;
451
452                 if (bif->bif_designated_port < root_port->bif_designated_port)
453                         goto set_port;
454                 if (bif->bif_designated_port > root_port->bif_designated_port)
455                         continue;
456
457                 if (bif->bif_port_id >= root_port->bif_port_id)
458                         continue;
459 set_port:
460                 root_port = bif;
461         }
462
463         if (root_port == NULL) {
464                 sc->sc_root_port = NULL;
465                 sc->sc_designated_root = sc->sc_bridge_id;
466                 sc->sc_root_path_cost = 0;
467         } else {
468                 sc->sc_root_port = root_port->bif_info;
469                 sc->sc_designated_root = root_port->bif_designated_root;
470                 sc->sc_root_path_cost = root_port->bif_designated_cost +
471                     root_port->bif_path_cost;
472         }
473 }
474
475 static void
476 bstp_designated_port_selection(struct bridge_softc *sc)
477 {
478         struct bridge_iflist *bif;
479
480         LIST_FOREACH(bif, &sc->sc_iflists[mycpuid], bif_next) {
481                 if ((bif->bif_flags & IFBIF_STP) == 0)
482                         continue;
483                 if (bstp_designated_port(sc, bif))
484                         goto designated;
485                 if (bif->bif_designated_root != sc->sc_designated_root)
486                         goto designated;
487
488                 if (sc->sc_root_path_cost < bif->bif_designated_cost)
489                         goto designated;
490                 if (sc->sc_root_path_cost > bif->bif_designated_cost)
491                         continue;
492
493                 if (sc->sc_bridge_id < bif->bif_designated_bridge)
494                         goto designated;
495                 if (sc->sc_bridge_id > bif->bif_designated_bridge)
496                         continue;
497
498                 if (bif->bif_port_id > bif->bif_designated_port)
499                         continue;
500 designated:
501                 bstp_become_designated_port(sc, bif);
502         }
503 }
504
505 static void
506 bstp_become_designated_port(struct bridge_softc *sc, struct bridge_iflist *bif)
507 {
508         bif->bif_designated_root = sc->sc_designated_root;
509         bif->bif_designated_cost = sc->sc_root_path_cost;
510         bif->bif_designated_bridge = sc->sc_bridge_id;
511         bif->bif_designated_port = bif->bif_port_id;
512 }
513
514 static void
515 bstp_port_state_selection(struct bridge_softc *sc)
516 {
517         struct bridge_iflist *bif, *nbif;
518
519         LIST_FOREACH_MUTABLE(bif, &sc->sc_iflists[mycpuid], bif_next, nbif) {
520                 if ((bif->bif_flags & IFBIF_STP) == 0)
521                         continue;
522                 if (bif->bif_info == sc->sc_root_port) {
523                         bif->bif_config_pending = 0;
524                         bif->bif_topology_change_acknowledge = 0;
525                         bstp_make_forwarding(sc, bif);
526                 } else if (bstp_designated_port(sc, bif)) {
527                         bstp_timer_stop(&bif->bif_message_age_timer);
528                         bstp_make_forwarding(sc, bif);
529                 } else {
530                         bif->bif_config_pending = 0;
531                         bif->bif_topology_change_acknowledge = 0;
532                         bstp_make_blocking(sc, bif);
533                 }
534
535                 if (nbif != NULL && !nbif->bif_onlist) {
536                         KKASSERT(bif->bif_onlist);
537                         nbif = LIST_NEXT(bif, bif_next);
538                 }
539         }
540 }
541
542 static void
543 bstp_make_forwarding(struct bridge_softc *sc, struct bridge_iflist *bif)
544 {
545         if (bif->bif_state == BSTP_IFSTATE_BLOCKING) {
546                 bstp_set_port_state(bif, BSTP_IFSTATE_LISTENING);
547                 bstp_timer_start(&bif->bif_forward_delay_timer, 0);
548         }
549 }
550
551 static void
552 bstp_make_blocking(struct bridge_softc *sc, struct bridge_iflist *bif)
553 {
554         if ((bif->bif_state != BSTP_IFSTATE_DISABLED) &&
555             (bif->bif_state != BSTP_IFSTATE_BLOCKING)) {
556                 if ((bif->bif_state == BSTP_IFSTATE_FORWARDING) ||
557                     (bif->bif_state == BSTP_IFSTATE_LEARNING)) {
558                         if (bif->bif_change_detection_enabled) {
559                                 bstp_topology_change_detection(sc);
560                         }
561                 }
562                 bstp_set_port_state(bif, BSTP_IFSTATE_BLOCKING);
563                 bridge_rtdelete(sc, bif->bif_ifp, IFBF_FLUSHDYN);
564                 bstp_timer_stop(&bif->bif_forward_delay_timer);
565         }
566 }
567
568 static void
569 bstp_set_port_state(struct bridge_iflist *bif, uint8_t state)
570 {
571         bif->bif_state = state;
572 }
573
574 static void
575 bstp_topology_change_detection(struct bridge_softc *sc)
576 {
577         if (bstp_root_bridge(sc)) {
578                 sc->sc_topology_change = 1;
579                 bstp_timer_start(&sc->sc_topology_change_timer, 0);
580         } else if (!sc->sc_topology_change_detected) {
581                 bstp_transmit_tcn(sc);
582                 bstp_timer_start(&sc->sc_tcn_timer, 0);
583         }
584         sc->sc_topology_change_detected = 1;
585 }
586
587 static void
588 bstp_topology_change_acknowledged(struct bridge_softc *sc)
589 {
590         sc->sc_topology_change_detected = 0;
591         bstp_timer_stop(&sc->sc_tcn_timer);
592 }
593
594 static void
595 bstp_acknowledge_topology_change(struct bridge_softc *sc,
596     struct bridge_iflist *bif)
597 {
598         bif->bif_topology_change_acknowledge = 1;
599         bstp_transmit_config(sc, bif);
600 }
601
602 void
603 bstp_input(struct bridge_softc *sc, struct bridge_iflist *bif, struct mbuf *m)
604 {
605         struct ether_header *eh;
606         struct bstp_tbpdu tpdu;
607         struct bstp_cbpdu cpdu;
608         struct bstp_config_unit cu;
609         struct bstp_tcn_unit tu;
610         uint16_t len;
611
612         if ((bif->bif_flags & IFBIF_STP) == 0)
613                 goto out;
614
615         eh = mtod(m, struct ether_header *);
616
617         len = ntohs(eh->ether_type);
618         if (len < sizeof(tpdu))
619                 goto out;
620
621         m_adj(m, ETHER_HDR_LEN);
622
623         if (m->m_pkthdr.len > len)
624                 m_adj(m, len - m->m_pkthdr.len);
625         if (m->m_len < sizeof(tpdu) &&
626             (m = m_pullup(m, sizeof(tpdu))) == NULL)
627                 goto out;
628
629         memcpy(&tpdu, mtod(m, caddr_t), sizeof(tpdu));
630
631         if (tpdu.tbu_dsap != LLC_8021D_LSAP ||
632             tpdu.tbu_ssap != LLC_8021D_LSAP ||
633             tpdu.tbu_ctl != LLC_UI)
634                 goto out;
635         if (tpdu.tbu_protoid != 0 || tpdu.tbu_protover != 0)
636                 goto out;
637
638         switch (tpdu.tbu_bpdutype) {
639         case BSTP_MSGTYPE_TCN:
640                 tu.tu_message_type = tpdu.tbu_bpdutype;
641                 bstp_received_tcn_bpdu(sc, bif, &tu);
642                 break;
643         case BSTP_MSGTYPE_CFG:
644                 if (m->m_len < sizeof(cpdu) &&
645                     (m = m_pullup(m, sizeof(cpdu))) == NULL)
646                         goto out;
647                 memcpy(&cpdu, mtod(m, caddr_t), sizeof(cpdu));
648
649                 cu.cu_rootid =
650                     (((uint64_t)ntohs(cpdu.cbu_rootpri)) << 48) |
651                     (((uint64_t)cpdu.cbu_rootaddr[0]) << 40) |
652                     (((uint64_t)cpdu.cbu_rootaddr[1]) << 32) |
653                     (((uint64_t)cpdu.cbu_rootaddr[2]) << 24) |
654                     (((uint64_t)cpdu.cbu_rootaddr[3]) << 16) |
655                     (((uint64_t)cpdu.cbu_rootaddr[4]) << 8) |
656                     (((uint64_t)cpdu.cbu_rootaddr[5]) << 0);
657
658                 cu.cu_bridge_id =
659                     (((uint64_t)ntohs(cpdu.cbu_bridgepri)) << 48) |
660                     (((uint64_t)cpdu.cbu_bridgeaddr[0]) << 40) |
661                     (((uint64_t)cpdu.cbu_bridgeaddr[1]) << 32) |
662                     (((uint64_t)cpdu.cbu_bridgeaddr[2]) << 24) |
663                     (((uint64_t)cpdu.cbu_bridgeaddr[3]) << 16) |
664                     (((uint64_t)cpdu.cbu_bridgeaddr[4]) << 8) |
665                     (((uint64_t)cpdu.cbu_bridgeaddr[5]) << 0);
666
667                 cu.cu_root_path_cost = ntohl(cpdu.cbu_rootpathcost);
668                 cu.cu_message_age = ntohs(cpdu.cbu_messageage);
669                 cu.cu_max_age = ntohs(cpdu.cbu_maxage);
670                 cu.cu_hello_time = ntohs(cpdu.cbu_hellotime);
671                 cu.cu_forward_delay = ntohs(cpdu.cbu_forwarddelay);
672                 cu.cu_port_id = ntohs(cpdu.cbu_portid);
673                 cu.cu_message_type = cpdu.cbu_bpdutype;
674                 cu.cu_topology_change_acknowledgment =
675                     (cpdu.cbu_flags & BSTP_FLAG_TCA) ? 1 : 0;
676                 cu.cu_topology_change =
677                     (cpdu.cbu_flags & BSTP_FLAG_TC) ? 1 : 0;
678                 bstp_received_config_bpdu(sc, bif, &cu);
679                 break;
680         default:
681                 goto out;
682         }
683 out:
684         if (m)
685                 m_freem(m);
686 }
687
688 static void
689 bstp_received_config_bpdu(struct bridge_softc *sc, struct bridge_iflist *bif,
690     struct bstp_config_unit *cu)
691 {
692         int root;
693
694         root = bstp_root_bridge(sc);
695
696         if (bif->bif_state != BSTP_IFSTATE_DISABLED) {
697                 if (bstp_supersedes_port_info(sc, bif, cu)) {
698                         bstp_record_config_information(sc, bif, cu);
699                         bstp_configuration_update(sc);
700                         bstp_port_state_selection(sc);
701
702                         if ((bstp_root_bridge(sc) == 0) && root) {
703                                 bstp_timer_stop(&sc->sc_hello_timer);
704
705                                 if (sc->sc_topology_change_detected) {
706                                         bstp_timer_stop(
707                                             &sc->sc_topology_change_timer);
708                                         bstp_transmit_tcn(sc);
709                                         bstp_timer_start(&sc->sc_tcn_timer, 0);
710                                 }
711                         }
712
713                         if (bif->bif_info == sc->sc_root_port) {
714                                 bstp_record_config_timeout_values(sc, cu);
715                                 bstp_config_bpdu_generation(sc);
716
717                                 if (cu->cu_topology_change_acknowledgment)
718                                         bstp_topology_change_acknowledged(sc);
719                         }
720                 } else if (bstp_designated_port(sc, bif))
721                         bstp_transmit_config(sc, bif);
722         }
723 }
724
725 static void
726 bstp_received_tcn_bpdu(struct bridge_softc *sc, struct bridge_iflist *bif,
727     struct bstp_tcn_unit *tcn)
728 {
729         if (bif->bif_state != BSTP_IFSTATE_DISABLED &&
730             bstp_designated_port(sc, bif)) {
731                 bstp_topology_change_detection(sc);
732                 bstp_acknowledge_topology_change(sc, bif);
733         }
734 }
735
736 static void
737 bstp_hello_timer_expiry(struct bridge_softc *sc)
738 {
739         bstp_config_bpdu_generation(sc);
740         bstp_timer_start(&sc->sc_hello_timer, 0);
741 }
742
743 static void
744 bstp_message_age_timer_expiry(struct bridge_softc *sc,
745     struct bridge_iflist *bif)
746 {
747         int root;
748
749         root = bstp_root_bridge(sc);
750         bstp_become_designated_port(sc, bif);
751         bstp_configuration_update(sc);
752         bstp_port_state_selection(sc);
753
754         if ((bstp_root_bridge(sc)) && (root == 0)) {
755                 sc->sc_max_age = sc->sc_bridge_max_age;
756                 sc->sc_hello_time = sc->sc_bridge_hello_time;
757                 sc->sc_forward_delay = sc->sc_bridge_forward_delay;
758
759                 bstp_topology_change_detection(sc);
760                 bstp_timer_stop(&sc->sc_tcn_timer);
761                 bstp_config_bpdu_generation(sc);
762                 bstp_timer_start(&sc->sc_hello_timer, 0);
763         }
764 }
765
766 static void
767 bstp_forward_delay_timer_expiry(struct bridge_softc *sc,
768     struct bridge_iflist *bif)
769 {
770         if (bif->bif_state == BSTP_IFSTATE_LISTENING) {
771                 bstp_set_port_state(bif, BSTP_IFSTATE_LEARNING);
772                 bstp_timer_start(&bif->bif_forward_delay_timer, 0);
773         } else if (bif->bif_state == BSTP_IFSTATE_LEARNING) {
774                 bstp_set_port_state(bif, BSTP_IFSTATE_FORWARDING);
775                 if (bstp_designated_for_some_port(sc) &&
776                     bif->bif_change_detection_enabled)
777                         bstp_topology_change_detection(sc);
778         }
779 }
780
781 static int
782 bstp_designated_for_some_port(struct bridge_softc *sc)
783 {
784
785         struct bridge_iflist *bif;
786
787         LIST_FOREACH(bif, &sc->sc_iflists[mycpuid], bif_next) {
788                 if ((bif->bif_flags & IFBIF_STP) == 0)
789                         continue;
790                 if (bif->bif_designated_bridge == sc->sc_bridge_id)
791                         return (1);
792         }
793         return (0);
794 }
795
796 static void
797 bstp_tcn_timer_expiry(struct bridge_softc *sc)
798 {
799         bstp_transmit_tcn(sc);
800         bstp_timer_start(&sc->sc_tcn_timer, 0);
801 }
802
803 static void
804 bstp_topology_change_timer_expiry(struct bridge_softc *sc)
805 {
806         sc->sc_topology_change_detected = 0;
807         sc->sc_topology_change = 0;
808 }
809
810 static void
811 bstp_hold_timer_expiry(struct bridge_softc *sc, struct bridge_iflist *bif)
812 {
813         if (bif->bif_config_pending)
814                 bstp_transmit_config(sc, bif);
815 }
816
817 static int
818 bstp_addr_cmp(const uint8_t *a, const uint8_t *b)
819 {
820         int i, d;
821
822         for (i = 0, d = 0; i < ETHER_ADDR_LEN && d == 0; i++) {
823                 d = ((int)a[i]) - ((int)b[i]);
824         }
825
826         return (d);
827 }
828
829 void
830 bstp_initialization(struct bridge_softc *sc)
831 {
832         struct bridge_iflist *bif, *mif, *nbif;
833         u_char *e_addr;
834
835         KKASSERT(&curthread->td_msgport == BRIDGE_CFGPORT);
836
837         mif = NULL;
838         LIST_FOREACH(bif, &sc->sc_iflists[mycpuid], bif_next) {
839                 if ((bif->bif_flags & IFBIF_STP) == 0)
840                         continue;
841                 if (bif->bif_ifp->if_type != IFT_ETHER)
842                         continue;
843                 bif->bif_port_id = (bif->bif_priority << 8) |
844                     (bif->bif_ifp->if_index & 0xff);
845
846                 if (mif == NULL) {
847                         mif = bif;
848                         continue;
849                 }
850                 if (bstp_addr_cmp(IF_LLADDR(bif->bif_ifp),
851                     IF_LLADDR(mif->bif_ifp)) < 0) {
852                         mif = bif;
853                         continue;
854                 }
855         }
856         if (mif == NULL) {
857                 bstp_stop(sc);
858                 return;
859         }
860
861         e_addr = IF_LLADDR(mif->bif_ifp);
862         sc->sc_bridge_id =
863             (((uint64_t)sc->sc_bridge_priority) << 48) |
864             (((uint64_t)e_addr[0]) << 40) |
865             (((uint64_t)e_addr[1]) << 32) |
866             (((uint64_t)e_addr[2]) << 24) |
867             (((uint64_t)e_addr[3]) << 16) |
868             (((uint64_t)e_addr[4]) << 8) |
869             (((uint64_t)e_addr[5]));
870
871         sc->sc_designated_root = sc->sc_bridge_id;
872         sc->sc_root_path_cost = 0;
873         sc->sc_root_port = NULL;
874
875         sc->sc_max_age = sc->sc_bridge_max_age;
876         sc->sc_hello_time = sc->sc_bridge_hello_time;
877         sc->sc_forward_delay = sc->sc_bridge_forward_delay;
878         sc->sc_topology_change_detected = 0;
879         sc->sc_topology_change = 0;
880         bstp_timer_stop(&sc->sc_tcn_timer);
881         bstp_timer_stop(&sc->sc_topology_change_timer);
882
883         if (callout_pending(&sc->sc_bstpcallout) == 0)
884                 callout_reset(&sc->sc_bstpcallout, hz,
885                     bstp_tick, sc);
886
887         LIST_FOREACH_MUTABLE(bif, &sc->sc_iflists[mycpuid], bif_next, nbif) {
888                 if (bif->bif_flags & IFBIF_STP)
889                         bstp_ifupdstatus(sc, bif);
890                 else
891                         bstp_disable_port(sc, bif);
892
893                 if (nbif != NULL && !nbif->bif_onlist) {
894                         KKASSERT(bif->bif_onlist);
895                         nbif = LIST_NEXT(bif, bif_next);
896                 }
897         }
898
899         bstp_port_state_selection(sc);
900         bstp_config_bpdu_generation(sc);
901         bstp_timer_start(&sc->sc_hello_timer, 0);
902 }
903
904 void
905 bstp_stop(struct bridge_softc *sc)
906 {
907         struct bridge_iflist *bif;
908         struct lwkt_msg *lmsg;
909
910         KKASSERT(&curthread->td_msgport == BRIDGE_CFGPORT);
911
912         LIST_FOREACH(bif, &sc->sc_iflists[mycpuid], bif_next) {
913                 bstp_set_port_state(bif, BSTP_IFSTATE_DISABLED);
914                 bstp_timer_stop(&bif->bif_hold_timer);
915                 bstp_timer_stop(&bif->bif_message_age_timer);
916                 bstp_timer_stop(&bif->bif_forward_delay_timer);
917         }
918
919         callout_stop(&sc->sc_bstpcallout);
920
921         bstp_timer_stop(&sc->sc_topology_change_timer);
922         bstp_timer_stop(&sc->sc_tcn_timer);
923         bstp_timer_stop(&sc->sc_hello_timer);
924
925         crit_enter();
926         lmsg = &sc->sc_bstptimemsg.nm_lmsg;
927         if ((lmsg->ms_flags & MSGF_DONE) == 0) {
928                 /* Pending to be processed; drop it */
929                 lwkt_dropmsg(lmsg);
930         }
931         crit_exit();
932 }
933
934 static void
935 bstp_initialize_port(struct bridge_softc *sc, struct bridge_iflist *bif)
936 {
937         bstp_become_designated_port(sc, bif);
938         bstp_set_port_state(bif, BSTP_IFSTATE_BLOCKING);
939         bif->bif_topology_change_acknowledge = 0;
940         bif->bif_config_pending = 0;
941         bif->bif_change_detection_enabled = 1;
942         bstp_timer_stop(&bif->bif_message_age_timer);
943         bstp_timer_stop(&bif->bif_forward_delay_timer);
944         bstp_timer_stop(&bif->bif_hold_timer);
945 }
946
947 static void
948 bstp_enable_port(struct bridge_softc *sc, struct bridge_iflist *bif)
949 {
950         bstp_initialize_port(sc, bif);
951         bstp_port_state_selection(sc);
952 }
953
954 static void
955 bstp_disable_port(struct bridge_softc *sc, struct bridge_iflist *bif)
956 {
957         int root;
958
959         root = bstp_root_bridge(sc);
960         bstp_become_designated_port(sc, bif);
961         bstp_set_port_state(bif, BSTP_IFSTATE_DISABLED);
962         bif->bif_topology_change_acknowledge = 0;
963         bif->bif_config_pending = 0;
964         bstp_timer_stop(&bif->bif_message_age_timer);
965         bstp_timer_stop(&bif->bif_forward_delay_timer);
966         bstp_configuration_update(sc);
967         bstp_port_state_selection(sc);
968         bridge_rtdelete(sc, bif->bif_ifp, IFBF_FLUSHDYN);
969
970         if (bstp_root_bridge(sc) && (root == 0)) {
971                 sc->sc_max_age = sc->sc_bridge_max_age;
972                 sc->sc_hello_time = sc->sc_bridge_hello_time;
973                 sc->sc_forward_delay = sc->sc_bridge_forward_delay;
974
975                 bstp_topology_change_detection(sc);
976                 bstp_timer_stop(&sc->sc_tcn_timer);
977                 bstp_config_bpdu_generation(sc);
978                 bstp_timer_start(&sc->sc_hello_timer, 0);
979         }
980 }
981
982 #ifdef notused
983 static void
984 bstp_set_bridge_priority(struct bridge_softc *sc, uint64_t new_bridge_id)
985 {
986         struct bridge_iflist *bif;
987         int root;
988
989         root = bstp_root_bridge(sc);
990
991         LIST_FOREACH(bif, &sc->sc_iflists[mycpuid], bif_next) {
992                 if ((bif->bif_flags & IFBIF_STP) == 0)
993                         continue;
994                 if (bstp_designated_port(sc, bif))
995                         bif->bif_designated_bridge = new_bridge_id;
996         }
997
998         sc->sc_bridge_id = new_bridge_id;
999
1000         bstp_configuration_update(sc);
1001         bstp_port_state_selection(sc);
1002
1003         if (bstp_root_bridge(sc) && (root == 0)) {
1004                 sc->sc_max_age = sc->sc_bridge_max_age;
1005                 sc->sc_hello_time = sc->sc_bridge_hello_time;
1006                 sc->sc_forward_delay = sc->sc_bridge_forward_delay;
1007
1008                 bstp_topology_change_detection(sc);
1009                 bstp_timer_stop(&sc->sc_tcn_timer);
1010                 bstp_config_bpdu_generation(sc);
1011                 bstp_timer_start(&sc->sc_hello_timer, 0);
1012         }
1013 }
1014
1015 static void
1016 bstp_set_port_priority(struct bridge_softc *sc, struct bridge_iflist *bif,
1017     uint16_t new_port_id)
1018 {
1019         if (bstp_designated_port(sc, bif))
1020                 bif->bif_designated_port = new_port_id;
1021
1022         bif->bif_port_id = new_port_id;
1023
1024         if ((sc->sc_bridge_id == bif->bif_designated_bridge) &&
1025             (bif->bif_port_id < bif->bif_designated_port)) {
1026                 bstp_become_designated_port(sc, bif);
1027                 bstp_port_state_selection(sc);
1028         }
1029 }
1030
1031 static void
1032 bstp_set_path_cost(struct bridge_softc *sc, struct bridge_iflist *bif,
1033     uint32_t path_cost)
1034 {
1035         bif->bif_path_cost = path_cost;
1036         bstp_configuration_update(sc);
1037         bstp_port_state_selection(sc);
1038 }
1039
1040 static void
1041 bstp_enable_change_detection(struct bridge_iflist *bif)
1042 {
1043         bif->bif_change_detection_enabled = 1;
1044 }
1045
1046 static void
1047 bstp_disable_change_detection(struct bridge_iflist *bif)
1048 {
1049         bif->bif_change_detection_enabled = 0;
1050 }
1051 #endif /* notused */
1052
1053 void
1054 bstp_linkstate(struct ifnet *ifp, int state)
1055 {
1056         struct bridge_softc *sc;
1057         struct bridge_iflist *bif;
1058
1059         sc = ifp->if_bridge;
1060         ifnet_serialize_all(sc->sc_ifp);
1061
1062         /*
1063          * bstp_ifupdstatus() may block, but it is the last
1064          * operation of the member iface iteration, so we
1065          * don't need to use LIST_FOREACH_MUTABLE()+bif_onlist
1066          * check here.
1067          */
1068         LIST_FOREACH(bif, &sc->sc_iflists[mycpuid], bif_next) {
1069                 if ((bif->bif_flags & IFBIF_STP) == 0)
1070                         continue;
1071
1072                 if (bif->bif_ifp == ifp) {
1073                         bstp_ifupdstatus(sc, bif);
1074                         break;
1075                 }
1076         }
1077         ifnet_deserialize_all(sc->sc_ifp);
1078 }
1079
1080 static void
1081 bstp_ifupdstatus(struct bridge_softc *sc, struct bridge_iflist *bif)
1082 {
1083         struct ifnet *ifp = bif->bif_ifp;
1084         struct ifmediareq ifmr;
1085         int error = 0;
1086
1087         bzero((char *)&ifmr, sizeof(ifmr));
1088         ifnet_serialize_all(ifp);
1089         error = (*ifp->if_ioctl)(ifp, SIOCGIFMEDIA, (caddr_t)&ifmr, NULL);
1090         ifnet_deserialize_all(ifp);
1091
1092         if ((error == 0) && (ifp->if_flags & IFF_UP)) {
1093                 if (ifmr.ifm_status & IFM_ACTIVE) {
1094                         if (bif->bif_state == BSTP_IFSTATE_DISABLED)
1095                                 bstp_enable_port(sc, bif);
1096
1097                 } else {
1098                         if (bif->bif_state != BSTP_IFSTATE_DISABLED)
1099                                 bstp_disable_port(sc, bif);
1100                 }
1101                 return;
1102         }
1103
1104         if (bif->bif_state != BSTP_IFSTATE_DISABLED)
1105                 bstp_disable_port(sc, bif);
1106 }
1107
1108 static void
1109 bstp_tick(void *arg)
1110 {
1111         struct bridge_softc *sc = arg;
1112         struct lwkt_msg *lmsg;
1113
1114         KKASSERT(mycpuid == BRIDGE_CFGCPU);
1115
1116         crit_enter();
1117
1118         if (callout_pending(&sc->sc_bstpcallout) ||
1119             !callout_active(&sc->sc_bstpcallout)) {
1120                 crit_exit();
1121                 return;
1122         }
1123         callout_deactivate(&sc->sc_bstpcallout);
1124
1125         lmsg = &sc->sc_bstptimemsg.nm_lmsg;
1126         KKASSERT(lmsg->ms_flags & MSGF_DONE);
1127         lwkt_sendmsg(BRIDGE_CFGPORT, lmsg);
1128
1129         crit_exit();
1130 }
1131
1132 void
1133 bstp_tick_handler(struct netmsg *nmsg)
1134 {
1135         struct bridge_softc *sc = nmsg->nm_lmsg.u.ms_resultp;
1136         struct bridge_iflist *bif;
1137
1138         KKASSERT(&curthread->td_msgport == BRIDGE_CFGPORT);
1139         crit_enter();
1140         /* Reply ASAP */
1141         lwkt_replymsg(&nmsg->nm_lmsg, 0);
1142         crit_exit();
1143
1144         ifnet_serialize_all(sc->sc_ifp);
1145
1146         /*
1147          * NOTE:
1148          * We don't need to worry that member iface is ripped
1149          * from the per-cpu list during the blocking operation
1150          * in the loop body, since deletion is serialized by
1151          * BRIDGE_CFGPORT
1152          */
1153
1154         LIST_FOREACH(bif, &sc->sc_iflists[mycpuid], bif_next) {
1155                 if ((bif->bif_flags & IFBIF_STP) == 0)
1156                         continue;
1157                 /*
1158                  * XXX This can cause a lag in "link does away"
1159                  * XXX and "spanning tree gets updated".  We need
1160                  * XXX come sort of callback from the link state
1161                  * XXX update code to kick spanning tree.
1162                  * XXX --thorpej@NetBSD.org
1163                  */
1164                 bstp_ifupdstatus(sc, bif);
1165         }
1166
1167         if (bstp_timer_expired(&sc->sc_hello_timer, sc->sc_hello_time))
1168                 bstp_hello_timer_expiry(sc);
1169
1170         if (bstp_timer_expired(&sc->sc_tcn_timer, sc->sc_bridge_hello_time))
1171                 bstp_tcn_timer_expiry(sc);
1172
1173         if (bstp_timer_expired(&sc->sc_topology_change_timer,
1174             sc->sc_topology_change_time))
1175                 bstp_topology_change_timer_expiry(sc);
1176
1177         LIST_FOREACH(bif, &sc->sc_iflists[mycpuid], bif_next) {
1178                 if ((bif->bif_flags & IFBIF_STP) == 0)
1179                         continue;
1180                 if (bstp_timer_expired(&bif->bif_message_age_timer,
1181                     sc->sc_max_age))
1182                         bstp_message_age_timer_expiry(sc, bif);
1183         }
1184
1185         LIST_FOREACH(bif, &sc->sc_iflists[mycpuid], bif_next) {
1186                 if ((bif->bif_flags & IFBIF_STP) == 0)
1187                         continue;
1188                 if (bstp_timer_expired(&bif->bif_forward_delay_timer,
1189                     sc->sc_forward_delay))
1190                         bstp_forward_delay_timer_expiry(sc, bif);
1191
1192                 if (bstp_timer_expired(&bif->bif_hold_timer,
1193                     sc->sc_hold_time))
1194                         bstp_hold_timer_expiry(sc, bif);
1195         }
1196
1197         if (sc->sc_ifp->if_flags & IFF_RUNNING)
1198                 callout_reset(&sc->sc_bstpcallout, hz, bstp_tick, sc);
1199
1200         ifnet_deserialize_all(sc->sc_ifp);
1201 }
1202
1203 static void
1204 bstp_timer_start(struct bridge_timer *t, uint16_t v)
1205 {
1206         t->value = v;
1207         t->active = 1;
1208 }
1209
1210 static void
1211 bstp_timer_stop(struct bridge_timer *t)
1212 {
1213         t->value = 0;
1214         t->active = 0;
1215 }
1216
1217 static int
1218 bstp_timer_expired(struct bridge_timer *t, uint16_t v)
1219 {
1220         if (t->active == 0)
1221                 return (0);
1222         t->value += BSTP_TICK_VAL;
1223         if (t->value >= v) {
1224                 bstp_timer_stop(t);
1225                 return (1);
1226         }
1227         return (0);
1228
1229 }