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