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