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