]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/net/bridgestp.c
less: upgrade to v581.
[FreeBSD/FreeBSD.git] / sys / net / bridgestp.c
1 /*      $NetBSD: bridgestp.c,v 1.5 2003/11/28 08:56:48 keihan Exp $     */
2
3 /*-
4  * SPDX-License-Identifier: BSD-2-Clause-NetBSD
5  *
6  * Copyright (c) 2000 Jason L. Wright (jason@thought.net)
7  * Copyright (c) 2006 Andrew Thompson (thompsa@FreeBSD.org)
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
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  */
33
34 /*
35  * Implementation of the spanning tree protocol as defined in
36  * ISO/IEC 802.1D-2004, June 9, 2004.
37  */
38
39 #include <sys/cdefs.h>
40 __FBSDID("$FreeBSD$");
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/malloc.h>
49 #include <sys/callout.h>
50 #include <sys/module.h>
51 #include <sys/proc.h>
52 #include <sys/lock.h>
53 #include <sys/mutex.h>
54 #include <sys/taskqueue.h>
55
56 #include <net/if.h>
57 #include <net/if_var.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 #include <net/vnet.h>
63
64 #include <netinet/in.h>
65 #include <netinet/in_systm.h>
66 #include <netinet/in_var.h>
67 #include <netinet/if_ether.h>
68 #include <net/bridgestp.h>
69
70 #ifdef  BRIDGESTP_DEBUG
71 #define DPRINTF(fmt, arg...)    printf("bstp: " fmt, ##arg)
72 #else
73 #define DPRINTF(fmt, arg...)    (void)0
74 #endif
75
76 #define PV2ADDR(pv, eaddr)      do {            \
77         eaddr[0] = pv >> 40;                    \
78         eaddr[1] = pv >> 32;                    \
79         eaddr[2] = pv >> 24;                    \
80         eaddr[3] = pv >> 16;                    \
81         eaddr[4] = pv >> 8;                     \
82         eaddr[5] = pv >> 0;                     \
83 } while (0)
84
85 #define INFO_BETTER     1
86 #define INFO_SAME       0
87 #define INFO_WORSE      -1
88
89 const uint8_t bstp_etheraddr[] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
90
91 LIST_HEAD(, bstp_state) bstp_list;
92 static struct mtx       bstp_list_mtx;
93
94 static void     bstp_transmit(struct bstp_state *, struct bstp_port *);
95 static void     bstp_transmit_bpdu(struct bstp_state *, struct bstp_port *);
96 static void     bstp_transmit_tcn(struct bstp_state *, struct bstp_port *);
97 static void     bstp_decode_bpdu(struct bstp_port *, struct bstp_cbpdu *,
98                     struct bstp_config_unit *);
99 static void     bstp_send_bpdu(struct bstp_state *, struct bstp_port *,
100                     struct bstp_cbpdu *);
101 static int      bstp_pdu_flags(struct bstp_port *);
102 static void     bstp_received_stp(struct bstp_state *, struct bstp_port *,
103                     struct mbuf **, struct bstp_tbpdu *);
104 static void     bstp_received_rstp(struct bstp_state *, struct bstp_port *,
105                     struct mbuf **, struct bstp_tbpdu *);
106 static void     bstp_received_tcn(struct bstp_state *, struct bstp_port *,
107                     struct bstp_tcn_unit *);
108 static void     bstp_received_bpdu(struct bstp_state *, struct bstp_port *,
109                     struct bstp_config_unit *);
110 static int      bstp_pdu_rcvtype(struct bstp_port *, struct bstp_config_unit *);
111 static int      bstp_pdu_bettersame(struct bstp_port *, int);
112 static int      bstp_info_cmp(struct bstp_pri_vector *,
113                     struct bstp_pri_vector *);
114 static int      bstp_info_superior(struct bstp_pri_vector *,
115                     struct bstp_pri_vector *);
116 static void     bstp_assign_roles(struct bstp_state *);
117 static void     bstp_update_roles(struct bstp_state *, struct bstp_port *);
118 static void     bstp_update_state(struct bstp_state *, struct bstp_port *);
119 static void     bstp_update_tc(struct bstp_port *);
120 static void     bstp_update_info(struct bstp_port *);
121 static void     bstp_set_other_tcprop(struct bstp_port *);
122 static void     bstp_set_all_reroot(struct bstp_state *);
123 static void     bstp_set_all_sync(struct bstp_state *);
124 static void     bstp_set_port_state(struct bstp_port *, int);
125 static void     bstp_set_port_role(struct bstp_port *, int);
126 static void     bstp_set_port_proto(struct bstp_port *, int);
127 static void     bstp_set_port_tc(struct bstp_port *, int);
128 static void     bstp_set_timer_tc(struct bstp_port *);
129 static void     bstp_set_timer_msgage(struct bstp_port *);
130 static int      bstp_rerooted(struct bstp_state *, struct bstp_port *);
131 static uint32_t bstp_calc_path_cost(struct bstp_port *);
132 static void     bstp_notify_state(void *, int);
133 static void     bstp_notify_rtage(void *, int);
134 static void     bstp_ifupdstatus(void *, int);
135 static void     bstp_enable_port(struct bstp_state *, struct bstp_port *);
136 static void     bstp_disable_port(struct bstp_state *, struct bstp_port *);
137 static void     bstp_tick(void *);
138 static void     bstp_timer_start(struct bstp_timer *, uint16_t);
139 static void     bstp_timer_stop(struct bstp_timer *);
140 static void     bstp_timer_latch(struct bstp_timer *);
141 static int      bstp_timer_dectest(struct bstp_timer *);
142 static void     bstp_hello_timer_expiry(struct bstp_state *,
143                     struct bstp_port *);
144 static void     bstp_message_age_expiry(struct bstp_state *,
145                     struct bstp_port *);
146 static void     bstp_migrate_delay_expiry(struct bstp_state *,
147                     struct bstp_port *);
148 static void     bstp_edge_delay_expiry(struct bstp_state *,
149                     struct bstp_port *);
150 static int      bstp_addr_cmp(const uint8_t *, const uint8_t *);
151 static int      bstp_same_bridgeid(uint64_t, uint64_t);
152 static void     bstp_reinit(struct bstp_state *);
153
154 static void
155 bstp_transmit(struct bstp_state *bs, struct bstp_port *bp)
156 {
157         NET_EPOCH_ASSERT();
158
159         if (bs->bs_running == 0)
160                 return;
161
162         /*
163          * a PDU can only be sent if we have tx quota left and the
164          * hello timer is running.
165          */
166         if (bp->bp_hello_timer.active == 0) {
167                 /* Test if it needs to be reset */
168                 bstp_hello_timer_expiry(bs, bp);
169                 return;
170         }
171         if (bp->bp_txcount > bs->bs_txholdcount)
172                 /* Ran out of karma */
173                 return;
174
175         if (bp->bp_protover == BSTP_PROTO_RSTP) {
176                 bstp_transmit_bpdu(bs, bp);
177                 bp->bp_tc_ack = 0;
178         } else { /* STP */
179                 switch (bp->bp_role) {
180                         case BSTP_ROLE_DESIGNATED:
181                                 bstp_transmit_bpdu(bs, bp);
182                                 bp->bp_tc_ack = 0;
183                                 break;
184
185                         case BSTP_ROLE_ROOT:
186                                 bstp_transmit_tcn(bs, bp);
187                                 break;
188                 }
189         }
190         bstp_timer_start(&bp->bp_hello_timer, bp->bp_desg_htime);
191         bp->bp_flags &= ~BSTP_PORT_NEWINFO;
192 }
193
194 static void
195 bstp_transmit_bpdu(struct bstp_state *bs, struct bstp_port *bp)
196 {
197         struct bstp_cbpdu bpdu;
198
199         BSTP_LOCK_ASSERT(bs);
200
201         bpdu.cbu_rootpri = htons(bp->bp_desg_pv.pv_root_id >> 48);
202         PV2ADDR(bp->bp_desg_pv.pv_root_id, bpdu.cbu_rootaddr);
203
204         bpdu.cbu_rootpathcost = htonl(bp->bp_desg_pv.pv_cost);
205
206         bpdu.cbu_bridgepri = htons(bp->bp_desg_pv.pv_dbridge_id >> 48);
207         PV2ADDR(bp->bp_desg_pv.pv_dbridge_id, bpdu.cbu_bridgeaddr);
208
209         bpdu.cbu_portid = htons(bp->bp_port_id);
210         bpdu.cbu_messageage = htons(bp->bp_desg_msg_age);
211         bpdu.cbu_maxage = htons(bp->bp_desg_max_age);
212         bpdu.cbu_hellotime = htons(bp->bp_desg_htime);
213         bpdu.cbu_forwarddelay = htons(bp->bp_desg_fdelay);
214
215         bpdu.cbu_flags = bstp_pdu_flags(bp);
216
217         switch (bp->bp_protover) {
218                 case BSTP_PROTO_STP:
219                         bpdu.cbu_bpdutype = BSTP_MSGTYPE_CFG;
220                         break;
221
222                 case BSTP_PROTO_RSTP:
223                         bpdu.cbu_bpdutype = BSTP_MSGTYPE_RSTP;
224                         break;
225         }
226
227         bstp_send_bpdu(bs, bp, &bpdu);
228 }
229
230 static void
231 bstp_transmit_tcn(struct bstp_state *bs, struct bstp_port *bp)
232 {
233         struct bstp_tbpdu bpdu;
234         struct ifnet *ifp = bp->bp_ifp;
235         struct ether_header *eh;
236         struct mbuf *m;
237
238         KASSERT(bp == bs->bs_root_port, ("%s: bad root port\n", __func__));
239
240         if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
241                 return;
242
243         m = m_gethdr(M_NOWAIT, MT_DATA);
244         if (m == NULL)
245                 return;
246
247         m->m_pkthdr.rcvif = ifp;
248         m->m_pkthdr.len = sizeof(*eh) + sizeof(bpdu);
249         m->m_len = m->m_pkthdr.len;
250
251         eh = mtod(m, struct ether_header *);
252
253         memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN);
254         memcpy(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN);
255         eh->ether_type = htons(sizeof(bpdu));
256
257         bpdu.tbu_ssap = bpdu.tbu_dsap = LLC_8021D_LSAP;
258         bpdu.tbu_ctl = LLC_UI;
259         bpdu.tbu_protoid = 0;
260         bpdu.tbu_protover = 0;
261         bpdu.tbu_bpdutype = BSTP_MSGTYPE_TCN;
262
263         memcpy(mtod(m, caddr_t) + sizeof(*eh), &bpdu, sizeof(bpdu));
264
265         bp->bp_txcount++;
266         ifp->if_transmit(ifp, m);
267 }
268
269 static void
270 bstp_decode_bpdu(struct bstp_port *bp, struct bstp_cbpdu *cpdu,
271     struct bstp_config_unit *cu)
272 {
273         int flags;
274
275         cu->cu_pv.pv_root_id =
276             (((uint64_t)ntohs(cpdu->cbu_rootpri)) << 48) |
277             (((uint64_t)cpdu->cbu_rootaddr[0]) << 40) |
278             (((uint64_t)cpdu->cbu_rootaddr[1]) << 32) |
279             (((uint64_t)cpdu->cbu_rootaddr[2]) << 24) |
280             (((uint64_t)cpdu->cbu_rootaddr[3]) << 16) |
281             (((uint64_t)cpdu->cbu_rootaddr[4]) << 8) |
282             (((uint64_t)cpdu->cbu_rootaddr[5]) << 0);
283
284         cu->cu_pv.pv_dbridge_id =
285             (((uint64_t)ntohs(cpdu->cbu_bridgepri)) << 48) |
286             (((uint64_t)cpdu->cbu_bridgeaddr[0]) << 40) |
287             (((uint64_t)cpdu->cbu_bridgeaddr[1]) << 32) |
288             (((uint64_t)cpdu->cbu_bridgeaddr[2]) << 24) |
289             (((uint64_t)cpdu->cbu_bridgeaddr[3]) << 16) |
290             (((uint64_t)cpdu->cbu_bridgeaddr[4]) << 8) |
291             (((uint64_t)cpdu->cbu_bridgeaddr[5]) << 0);
292
293         cu->cu_pv.pv_cost = ntohl(cpdu->cbu_rootpathcost);
294         cu->cu_message_age = ntohs(cpdu->cbu_messageage);
295         cu->cu_max_age = ntohs(cpdu->cbu_maxage);
296         cu->cu_hello_time = ntohs(cpdu->cbu_hellotime);
297         cu->cu_forward_delay = ntohs(cpdu->cbu_forwarddelay);
298         cu->cu_pv.pv_dport_id = ntohs(cpdu->cbu_portid);
299         cu->cu_pv.pv_port_id = bp->bp_port_id;
300         cu->cu_message_type = cpdu->cbu_bpdutype;
301
302         /* Strip off unused flags in STP mode */
303         flags = cpdu->cbu_flags;
304         switch (cpdu->cbu_protover) {
305                 case BSTP_PROTO_STP:
306                         flags &= BSTP_PDU_STPMASK;
307                         /* A STP BPDU explicitly conveys a Designated Port */
308                         cu->cu_role = BSTP_ROLE_DESIGNATED;
309                         break;
310
311                 case BSTP_PROTO_RSTP:
312                         flags &= BSTP_PDU_RSTPMASK;
313                         break;
314         }
315
316         cu->cu_topology_change_ack =
317                 (flags & BSTP_PDU_F_TCA) ? 1 : 0;
318         cu->cu_proposal =
319                 (flags & BSTP_PDU_F_P) ? 1 : 0;
320         cu->cu_agree =
321                 (flags & BSTP_PDU_F_A) ? 1 : 0;
322         cu->cu_learning =
323                 (flags & BSTP_PDU_F_L) ? 1 : 0;
324         cu->cu_forwarding =
325                 (flags & BSTP_PDU_F_F) ? 1 : 0;
326         cu->cu_topology_change =
327                 (flags & BSTP_PDU_F_TC) ? 1 : 0;
328
329         switch ((flags & BSTP_PDU_PRMASK) >> BSTP_PDU_PRSHIFT) {
330                 case BSTP_PDU_F_ROOT:
331                         cu->cu_role = BSTP_ROLE_ROOT;
332                         break;
333                 case BSTP_PDU_F_ALT:
334                         cu->cu_role = BSTP_ROLE_ALTERNATE;
335                         break;
336                 case BSTP_PDU_F_DESG:
337                         cu->cu_role = BSTP_ROLE_DESIGNATED;
338                         break;
339         }
340 }
341
342 static void
343 bstp_send_bpdu(struct bstp_state *bs, struct bstp_port *bp,
344     struct bstp_cbpdu *bpdu)
345 {
346         struct ifnet *ifp;
347         struct mbuf *m;
348         struct ether_header *eh;
349
350         BSTP_LOCK_ASSERT(bs);
351         NET_EPOCH_ASSERT();
352
353         ifp = bp->bp_ifp;
354
355         if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
356                 return;
357
358         m = m_gethdr(M_NOWAIT, MT_DATA);
359         if (m == NULL)
360                 return;
361
362         eh = mtod(m, struct ether_header *);
363
364         bpdu->cbu_ssap = bpdu->cbu_dsap = LLC_8021D_LSAP;
365         bpdu->cbu_ctl = LLC_UI;
366         bpdu->cbu_protoid = htons(BSTP_PROTO_ID);
367
368         memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN);
369         memcpy(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN);
370
371         switch (bpdu->cbu_bpdutype) {
372                 case BSTP_MSGTYPE_CFG:
373                         bpdu->cbu_protover = BSTP_PROTO_STP;
374                         m->m_pkthdr.len = sizeof(*eh) + BSTP_BPDU_STP_LEN;
375                         eh->ether_type = htons(BSTP_BPDU_STP_LEN);
376                         memcpy(mtod(m, caddr_t) + sizeof(*eh), bpdu,
377                             BSTP_BPDU_STP_LEN);
378                         break;
379
380                 case BSTP_MSGTYPE_RSTP:
381                         bpdu->cbu_protover = BSTP_PROTO_RSTP;
382                         bpdu->cbu_versionlen = htons(0);
383                         m->m_pkthdr.len = sizeof(*eh) + BSTP_BPDU_RSTP_LEN;
384                         eh->ether_type = htons(BSTP_BPDU_RSTP_LEN);
385                         memcpy(mtod(m, caddr_t) + sizeof(*eh), bpdu,
386                             BSTP_BPDU_RSTP_LEN);
387                         break;
388
389                 default:
390                         panic("not implemented");
391         }
392         m->m_pkthdr.rcvif = ifp;
393         m->m_len = m->m_pkthdr.len;
394
395         bp->bp_txcount++;
396         ifp->if_transmit(ifp, m);
397 }
398
399 static int
400 bstp_pdu_flags(struct bstp_port *bp)
401 {
402         int flags = 0;
403
404         if (bp->bp_proposing && bp->bp_state != BSTP_IFSTATE_FORWARDING)
405                 flags |= BSTP_PDU_F_P;
406
407         if (bp->bp_agree)
408                 flags |= BSTP_PDU_F_A;
409
410         if (bp->bp_tc_timer.active)
411                 flags |= BSTP_PDU_F_TC;
412
413         if (bp->bp_tc_ack)
414                 flags |= BSTP_PDU_F_TCA;
415
416         switch (bp->bp_state) {
417                 case BSTP_IFSTATE_LEARNING:
418                         flags |= BSTP_PDU_F_L;
419                         break;
420
421                 case BSTP_IFSTATE_FORWARDING:
422                         flags |= (BSTP_PDU_F_L | BSTP_PDU_F_F);
423                         break;
424         }
425
426         switch (bp->bp_role) {
427                 case BSTP_ROLE_ROOT:
428                         flags |=
429                                 (BSTP_PDU_F_ROOT << BSTP_PDU_PRSHIFT);
430                         break;
431
432                 case BSTP_ROLE_ALTERNATE:
433                 case BSTP_ROLE_BACKUP:  /* fall through */
434                         flags |=
435                                 (BSTP_PDU_F_ALT << BSTP_PDU_PRSHIFT);
436                         break;
437
438                 case BSTP_ROLE_DESIGNATED:
439                         flags |=
440                                 (BSTP_PDU_F_DESG << BSTP_PDU_PRSHIFT);
441                         break;
442         }
443
444         /* Strip off unused flags in either mode */
445         switch (bp->bp_protover) {
446                 case BSTP_PROTO_STP:
447                         flags &= BSTP_PDU_STPMASK;
448                         break;
449                 case BSTP_PROTO_RSTP:
450                         flags &= BSTP_PDU_RSTPMASK;
451                         break;
452         }
453         return (flags);
454 }
455
456 void
457 bstp_input(struct bstp_port *bp, struct ifnet *ifp, struct mbuf *m)
458 {
459         struct bstp_state *bs = bp->bp_bs;
460         struct ether_header *eh;
461         struct bstp_tbpdu tpdu;
462         uint16_t len;
463
464         if (bp->bp_active == 0) {
465                 m_freem(m);
466                 return;
467         }
468
469         BSTP_LOCK(bs);
470
471         eh = mtod(m, struct ether_header *);
472
473         len = ntohs(eh->ether_type);
474         if (len < sizeof(tpdu))
475                 goto out;
476
477         m_adj(m, ETHER_HDR_LEN);
478
479         if (m->m_pkthdr.len > len)
480                 m_adj(m, len - m->m_pkthdr.len);
481         if (m->m_len < sizeof(tpdu) &&
482             (m = m_pullup(m, sizeof(tpdu))) == NULL)
483                 goto out;
484
485         memcpy(&tpdu, mtod(m, caddr_t), sizeof(tpdu));
486
487         /* basic packet checks */
488         if (tpdu.tbu_dsap != LLC_8021D_LSAP ||
489             tpdu.tbu_ssap != LLC_8021D_LSAP ||
490             tpdu.tbu_ctl != LLC_UI)
491                 goto out;
492         if (tpdu.tbu_protoid != BSTP_PROTO_ID)
493                 goto out;
494
495         /*
496          * We can treat later versions of the PDU as the same as the maximum
497          * version we implement. All additional parameters/flags are ignored.
498          */
499         if (tpdu.tbu_protover > BSTP_PROTO_MAX)
500                 tpdu.tbu_protover = BSTP_PROTO_MAX;
501
502         if (tpdu.tbu_protover != bp->bp_protover) {
503                 /*
504                  * Wait for the migration delay timer to expire before changing
505                  * protocol version to avoid flip-flops.
506                  */
507                 if (bp->bp_flags & BSTP_PORT_CANMIGRATE)
508                         bstp_set_port_proto(bp, tpdu.tbu_protover);
509                 else
510                         goto out;
511         }
512
513         /* Clear operedge upon receiving a PDU on the port */
514         bp->bp_operedge = 0;
515         bstp_timer_start(&bp->bp_edge_delay_timer,
516             BSTP_DEFAULT_MIGRATE_DELAY);
517
518         switch (tpdu.tbu_protover) {
519                 case BSTP_PROTO_STP:
520                         bstp_received_stp(bs, bp, &m, &tpdu);
521                         break;
522
523                 case BSTP_PROTO_RSTP:
524                         bstp_received_rstp(bs, bp, &m, &tpdu);
525                         break;
526         }
527 out:
528         BSTP_UNLOCK(bs);
529         if (m)
530                 m_freem(m);
531 }
532
533 static void
534 bstp_received_stp(struct bstp_state *bs, struct bstp_port *bp,
535     struct mbuf **mp, struct bstp_tbpdu *tpdu)
536 {
537         struct bstp_cbpdu cpdu;
538         struct bstp_config_unit *cu = &bp->bp_msg_cu;
539         struct bstp_tcn_unit tu;
540
541         switch (tpdu->tbu_bpdutype) {
542         case BSTP_MSGTYPE_TCN:
543                 tu.tu_message_type = tpdu->tbu_bpdutype;
544                 bstp_received_tcn(bs, bp, &tu);
545                 break;
546         case BSTP_MSGTYPE_CFG:
547                 if ((*mp)->m_len < BSTP_BPDU_STP_LEN &&
548                     (*mp = m_pullup(*mp, BSTP_BPDU_STP_LEN)) == NULL)
549                         return;
550                 memcpy(&cpdu, mtod(*mp, caddr_t), BSTP_BPDU_STP_LEN);
551
552                 bstp_decode_bpdu(bp, &cpdu, cu);
553                 bstp_received_bpdu(bs, bp, cu);
554                 break;
555         }
556 }
557
558 static void
559 bstp_received_rstp(struct bstp_state *bs, struct bstp_port *bp,
560     struct mbuf **mp, struct bstp_tbpdu *tpdu)
561 {
562         struct bstp_cbpdu cpdu;
563         struct bstp_config_unit *cu = &bp->bp_msg_cu;
564
565         if (tpdu->tbu_bpdutype != BSTP_MSGTYPE_RSTP)
566                 return;
567
568         if ((*mp)->m_len < BSTP_BPDU_RSTP_LEN &&
569             (*mp = m_pullup(*mp, BSTP_BPDU_RSTP_LEN)) == NULL)
570                 return;
571         memcpy(&cpdu, mtod(*mp, caddr_t), BSTP_BPDU_RSTP_LEN);
572
573         bstp_decode_bpdu(bp, &cpdu, cu);
574         bstp_received_bpdu(bs, bp, cu);
575 }
576
577 static void
578 bstp_received_tcn(struct bstp_state *bs, struct bstp_port *bp,
579     struct bstp_tcn_unit *tcn)
580 {
581         bp->bp_rcvdtcn = 1;
582         bstp_update_tc(bp);
583 }
584
585 static void
586 bstp_received_bpdu(struct bstp_state *bs, struct bstp_port *bp,
587     struct bstp_config_unit *cu)
588 {
589         int type;
590
591         BSTP_LOCK_ASSERT(bs);
592
593         /* We need to have transitioned to INFO_MINE before proceeding */
594         switch (bp->bp_infois) {
595                 case BSTP_INFO_DISABLED:
596                 case BSTP_INFO_AGED:
597                         return;
598         }
599
600         type = bstp_pdu_rcvtype(bp, cu);
601
602         switch (type) {
603                 case BSTP_PDU_SUPERIOR:
604                         bs->bs_allsynced = 0;
605                         bp->bp_agreed = 0;
606                         bp->bp_proposing = 0;
607
608                         if (cu->cu_proposal && cu->cu_forwarding == 0)
609                                 bp->bp_proposed = 1;
610                         if (cu->cu_topology_change)
611                                 bp->bp_rcvdtc = 1;
612                         if (cu->cu_topology_change_ack)
613                                 bp->bp_rcvdtca = 1;
614
615                         if (bp->bp_agree &&
616                             !bstp_pdu_bettersame(bp, BSTP_INFO_RECEIVED))
617                                 bp->bp_agree = 0;
618
619                         /* copy the received priority and timers to the port */
620                         bp->bp_port_pv = cu->cu_pv;
621                         bp->bp_port_msg_age = cu->cu_message_age;
622                         bp->bp_port_max_age = cu->cu_max_age;
623                         bp->bp_port_fdelay = cu->cu_forward_delay;
624                         bp->bp_port_htime =
625                                 (cu->cu_hello_time > BSTP_MIN_HELLO_TIME ?
626                                  cu->cu_hello_time : BSTP_MIN_HELLO_TIME);
627
628                         /* set expiry for the new info */
629                         bstp_set_timer_msgage(bp);
630
631                         bp->bp_infois = BSTP_INFO_RECEIVED;
632                         bstp_assign_roles(bs);
633                         break;
634
635                 case BSTP_PDU_REPEATED:
636                         if (cu->cu_proposal && cu->cu_forwarding == 0)
637                                 bp->bp_proposed = 1;
638                         if (cu->cu_topology_change)
639                                 bp->bp_rcvdtc = 1;
640                         if (cu->cu_topology_change_ack)
641                                 bp->bp_rcvdtca = 1;
642
643                         /* rearm the age timer */
644                         bstp_set_timer_msgage(bp);
645                         break;
646
647                 case BSTP_PDU_INFERIOR:
648                         if (cu->cu_learning) {
649                                 bp->bp_agreed = 1;
650                                 bp->bp_proposing = 0;
651                         }
652                         break;
653
654                 case BSTP_PDU_INFERIORALT:
655                         /*
656                          * only point to point links are allowed fast
657                          * transitions to forwarding.
658                          */
659                         if (cu->cu_agree && bp->bp_ptp_link) {
660                                 bp->bp_agreed = 1;
661                                 bp->bp_proposing = 0;
662                         } else
663                                 bp->bp_agreed = 0;
664
665                         if (cu->cu_topology_change)
666                                 bp->bp_rcvdtc = 1;
667                         if (cu->cu_topology_change_ack)
668                                 bp->bp_rcvdtca = 1;
669                         break;
670
671                 case BSTP_PDU_OTHER:
672                         return; /* do nothing */
673         }
674         /* update the state machines with the new data */
675         bstp_update_state(bs, bp);
676 }
677
678 static int
679 bstp_pdu_rcvtype(struct bstp_port *bp, struct bstp_config_unit *cu)
680 {
681         int type;
682
683         /* default return type */
684         type = BSTP_PDU_OTHER;
685
686         switch (cu->cu_role) {
687         case BSTP_ROLE_DESIGNATED:
688                 if (bstp_info_superior(&bp->bp_port_pv, &cu->cu_pv))
689                         /* bpdu priority is superior */
690                         type = BSTP_PDU_SUPERIOR;
691                 else if (bstp_info_cmp(&bp->bp_port_pv, &cu->cu_pv) ==
692                     INFO_SAME) {
693                         if (bp->bp_port_msg_age != cu->cu_message_age ||
694                             bp->bp_port_max_age != cu->cu_max_age ||
695                             bp->bp_port_fdelay != cu->cu_forward_delay ||
696                             bp->bp_port_htime != cu->cu_hello_time)
697                                 /* bpdu priority is equal and timers differ */
698                                 type = BSTP_PDU_SUPERIOR;
699                         else
700                                 /* bpdu is equal */
701                                 type = BSTP_PDU_REPEATED;
702                 } else
703                         /* bpdu priority is worse */
704                         type = BSTP_PDU_INFERIOR;
705
706                 break;
707
708         case BSTP_ROLE_ROOT:
709         case BSTP_ROLE_ALTERNATE:
710         case BSTP_ROLE_BACKUP:
711                 if (bstp_info_cmp(&bp->bp_port_pv, &cu->cu_pv) <= INFO_SAME)
712                         /*
713                          * not a designated port and priority is the same or
714                          * worse
715                          */
716                         type = BSTP_PDU_INFERIORALT;
717                 break;
718         }
719
720         return (type);
721 }
722
723 static int
724 bstp_pdu_bettersame(struct bstp_port *bp, int newinfo)
725 {
726         if (newinfo == BSTP_INFO_RECEIVED &&
727             bp->bp_infois == BSTP_INFO_RECEIVED &&
728             bstp_info_cmp(&bp->bp_port_pv, &bp->bp_msg_cu.cu_pv) >= INFO_SAME)
729                 return (1);
730
731         if (newinfo == BSTP_INFO_MINE &&
732             bp->bp_infois == BSTP_INFO_MINE &&
733             bstp_info_cmp(&bp->bp_port_pv, &bp->bp_desg_pv) >= INFO_SAME)
734                 return (1);
735
736         return (0);
737 }
738
739 static int
740 bstp_info_cmp(struct bstp_pri_vector *pv,
741     struct bstp_pri_vector *cpv)
742 {
743         if (cpv->pv_root_id < pv->pv_root_id)
744                 return (INFO_BETTER);
745         if (cpv->pv_root_id > pv->pv_root_id)
746                 return (INFO_WORSE);
747
748         if (cpv->pv_cost < pv->pv_cost)
749                 return (INFO_BETTER);
750         if (cpv->pv_cost > pv->pv_cost)
751                 return (INFO_WORSE);
752
753         if (cpv->pv_dbridge_id < pv->pv_dbridge_id)
754                 return (INFO_BETTER);
755         if (cpv->pv_dbridge_id > pv->pv_dbridge_id)
756                 return (INFO_WORSE);
757
758         if (cpv->pv_dport_id < pv->pv_dport_id)
759                 return (INFO_BETTER);
760         if (cpv->pv_dport_id > pv->pv_dport_id)
761                 return (INFO_WORSE);
762
763         return (INFO_SAME);
764 }
765
766 /*
767  * This message priority vector is superior to the port priority vector and
768  * will replace it if, and only if, the message priority vector is better than
769  * the port priority vector, or the message has been transmitted from the same
770  * designated bridge and designated port as the port priority vector.
771  */
772 static int
773 bstp_info_superior(struct bstp_pri_vector *pv,
774     struct bstp_pri_vector *cpv)
775 {
776         if (bstp_info_cmp(pv, cpv) == INFO_BETTER ||
777             (bstp_same_bridgeid(pv->pv_dbridge_id, cpv->pv_dbridge_id) &&
778             (cpv->pv_dport_id & 0xfff) == (pv->pv_dport_id & 0xfff)))
779                 return (1);
780         return (0);
781 }
782
783 static void
784 bstp_assign_roles(struct bstp_state *bs)
785 {
786         struct bstp_port *bp, *rbp = NULL;
787         struct bstp_pri_vector pv;
788
789         /* default to our priority vector */
790         bs->bs_root_pv = bs->bs_bridge_pv;
791         bs->bs_root_msg_age = 0;
792         bs->bs_root_max_age = bs->bs_bridge_max_age;
793         bs->bs_root_fdelay = bs->bs_bridge_fdelay;
794         bs->bs_root_htime = bs->bs_bridge_htime;
795         bs->bs_root_port = NULL;
796
797         /* check if any received info supersedes us */
798         LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
799                 if (bp->bp_infois != BSTP_INFO_RECEIVED)
800                         continue;
801
802                 pv = bp->bp_port_pv;
803                 pv.pv_cost += bp->bp_path_cost;
804
805                 /*
806                  * The root priority vector is the best of the set comprising
807                  * the bridge priority vector plus all root path priority
808                  * vectors whose bridge address is not equal to us.
809                  */
810                 if (bstp_same_bridgeid(pv.pv_dbridge_id,
811                     bs->bs_bridge_pv.pv_dbridge_id) == 0 &&
812                     bstp_info_cmp(&bs->bs_root_pv, &pv) == INFO_BETTER) {
813                         /* the port vector replaces the root */
814                         bs->bs_root_pv = pv;
815                         bs->bs_root_msg_age = bp->bp_port_msg_age +
816                             BSTP_MESSAGE_AGE_INCR;
817                         bs->bs_root_max_age = bp->bp_port_max_age;
818                         bs->bs_root_fdelay = bp->bp_port_fdelay;
819                         bs->bs_root_htime = bp->bp_port_htime;
820                         rbp = bp;
821                 }
822         }
823
824         LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
825                 /* calculate the port designated vector */
826                 bp->bp_desg_pv.pv_root_id = bs->bs_root_pv.pv_root_id;
827                 bp->bp_desg_pv.pv_cost = bs->bs_root_pv.pv_cost;
828                 bp->bp_desg_pv.pv_dbridge_id = bs->bs_bridge_pv.pv_dbridge_id;
829                 bp->bp_desg_pv.pv_dport_id = bp->bp_port_id;
830                 bp->bp_desg_pv.pv_port_id = bp->bp_port_id;
831
832                 /* calculate designated times */
833                 bp->bp_desg_msg_age = bs->bs_root_msg_age;
834                 bp->bp_desg_max_age = bs->bs_root_max_age;
835                 bp->bp_desg_fdelay = bs->bs_root_fdelay;
836                 bp->bp_desg_htime = bs->bs_bridge_htime;
837
838                 switch (bp->bp_infois) {
839                 case BSTP_INFO_DISABLED:
840                         bstp_set_port_role(bp, BSTP_ROLE_DISABLED);
841                         break;
842
843                 case BSTP_INFO_AGED:
844                         bstp_set_port_role(bp, BSTP_ROLE_DESIGNATED);
845                         bstp_update_info(bp);
846                         break;
847
848                 case BSTP_INFO_MINE:
849                         bstp_set_port_role(bp, BSTP_ROLE_DESIGNATED);
850                         /* update the port info if stale */
851                         if (bstp_info_cmp(&bp->bp_port_pv,
852                             &bp->bp_desg_pv) != INFO_SAME ||
853                             (rbp != NULL &&
854                             (bp->bp_port_msg_age != rbp->bp_port_msg_age ||
855                             bp->bp_port_max_age != rbp->bp_port_max_age ||
856                             bp->bp_port_fdelay != rbp->bp_port_fdelay ||
857                             bp->bp_port_htime != rbp->bp_port_htime)))
858                                 bstp_update_info(bp);
859                         break;
860
861                 case BSTP_INFO_RECEIVED:
862                         if (bp == rbp) {
863                                 /*
864                                  * root priority is derived from this
865                                  * port, make it the root port.
866                                  */
867                                 bstp_set_port_role(bp, BSTP_ROLE_ROOT);
868                                 bs->bs_root_port = bp;
869                         } else if (bstp_info_cmp(&bp->bp_port_pv,
870                                     &bp->bp_desg_pv) == INFO_BETTER) {
871                                 /*
872                                  * the port priority is lower than the root
873                                  * port.
874                                  */
875                                 bstp_set_port_role(bp, BSTP_ROLE_DESIGNATED);
876                                 bstp_update_info(bp);
877                         } else {
878                                 if (bstp_same_bridgeid(
879                                     bp->bp_port_pv.pv_dbridge_id,
880                                     bs->bs_bridge_pv.pv_dbridge_id)) {
881                                         /*
882                                          * the designated bridge refers to
883                                          * another port on this bridge.
884                                          */
885                                         bstp_set_port_role(bp,
886                                             BSTP_ROLE_BACKUP);
887                                 } else {
888                                         /*
889                                          * the port is an inferior path to the
890                                          * root bridge.
891                                          */
892                                         bstp_set_port_role(bp,
893                                             BSTP_ROLE_ALTERNATE);
894                                 }
895                         }
896                         break;
897                 }
898         }
899 }
900
901 static void
902 bstp_update_state(struct bstp_state *bs, struct bstp_port *bp)
903 {
904         struct bstp_port *bp2;
905         int synced;
906
907         BSTP_LOCK_ASSERT(bs);
908
909         /* check if all the ports have syncronised again */
910         if (!bs->bs_allsynced) {
911                 synced = 1;
912                 LIST_FOREACH(bp2, &bs->bs_bplist, bp_next) {
913                         if (!(bp2->bp_synced ||
914                              bp2->bp_role == BSTP_ROLE_ROOT)) {
915                                 synced = 0;
916                                 break;
917                         }
918                 }
919                 bs->bs_allsynced = synced;
920         }
921
922         bstp_update_roles(bs, bp);
923         bstp_update_tc(bp);
924 }
925
926 static void
927 bstp_update_roles(struct bstp_state *bs, struct bstp_port *bp)
928 {
929         NET_EPOCH_ASSERT();
930
931         switch (bp->bp_role) {
932         case BSTP_ROLE_DISABLED:
933                 /* Clear any flags if set */
934                 if (bp->bp_sync || !bp->bp_synced || bp->bp_reroot) {
935                         bp->bp_sync = 0;
936                         bp->bp_synced = 1;
937                         bp->bp_reroot = 0;
938                 }
939                 break;
940
941         case BSTP_ROLE_ALTERNATE:
942         case BSTP_ROLE_BACKUP:
943                 if ((bs->bs_allsynced && !bp->bp_agree) ||
944                     (bp->bp_proposed && bp->bp_agree)) {
945                         bp->bp_proposed = 0;
946                         bp->bp_agree = 1;
947                         bp->bp_flags |= BSTP_PORT_NEWINFO;
948                         DPRINTF("%s -> ALTERNATE_AGREED\n",
949                             bp->bp_ifp->if_xname);
950                 }
951
952                 if (bp->bp_proposed && !bp->bp_agree) {
953                         bstp_set_all_sync(bs);
954                         bp->bp_proposed = 0;
955                         DPRINTF("%s -> ALTERNATE_PROPOSED\n",
956                             bp->bp_ifp->if_xname);
957                 }
958
959                 /* Clear any flags if set */
960                 if (bp->bp_sync || !bp->bp_synced || bp->bp_reroot) {
961                         bp->bp_sync = 0;
962                         bp->bp_synced = 1;
963                         bp->bp_reroot = 0;
964                         DPRINTF("%s -> ALTERNATE_PORT\n", bp->bp_ifp->if_xname);
965                 }
966                 break;
967
968         case BSTP_ROLE_ROOT:
969                 if (bp->bp_state != BSTP_IFSTATE_FORWARDING && !bp->bp_reroot) {
970                         bstp_set_all_reroot(bs);
971                         DPRINTF("%s -> ROOT_REROOT\n", bp->bp_ifp->if_xname);
972                 }
973
974                 if ((bs->bs_allsynced && !bp->bp_agree) ||
975                     (bp->bp_proposed && bp->bp_agree)) {
976                         bp->bp_proposed = 0;
977                         bp->bp_sync = 0;
978                         bp->bp_agree = 1;
979                         bp->bp_flags |= BSTP_PORT_NEWINFO;
980                         DPRINTF("%s -> ROOT_AGREED\n", bp->bp_ifp->if_xname);
981                 }
982
983                 if (bp->bp_proposed && !bp->bp_agree) {
984                         bstp_set_all_sync(bs);
985                         bp->bp_proposed = 0;
986                         DPRINTF("%s -> ROOT_PROPOSED\n", bp->bp_ifp->if_xname);
987                 }
988
989                 if (bp->bp_state != BSTP_IFSTATE_FORWARDING &&
990                     (bp->bp_forward_delay_timer.active == 0 ||
991                     (bstp_rerooted(bs, bp) &&
992                     bp->bp_recent_backup_timer.active == 0 &&
993                     bp->bp_protover == BSTP_PROTO_RSTP))) {
994                         switch (bp->bp_state) {
995                         case BSTP_IFSTATE_DISCARDING:
996                                 bstp_set_port_state(bp, BSTP_IFSTATE_LEARNING);
997                                 break;
998                         case BSTP_IFSTATE_LEARNING:
999                                 bstp_set_port_state(bp,
1000                                     BSTP_IFSTATE_FORWARDING);
1001                                 break;
1002                         }
1003                 }
1004
1005                 if (bp->bp_state == BSTP_IFSTATE_FORWARDING && bp->bp_reroot) {
1006                         bp->bp_reroot = 0;
1007                         DPRINTF("%s -> ROOT_REROOTED\n", bp->bp_ifp->if_xname);
1008                 }
1009                 break;
1010
1011         case BSTP_ROLE_DESIGNATED:
1012                 if (bp->bp_recent_root_timer.active == 0 && bp->bp_reroot) {
1013                         bp->bp_reroot = 0;
1014                         DPRINTF("%s -> DESIGNATED_RETIRED\n",
1015                             bp->bp_ifp->if_xname);
1016                 }
1017
1018                 if ((bp->bp_state == BSTP_IFSTATE_DISCARDING &&
1019                     !bp->bp_synced) || (bp->bp_agreed && !bp->bp_synced) ||
1020                     (bp->bp_operedge && !bp->bp_synced) ||
1021                     (bp->bp_sync && bp->bp_synced)) {
1022                         bstp_timer_stop(&bp->bp_recent_root_timer);
1023                         bp->bp_synced = 1;
1024                         bp->bp_sync = 0;
1025                         DPRINTF("%s -> DESIGNATED_SYNCED\n",
1026                             bp->bp_ifp->if_xname);
1027                 }
1028
1029                 if (bp->bp_state != BSTP_IFSTATE_FORWARDING &&
1030                     !bp->bp_agreed && !bp->bp_proposing &&
1031                     !bp->bp_operedge) {
1032                         bp->bp_proposing = 1;
1033                         bp->bp_flags |= BSTP_PORT_NEWINFO;
1034                         bstp_timer_start(&bp->bp_edge_delay_timer,
1035                             (bp->bp_ptp_link ? BSTP_DEFAULT_MIGRATE_DELAY :
1036                              bp->bp_desg_max_age));
1037                         DPRINTF("%s -> DESIGNATED_PROPOSE\n",
1038                             bp->bp_ifp->if_xname);
1039                 }
1040
1041                 if (bp->bp_state != BSTP_IFSTATE_FORWARDING &&
1042                     (bp->bp_forward_delay_timer.active == 0 || bp->bp_agreed ||
1043                     bp->bp_operedge) &&
1044                     (bp->bp_recent_root_timer.active == 0 || !bp->bp_reroot) &&
1045                     !bp->bp_sync) {
1046                         if (bp->bp_agreed)
1047                                 DPRINTF("%s -> AGREED\n", bp->bp_ifp->if_xname);
1048                         /*
1049                          * If agreed|operedge then go straight to forwarding,
1050                          * otherwise follow discard -> learn -> forward.
1051                          */
1052                         if (bp->bp_agreed || bp->bp_operedge ||
1053                             bp->bp_state == BSTP_IFSTATE_LEARNING) {
1054                                 bstp_set_port_state(bp,
1055                                     BSTP_IFSTATE_FORWARDING);
1056                                 bp->bp_agreed = bp->bp_protover;
1057                         } else if (bp->bp_state == BSTP_IFSTATE_DISCARDING)
1058                                 bstp_set_port_state(bp, BSTP_IFSTATE_LEARNING);
1059                 }
1060
1061                 if (((bp->bp_sync && !bp->bp_synced) ||
1062                     (bp->bp_reroot && bp->bp_recent_root_timer.active) ||
1063                     (bp->bp_flags & BSTP_PORT_DISPUTED)) && !bp->bp_operedge &&
1064                     bp->bp_state != BSTP_IFSTATE_DISCARDING) {
1065                         bstp_set_port_state(bp, BSTP_IFSTATE_DISCARDING);
1066                         bp->bp_flags &= ~BSTP_PORT_DISPUTED;
1067                         bstp_timer_start(&bp->bp_forward_delay_timer,
1068                             bp->bp_protover == BSTP_PROTO_RSTP ?
1069                             bp->bp_desg_htime : bp->bp_desg_fdelay);
1070                         DPRINTF("%s -> DESIGNATED_DISCARD\n",
1071                             bp->bp_ifp->if_xname);
1072                 }
1073                 break;
1074         }
1075
1076         if (bp->bp_flags & BSTP_PORT_NEWINFO)
1077                 bstp_transmit(bs, bp);
1078 }
1079
1080 static void
1081 bstp_update_tc(struct bstp_port *bp)
1082 {
1083         switch (bp->bp_tcstate) {
1084                 case BSTP_TCSTATE_ACTIVE:
1085                         if ((bp->bp_role != BSTP_ROLE_DESIGNATED &&
1086                             bp->bp_role != BSTP_ROLE_ROOT) || bp->bp_operedge)
1087                                 bstp_set_port_tc(bp, BSTP_TCSTATE_LEARNING);
1088
1089                         if (bp->bp_rcvdtcn)
1090                                 bstp_set_port_tc(bp, BSTP_TCSTATE_TCN);
1091                         if (bp->bp_rcvdtc)
1092                                 bstp_set_port_tc(bp, BSTP_TCSTATE_TC);
1093
1094                         if (bp->bp_tc_prop && !bp->bp_operedge)
1095                                 bstp_set_port_tc(bp, BSTP_TCSTATE_PROPAG);
1096
1097                         if (bp->bp_rcvdtca)
1098                                 bstp_set_port_tc(bp, BSTP_TCSTATE_ACK);
1099                         break;
1100
1101                 case BSTP_TCSTATE_INACTIVE:
1102                         if ((bp->bp_state == BSTP_IFSTATE_LEARNING ||
1103                             bp->bp_state == BSTP_IFSTATE_FORWARDING) &&
1104                             bp->bp_fdbflush == 0)
1105                                 bstp_set_port_tc(bp, BSTP_TCSTATE_LEARNING);
1106                         break;
1107
1108                 case BSTP_TCSTATE_LEARNING:
1109                         if (bp->bp_rcvdtc || bp->bp_rcvdtcn || bp->bp_rcvdtca ||
1110                             bp->bp_tc_prop)
1111                                 bstp_set_port_tc(bp, BSTP_TCSTATE_LEARNING);
1112                         else if (bp->bp_role != BSTP_ROLE_DESIGNATED &&
1113                                  bp->bp_role != BSTP_ROLE_ROOT &&
1114                                  bp->bp_state == BSTP_IFSTATE_DISCARDING)
1115                                 bstp_set_port_tc(bp, BSTP_TCSTATE_INACTIVE);
1116
1117                         if ((bp->bp_role == BSTP_ROLE_DESIGNATED ||
1118                             bp->bp_role == BSTP_ROLE_ROOT) &&
1119                             bp->bp_state == BSTP_IFSTATE_FORWARDING &&
1120                             !bp->bp_operedge)
1121                                 bstp_set_port_tc(bp, BSTP_TCSTATE_DETECTED);
1122                         break;
1123
1124                 /* these are transient states and go straight back to ACTIVE */
1125                 case BSTP_TCSTATE_DETECTED:
1126                 case BSTP_TCSTATE_TCN:
1127                 case BSTP_TCSTATE_TC:
1128                 case BSTP_TCSTATE_PROPAG:
1129                 case BSTP_TCSTATE_ACK:
1130                         DPRINTF("Invalid TC state for %s\n",
1131                             bp->bp_ifp->if_xname);
1132                         break;
1133         }
1134
1135 }
1136
1137 static void
1138 bstp_update_info(struct bstp_port *bp)
1139 {
1140         struct bstp_state *bs = bp->bp_bs;
1141
1142         bp->bp_proposing = 0;
1143         bp->bp_proposed = 0;
1144
1145         if (bp->bp_agreed && !bstp_pdu_bettersame(bp, BSTP_INFO_MINE))
1146                 bp->bp_agreed = 0;
1147
1148         if (bp->bp_synced && !bp->bp_agreed) {
1149                 bp->bp_synced = 0;
1150                 bs->bs_allsynced = 0;
1151         }
1152
1153         /* copy the designated pv to the port */
1154         bp->bp_port_pv = bp->bp_desg_pv;
1155         bp->bp_port_msg_age = bp->bp_desg_msg_age;
1156         bp->bp_port_max_age = bp->bp_desg_max_age;
1157         bp->bp_port_fdelay = bp->bp_desg_fdelay;
1158         bp->bp_port_htime = bp->bp_desg_htime;
1159         bp->bp_infois = BSTP_INFO_MINE;
1160
1161         /* Set transmit flag but do not immediately send */
1162         bp->bp_flags |= BSTP_PORT_NEWINFO;
1163 }
1164
1165 /* set tcprop on every port other than the caller */
1166 static void
1167 bstp_set_other_tcprop(struct bstp_port *bp)
1168 {
1169         struct bstp_state *bs = bp->bp_bs;
1170         struct bstp_port *bp2;
1171
1172         BSTP_LOCK_ASSERT(bs);
1173
1174         LIST_FOREACH(bp2, &bs->bs_bplist, bp_next) {
1175                 if (bp2 == bp)
1176                         continue;
1177                 bp2->bp_tc_prop = 1;
1178         }
1179 }
1180
1181 static void
1182 bstp_set_all_reroot(struct bstp_state *bs)
1183 {
1184         struct bstp_port *bp;
1185
1186         BSTP_LOCK_ASSERT(bs);
1187
1188         LIST_FOREACH(bp, &bs->bs_bplist, bp_next)
1189                 bp->bp_reroot = 1;
1190 }
1191
1192 static void
1193 bstp_set_all_sync(struct bstp_state *bs)
1194 {
1195         struct bstp_port *bp;
1196
1197         BSTP_LOCK_ASSERT(bs);
1198
1199         LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
1200                 bp->bp_sync = 1;
1201                 bp->bp_synced = 0;      /* Not explicit in spec */
1202         }
1203
1204         bs->bs_allsynced = 0;
1205 }
1206
1207 static void
1208 bstp_set_port_state(struct bstp_port *bp, int state)
1209 {
1210         if (bp->bp_state == state)
1211                 return;
1212
1213         bp->bp_state = state;
1214
1215         switch (bp->bp_state) {
1216                 case BSTP_IFSTATE_DISCARDING:
1217                         DPRINTF("state changed to DISCARDING on %s\n",
1218                             bp->bp_ifp->if_xname);
1219                         break;
1220
1221                 case BSTP_IFSTATE_LEARNING:
1222                         DPRINTF("state changed to LEARNING on %s\n",
1223                             bp->bp_ifp->if_xname);
1224
1225                         bstp_timer_start(&bp->bp_forward_delay_timer,
1226                             bp->bp_protover == BSTP_PROTO_RSTP ?
1227                             bp->bp_desg_htime : bp->bp_desg_fdelay);
1228                         break;
1229
1230                 case BSTP_IFSTATE_FORWARDING:
1231                         DPRINTF("state changed to FORWARDING on %s\n",
1232                             bp->bp_ifp->if_xname);
1233
1234                         bstp_timer_stop(&bp->bp_forward_delay_timer);
1235                         /* Record that we enabled forwarding */
1236                         bp->bp_forward_transitions++;
1237                         break;
1238         }
1239
1240         /* notify the parent bridge */
1241         taskqueue_enqueue(taskqueue_swi, &bp->bp_statetask);
1242 }
1243
1244 static void
1245 bstp_set_port_role(struct bstp_port *bp, int role)
1246 {
1247         struct bstp_state *bs = bp->bp_bs;
1248
1249         if (bp->bp_role == role)
1250                 return;
1251
1252         /* perform pre-change tasks */
1253         switch (bp->bp_role) {
1254                 case BSTP_ROLE_DISABLED:
1255                         bstp_timer_start(&bp->bp_forward_delay_timer,
1256                             bp->bp_desg_max_age);
1257                         break;
1258
1259                 case BSTP_ROLE_BACKUP:
1260                         bstp_timer_start(&bp->bp_recent_backup_timer,
1261                             bp->bp_desg_htime * 2);
1262                         /* fall through */
1263                 case BSTP_ROLE_ALTERNATE:
1264                         bstp_timer_start(&bp->bp_forward_delay_timer,
1265                             bp->bp_desg_fdelay);
1266                         bp->bp_sync = 0;
1267                         bp->bp_synced = 1;
1268                         bp->bp_reroot = 0;
1269                         break;
1270
1271                 case BSTP_ROLE_ROOT:
1272                         bstp_timer_start(&bp->bp_recent_root_timer,
1273                             BSTP_DEFAULT_FORWARD_DELAY);
1274                         break;
1275         }
1276
1277         bp->bp_role = role;
1278         /* clear values not carried between roles */
1279         bp->bp_proposing = 0;
1280         bs->bs_allsynced = 0;
1281
1282         /* initialise the new role */
1283         switch (bp->bp_role) {
1284                 case BSTP_ROLE_DISABLED:
1285                 case BSTP_ROLE_ALTERNATE:
1286                 case BSTP_ROLE_BACKUP:
1287                         DPRINTF("%s role -> ALT/BACK/DISABLED\n",
1288                             bp->bp_ifp->if_xname);
1289                         bstp_set_port_state(bp, BSTP_IFSTATE_DISCARDING);
1290                         bstp_timer_stop(&bp->bp_recent_root_timer);
1291                         bstp_timer_latch(&bp->bp_forward_delay_timer);
1292                         bp->bp_sync = 0;
1293                         bp->bp_synced = 1;
1294                         bp->bp_reroot = 0;
1295                         break;
1296
1297                 case BSTP_ROLE_ROOT:
1298                         DPRINTF("%s role -> ROOT\n",
1299                             bp->bp_ifp->if_xname);
1300                         bstp_set_port_state(bp, BSTP_IFSTATE_DISCARDING);
1301                         bstp_timer_latch(&bp->bp_recent_root_timer);
1302                         bp->bp_proposing = 0;
1303                         break;
1304
1305                 case BSTP_ROLE_DESIGNATED:
1306                         DPRINTF("%s role -> DESIGNATED\n",
1307                             bp->bp_ifp->if_xname);
1308                         bstp_timer_start(&bp->bp_hello_timer,
1309                             bp->bp_desg_htime);
1310                         bp->bp_agree = 0;
1311                         break;
1312         }
1313
1314         /* let the TC state know that the role changed */
1315         bstp_update_tc(bp);
1316 }
1317
1318 static void
1319 bstp_set_port_proto(struct bstp_port *bp, int proto)
1320 {
1321         struct bstp_state *bs = bp->bp_bs;
1322
1323         /* supported protocol versions */
1324         switch (proto) {
1325                 case BSTP_PROTO_STP:
1326                         /* we can downgrade protocols only */
1327                         bstp_timer_stop(&bp->bp_migrate_delay_timer);
1328                         /* clear unsupported features */
1329                         bp->bp_operedge = 0;
1330                         /* STP compat mode only uses 16 bits of the 32 */
1331                         if (bp->bp_path_cost > 65535)
1332                                 bp->bp_path_cost = 65535;
1333                         break;
1334
1335                 case BSTP_PROTO_RSTP:
1336                         bstp_timer_start(&bp->bp_migrate_delay_timer,
1337                             bs->bs_migration_delay);
1338                         break;
1339
1340                 default:
1341                         DPRINTF("Unsupported STP version %d\n", proto);
1342                         return;
1343         }
1344
1345         bp->bp_protover = proto;
1346         bp->bp_flags &= ~BSTP_PORT_CANMIGRATE;
1347 }
1348
1349 static void
1350 bstp_set_port_tc(struct bstp_port *bp, int state)
1351 {
1352         struct bstp_state *bs = bp->bp_bs;
1353
1354         bp->bp_tcstate = state;
1355
1356         /* initialise the new state */
1357         switch (bp->bp_tcstate) {
1358                 case BSTP_TCSTATE_ACTIVE:
1359                         DPRINTF("%s -> TC_ACTIVE\n", bp->bp_ifp->if_xname);
1360                         /* nothing to do */
1361                         break;
1362
1363                 case BSTP_TCSTATE_INACTIVE:
1364                         bstp_timer_stop(&bp->bp_tc_timer);
1365                         /* flush routes on the parent bridge */
1366                         bp->bp_fdbflush = 1;
1367                         taskqueue_enqueue(taskqueue_swi, &bp->bp_rtagetask);
1368                         bp->bp_tc_ack = 0;
1369                         DPRINTF("%s -> TC_INACTIVE\n", bp->bp_ifp->if_xname);
1370                         break;
1371
1372                 case BSTP_TCSTATE_LEARNING:
1373                         bp->bp_rcvdtc = 0;
1374                         bp->bp_rcvdtcn = 0;
1375                         bp->bp_rcvdtca = 0;
1376                         bp->bp_tc_prop = 0;
1377                         DPRINTF("%s -> TC_LEARNING\n", bp->bp_ifp->if_xname);
1378                         break;
1379
1380                 case BSTP_TCSTATE_DETECTED:
1381                         bstp_set_timer_tc(bp);
1382                         bstp_set_other_tcprop(bp);
1383                         /* send out notification */
1384                         bp->bp_flags |= BSTP_PORT_NEWINFO;
1385                         bstp_transmit(bs, bp);
1386                         getmicrotime(&bs->bs_last_tc_time);
1387                         DPRINTF("%s -> TC_DETECTED\n", bp->bp_ifp->if_xname);
1388                         bp->bp_tcstate = BSTP_TCSTATE_ACTIVE; /* UCT */
1389                         break;
1390
1391                 case BSTP_TCSTATE_TCN:
1392                         bstp_set_timer_tc(bp);
1393                         DPRINTF("%s -> TC_TCN\n", bp->bp_ifp->if_xname);
1394                         /* fall through */
1395                 case BSTP_TCSTATE_TC:
1396                         bp->bp_rcvdtc = 0;
1397                         bp->bp_rcvdtcn = 0;
1398                         if (bp->bp_role == BSTP_ROLE_DESIGNATED)
1399                                 bp->bp_tc_ack = 1;
1400
1401                         bstp_set_other_tcprop(bp);
1402                         DPRINTF("%s -> TC_TC\n", bp->bp_ifp->if_xname);
1403                         bp->bp_tcstate = BSTP_TCSTATE_ACTIVE; /* UCT */
1404                         break;
1405
1406                 case BSTP_TCSTATE_PROPAG:
1407                         /* flush routes on the parent bridge */
1408                         bp->bp_fdbflush = 1;
1409                         taskqueue_enqueue(taskqueue_swi, &bp->bp_rtagetask);
1410                         bp->bp_tc_prop = 0;
1411                         bstp_set_timer_tc(bp);
1412                         DPRINTF("%s -> TC_PROPAG\n", bp->bp_ifp->if_xname);
1413                         bp->bp_tcstate = BSTP_TCSTATE_ACTIVE; /* UCT */
1414                         break;
1415
1416                 case BSTP_TCSTATE_ACK:
1417                         bstp_timer_stop(&bp->bp_tc_timer);
1418                         bp->bp_rcvdtca = 0;
1419                         DPRINTF("%s -> TC_ACK\n", bp->bp_ifp->if_xname);
1420                         bp->bp_tcstate = BSTP_TCSTATE_ACTIVE; /* UCT */
1421                         break;
1422         }
1423 }
1424
1425 static void
1426 bstp_set_timer_tc(struct bstp_port *bp)
1427 {
1428         struct bstp_state *bs = bp->bp_bs;
1429
1430         if (bp->bp_tc_timer.active)
1431                 return;
1432
1433         switch (bp->bp_protover) {
1434                 case BSTP_PROTO_RSTP:
1435                         bstp_timer_start(&bp->bp_tc_timer,
1436                             bp->bp_desg_htime + BSTP_TICK_VAL);
1437                         bp->bp_flags |= BSTP_PORT_NEWINFO;
1438                         break;
1439
1440                 case BSTP_PROTO_STP:
1441                         bstp_timer_start(&bp->bp_tc_timer,
1442                             bs->bs_root_max_age + bs->bs_root_fdelay);
1443                         break;
1444         }
1445 }
1446
1447 static void
1448 bstp_set_timer_msgage(struct bstp_port *bp)
1449 {
1450         if (bp->bp_port_msg_age + BSTP_MESSAGE_AGE_INCR <=
1451             bp->bp_port_max_age) {
1452                 bstp_timer_start(&bp->bp_message_age_timer,
1453                     bp->bp_port_htime * 3);
1454         } else
1455                 /* expires immediately */
1456                 bstp_timer_start(&bp->bp_message_age_timer, 0);
1457 }
1458
1459 static int
1460 bstp_rerooted(struct bstp_state *bs, struct bstp_port *bp)
1461 {
1462         struct bstp_port *bp2;
1463         int rr_set = 0;
1464
1465         LIST_FOREACH(bp2, &bs->bs_bplist, bp_next) {
1466                 if (bp2 == bp)
1467                         continue;
1468                 if (bp2->bp_recent_root_timer.active) {
1469                         rr_set = 1;
1470                         break;
1471                 }
1472         }
1473         return (!rr_set);
1474 }
1475
1476 int
1477 bstp_set_htime(struct bstp_state *bs, int t)
1478 {
1479         /* convert seconds to ticks */
1480         t *=  BSTP_TICK_VAL;
1481
1482         /* value can only be changed in leagacy stp mode */
1483         if (bs->bs_protover != BSTP_PROTO_STP)
1484                 return (EPERM);
1485
1486         if (t < BSTP_MIN_HELLO_TIME || t > BSTP_MAX_HELLO_TIME)
1487                 return (EINVAL);
1488
1489         BSTP_LOCK(bs);
1490         bs->bs_bridge_htime = t;
1491         bstp_reinit(bs);
1492         BSTP_UNLOCK(bs);
1493         return (0);
1494 }
1495
1496 int
1497 bstp_set_fdelay(struct bstp_state *bs, int t)
1498 {
1499         /* convert seconds to ticks */
1500         t *= BSTP_TICK_VAL;
1501
1502         if (t < BSTP_MIN_FORWARD_DELAY || t > BSTP_MAX_FORWARD_DELAY)
1503                 return (EINVAL);
1504
1505         BSTP_LOCK(bs);
1506         bs->bs_bridge_fdelay = t;
1507         bstp_reinit(bs);
1508         BSTP_UNLOCK(bs);
1509         return (0);
1510 }
1511
1512 int
1513 bstp_set_maxage(struct bstp_state *bs, int t)
1514 {
1515         /* convert seconds to ticks */
1516         t *= BSTP_TICK_VAL;
1517
1518         if (t < BSTP_MIN_MAX_AGE || t > BSTP_MAX_MAX_AGE)
1519                 return (EINVAL);
1520
1521         BSTP_LOCK(bs);
1522         bs->bs_bridge_max_age = t;
1523         bstp_reinit(bs);
1524         BSTP_UNLOCK(bs);
1525         return (0);
1526 }
1527
1528 int
1529 bstp_set_holdcount(struct bstp_state *bs, int count)
1530 {
1531         struct bstp_port *bp;
1532
1533         if (count < BSTP_MIN_HOLD_COUNT ||
1534             count > BSTP_MAX_HOLD_COUNT)
1535                 return (EINVAL);
1536
1537         BSTP_LOCK(bs);
1538         bs->bs_txholdcount = count;
1539         LIST_FOREACH(bp, &bs->bs_bplist, bp_next)
1540                 bp->bp_txcount = 0;
1541         BSTP_UNLOCK(bs);
1542         return (0);
1543 }
1544
1545 int
1546 bstp_set_protocol(struct bstp_state *bs, int proto)
1547 {
1548         struct bstp_port *bp;
1549
1550         switch (proto) {
1551                 /* Supported protocol versions */
1552                 case BSTP_PROTO_STP:
1553                 case BSTP_PROTO_RSTP:
1554                         break;
1555
1556                 default:
1557                         return (EINVAL);
1558         }
1559
1560         BSTP_LOCK(bs);
1561         bs->bs_protover = proto;
1562         bs->bs_bridge_htime = BSTP_DEFAULT_HELLO_TIME;
1563         LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
1564                 /* reinit state */
1565                 bp->bp_infois = BSTP_INFO_DISABLED;
1566                 bp->bp_txcount = 0;
1567                 bstp_set_port_proto(bp, bs->bs_protover);
1568                 bstp_set_port_role(bp, BSTP_ROLE_DISABLED);
1569                 bstp_set_port_tc(bp, BSTP_TCSTATE_INACTIVE);
1570                 bstp_timer_stop(&bp->bp_recent_backup_timer);
1571         }
1572         bstp_reinit(bs);
1573         BSTP_UNLOCK(bs);
1574         return (0);
1575 }
1576
1577 int
1578 bstp_set_priority(struct bstp_state *bs, int pri)
1579 {
1580         if (pri < 0 || pri > BSTP_MAX_PRIORITY)
1581                 return (EINVAL);
1582
1583         /* Limit to steps of 4096 */
1584         pri -= pri % 4096;
1585
1586         BSTP_LOCK(bs);
1587         bs->bs_bridge_priority = pri;
1588         bstp_reinit(bs);
1589         BSTP_UNLOCK(bs);
1590         return (0);
1591 }
1592
1593 int
1594 bstp_set_port_priority(struct bstp_port *bp, int pri)
1595 {
1596         struct bstp_state *bs = bp->bp_bs;
1597
1598         if (pri < 0 || pri > BSTP_MAX_PORT_PRIORITY)
1599                 return (EINVAL);
1600
1601         /* Limit to steps of 16 */
1602         pri -= pri % 16;
1603
1604         BSTP_LOCK(bs);
1605         bp->bp_priority = pri;
1606         bstp_reinit(bs);
1607         BSTP_UNLOCK(bs);
1608         return (0);
1609 }
1610
1611 int
1612 bstp_set_path_cost(struct bstp_port *bp, uint32_t path_cost)
1613 {
1614         struct bstp_state *bs = bp->bp_bs;
1615
1616         if (path_cost > BSTP_MAX_PATH_COST)
1617                 return (EINVAL);
1618
1619         /* STP compat mode only uses 16 bits of the 32 */
1620         if (bp->bp_protover == BSTP_PROTO_STP && path_cost > 65535)
1621                 path_cost = 65535;
1622
1623         BSTP_LOCK(bs);
1624
1625         if (path_cost == 0) {   /* use auto */
1626                 bp->bp_flags &= ~BSTP_PORT_ADMCOST;
1627                 bp->bp_path_cost = bstp_calc_path_cost(bp);
1628         } else {
1629                 bp->bp_path_cost = path_cost;
1630                 bp->bp_flags |= BSTP_PORT_ADMCOST;
1631         }
1632         bstp_reinit(bs);
1633         BSTP_UNLOCK(bs);
1634         return (0);
1635 }
1636
1637 int
1638 bstp_set_edge(struct bstp_port *bp, int set)
1639 {
1640         struct bstp_state *bs = bp->bp_bs;
1641
1642         BSTP_LOCK(bs);
1643         if ((bp->bp_operedge = set) == 0)
1644                 bp->bp_flags &= ~BSTP_PORT_ADMEDGE;
1645         else
1646                 bp->bp_flags |= BSTP_PORT_ADMEDGE;
1647         BSTP_UNLOCK(bs);
1648         return (0);
1649 }
1650
1651 int
1652 bstp_set_autoedge(struct bstp_port *bp, int set)
1653 {
1654         struct bstp_state *bs = bp->bp_bs;
1655
1656         BSTP_LOCK(bs);
1657         if (set) {
1658                 bp->bp_flags |= BSTP_PORT_AUTOEDGE;
1659                 /* we may be able to transition straight to edge */
1660                 if (bp->bp_edge_delay_timer.active == 0)
1661                         bstp_edge_delay_expiry(bs, bp);
1662         } else
1663                 bp->bp_flags &= ~BSTP_PORT_AUTOEDGE;
1664         BSTP_UNLOCK(bs);
1665         return (0);
1666 }
1667
1668 int
1669 bstp_set_ptp(struct bstp_port *bp, int set)
1670 {
1671         struct bstp_state *bs = bp->bp_bs;
1672
1673         BSTP_LOCK(bs);
1674         bp->bp_ptp_link = set;
1675         BSTP_UNLOCK(bs);
1676         return (0);
1677 }
1678
1679 int
1680 bstp_set_autoptp(struct bstp_port *bp, int set)
1681 {
1682         struct bstp_state *bs = bp->bp_bs;
1683
1684         BSTP_LOCK(bs);
1685         if (set) {
1686                 bp->bp_flags |= BSTP_PORT_AUTOPTP;
1687                 if (bp->bp_role != BSTP_ROLE_DISABLED)
1688                         taskqueue_enqueue(taskqueue_swi, &bp->bp_mediatask);
1689         } else
1690                 bp->bp_flags &= ~BSTP_PORT_AUTOPTP;
1691         BSTP_UNLOCK(bs);
1692         return (0);
1693 }
1694
1695 /*
1696  * Calculate the path cost according to the link speed.
1697  */
1698 static uint32_t
1699 bstp_calc_path_cost(struct bstp_port *bp)
1700 {
1701         struct ifnet *ifp = bp->bp_ifp;
1702         uint32_t path_cost;
1703
1704         /* If the priority has been manually set then retain the value */
1705         if (bp->bp_flags & BSTP_PORT_ADMCOST)
1706                 return bp->bp_path_cost;
1707
1708         if (ifp->if_link_state == LINK_STATE_DOWN) {
1709                 /* Recalc when the link comes up again */
1710                 bp->bp_flags |= BSTP_PORT_PNDCOST;
1711                 return (BSTP_DEFAULT_PATH_COST);
1712         }
1713
1714         if (ifp->if_baudrate < 1000)
1715                 return (BSTP_DEFAULT_PATH_COST);
1716
1717         /* formula from section 17.14, IEEE Std 802.1D-2004 */
1718         path_cost = 20000000000ULL / (ifp->if_baudrate / 1000);
1719
1720         if (path_cost > BSTP_MAX_PATH_COST)
1721                 path_cost = BSTP_MAX_PATH_COST;
1722
1723         /* STP compat mode only uses 16 bits of the 32 */
1724         if (bp->bp_protover == BSTP_PROTO_STP && path_cost > 65535)
1725                 path_cost = 65535;
1726
1727         return (path_cost);
1728 }
1729
1730 /*
1731  * Notify the bridge that a port state has changed, we need to do this from a
1732  * taskqueue to avoid a LOR.
1733  */
1734 static void
1735 bstp_notify_state(void *arg, int pending)
1736 {
1737         struct bstp_port *bp = (struct bstp_port *)arg;
1738         struct bstp_state *bs = bp->bp_bs;
1739
1740         if (bp->bp_active == 1 && bs->bs_state_cb != NULL)
1741                 (*bs->bs_state_cb)(bp->bp_ifp, bp->bp_state);
1742 }
1743
1744 /*
1745  * Flush the routes on the bridge port, we need to do this from a
1746  * taskqueue to avoid a LOR.
1747  */
1748 static void
1749 bstp_notify_rtage(void *arg, int pending)
1750 {
1751         struct bstp_port *bp = (struct bstp_port *)arg;
1752         struct bstp_state *bs = bp->bp_bs;
1753         int age = 0;
1754
1755         BSTP_LOCK(bs);
1756         switch (bp->bp_protover) {
1757                 case BSTP_PROTO_STP:
1758                         /* convert to seconds */
1759                         age = bp->bp_desg_fdelay / BSTP_TICK_VAL;
1760                         break;
1761
1762                 case BSTP_PROTO_RSTP:
1763                         age = 0;
1764                         break;
1765         }
1766         BSTP_UNLOCK(bs);
1767
1768         if (bp->bp_active == 1 && bs->bs_rtage_cb != NULL)
1769                 (*bs->bs_rtage_cb)(bp->bp_ifp, age);
1770
1771         /* flush is complete */
1772         BSTP_LOCK(bs);
1773         bp->bp_fdbflush = 0;
1774         BSTP_UNLOCK(bs);
1775 }
1776
1777 void
1778 bstp_linkstate(struct bstp_port *bp)
1779 {
1780         struct bstp_state *bs = bp->bp_bs;
1781
1782         if (!bp->bp_active)
1783                 return;
1784
1785         bstp_ifupdstatus(bp, 0);
1786         BSTP_LOCK(bs);
1787         bstp_update_state(bs, bp);
1788         BSTP_UNLOCK(bs);
1789 }
1790
1791 static void
1792 bstp_ifupdstatus(void *arg, int pending)
1793 {
1794         struct bstp_port *bp = (struct bstp_port *)arg;
1795         struct bstp_state *bs = bp->bp_bs;
1796         struct ifnet *ifp = bp->bp_ifp;
1797         struct ifmediareq ifmr;
1798         int error, changed;
1799
1800         if (!bp->bp_active)
1801                 return;
1802
1803         bzero((char *)&ifmr, sizeof(ifmr));
1804         error = (*ifp->if_ioctl)(ifp, SIOCGIFMEDIA, (caddr_t)&ifmr);
1805
1806         BSTP_LOCK(bs);
1807         changed = 0;
1808         if ((error == 0) && (ifp->if_flags & IFF_UP)) {
1809                 if (ifmr.ifm_status & IFM_ACTIVE) {
1810                         /* A full-duplex link is assumed to be point to point */
1811                         if (bp->bp_flags & BSTP_PORT_AUTOPTP) {
1812                                 int fdx;
1813
1814                                 fdx = ifmr.ifm_active & IFM_FDX ? 1 : 0;
1815                                 if (bp->bp_ptp_link ^ fdx) {
1816                                         bp->bp_ptp_link = fdx;
1817                                         changed = 1;
1818                                 }
1819                         }
1820
1821                         /* Calc the cost if the link was down previously */
1822                         if (bp->bp_flags & BSTP_PORT_PNDCOST) {
1823                                 uint32_t cost;
1824
1825                                 cost = bstp_calc_path_cost(bp);
1826                                 if (bp->bp_path_cost != cost) {
1827                                         bp->bp_path_cost = cost;
1828                                         changed = 1;
1829                                 }
1830                                 bp->bp_flags &= ~BSTP_PORT_PNDCOST;
1831                         }
1832
1833                         if (bp->bp_role == BSTP_ROLE_DISABLED) {
1834                                 bstp_enable_port(bs, bp);
1835                                 changed = 1;
1836                         }
1837                 } else {
1838                         if (bp->bp_role != BSTP_ROLE_DISABLED) {
1839                                 bstp_disable_port(bs, bp);
1840                                 changed = 1;
1841                                 if ((bp->bp_flags & BSTP_PORT_ADMEDGE) &&
1842                                     bp->bp_protover == BSTP_PROTO_RSTP)
1843                                         bp->bp_operedge = 1;
1844                         }
1845                 }
1846         } else if (bp->bp_infois != BSTP_INFO_DISABLED) {
1847                 bstp_disable_port(bs, bp);
1848                 changed = 1;
1849         }
1850         if (changed)
1851                 bstp_assign_roles(bs);
1852         BSTP_UNLOCK(bs);
1853 }
1854
1855 static void
1856 bstp_enable_port(struct bstp_state *bs, struct bstp_port *bp)
1857 {
1858         bp->bp_infois = BSTP_INFO_AGED;
1859 }
1860
1861 static void
1862 bstp_disable_port(struct bstp_state *bs, struct bstp_port *bp)
1863 {
1864         bp->bp_infois = BSTP_INFO_DISABLED;
1865 }
1866
1867 static void
1868 bstp_tick(void *arg)
1869 {
1870         struct epoch_tracker et;
1871         struct bstp_state *bs = arg;
1872         struct bstp_port *bp;
1873
1874         BSTP_LOCK_ASSERT(bs);
1875
1876         if (bs->bs_running == 0)
1877                 return;
1878
1879         NET_EPOCH_ENTER(et);
1880         CURVNET_SET(bs->bs_vnet);
1881
1882         /* poll link events on interfaces that do not support linkstate */
1883         if (bstp_timer_dectest(&bs->bs_link_timer)) {
1884                 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
1885                         if (!(bp->bp_ifp->if_capabilities & IFCAP_LINKSTATE))
1886                                 taskqueue_enqueue(taskqueue_swi, &bp->bp_mediatask);
1887                 }
1888                 bstp_timer_start(&bs->bs_link_timer, BSTP_LINK_TIMER);
1889         }
1890
1891         LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
1892                 /* no events need to happen for these */
1893                 bstp_timer_dectest(&bp->bp_tc_timer);
1894                 bstp_timer_dectest(&bp->bp_recent_root_timer);
1895                 bstp_timer_dectest(&bp->bp_forward_delay_timer);
1896                 bstp_timer_dectest(&bp->bp_recent_backup_timer);
1897
1898                 if (bstp_timer_dectest(&bp->bp_hello_timer))
1899                         bstp_hello_timer_expiry(bs, bp);
1900
1901                 if (bstp_timer_dectest(&bp->bp_message_age_timer))
1902                         bstp_message_age_expiry(bs, bp);
1903
1904                 if (bstp_timer_dectest(&bp->bp_migrate_delay_timer))
1905                         bstp_migrate_delay_expiry(bs, bp);
1906
1907                 if (bstp_timer_dectest(&bp->bp_edge_delay_timer))
1908                         bstp_edge_delay_expiry(bs, bp);
1909
1910                 /* update the various state machines for the port */
1911                 bstp_update_state(bs, bp);
1912
1913                 if (bp->bp_txcount > 0)
1914                         bp->bp_txcount--;
1915         }
1916
1917         CURVNET_RESTORE();
1918         NET_EPOCH_EXIT(et);
1919
1920         callout_reset(&bs->bs_bstpcallout, hz, bstp_tick, bs);
1921 }
1922
1923 static void
1924 bstp_timer_start(struct bstp_timer *t, uint16_t v)
1925 {
1926         t->value = v;
1927         t->active = 1;
1928         t->latched = 0;
1929 }
1930
1931 static void
1932 bstp_timer_stop(struct bstp_timer *t)
1933 {
1934         t->value = 0;
1935         t->active = 0;
1936         t->latched = 0;
1937 }
1938
1939 static void
1940 bstp_timer_latch(struct bstp_timer *t)
1941 {
1942         t->latched = 1;
1943         t->active = 1;
1944 }
1945
1946 static int
1947 bstp_timer_dectest(struct bstp_timer *t)
1948 {
1949         if (t->active == 0 || t->latched)
1950                 return (0);
1951         t->value -= BSTP_TICK_VAL;
1952         if (t->value <= 0) {
1953                 bstp_timer_stop(t);
1954                 return (1);
1955         }
1956         return (0);
1957 }
1958
1959 static void
1960 bstp_hello_timer_expiry(struct bstp_state *bs, struct bstp_port *bp)
1961 {
1962         if ((bp->bp_flags & BSTP_PORT_NEWINFO) ||
1963             bp->bp_role == BSTP_ROLE_DESIGNATED ||
1964             (bp->bp_role == BSTP_ROLE_ROOT &&
1965              bp->bp_tc_timer.active == 1)) {
1966                 bstp_timer_start(&bp->bp_hello_timer, bp->bp_desg_htime);
1967                 bp->bp_flags |= BSTP_PORT_NEWINFO;
1968                 bstp_transmit(bs, bp);
1969         }
1970 }
1971
1972 static void
1973 bstp_message_age_expiry(struct bstp_state *bs, struct bstp_port *bp)
1974 {
1975         if (bp->bp_infois == BSTP_INFO_RECEIVED) {
1976                 bp->bp_infois = BSTP_INFO_AGED;
1977                 bstp_assign_roles(bs);
1978                 DPRINTF("aged info on %s\n", bp->bp_ifp->if_xname);
1979         }
1980 }
1981
1982 static void
1983 bstp_migrate_delay_expiry(struct bstp_state *bs, struct bstp_port *bp)
1984 {
1985         bp->bp_flags |= BSTP_PORT_CANMIGRATE;
1986 }
1987
1988 static void
1989 bstp_edge_delay_expiry(struct bstp_state *bs, struct bstp_port *bp)
1990 {
1991         if ((bp->bp_flags & BSTP_PORT_AUTOEDGE) &&
1992             bp->bp_protover == BSTP_PROTO_RSTP && bp->bp_proposing &&
1993             bp->bp_role == BSTP_ROLE_DESIGNATED) {
1994                 bp->bp_operedge = 1;
1995                 DPRINTF("%s -> edge port\n", bp->bp_ifp->if_xname);
1996         }
1997 }
1998
1999 static int
2000 bstp_addr_cmp(const uint8_t *a, const uint8_t *b)
2001 {
2002         int i, d;
2003
2004         for (i = 0, d = 0; i < ETHER_ADDR_LEN && d == 0; i++) {
2005                 d = ((int)a[i]) - ((int)b[i]);
2006         }
2007
2008         return (d);
2009 }
2010
2011 /*
2012  * compare the bridge address component of the bridgeid
2013  */
2014 static int
2015 bstp_same_bridgeid(uint64_t id1, uint64_t id2)
2016 {
2017         u_char addr1[ETHER_ADDR_LEN];
2018         u_char addr2[ETHER_ADDR_LEN];
2019
2020         PV2ADDR(id1, addr1);
2021         PV2ADDR(id2, addr2);
2022
2023         if (bstp_addr_cmp(addr1, addr2) == 0)
2024                 return (1);
2025
2026         return (0);
2027 }
2028
2029 void
2030 bstp_reinit(struct bstp_state *bs)
2031 {
2032         struct epoch_tracker et;
2033         struct bstp_port *bp;
2034         struct ifnet *ifp, *mif;
2035         u_char *e_addr;
2036         void *bridgeptr;
2037         static const u_char llzero[ETHER_ADDR_LEN];     /* 00:00:00:00:00:00 */
2038
2039         BSTP_LOCK_ASSERT(bs);
2040
2041         if (LIST_EMPTY(&bs->bs_bplist))
2042                 goto disablestp;
2043
2044         mif = NULL;
2045         bridgeptr = LIST_FIRST(&bs->bs_bplist)->bp_ifp->if_bridge;
2046         KASSERT(bridgeptr != NULL, ("Invalid bridge pointer"));
2047         /*
2048          * Search through the Ethernet adapters and find the one with the
2049          * lowest value. Make sure the adapter which we take the MAC address
2050          * from is part of this bridge, so we can have more than one independent
2051          * bridges in the same STP domain.
2052          */
2053         NET_EPOCH_ENTER(et);
2054         CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
2055                 if (ifp->if_type != IFT_ETHER && ifp->if_type != IFT_L2VLAN)
2056                         continue;       /* Not Ethernet */
2057
2058                 if (ifp->if_bridge != bridgeptr)
2059                         continue;       /* Not part of our bridge */
2060
2061                 if (bstp_addr_cmp(IF_LLADDR(ifp), llzero) == 0)
2062                         continue;       /* No mac address set */
2063
2064                 if (mif == NULL) {
2065                         mif = ifp;
2066                         continue;
2067                 }
2068                 if (bstp_addr_cmp(IF_LLADDR(ifp), IF_LLADDR(mif)) < 0) {
2069                         mif = ifp;
2070                         continue;
2071                 }
2072         }
2073         NET_EPOCH_EXIT(et);
2074         if (mif == NULL)
2075                 goto disablestp;
2076
2077         e_addr = IF_LLADDR(mif);
2078         bs->bs_bridge_pv.pv_dbridge_id =
2079             (((uint64_t)bs->bs_bridge_priority) << 48) |
2080             (((uint64_t)e_addr[0]) << 40) |
2081             (((uint64_t)e_addr[1]) << 32) |
2082             (((uint64_t)e_addr[2]) << 24) |
2083             (((uint64_t)e_addr[3]) << 16) |
2084             (((uint64_t)e_addr[4]) << 8) |
2085             (((uint64_t)e_addr[5]));
2086
2087         bs->bs_bridge_pv.pv_root_id = bs->bs_bridge_pv.pv_dbridge_id;
2088         bs->bs_bridge_pv.pv_cost = 0;
2089         bs->bs_bridge_pv.pv_dport_id = 0;
2090         bs->bs_bridge_pv.pv_port_id = 0;
2091
2092         if (bs->bs_running && callout_pending(&bs->bs_bstpcallout) == 0)
2093                 callout_reset(&bs->bs_bstpcallout, hz, bstp_tick, bs);
2094
2095         LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
2096                 bp->bp_port_id = (bp->bp_priority << 8) |
2097                     (bp->bp_ifp->if_index  & 0xfff);
2098                 taskqueue_enqueue(taskqueue_swi, &bp->bp_mediatask);
2099         }
2100
2101         bstp_assign_roles(bs);
2102         bstp_timer_start(&bs->bs_link_timer, BSTP_LINK_TIMER);
2103         return;
2104
2105 disablestp:
2106         /* Set the bridge and root id (lower bits) to zero */
2107         bs->bs_bridge_pv.pv_dbridge_id =
2108             ((uint64_t)bs->bs_bridge_priority) << 48;
2109         bs->bs_bridge_pv.pv_root_id = bs->bs_bridge_pv.pv_dbridge_id;
2110         bs->bs_root_pv = bs->bs_bridge_pv;
2111         /* Disable any remaining ports, they will have no MAC address */
2112         LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
2113                 bp->bp_infois = BSTP_INFO_DISABLED;
2114                 bstp_set_port_role(bp, BSTP_ROLE_DISABLED);
2115         }
2116         callout_stop(&bs->bs_bstpcallout);
2117 }
2118
2119 static int
2120 bstp_modevent(module_t mod, int type, void *data)
2121 {
2122         switch (type) {
2123         case MOD_LOAD:
2124                 mtx_init(&bstp_list_mtx, "bridgestp list", NULL, MTX_DEF);
2125                 LIST_INIT(&bstp_list);
2126                 break;
2127         case MOD_UNLOAD:
2128                 mtx_destroy(&bstp_list_mtx);
2129                 break;
2130         default:
2131                 return (EOPNOTSUPP);
2132         }
2133         return (0);
2134 }
2135
2136 static moduledata_t bstp_mod = {
2137         "bridgestp",
2138         bstp_modevent,
2139         0
2140 };
2141
2142 DECLARE_MODULE(bridgestp, bstp_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
2143 MODULE_VERSION(bridgestp, 1);
2144
2145 void
2146 bstp_attach(struct bstp_state *bs, struct bstp_cb_ops *cb)
2147 {
2148         BSTP_LOCK_INIT(bs);
2149         callout_init_mtx(&bs->bs_bstpcallout, &bs->bs_mtx, 0);
2150         LIST_INIT(&bs->bs_bplist);
2151
2152         bs->bs_bridge_max_age = BSTP_DEFAULT_MAX_AGE;
2153         bs->bs_bridge_htime = BSTP_DEFAULT_HELLO_TIME;
2154         bs->bs_bridge_fdelay = BSTP_DEFAULT_FORWARD_DELAY;
2155         bs->bs_bridge_priority = BSTP_DEFAULT_BRIDGE_PRIORITY;
2156         bs->bs_hold_time = BSTP_DEFAULT_HOLD_TIME;
2157         bs->bs_migration_delay = BSTP_DEFAULT_MIGRATE_DELAY;
2158         bs->bs_txholdcount = BSTP_DEFAULT_HOLD_COUNT;
2159         bs->bs_protover = BSTP_PROTO_RSTP;
2160         bs->bs_state_cb = cb->bcb_state;
2161         bs->bs_rtage_cb = cb->bcb_rtage;
2162         bs->bs_vnet = curvnet;
2163
2164         getmicrotime(&bs->bs_last_tc_time);
2165
2166         mtx_lock(&bstp_list_mtx);
2167         LIST_INSERT_HEAD(&bstp_list, bs, bs_list);
2168         mtx_unlock(&bstp_list_mtx);
2169 }
2170
2171 void
2172 bstp_detach(struct bstp_state *bs)
2173 {
2174         KASSERT(LIST_EMPTY(&bs->bs_bplist), ("bstp still active"));
2175
2176         mtx_lock(&bstp_list_mtx);
2177         LIST_REMOVE(bs, bs_list);
2178         mtx_unlock(&bstp_list_mtx);
2179         callout_drain(&bs->bs_bstpcallout);
2180         BSTP_LOCK_DESTROY(bs);
2181 }
2182
2183 void
2184 bstp_init(struct bstp_state *bs)
2185 {
2186         BSTP_LOCK(bs);
2187         callout_reset(&bs->bs_bstpcallout, hz, bstp_tick, bs);
2188         bs->bs_running = 1;
2189         bstp_reinit(bs);
2190         BSTP_UNLOCK(bs);
2191 }
2192
2193 void
2194 bstp_stop(struct bstp_state *bs)
2195 {
2196         struct bstp_port *bp;
2197
2198         BSTP_LOCK(bs);
2199
2200         LIST_FOREACH(bp, &bs->bs_bplist, bp_next)
2201                 bstp_set_port_state(bp, BSTP_IFSTATE_DISCARDING);
2202
2203         bs->bs_running = 0;
2204         callout_stop(&bs->bs_bstpcallout);
2205         BSTP_UNLOCK(bs);
2206 }
2207
2208 int
2209 bstp_create(struct bstp_state *bs, struct bstp_port *bp, struct ifnet *ifp)
2210 {
2211         bzero(bp, sizeof(struct bstp_port));
2212
2213         BSTP_LOCK(bs);
2214         bp->bp_ifp = ifp;
2215         bp->bp_bs = bs;
2216         bp->bp_priority = BSTP_DEFAULT_PORT_PRIORITY;
2217         TASK_INIT(&bp->bp_statetask, 0, bstp_notify_state, bp);
2218         TASK_INIT(&bp->bp_rtagetask, 0, bstp_notify_rtage, bp);
2219         TASK_INIT(&bp->bp_mediatask, 0, bstp_ifupdstatus, bp);
2220
2221         /* Init state */
2222         bp->bp_infois = BSTP_INFO_DISABLED;
2223         bp->bp_flags = BSTP_PORT_AUTOEDGE|BSTP_PORT_AUTOPTP;
2224         bstp_set_port_state(bp, BSTP_IFSTATE_DISCARDING);
2225         bstp_set_port_proto(bp, bs->bs_protover);
2226         bstp_set_port_role(bp, BSTP_ROLE_DISABLED);
2227         bstp_set_port_tc(bp, BSTP_TCSTATE_INACTIVE);
2228         bp->bp_path_cost = bstp_calc_path_cost(bp);
2229         BSTP_UNLOCK(bs);
2230         return (0);
2231 }
2232
2233 int
2234 bstp_enable(struct bstp_port *bp)
2235 {
2236         struct bstp_state *bs = bp->bp_bs;
2237         struct ifnet *ifp = bp->bp_ifp;
2238
2239         KASSERT(bp->bp_active == 0, ("already a bstp member"));
2240         NET_EPOCH_ASSERT(); /* Because bstp_update_roles() causes traffic. */
2241
2242         switch (ifp->if_type) {
2243                 case IFT_ETHER: /* These can do spanning tree. */
2244                 case IFT_L2VLAN:
2245                         break;
2246                 default:
2247                         /* Nothing else can. */
2248                         return (EINVAL);
2249         }
2250
2251         BSTP_LOCK(bs);
2252         LIST_INSERT_HEAD(&bs->bs_bplist, bp, bp_next);
2253         bp->bp_active = 1;
2254         bp->bp_flags |= BSTP_PORT_NEWINFO;
2255         bstp_reinit(bs);
2256         bstp_update_roles(bs, bp);
2257         BSTP_UNLOCK(bs);
2258         return (0);
2259 }
2260
2261 void
2262 bstp_disable(struct bstp_port *bp)
2263 {
2264         struct bstp_state *bs = bp->bp_bs;
2265
2266         KASSERT(bp->bp_active == 1, ("not a bstp member"));
2267
2268         BSTP_LOCK(bs);
2269         bstp_disable_port(bs, bp);
2270         LIST_REMOVE(bp, bp_next);
2271         bp->bp_active = 0;
2272         bstp_reinit(bs);
2273         BSTP_UNLOCK(bs);
2274 }
2275
2276 /*
2277  * The bstp_port structure is about to be freed by the parent bridge.
2278  */
2279 void
2280 bstp_destroy(struct bstp_port *bp)
2281 {
2282         KASSERT(bp->bp_active == 0, ("port is still attached"));
2283         taskqueue_drain(taskqueue_swi, &bp->bp_statetask);
2284         taskqueue_drain(taskqueue_swi, &bp->bp_rtagetask);
2285         taskqueue_drain(taskqueue_swi, &bp->bp_mediatask);
2286
2287         if (bp->bp_bs->bs_root_port == bp)
2288                 bstp_assign_roles(bp->bp_bs);
2289 }