]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/net/ieee8023ad_lacp.c
Bring over some link aggregation / LACP protocol improvements and debugging
[FreeBSD/FreeBSD.git] / sys / net / ieee8023ad_lacp.c
1 /*      $NetBSD: ieee8023ad_lacp.c,v 1.3 2005/12/11 12:24:54 christos Exp $     */
2
3 /*-
4  * Copyright (c)2005 YAMAMOTO Takashi,
5  * Copyright (c)2008 Andrew Thompson <thompsa@FreeBSD.org>
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include <sys/param.h>
34 #include <sys/callout.h>
35 #include <sys/mbuf.h>
36 #include <sys/systm.h>
37 #include <sys/malloc.h>
38 #include <sys/kernel.h> /* hz */
39 #include <sys/socket.h> /* for net/if.h */
40 #include <sys/sockio.h>
41 #include <sys/sysctl.h>
42 #include <machine/stdarg.h>
43 #include <sys/lock.h>
44 #include <sys/rwlock.h>
45
46 #include <net/if.h>
47 #include <net/if_dl.h>
48 #include <net/ethernet.h>
49 #include <net/if_media.h>
50 #include <net/if_types.h>
51
52 #include <net/if_lagg.h>
53 #include <net/ieee8023ad_lacp.h>
54
55 /*
56  * actor system priority and port priority.
57  * XXX should be configurable.
58  */
59
60 #define LACP_SYSTEM_PRIO        0x8000
61 #define LACP_PORT_PRIO          0x8000
62
63 const uint8_t ethermulticastaddr_slowprotocols[ETHER_ADDR_LEN] =
64     { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x02 };
65
66 static const struct tlv_template lacp_info_tlv_template[] = {
67         { LACP_TYPE_ACTORINFO,
68             sizeof(struct tlvhdr) + sizeof(struct lacp_peerinfo) },
69         { LACP_TYPE_PARTNERINFO,
70             sizeof(struct tlvhdr) + sizeof(struct lacp_peerinfo) },
71         { LACP_TYPE_COLLECTORINFO,
72             sizeof(struct tlvhdr) + sizeof(struct lacp_collectorinfo) },
73         { 0, 0 },
74 };
75
76 static const struct tlv_template marker_info_tlv_template[] = {
77         { MARKER_TYPE_INFO,
78             sizeof(struct tlvhdr) + sizeof(struct lacp_markerinfo) },
79         { 0, 0 },
80 };
81
82 static const struct tlv_template marker_response_tlv_template[] = {
83         { MARKER_TYPE_RESPONSE,
84             sizeof(struct tlvhdr) + sizeof(struct lacp_markerinfo) },
85         { 0, 0 },
86 };
87
88 typedef void (*lacp_timer_func_t)(struct lacp_port *);
89
90 static void     lacp_fill_actorinfo(struct lacp_port *, struct lacp_peerinfo *);
91 static void     lacp_fill_markerinfo(struct lacp_port *,
92                     struct lacp_markerinfo *);
93
94 static uint64_t lacp_aggregator_bandwidth(struct lacp_aggregator *);
95 static void     lacp_suppress_distributing(struct lacp_softc *,
96                     struct lacp_aggregator *);
97 static void     lacp_transit_expire(void *);
98 static void     lacp_update_portmap(struct lacp_softc *);
99 static void     lacp_select_active_aggregator(struct lacp_softc *);
100 static uint16_t lacp_compose_key(struct lacp_port *);
101 static int      tlv_check(const void *, size_t, const struct tlvhdr *,
102                     const struct tlv_template *, boolean_t);
103 static void     lacp_tick(void *);
104
105 static void     lacp_fill_aggregator_id(struct lacp_aggregator *,
106                     const struct lacp_port *);
107 static void     lacp_fill_aggregator_id_peer(struct lacp_peerinfo *,
108                     const struct lacp_peerinfo *);
109 static int      lacp_aggregator_is_compatible(const struct lacp_aggregator *,
110                     const struct lacp_port *);
111 static int      lacp_peerinfo_is_compatible(const struct lacp_peerinfo *,
112                     const struct lacp_peerinfo *);
113
114 static struct lacp_aggregator *lacp_aggregator_get(struct lacp_softc *,
115                     struct lacp_port *);
116 static void     lacp_aggregator_addref(struct lacp_softc *,
117                     struct lacp_aggregator *);
118 static void     lacp_aggregator_delref(struct lacp_softc *,
119                     struct lacp_aggregator *);
120
121 /* receive machine */
122
123 static int      lacp_pdu_input(struct lacp_port *, struct mbuf *);
124 static int      lacp_marker_input(struct lacp_port *, struct mbuf *);
125 static void     lacp_sm_rx(struct lacp_port *, const struct lacpdu *);
126 static void     lacp_sm_rx_timer(struct lacp_port *);
127 static void     lacp_sm_rx_set_expired(struct lacp_port *);
128 static void     lacp_sm_rx_update_ntt(struct lacp_port *,
129                     const struct lacpdu *);
130 static void     lacp_sm_rx_record_pdu(struct lacp_port *,
131                     const struct lacpdu *);
132 static void     lacp_sm_rx_update_selected(struct lacp_port *,
133                     const struct lacpdu *);
134 static void     lacp_sm_rx_record_default(struct lacp_port *);
135 static void     lacp_sm_rx_update_default_selected(struct lacp_port *);
136 static void     lacp_sm_rx_update_selected_from_peerinfo(struct lacp_port *,
137                     const struct lacp_peerinfo *);
138
139 /* mux machine */
140
141 static void     lacp_sm_mux(struct lacp_port *);
142 static void     lacp_set_mux(struct lacp_port *, enum lacp_mux_state);
143 static void     lacp_sm_mux_timer(struct lacp_port *);
144
145 /* periodic transmit machine */
146
147 static void     lacp_sm_ptx_update_timeout(struct lacp_port *, uint8_t);
148 static void     lacp_sm_ptx_tx_schedule(struct lacp_port *);
149 static void     lacp_sm_ptx_timer(struct lacp_port *);
150
151 /* transmit machine */
152
153 static void     lacp_sm_tx(struct lacp_port *);
154 static void     lacp_sm_assert_ntt(struct lacp_port *);
155
156 static void     lacp_run_timers(struct lacp_port *);
157 static int      lacp_compare_peerinfo(const struct lacp_peerinfo *,
158                     const struct lacp_peerinfo *);
159 static int      lacp_compare_systemid(const struct lacp_systemid *,
160                     const struct lacp_systemid *);
161 static void     lacp_port_enable(struct lacp_port *);
162 static void     lacp_port_disable(struct lacp_port *);
163 static void     lacp_select(struct lacp_port *);
164 static void     lacp_unselect(struct lacp_port *);
165 static void     lacp_disable_collecting(struct lacp_port *);
166 static void     lacp_enable_collecting(struct lacp_port *);
167 static void     lacp_disable_distributing(struct lacp_port *);
168 static void     lacp_enable_distributing(struct lacp_port *);
169 static int      lacp_xmit_lacpdu(struct lacp_port *);
170 static int      lacp_xmit_marker(struct lacp_port *);
171
172 /* Debugging */
173
174 static void     lacp_dump_lacpdu(const struct lacpdu *);
175 static const char *lacp_format_partner(const struct lacp_peerinfo *, char *,
176                     size_t);
177 static const char *lacp_format_lagid(const struct lacp_peerinfo *,
178                     const struct lacp_peerinfo *, char *, size_t);
179 static const char *lacp_format_lagid_aggregator(const struct lacp_aggregator *,
180                     char *, size_t);
181 static const char *lacp_format_state(uint8_t, char *, size_t);
182 static const char *lacp_format_mac(const uint8_t *, char *, size_t);
183 static const char *lacp_format_systemid(const struct lacp_systemid *, char *,
184                     size_t);
185 static const char *lacp_format_portid(const struct lacp_portid *, char *,
186                     size_t);
187 static void     lacp_dprintf(const struct lacp_port *, const char *, ...)
188                     __attribute__((__format__(__printf__, 2, 3)));
189
190 static int lacp_debug = 0;
191 SYSCTL_NODE(_net_link_lagg, OID_AUTO, lacp, CTLFLAG_RD, 0, "ieee802.3ad");
192 SYSCTL_INT(_net_link_lagg_lacp, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN,
193     &lacp_debug, 0, "Enable LACP debug logging (1=debug, 2=trace)");
194 TUNABLE_INT("net.link.lagg.lacp.debug", &lacp_debug);
195
196 /* bitmap of ports */
197 static int lacp_rx_test = 0;
198 static int lacp_tx_test = 0;
199 SYSCTL_INT(_net_link_lagg_lacp, OID_AUTO, rxtest, CTLFLAG_RW, &lacp_rx_test, 0,
200     "RXTest");
201 SYSCTL_INT(_net_link_lagg_lacp, OID_AUTO, txtest, CTLFLAG_RW, &lacp_tx_test, 0,
202     "TXTest");
203
204 static int lacp_strict = 1;
205 SYSCTL_INT(_net_link_lagg_lacp, OID_AUTO, strict, CTLFLAG_RW, &lacp_strict,
206     0, "Strict spec compliance");
207
208 #define LACP_DPRINTF(a) if (lacp_debug & 0x01) { lacp_dprintf a ; }
209 #define LACP_TRACE(a) if (lacp_debug & 0x02) { lacp_dprintf(a,"%s\n",__func__); }
210 #define LACP_TPRINTF(a) if (lacp_debug & 0x04) { lacp_dprintf a ; }
211
212 /*
213  * partner administration variables.
214  * XXX should be configurable.
215  */
216
217 static const struct lacp_peerinfo lacp_partner_admin_optimistic = {
218         .lip_systemid = { .lsi_prio = 0xffff },
219         .lip_portid = { .lpi_prio = 0xffff },
220         .lip_state = LACP_STATE_SYNC | LACP_STATE_AGGREGATION |
221             LACP_STATE_COLLECTING | LACP_STATE_DISTRIBUTING,
222 };
223
224 static const struct lacp_peerinfo lacp_partner_admin_strict = {
225         .lip_systemid = { .lsi_prio = 0xffff },
226         .lip_portid = { .lpi_prio = 0xffff },
227         .lip_state = 0,
228 };
229
230 static const lacp_timer_func_t lacp_timer_funcs[LACP_NTIMER] = {
231         [LACP_TIMER_CURRENT_WHILE] = lacp_sm_rx_timer,
232         [LACP_TIMER_PERIODIC] = lacp_sm_ptx_timer,
233         [LACP_TIMER_WAIT_WHILE] = lacp_sm_mux_timer,
234 };
235
236 struct mbuf *
237 lacp_input(struct lagg_port *lgp, struct mbuf *m)
238 {
239         struct lacp_port *lp = LACP_PORT(lgp);
240         uint8_t subtype;
241
242         if (m->m_pkthdr.len < sizeof(struct ether_header) + sizeof(subtype)) {
243                 m_freem(m);
244                 return (NULL);
245         }
246
247         m_copydata(m, sizeof(struct ether_header), sizeof(subtype), &subtype);
248         switch (subtype) {
249                 case SLOWPROTOCOLS_SUBTYPE_LACP:
250                         lacp_pdu_input(lp, m);
251                         return (NULL);
252
253                 case SLOWPROTOCOLS_SUBTYPE_MARKER:
254                         lacp_marker_input(lp, m);
255                         return (NULL);
256         }
257
258         /* Not a subtype we are interested in */
259         return (m);
260 }
261
262 /*
263  * lacp_pdu_input: process lacpdu
264  */
265 static int
266 lacp_pdu_input(struct lacp_port *lp, struct mbuf *m)
267 {
268         struct lacp_softc *lsc = lp->lp_lsc;
269         struct lacpdu *du;
270         int error = 0;
271
272         if (m->m_pkthdr.len != sizeof(*du)) {
273                 goto bad;
274         }
275
276         if ((m->m_flags & M_MCAST) == 0) {
277                 goto bad;
278         }
279
280         if (m->m_len < sizeof(*du)) {
281                 m = m_pullup(m, sizeof(*du));
282                 if (m == NULL) {
283                         return (ENOMEM);
284                 }
285         }
286
287         du = mtod(m, struct lacpdu *);
288
289         if (memcmp(&du->ldu_eh.ether_dhost,
290             &ethermulticastaddr_slowprotocols, ETHER_ADDR_LEN)) {
291                 goto bad;
292         }
293
294         /*
295          * ignore the version for compatibility with
296          * the future protocol revisions.
297          */
298 #if 0
299         if (du->ldu_sph.sph_version != 1) {
300                 goto bad;
301         }
302 #endif
303
304         /*
305          * ignore tlv types for compatibility with
306          * the future protocol revisions.
307          */
308         if (tlv_check(du, sizeof(*du), &du->ldu_tlv_actor,
309             lacp_info_tlv_template, FALSE)) {
310                 goto bad;
311         }
312
313         if (lacp_debug > 0) {
314                 lacp_dprintf(lp, "lacpdu receive\n");
315                 lacp_dump_lacpdu(du);
316         }
317
318         if ((1 << lp->lp_ifp->if_dunit) & lacp_rx_test) {
319                 LACP_TPRINTF((lp, "Dropping RX PDU\n"));
320                 goto bad;
321         }
322
323         LACP_LOCK(lsc);
324         lacp_sm_rx(lp, du);
325         LACP_UNLOCK(lsc);
326
327         m_freem(m);
328         return (error);
329
330 bad:
331         m_freem(m);
332         return (EINVAL);
333 }
334
335 static void
336 lacp_fill_actorinfo(struct lacp_port *lp, struct lacp_peerinfo *info)
337 {
338         struct lagg_port *lgp = lp->lp_lagg;
339         struct lagg_softc *sc = lgp->lp_softc;
340
341         info->lip_systemid.lsi_prio = htons(LACP_SYSTEM_PRIO);
342         memcpy(&info->lip_systemid.lsi_mac,
343             IF_LLADDR(sc->sc_ifp), ETHER_ADDR_LEN);
344         info->lip_portid.lpi_prio = htons(LACP_PORT_PRIO);
345         info->lip_portid.lpi_portno = htons(lp->lp_ifp->if_index);
346         info->lip_state = lp->lp_state;
347 }
348
349 static void
350 lacp_fill_markerinfo(struct lacp_port *lp, struct lacp_markerinfo *info)
351 {
352         struct ifnet *ifp = lp->lp_ifp;
353
354         /* Fill in the port index and system id (encoded as the MAC) */
355         info->mi_rq_port = htons(ifp->if_index);
356         memcpy(&info->mi_rq_system, lp->lp_systemid.lsi_mac, ETHER_ADDR_LEN);
357         info->mi_rq_xid = htonl(0);
358 }
359
360 static int
361 lacp_xmit_lacpdu(struct lacp_port *lp)
362 {
363         struct lagg_port *lgp = lp->lp_lagg;
364         struct mbuf *m;
365         struct lacpdu *du;
366         int error;
367
368         LACP_LOCK_ASSERT(lp->lp_lsc);
369
370         m = m_gethdr(M_NOWAIT, MT_DATA);
371         if (m == NULL) {
372                 return (ENOMEM);
373         }
374         m->m_len = m->m_pkthdr.len = sizeof(*du);
375
376         du = mtod(m, struct lacpdu *);
377         memset(du, 0, sizeof(*du));
378
379         memcpy(&du->ldu_eh.ether_dhost, ethermulticastaddr_slowprotocols,
380             ETHER_ADDR_LEN);
381         memcpy(&du->ldu_eh.ether_shost, lgp->lp_lladdr, ETHER_ADDR_LEN);
382         du->ldu_eh.ether_type = htons(ETHERTYPE_SLOW);
383
384         du->ldu_sph.sph_subtype = SLOWPROTOCOLS_SUBTYPE_LACP;
385         du->ldu_sph.sph_version = 1;
386
387         TLV_SET(&du->ldu_tlv_actor, LACP_TYPE_ACTORINFO, sizeof(du->ldu_actor));
388         du->ldu_actor = lp->lp_actor;
389
390         TLV_SET(&du->ldu_tlv_partner, LACP_TYPE_PARTNERINFO,
391             sizeof(du->ldu_partner));
392         du->ldu_partner = lp->lp_partner;
393
394         TLV_SET(&du->ldu_tlv_collector, LACP_TYPE_COLLECTORINFO,
395             sizeof(du->ldu_collector));
396         du->ldu_collector.lci_maxdelay = 0;
397
398         if (lacp_debug > 0) {
399                 lacp_dprintf(lp, "lacpdu transmit\n");
400                 lacp_dump_lacpdu(du);
401         }
402
403         m->m_flags |= M_MCAST;
404
405         /*
406          * XXX should use higher priority queue.
407          * otherwise network congestion can break aggregation.
408          */
409
410         error = lagg_enqueue(lp->lp_ifp, m);
411         return (error);
412 }
413
414 static int
415 lacp_xmit_marker(struct lacp_port *lp)
416 {
417         struct lagg_port *lgp = lp->lp_lagg;
418         struct mbuf *m;
419         struct markerdu *mdu;
420         int error;
421
422         LACP_LOCK_ASSERT(lp->lp_lsc);
423
424         m = m_gethdr(M_NOWAIT, MT_DATA);
425         if (m == NULL) {
426                 return (ENOMEM);
427         }
428         m->m_len = m->m_pkthdr.len = sizeof(*mdu);
429
430         mdu = mtod(m, struct markerdu *);
431         memset(mdu, 0, sizeof(*mdu));
432
433         memcpy(&mdu->mdu_eh.ether_dhost, ethermulticastaddr_slowprotocols,
434             ETHER_ADDR_LEN);
435         memcpy(&mdu->mdu_eh.ether_shost, lgp->lp_lladdr, ETHER_ADDR_LEN);
436         mdu->mdu_eh.ether_type = htons(ETHERTYPE_SLOW);
437
438         mdu->mdu_sph.sph_subtype = SLOWPROTOCOLS_SUBTYPE_MARKER;
439         mdu->mdu_sph.sph_version = 1;
440
441         /* Bump the transaction id and copy over the marker info */
442         lp->lp_marker.mi_rq_xid = htonl(ntohl(lp->lp_marker.mi_rq_xid) + 1);
443         TLV_SET(&mdu->mdu_tlv, MARKER_TYPE_INFO, sizeof(mdu->mdu_info));
444         mdu->mdu_info = lp->lp_marker;
445
446         LACP_DPRINTF((lp, "marker transmit, port=%u, sys=%6D, id=%u\n",
447             ntohs(mdu->mdu_info.mi_rq_port), mdu->mdu_info.mi_rq_system, ":",
448             ntohl(mdu->mdu_info.mi_rq_xid)));
449
450         m->m_flags |= M_MCAST;
451         error = lagg_enqueue(lp->lp_ifp, m);
452         return (error);
453 }
454
455 void
456 lacp_linkstate(struct lagg_port *lgp)
457 {
458         struct lacp_port *lp = LACP_PORT(lgp);
459         struct lacp_softc *lsc = lp->lp_lsc;
460         struct ifnet *ifp = lgp->lp_ifp;
461         struct ifmediareq ifmr;
462         int error = 0;
463         u_int media;
464         uint8_t old_state;
465         uint16_t old_key;
466
467         bzero((char *)&ifmr, sizeof(ifmr));
468         error = (*ifp->if_ioctl)(ifp, SIOCGIFMEDIA, (caddr_t)&ifmr);
469         if (error != 0)
470                 return;
471
472         LACP_LOCK(lsc);
473         media = ifmr.ifm_active;
474         LACP_DPRINTF((lp, "media changed 0x%x -> 0x%x, ether = %d, fdx = %d, "
475             "link = %d\n", lp->lp_media, media, IFM_TYPE(media) == IFM_ETHER,
476             (media & IFM_FDX) != 0, ifp->if_link_state == LINK_STATE_UP));
477         old_state = lp->lp_state;
478         old_key = lp->lp_key;
479
480         lp->lp_media = media;
481         /*
482          * If the port is not an active full duplex Ethernet link then it can
483          * not be aggregated.
484          */
485         if (IFM_TYPE(media) != IFM_ETHER || (media & IFM_FDX) == 0 ||
486             ifp->if_link_state != LINK_STATE_UP) {
487                 lacp_port_disable(lp);
488         } else {
489                 lacp_port_enable(lp);
490         }
491         lp->lp_key = lacp_compose_key(lp);
492
493         if (old_state != lp->lp_state || old_key != lp->lp_key) {
494                 LACP_DPRINTF((lp, "-> UNSELECTED\n"));
495                 lp->lp_selected = LACP_UNSELECTED;
496         }
497         LACP_UNLOCK(lsc);
498 }
499
500 static void
501 lacp_tick(void *arg)
502 {
503         struct lacp_softc *lsc = arg;
504         struct lacp_port *lp;
505
506         LIST_FOREACH(lp, &lsc->lsc_ports, lp_next) {
507                 if ((lp->lp_state & LACP_STATE_AGGREGATION) == 0)
508                         continue;
509
510                 lacp_run_timers(lp);
511
512                 lacp_select(lp);
513                 lacp_sm_mux(lp);
514                 lacp_sm_tx(lp);
515                 lacp_sm_ptx_tx_schedule(lp);
516         }
517         callout_reset(&lsc->lsc_callout, hz, lacp_tick, lsc);
518 }
519
520 int
521 lacp_port_create(struct lagg_port *lgp)
522 {
523         struct lagg_softc *sc = lgp->lp_softc;
524         struct lacp_softc *lsc = LACP_SOFTC(sc);
525         struct lacp_port *lp;
526         struct ifnet *ifp = lgp->lp_ifp;
527         struct sockaddr_dl sdl;
528         struct ifmultiaddr *rifma = NULL;
529         int error;
530
531         boolean_t active = TRUE; /* XXX should be configurable */
532         boolean_t fast = FALSE; /* XXX should be configurable */
533
534         bzero((char *)&sdl, sizeof(sdl));
535         sdl.sdl_len = sizeof(sdl);
536         sdl.sdl_family = AF_LINK;
537         sdl.sdl_index = ifp->if_index;
538         sdl.sdl_type = IFT_ETHER;
539         sdl.sdl_alen = ETHER_ADDR_LEN;
540
541         bcopy(&ethermulticastaddr_slowprotocols,
542             LLADDR(&sdl), ETHER_ADDR_LEN);
543         error = if_addmulti(ifp, (struct sockaddr *)&sdl, &rifma);
544         if (error) {
545                 printf("%s: ADDMULTI failed on %s\n", __func__, lgp->lp_ifname);
546                 return (error);
547         }
548
549         lp = malloc(sizeof(struct lacp_port),
550             M_DEVBUF, M_NOWAIT|M_ZERO);
551         if (lp == NULL)
552                 return (ENOMEM);
553
554         LACP_LOCK(lsc);
555         lgp->lp_psc = (caddr_t)lp;
556         lp->lp_ifp = ifp;
557         lp->lp_lagg = lgp;
558         lp->lp_lsc = lsc;
559         lp->lp_ifma = rifma;
560
561         LIST_INSERT_HEAD(&lsc->lsc_ports, lp, lp_next);
562
563         lacp_fill_actorinfo(lp, &lp->lp_actor);
564         lacp_fill_markerinfo(lp, &lp->lp_marker);
565         lp->lp_state =
566             (active ? LACP_STATE_ACTIVITY : 0) |
567             (fast ? LACP_STATE_TIMEOUT : 0);
568         lp->lp_aggregator = NULL;
569         lacp_sm_rx_set_expired(lp);
570         LACP_UNLOCK(lsc);
571         lacp_linkstate(lgp);
572
573         return (0);
574 }
575
576 void
577 lacp_port_destroy(struct lagg_port *lgp)
578 {
579         struct lacp_port *lp = LACP_PORT(lgp);
580         struct lacp_softc *lsc = lp->lp_lsc;
581         int i;
582
583         LACP_LOCK(lsc);
584         for (i = 0; i < LACP_NTIMER; i++) {
585                 LACP_TIMER_DISARM(lp, i);
586         }
587
588         lacp_disable_collecting(lp);
589         lacp_disable_distributing(lp);
590         lacp_unselect(lp);
591
592         /* The address may have already been removed by if_purgemaddrs() */
593         if (!lgp->lp_detaching)
594                 if_delmulti_ifma(lp->lp_ifma);
595
596         LIST_REMOVE(lp, lp_next);
597         LACP_UNLOCK(lsc);
598         free(lp, M_DEVBUF);
599 }
600
601 void
602 lacp_req(struct lagg_softc *sc, caddr_t data)
603 {
604         struct lacp_opreq *req = (struct lacp_opreq *)data;
605         struct lacp_softc *lsc = LACP_SOFTC(sc);
606         struct lacp_aggregator *la = lsc->lsc_active_aggregator;
607
608         LACP_LOCK(lsc);
609         bzero(req, sizeof(struct lacp_opreq));
610         if (la != NULL) {
611                 req->actor_prio = ntohs(la->la_actor.lip_systemid.lsi_prio);
612                 memcpy(&req->actor_mac, &la->la_actor.lip_systemid.lsi_mac,
613                     ETHER_ADDR_LEN);
614                 req->actor_key = ntohs(la->la_actor.lip_key);
615                 req->actor_portprio = ntohs(la->la_actor.lip_portid.lpi_prio);
616                 req->actor_portno = ntohs(la->la_actor.lip_portid.lpi_portno);
617                 req->actor_state = la->la_actor.lip_state;
618
619                 req->partner_prio = ntohs(la->la_partner.lip_systemid.lsi_prio);
620                 memcpy(&req->partner_mac, &la->la_partner.lip_systemid.lsi_mac,
621                     ETHER_ADDR_LEN);
622                 req->partner_key = ntohs(la->la_partner.lip_key);
623                 req->partner_portprio = ntohs(la->la_partner.lip_portid.lpi_prio);
624                 req->partner_portno = ntohs(la->la_partner.lip_portid.lpi_portno);
625                 req->partner_state = la->la_partner.lip_state;
626         }
627         LACP_UNLOCK(lsc);
628 }
629
630 void
631 lacp_portreq(struct lagg_port *lgp, caddr_t data)
632 {
633         struct lacp_opreq *req = (struct lacp_opreq *)data;
634         struct lacp_port *lp = LACP_PORT(lgp);
635         struct lacp_softc *lsc = lp->lp_lsc;
636
637         LACP_LOCK(lsc);
638         req->actor_prio = ntohs(lp->lp_actor.lip_systemid.lsi_prio);
639         memcpy(&req->actor_mac, &lp->lp_actor.lip_systemid.lsi_mac,
640             ETHER_ADDR_LEN);
641         req->actor_key = ntohs(lp->lp_actor.lip_key);
642         req->actor_portprio = ntohs(lp->lp_actor.lip_portid.lpi_prio);
643         req->actor_portno = ntohs(lp->lp_actor.lip_portid.lpi_portno);
644         req->actor_state = lp->lp_actor.lip_state;
645
646         req->partner_prio = ntohs(lp->lp_partner.lip_systemid.lsi_prio);
647         memcpy(&req->partner_mac, &lp->lp_partner.lip_systemid.lsi_mac,
648             ETHER_ADDR_LEN);
649         req->partner_key = ntohs(lp->lp_partner.lip_key);
650         req->partner_portprio = ntohs(lp->lp_partner.lip_portid.lpi_prio);
651         req->partner_portno = ntohs(lp->lp_partner.lip_portid.lpi_portno);
652         req->partner_state = lp->lp_partner.lip_state;
653         LACP_UNLOCK(lsc);
654 }
655
656 static void
657 lacp_disable_collecting(struct lacp_port *lp)
658 {
659         LACP_DPRINTF((lp, "collecting disabled\n"));
660         lp->lp_state &= ~LACP_STATE_COLLECTING;
661 }
662
663 static void
664 lacp_enable_collecting(struct lacp_port *lp)
665 {
666         LACP_DPRINTF((lp, "collecting enabled\n"));
667         lp->lp_state |= LACP_STATE_COLLECTING;
668 }
669
670 static void
671 lacp_disable_distributing(struct lacp_port *lp)
672 {
673         struct lacp_aggregator *la = lp->lp_aggregator;
674         struct lacp_softc *lsc = lp->lp_lsc;
675         struct lagg_softc *sc = lsc->lsc_softc;
676         char buf[LACP_LAGIDSTR_MAX+1];
677
678         LACP_LOCK_ASSERT(lsc);
679
680         if (la == NULL || (lp->lp_state & LACP_STATE_DISTRIBUTING) == 0) {
681                 return;
682         }
683
684         KASSERT(!TAILQ_EMPTY(&la->la_ports), ("no aggregator ports"));
685         KASSERT(la->la_nports > 0, ("nports invalid (%d)", la->la_nports));
686         KASSERT(la->la_refcnt >= la->la_nports, ("aggregator refcnt invalid"));
687
688         LACP_DPRINTF((lp, "disable distributing on aggregator %s, "
689             "nports %d -> %d\n",
690             lacp_format_lagid_aggregator(la, buf, sizeof(buf)),
691             la->la_nports, la->la_nports - 1));
692
693         TAILQ_REMOVE(&la->la_ports, lp, lp_dist_q);
694         la->la_nports--;
695         sc->sc_active = la->la_nports;
696
697         if (lsc->lsc_active_aggregator == la) {
698                 lacp_suppress_distributing(lsc, la);
699                 lacp_select_active_aggregator(lsc);
700                 /* regenerate the port map, the active aggregator has changed */
701                 lacp_update_portmap(lsc);
702         }
703
704         lp->lp_state &= ~LACP_STATE_DISTRIBUTING;
705 }
706
707 static void
708 lacp_enable_distributing(struct lacp_port *lp)
709 {
710         struct lacp_aggregator *la = lp->lp_aggregator;
711         struct lacp_softc *lsc = lp->lp_lsc;
712         struct lagg_softc *sc = lsc->lsc_softc;
713         char buf[LACP_LAGIDSTR_MAX+1];
714
715         LACP_LOCK_ASSERT(lsc);
716
717         if ((lp->lp_state & LACP_STATE_DISTRIBUTING) != 0) {
718                 return;
719         }
720
721         LACP_DPRINTF((lp, "enable distributing on aggregator %s, "
722             "nports %d -> %d\n",
723             lacp_format_lagid_aggregator(la, buf, sizeof(buf)),
724             la->la_nports, la->la_nports + 1));
725
726         KASSERT(la->la_refcnt > la->la_nports, ("aggregator refcnt invalid"));
727         TAILQ_INSERT_HEAD(&la->la_ports, lp, lp_dist_q);
728         la->la_nports++;
729         sc->sc_active = la->la_nports;
730
731         lp->lp_state |= LACP_STATE_DISTRIBUTING;
732
733         if (lsc->lsc_active_aggregator == la) {
734                 lacp_suppress_distributing(lsc, la);
735                 lacp_update_portmap(lsc);
736         } else
737                 /* try to become the active aggregator */
738                 lacp_select_active_aggregator(lsc);
739 }
740
741 static void
742 lacp_transit_expire(void *vp)
743 {
744         struct lacp_softc *lsc = vp;
745
746         LACP_LOCK_ASSERT(lsc);
747
748         LACP_TRACE(NULL);
749
750         lsc->lsc_suppress_distributing = FALSE;
751 }
752
753 int
754 lacp_attach(struct lagg_softc *sc)
755 {
756         struct lacp_softc *lsc;
757
758         lsc = malloc(sizeof(struct lacp_softc),
759             M_DEVBUF, M_NOWAIT|M_ZERO);
760         if (lsc == NULL)
761                 return (ENOMEM);
762
763         sc->sc_psc = (caddr_t)lsc;
764         lsc->lsc_softc = sc;
765
766         lsc->lsc_hashkey = arc4random();
767         lsc->lsc_active_aggregator = NULL;
768         LACP_LOCK_INIT(lsc);
769         TAILQ_INIT(&lsc->lsc_aggregators);
770         LIST_INIT(&lsc->lsc_ports);
771
772         callout_init_mtx(&lsc->lsc_transit_callout, &lsc->lsc_mtx, 0);
773         callout_init_mtx(&lsc->lsc_callout, &lsc->lsc_mtx, 0);
774
775         /* if the lagg is already up then do the same */
776         if (sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING)
777                 lacp_init(sc);
778
779         return (0);
780 }
781
782 int
783 lacp_detach(struct lagg_softc *sc)
784 {
785         struct lacp_softc *lsc = LACP_SOFTC(sc);
786
787         KASSERT(TAILQ_EMPTY(&lsc->lsc_aggregators),
788             ("aggregators still active"));
789         KASSERT(lsc->lsc_active_aggregator == NULL,
790             ("aggregator still attached"));
791
792         sc->sc_psc = NULL;
793         callout_drain(&lsc->lsc_transit_callout);
794         callout_drain(&lsc->lsc_callout);
795
796         LACP_LOCK_DESTROY(lsc);
797         free(lsc, M_DEVBUF);
798         return (0);
799 }
800
801 void
802 lacp_init(struct lagg_softc *sc)
803 {
804         struct lacp_softc *lsc = LACP_SOFTC(sc);
805
806         LACP_LOCK(lsc);
807         callout_reset(&lsc->lsc_callout, hz, lacp_tick, lsc);
808         LACP_UNLOCK(lsc);
809 }
810
811 void
812 lacp_stop(struct lagg_softc *sc)
813 {
814         struct lacp_softc *lsc = LACP_SOFTC(sc);
815
816         LACP_LOCK(lsc);
817         callout_stop(&lsc->lsc_transit_callout);
818         callout_stop(&lsc->lsc_callout);
819         LACP_UNLOCK(lsc);
820 }
821
822 struct lagg_port *
823 lacp_select_tx_port(struct lagg_softc *sc, struct mbuf *m)
824 {
825         struct lacp_softc *lsc = LACP_SOFTC(sc);
826         struct lacp_portmap *pm;
827         struct lacp_port *lp;
828         uint32_t hash;
829
830         if (__predict_false(lsc->lsc_suppress_distributing)) {
831                 LACP_DPRINTF((NULL, "%s: waiting transit\n", __func__));
832                 return (NULL);
833         }
834
835         pm = &lsc->lsc_pmap[lsc->lsc_activemap];
836         if (pm->pm_count == 0) {
837                 LACP_DPRINTF((NULL, "%s: no active aggregator\n", __func__));
838                 return (NULL);
839         }
840
841         if (sc->use_flowid && (m->m_flags & M_FLOWID))
842                 hash = m->m_pkthdr.flowid;
843         else
844                 hash = lagg_hashmbuf(sc, m, lsc->lsc_hashkey);
845         hash %= pm->pm_count;
846         lp = pm->pm_map[hash];
847
848         KASSERT((lp->lp_state & LACP_STATE_DISTRIBUTING) != 0,
849             ("aggregated port is not distributing"));
850
851         return (lp->lp_lagg);
852 }
853 /*
854  * lacp_suppress_distributing: drop transmit packets for a while
855  * to preserve packet ordering.
856  */
857
858 static void
859 lacp_suppress_distributing(struct lacp_softc *lsc, struct lacp_aggregator *la)
860 {
861         struct lacp_port *lp;
862
863         if (lsc->lsc_active_aggregator != la) {
864                 return;
865         }
866
867         LACP_TRACE(NULL);
868
869         lsc->lsc_suppress_distributing = TRUE;
870
871         /* send a marker frame down each port to verify the queues are empty */
872         LIST_FOREACH(lp, &lsc->lsc_ports, lp_next) {
873                 lp->lp_flags |= LACP_PORT_MARK;
874                 lacp_xmit_marker(lp);
875         }
876
877         /* set a timeout for the marker frames */
878         callout_reset(&lsc->lsc_transit_callout,
879             LACP_TRANSIT_DELAY * hz / 1000, lacp_transit_expire, lsc);
880 }
881
882 static int
883 lacp_compare_peerinfo(const struct lacp_peerinfo *a,
884     const struct lacp_peerinfo *b)
885 {
886         return (memcmp(a, b, offsetof(struct lacp_peerinfo, lip_state)));
887 }
888
889 static int
890 lacp_compare_systemid(const struct lacp_systemid *a,
891     const struct lacp_systemid *b)
892 {
893         return (memcmp(a, b, sizeof(*a)));
894 }
895
896 #if 0   /* unused */
897 static int
898 lacp_compare_portid(const struct lacp_portid *a,
899     const struct lacp_portid *b)
900 {
901         return (memcmp(a, b, sizeof(*a)));
902 }
903 #endif
904
905 static uint64_t
906 lacp_aggregator_bandwidth(struct lacp_aggregator *la)
907 {
908         struct lacp_port *lp;
909         uint64_t speed;
910
911         lp = TAILQ_FIRST(&la->la_ports);
912         if (lp == NULL) {
913                 return (0);
914         }
915
916         speed = ifmedia_baudrate(lp->lp_media);
917         speed *= la->la_nports;
918         if (speed == 0) {
919                 LACP_DPRINTF((lp, "speed 0? media=0x%x nports=%d\n",
920                     lp->lp_media, la->la_nports));
921         }
922
923         return (speed);
924 }
925
926 /*
927  * lacp_select_active_aggregator: select an aggregator to be used to transmit
928  * packets from lagg(4) interface.
929  */
930
931 static void
932 lacp_select_active_aggregator(struct lacp_softc *lsc)
933 {
934         struct lacp_aggregator *la;
935         struct lacp_aggregator *best_la = NULL;
936         uint64_t best_speed = 0;
937         char buf[LACP_LAGIDSTR_MAX+1];
938
939         LACP_TRACE(NULL);
940
941         TAILQ_FOREACH(la, &lsc->lsc_aggregators, la_q) {
942                 uint64_t speed;
943
944                 if (la->la_nports == 0) {
945                         continue;
946                 }
947
948                 speed = lacp_aggregator_bandwidth(la);
949                 LACP_DPRINTF((NULL, "%s, speed=%jd, nports=%d\n",
950                     lacp_format_lagid_aggregator(la, buf, sizeof(buf)),
951                     speed, la->la_nports));
952
953                 /* This aggregator is chosen if
954                  *      the partner has a better system priority
955                  *  or, the total aggregated speed is higher
956                  *  or, it is already the chosen aggregator
957                  */
958                 if ((best_la != NULL && LACP_SYS_PRI(la->la_partner) <
959                      LACP_SYS_PRI(best_la->la_partner)) ||
960                     speed > best_speed ||
961                     (speed == best_speed &&
962                     la == lsc->lsc_active_aggregator)) {
963                         best_la = la;
964                         best_speed = speed;
965                 }
966         }
967
968         KASSERT(best_la == NULL || best_la->la_nports > 0,
969             ("invalid aggregator refcnt"));
970         KASSERT(best_la == NULL || !TAILQ_EMPTY(&best_la->la_ports),
971             ("invalid aggregator list"));
972
973         if (lsc->lsc_active_aggregator != best_la) {
974                 LACP_DPRINTF((NULL, "active aggregator changed\n"));
975                 LACP_DPRINTF((NULL, "old %s\n",
976                     lacp_format_lagid_aggregator(lsc->lsc_active_aggregator,
977                     buf, sizeof(buf))));
978         } else {
979                 LACP_DPRINTF((NULL, "active aggregator not changed\n"));
980         }
981         LACP_DPRINTF((NULL, "new %s\n",
982             lacp_format_lagid_aggregator(best_la, buf, sizeof(buf))));
983
984         if (lsc->lsc_active_aggregator != best_la) {
985                 lsc->lsc_active_aggregator = best_la;
986                 lacp_update_portmap(lsc);
987                 if (best_la) {
988                         lacp_suppress_distributing(lsc, best_la);
989                 }
990         }
991 }
992
993 /*
994  * Updated the inactive portmap array with the new list of ports and
995  * make it live.
996  */
997 static void
998 lacp_update_portmap(struct lacp_softc *lsc)
999 {
1000         struct lagg_softc *sc = lsc->lsc_softc;
1001         struct lacp_aggregator *la;
1002         struct lacp_portmap *p;
1003         struct lacp_port *lp;
1004         uint64_t speed;
1005         u_int newmap;
1006         int i;
1007
1008         newmap = lsc->lsc_activemap == 0 ? 1 : 0;
1009         p = &lsc->lsc_pmap[newmap];
1010         la = lsc->lsc_active_aggregator;
1011         speed = 0;
1012         bzero(p, sizeof(struct lacp_portmap));
1013
1014         if (la != NULL && la->la_nports > 0) {
1015                 p->pm_count = la->la_nports;
1016                 i = 0;
1017                 TAILQ_FOREACH(lp, &la->la_ports, lp_dist_q)
1018                         p->pm_map[i++] = lp;
1019                 KASSERT(i == p->pm_count, ("Invalid port count"));
1020                 speed = lacp_aggregator_bandwidth(la);
1021         }
1022         sc->sc_ifp->if_baudrate = speed;
1023
1024         /* switch the active portmap over */
1025         atomic_store_rel_int(&lsc->lsc_activemap, newmap);
1026         LACP_DPRINTF((NULL, "Set table %d with %d ports\n",
1027                     lsc->lsc_activemap,
1028                     lsc->lsc_pmap[lsc->lsc_activemap].pm_count));
1029 }
1030
1031 static uint16_t
1032 lacp_compose_key(struct lacp_port *lp)
1033 {
1034         struct lagg_port *lgp = lp->lp_lagg;
1035         struct lagg_softc *sc = lgp->lp_softc;
1036         u_int media = lp->lp_media;
1037         uint16_t key;
1038
1039         if ((lp->lp_state & LACP_STATE_AGGREGATION) == 0) {
1040
1041                 /*
1042                  * non-aggregatable links should have unique keys.
1043                  *
1044                  * XXX this isn't really unique as if_index is 16 bit.
1045                  */
1046
1047                 /* bit 0..14:   (some bits of) if_index of this port */
1048                 key = lp->lp_ifp->if_index;
1049                 /* bit 15:      1 */
1050                 key |= 0x8000;
1051         } else {
1052                 u_int subtype = IFM_SUBTYPE(media);
1053
1054                 KASSERT(IFM_TYPE(media) == IFM_ETHER, ("invalid media type"));
1055                 KASSERT((media & IFM_FDX) != 0, ("aggregating HDX interface"));
1056
1057                 /* bit 0..4:    IFM_SUBTYPE */
1058                 key = subtype;
1059                 /* bit 5..14:   (some bits of) if_index of lagg device */
1060                 key |= 0x7fe0 & ((sc->sc_ifp->if_index) << 5);
1061                 /* bit 15:      0 */
1062         }
1063         return (htons(key));
1064 }
1065
1066 static void
1067 lacp_aggregator_addref(struct lacp_softc *lsc, struct lacp_aggregator *la)
1068 {
1069         char buf[LACP_LAGIDSTR_MAX+1];
1070
1071         LACP_DPRINTF((NULL, "%s: lagid=%s, refcnt %d -> %d\n",
1072             __func__,
1073             lacp_format_lagid(&la->la_actor, &la->la_partner,
1074             buf, sizeof(buf)),
1075             la->la_refcnt, la->la_refcnt + 1));
1076
1077         KASSERT(la->la_refcnt > 0, ("refcount <= 0"));
1078         la->la_refcnt++;
1079         KASSERT(la->la_refcnt > la->la_nports, ("invalid refcount"));
1080 }
1081
1082 static void
1083 lacp_aggregator_delref(struct lacp_softc *lsc, struct lacp_aggregator *la)
1084 {
1085         char buf[LACP_LAGIDSTR_MAX+1];
1086
1087         LACP_DPRINTF((NULL, "%s: lagid=%s, refcnt %d -> %d\n",
1088             __func__,
1089             lacp_format_lagid(&la->la_actor, &la->la_partner,
1090             buf, sizeof(buf)),
1091             la->la_refcnt, la->la_refcnt - 1));
1092
1093         KASSERT(la->la_refcnt > la->la_nports, ("invalid refcnt"));
1094         la->la_refcnt--;
1095         if (la->la_refcnt > 0) {
1096                 return;
1097         }
1098
1099         KASSERT(la->la_refcnt == 0, ("refcount not zero"));
1100         KASSERT(lsc->lsc_active_aggregator != la, ("aggregator active"));
1101
1102         TAILQ_REMOVE(&lsc->lsc_aggregators, la, la_q);
1103
1104         free(la, M_DEVBUF);
1105 }
1106
1107 /*
1108  * lacp_aggregator_get: allocate an aggregator.
1109  */
1110
1111 static struct lacp_aggregator *
1112 lacp_aggregator_get(struct lacp_softc *lsc, struct lacp_port *lp)
1113 {
1114         struct lacp_aggregator *la;
1115
1116         la = malloc(sizeof(*la), M_DEVBUF, M_NOWAIT);
1117         if (la) {
1118                 la->la_refcnt = 1;
1119                 la->la_nports = 0;
1120                 TAILQ_INIT(&la->la_ports);
1121                 la->la_pending = 0;
1122                 TAILQ_INSERT_TAIL(&lsc->lsc_aggregators, la, la_q);
1123         }
1124
1125         return (la);
1126 }
1127
1128 /*
1129  * lacp_fill_aggregator_id: setup a newly allocated aggregator from a port.
1130  */
1131
1132 static void
1133 lacp_fill_aggregator_id(struct lacp_aggregator *la, const struct lacp_port *lp)
1134 {
1135         lacp_fill_aggregator_id_peer(&la->la_partner, &lp->lp_partner);
1136         lacp_fill_aggregator_id_peer(&la->la_actor, &lp->lp_actor);
1137
1138         la->la_actor.lip_state = lp->lp_state & LACP_STATE_AGGREGATION;
1139 }
1140
1141 static void
1142 lacp_fill_aggregator_id_peer(struct lacp_peerinfo *lpi_aggr,
1143     const struct lacp_peerinfo *lpi_port)
1144 {
1145         memset(lpi_aggr, 0, sizeof(*lpi_aggr));
1146         lpi_aggr->lip_systemid = lpi_port->lip_systemid;
1147         lpi_aggr->lip_key = lpi_port->lip_key;
1148 }
1149
1150 /*
1151  * lacp_aggregator_is_compatible: check if a port can join to an aggregator.
1152  */
1153
1154 static int
1155 lacp_aggregator_is_compatible(const struct lacp_aggregator *la,
1156     const struct lacp_port *lp)
1157 {
1158         if (!(lp->lp_state & LACP_STATE_AGGREGATION) ||
1159             !(lp->lp_partner.lip_state & LACP_STATE_AGGREGATION)) {
1160                 return (0);
1161         }
1162
1163         if (!(la->la_actor.lip_state & LACP_STATE_AGGREGATION)) {
1164                 return (0);
1165         }
1166
1167         if (!lacp_peerinfo_is_compatible(&la->la_partner, &lp->lp_partner)) {
1168                 return (0);
1169         }
1170
1171         if (!lacp_peerinfo_is_compatible(&la->la_actor, &lp->lp_actor)) {
1172                 return (0);
1173         }
1174
1175         return (1);
1176 }
1177
1178 static int
1179 lacp_peerinfo_is_compatible(const struct lacp_peerinfo *a,
1180     const struct lacp_peerinfo *b)
1181 {
1182         if (memcmp(&a->lip_systemid, &b->lip_systemid,
1183             sizeof(a->lip_systemid))) {
1184                 return (0);
1185         }
1186
1187         if (memcmp(&a->lip_key, &b->lip_key, sizeof(a->lip_key))) {
1188                 return (0);
1189         }
1190
1191         return (1);
1192 }
1193
1194 static void
1195 lacp_port_enable(struct lacp_port *lp)
1196 {
1197         lp->lp_state |= LACP_STATE_AGGREGATION;
1198 }
1199
1200 static void
1201 lacp_port_disable(struct lacp_port *lp)
1202 {
1203         lacp_set_mux(lp, LACP_MUX_DETACHED);
1204
1205         lp->lp_state &= ~LACP_STATE_AGGREGATION;
1206         lp->lp_selected = LACP_UNSELECTED;
1207         lacp_sm_rx_record_default(lp);
1208         lp->lp_partner.lip_state &= ~LACP_STATE_AGGREGATION;
1209         lp->lp_state &= ~LACP_STATE_EXPIRED;
1210 }
1211
1212 /*
1213  * lacp_select: select an aggregator.  create one if necessary.
1214  */
1215 static void
1216 lacp_select(struct lacp_port *lp)
1217 {
1218         struct lacp_softc *lsc = lp->lp_lsc;
1219         struct lacp_aggregator *la;
1220         char buf[LACP_LAGIDSTR_MAX+1];
1221
1222         if (lp->lp_aggregator) {
1223                 return;
1224         }
1225
1226         KASSERT(!LACP_TIMER_ISARMED(lp, LACP_TIMER_WAIT_WHILE),
1227             ("timer_wait_while still active"));
1228
1229         LACP_DPRINTF((lp, "port lagid=%s\n",
1230             lacp_format_lagid(&lp->lp_actor, &lp->lp_partner,
1231             buf, sizeof(buf))));
1232
1233         TAILQ_FOREACH(la, &lsc->lsc_aggregators, la_q) {
1234                 if (lacp_aggregator_is_compatible(la, lp)) {
1235                         break;
1236                 }
1237         }
1238
1239         if (la == NULL) {
1240                 la = lacp_aggregator_get(lsc, lp);
1241                 if (la == NULL) {
1242                         LACP_DPRINTF((lp, "aggregator creation failed\n"));
1243
1244                         /*
1245                          * will retry on the next tick.
1246                          */
1247
1248                         return;
1249                 }
1250                 lacp_fill_aggregator_id(la, lp);
1251                 LACP_DPRINTF((lp, "aggregator created\n"));
1252         } else {
1253                 LACP_DPRINTF((lp, "compatible aggregator found\n"));
1254                 if (la->la_refcnt == LACP_MAX_PORTS)
1255                         return;
1256                 lacp_aggregator_addref(lsc, la);
1257         }
1258
1259         LACP_DPRINTF((lp, "aggregator lagid=%s\n",
1260             lacp_format_lagid(&la->la_actor, &la->la_partner,
1261             buf, sizeof(buf))));
1262
1263         lp->lp_aggregator = la;
1264         lp->lp_selected = LACP_SELECTED;
1265 }
1266
1267 /*
1268  * lacp_unselect: finish unselect/detach process.
1269  */
1270
1271 static void
1272 lacp_unselect(struct lacp_port *lp)
1273 {
1274         struct lacp_softc *lsc = lp->lp_lsc;
1275         struct lacp_aggregator *la = lp->lp_aggregator;
1276
1277         KASSERT(!LACP_TIMER_ISARMED(lp, LACP_TIMER_WAIT_WHILE),
1278             ("timer_wait_while still active"));
1279
1280         if (la == NULL) {
1281                 return;
1282         }
1283
1284         lp->lp_aggregator = NULL;
1285         lacp_aggregator_delref(lsc, la);
1286 }
1287
1288 /* mux machine */
1289
1290 static void
1291 lacp_sm_mux(struct lacp_port *lp)
1292 {
1293         struct lagg_port *lgp = lp->lp_lagg;
1294         struct lagg_softc *sc = lgp->lp_softc;
1295         enum lacp_mux_state new_state;
1296         boolean_t p_sync =
1297                     (lp->lp_partner.lip_state & LACP_STATE_SYNC) != 0;
1298         boolean_t p_collecting =
1299             (lp->lp_partner.lip_state & LACP_STATE_COLLECTING) != 0;
1300         enum lacp_selected selected = lp->lp_selected;
1301         struct lacp_aggregator *la;
1302
1303         if (lacp_debug > 1)
1304                 lacp_dprintf(lp, "%s: state= 0x%x, selected= 0x%x, "
1305                     "p_sync= 0x%x, p_collecting= 0x%x\n", __func__,
1306                     lp->lp_mux_state, selected, p_sync, p_collecting);
1307
1308 re_eval:
1309         la = lp->lp_aggregator;
1310         KASSERT(lp->lp_mux_state == LACP_MUX_DETACHED || la != NULL,
1311             ("MUX not detached"));
1312         new_state = lp->lp_mux_state;
1313         switch (lp->lp_mux_state) {
1314         case LACP_MUX_DETACHED:
1315                 if (selected != LACP_UNSELECTED) {
1316                         new_state = LACP_MUX_WAITING;
1317                 }
1318                 break;
1319         case LACP_MUX_WAITING:
1320                 KASSERT(la->la_pending > 0 ||
1321                     !LACP_TIMER_ISARMED(lp, LACP_TIMER_WAIT_WHILE),
1322                     ("timer_wait_while still active"));
1323                 if (selected == LACP_SELECTED && la->la_pending == 0) {
1324                         new_state = LACP_MUX_ATTACHED;
1325                 } else if (selected == LACP_UNSELECTED) {
1326                         new_state = LACP_MUX_DETACHED;
1327                 }
1328                 break;
1329         case LACP_MUX_ATTACHED:
1330                 if (selected == LACP_SELECTED && p_sync) {
1331                         new_state = LACP_MUX_COLLECTING;
1332                 } else if (selected != LACP_SELECTED) {
1333                         new_state = LACP_MUX_DETACHED;
1334                 }
1335                 break;
1336         case LACP_MUX_COLLECTING:
1337                 if (selected == LACP_SELECTED && p_sync && p_collecting) {
1338                         new_state = LACP_MUX_DISTRIBUTING;
1339                 } else if (selected != LACP_SELECTED || !p_sync) {
1340                         new_state = LACP_MUX_ATTACHED;
1341                 }
1342                 break;
1343         case LACP_MUX_DISTRIBUTING:
1344                 if (selected != LACP_SELECTED || !p_sync || !p_collecting) {
1345                         new_state = LACP_MUX_COLLECTING;
1346                         lacp_dprintf(lp, "Interface stopped DISTRIBUTING, possible flaping\n");
1347                         sc->sc_flapping++;
1348                 }
1349                 break;
1350         default:
1351                 panic("%s: unknown state", __func__);
1352         }
1353
1354         if (lp->lp_mux_state == new_state) {
1355                 return;
1356         }
1357
1358         lacp_set_mux(lp, new_state);
1359         goto re_eval;
1360 }
1361
1362 static void
1363 lacp_set_mux(struct lacp_port *lp, enum lacp_mux_state new_state)
1364 {
1365         struct lacp_aggregator *la = lp->lp_aggregator;
1366
1367         if (lp->lp_mux_state == new_state) {
1368                 return;
1369         }
1370
1371         switch (new_state) {
1372         case LACP_MUX_DETACHED:
1373                 lp->lp_state &= ~LACP_STATE_SYNC;
1374                 lacp_disable_distributing(lp);
1375                 lacp_disable_collecting(lp);
1376                 lacp_sm_assert_ntt(lp);
1377                 /* cancel timer */
1378                 if (LACP_TIMER_ISARMED(lp, LACP_TIMER_WAIT_WHILE)) {
1379                         KASSERT(la->la_pending > 0,
1380                             ("timer_wait_while not active"));
1381                         la->la_pending--;
1382                 }
1383                 LACP_TIMER_DISARM(lp, LACP_TIMER_WAIT_WHILE);
1384                 lacp_unselect(lp);
1385                 break;
1386         case LACP_MUX_WAITING:
1387                 LACP_TIMER_ARM(lp, LACP_TIMER_WAIT_WHILE,
1388                     LACP_AGGREGATE_WAIT_TIME);
1389                 la->la_pending++;
1390                 break;
1391         case LACP_MUX_ATTACHED:
1392                 lp->lp_state |= LACP_STATE_SYNC;
1393                 lacp_disable_collecting(lp);
1394                 lacp_sm_assert_ntt(lp);
1395                 break;
1396         case LACP_MUX_COLLECTING:
1397                 lacp_enable_collecting(lp);
1398                 lacp_disable_distributing(lp);
1399                 lacp_sm_assert_ntt(lp);
1400                 break;
1401         case LACP_MUX_DISTRIBUTING:
1402                 lacp_enable_distributing(lp);
1403                 break;
1404         default:
1405                 panic("%s: unknown state", __func__);
1406         }
1407
1408         LACP_DPRINTF((lp, "mux_state %d -> %d\n", lp->lp_mux_state, new_state));
1409
1410         lp->lp_mux_state = new_state;
1411 }
1412
1413 static void
1414 lacp_sm_mux_timer(struct lacp_port *lp)
1415 {
1416         struct lacp_aggregator *la = lp->lp_aggregator;
1417         char buf[LACP_LAGIDSTR_MAX+1];
1418
1419         KASSERT(la->la_pending > 0, ("no pending event"));
1420
1421         LACP_DPRINTF((lp, "%s: aggregator %s, pending %d -> %d\n", __func__,
1422             lacp_format_lagid(&la->la_actor, &la->la_partner,
1423             buf, sizeof(buf)),
1424             la->la_pending, la->la_pending - 1));
1425
1426         la->la_pending--;
1427 }
1428
1429 /* periodic transmit machine */
1430
1431 static void
1432 lacp_sm_ptx_update_timeout(struct lacp_port *lp, uint8_t oldpstate)
1433 {
1434         if (LACP_STATE_EQ(oldpstate, lp->lp_partner.lip_state,
1435             LACP_STATE_TIMEOUT)) {
1436                 return;
1437         }
1438
1439         LACP_DPRINTF((lp, "partner timeout changed\n"));
1440
1441         /*
1442          * FAST_PERIODIC -> SLOW_PERIODIC
1443          * or
1444          * SLOW_PERIODIC (-> PERIODIC_TX) -> FAST_PERIODIC
1445          *
1446          * let lacp_sm_ptx_tx_schedule to update timeout.
1447          */
1448
1449         LACP_TIMER_DISARM(lp, LACP_TIMER_PERIODIC);
1450
1451         /*
1452          * if timeout has been shortened, assert NTT.
1453          */
1454
1455         if ((lp->lp_partner.lip_state & LACP_STATE_TIMEOUT)) {
1456                 lacp_sm_assert_ntt(lp);
1457         }
1458 }
1459
1460 static void
1461 lacp_sm_ptx_tx_schedule(struct lacp_port *lp)
1462 {
1463         int timeout;
1464
1465         if (!(lp->lp_state & LACP_STATE_ACTIVITY) &&
1466             !(lp->lp_partner.lip_state & LACP_STATE_ACTIVITY)) {
1467
1468                 /*
1469                  * NO_PERIODIC
1470                  */
1471
1472                 LACP_TIMER_DISARM(lp, LACP_TIMER_PERIODIC);
1473                 return;
1474         }
1475
1476         if (LACP_TIMER_ISARMED(lp, LACP_TIMER_PERIODIC)) {
1477                 return;
1478         }
1479
1480         timeout = (lp->lp_partner.lip_state & LACP_STATE_TIMEOUT) ?
1481             LACP_FAST_PERIODIC_TIME : LACP_SLOW_PERIODIC_TIME;
1482
1483         LACP_TIMER_ARM(lp, LACP_TIMER_PERIODIC, timeout);
1484 }
1485
1486 static void
1487 lacp_sm_ptx_timer(struct lacp_port *lp)
1488 {
1489         lacp_sm_assert_ntt(lp);
1490 }
1491
1492 static void
1493 lacp_sm_rx(struct lacp_port *lp, const struct lacpdu *du)
1494 {
1495         int timeout;
1496
1497         /*
1498          * check LACP_DISABLED first
1499          */
1500
1501         if (!(lp->lp_state & LACP_STATE_AGGREGATION)) {
1502                 return;
1503         }
1504
1505         /*
1506          * check loopback condition.
1507          */
1508
1509         if (!lacp_compare_systemid(&du->ldu_actor.lip_systemid,
1510             &lp->lp_actor.lip_systemid)) {
1511                 return;
1512         }
1513
1514         /*
1515          * EXPIRED, DEFAULTED, CURRENT -> CURRENT
1516          */
1517
1518         lacp_sm_rx_update_selected(lp, du);
1519         lacp_sm_rx_update_ntt(lp, du);
1520         lacp_sm_rx_record_pdu(lp, du);
1521
1522         timeout = (lp->lp_state & LACP_STATE_TIMEOUT) ?
1523             LACP_SHORT_TIMEOUT_TIME : LACP_LONG_TIMEOUT_TIME;
1524         LACP_TIMER_ARM(lp, LACP_TIMER_CURRENT_WHILE, timeout);
1525
1526         lp->lp_state &= ~LACP_STATE_EXPIRED;
1527
1528         /*
1529          * kick transmit machine without waiting the next tick.
1530          */
1531
1532         lacp_sm_tx(lp);
1533 }
1534
1535 static void
1536 lacp_sm_rx_set_expired(struct lacp_port *lp)
1537 {
1538         lp->lp_partner.lip_state &= ~LACP_STATE_SYNC;
1539         lp->lp_partner.lip_state |= LACP_STATE_TIMEOUT;
1540         LACP_TIMER_ARM(lp, LACP_TIMER_CURRENT_WHILE, LACP_SHORT_TIMEOUT_TIME);
1541         lp->lp_state |= LACP_STATE_EXPIRED;
1542 }
1543
1544 static void
1545 lacp_sm_rx_timer(struct lacp_port *lp)
1546 {
1547         if ((lp->lp_state & LACP_STATE_EXPIRED) == 0) {
1548                 /* CURRENT -> EXPIRED */
1549                 LACP_DPRINTF((lp, "%s: CURRENT -> EXPIRED\n", __func__));
1550                 lacp_sm_rx_set_expired(lp);
1551         } else {
1552                 /* EXPIRED -> DEFAULTED */
1553                 LACP_DPRINTF((lp, "%s: EXPIRED -> DEFAULTED\n", __func__));
1554                 lacp_sm_rx_update_default_selected(lp);
1555                 lacp_sm_rx_record_default(lp);
1556                 lp->lp_state &= ~LACP_STATE_EXPIRED;
1557         }
1558 }
1559
1560 static void
1561 lacp_sm_rx_record_pdu(struct lacp_port *lp, const struct lacpdu *du)
1562 {
1563         boolean_t active;
1564         uint8_t oldpstate;
1565         char buf[LACP_STATESTR_MAX+1];
1566
1567         LACP_TRACE(lp);
1568
1569         oldpstate = lp->lp_partner.lip_state;
1570
1571         active = (du->ldu_actor.lip_state & LACP_STATE_ACTIVITY)
1572             || ((lp->lp_state & LACP_STATE_ACTIVITY) &&
1573             (du->ldu_partner.lip_state & LACP_STATE_ACTIVITY));
1574
1575         lp->lp_partner = du->ldu_actor;
1576         if (active &&
1577             ((LACP_STATE_EQ(lp->lp_state, du->ldu_partner.lip_state,
1578             LACP_STATE_AGGREGATION) &&
1579             !lacp_compare_peerinfo(&lp->lp_actor, &du->ldu_partner))
1580             || (du->ldu_partner.lip_state & LACP_STATE_AGGREGATION) == 0)) {
1581                 /* XXX nothing? */
1582         } else {
1583                 lp->lp_partner.lip_state &= ~LACP_STATE_SYNC;
1584         }
1585
1586         lp->lp_state &= ~LACP_STATE_DEFAULTED;
1587
1588         if (oldpstate != lp->lp_partner.lip_state) {
1589                 LACP_DPRINTF((lp, "old pstate %s\n",
1590                     lacp_format_state(oldpstate, buf, sizeof(buf))));
1591                 LACP_DPRINTF((lp, "new pstate %s\n",
1592                     lacp_format_state(lp->lp_partner.lip_state, buf,
1593                     sizeof(buf))));
1594         }
1595
1596         /* XXX Hack, still need to implement 5.4.9 para 2,3,4 */
1597         if (lacp_strict)
1598                 lp->lp_partner.lip_state |= LACP_STATE_SYNC;
1599
1600         lacp_sm_ptx_update_timeout(lp, oldpstate);
1601 }
1602
1603 static void
1604 lacp_sm_rx_update_ntt(struct lacp_port *lp, const struct lacpdu *du)
1605 {
1606
1607         LACP_TRACE(lp);
1608
1609         if (lacp_compare_peerinfo(&lp->lp_actor, &du->ldu_partner) ||
1610             !LACP_STATE_EQ(lp->lp_state, du->ldu_partner.lip_state,
1611             LACP_STATE_ACTIVITY | LACP_STATE_SYNC | LACP_STATE_AGGREGATION)) {
1612                 LACP_DPRINTF((lp, "%s: assert ntt\n", __func__));
1613                 lacp_sm_assert_ntt(lp);
1614         }
1615 }
1616
1617 static void
1618 lacp_sm_rx_record_default(struct lacp_port *lp)
1619 {
1620         uint8_t oldpstate;
1621
1622         LACP_TRACE(lp);
1623
1624         oldpstate = lp->lp_partner.lip_state;
1625         if (lacp_strict)
1626                 lp->lp_partner = lacp_partner_admin_strict;
1627         else
1628                 lp->lp_partner = lacp_partner_admin_optimistic;;
1629         lp->lp_state |= LACP_STATE_DEFAULTED;
1630         lacp_sm_ptx_update_timeout(lp, oldpstate);
1631 }
1632
1633 static void
1634 lacp_sm_rx_update_selected_from_peerinfo(struct lacp_port *lp,
1635     const struct lacp_peerinfo *info)
1636 {
1637
1638         LACP_TRACE(lp);
1639
1640         if (lacp_compare_peerinfo(&lp->lp_partner, info) ||
1641             !LACP_STATE_EQ(lp->lp_partner.lip_state, info->lip_state,
1642             LACP_STATE_AGGREGATION)) {
1643                 lp->lp_selected = LACP_UNSELECTED;
1644                 /* mux machine will clean up lp->lp_aggregator */
1645         }
1646 }
1647
1648 static void
1649 lacp_sm_rx_update_selected(struct lacp_port *lp, const struct lacpdu *du)
1650 {
1651
1652         LACP_TRACE(lp);
1653
1654         lacp_sm_rx_update_selected_from_peerinfo(lp, &du->ldu_actor);
1655 }
1656
1657 static void
1658 lacp_sm_rx_update_default_selected(struct lacp_port *lp)
1659 {
1660
1661         LACP_TRACE(lp);
1662
1663         if (lacp_strict)
1664                 lacp_sm_rx_update_selected_from_peerinfo(lp,
1665                     &lacp_partner_admin_strict);
1666         else
1667                 lacp_sm_rx_update_selected_from_peerinfo(lp,
1668                     &lacp_partner_admin_optimistic);
1669 }
1670
1671 /* transmit machine */
1672
1673 static void
1674 lacp_sm_tx(struct lacp_port *lp)
1675 {
1676         int error = 0;
1677
1678         if (!(lp->lp_state & LACP_STATE_AGGREGATION)
1679 #if 1
1680             || (!(lp->lp_state & LACP_STATE_ACTIVITY)
1681             && !(lp->lp_partner.lip_state & LACP_STATE_ACTIVITY))
1682 #endif
1683             ) {
1684                 lp->lp_flags &= ~LACP_PORT_NTT;
1685         }
1686
1687         if (!(lp->lp_flags & LACP_PORT_NTT)) {
1688                 return;
1689         }
1690
1691         /* Rate limit to 3 PDUs per LACP_FAST_PERIODIC_TIME */
1692         if (ppsratecheck(&lp->lp_last_lacpdu, &lp->lp_lacpdu_sent,
1693                     (3 / LACP_FAST_PERIODIC_TIME)) == 0) {
1694                 LACP_DPRINTF((lp, "rate limited pdu\n"));
1695                 return;
1696         }
1697
1698         if (((1 << lp->lp_ifp->if_dunit) & lacp_tx_test) == 0)
1699                 error = lacp_xmit_lacpdu(lp);
1700         else
1701                 LACP_TPRINTF((lp, "Dropping TX PDU\n"));
1702
1703         if (error == 0) {
1704                 lp->lp_flags &= ~LACP_PORT_NTT;
1705         } else {
1706                 LACP_DPRINTF((lp, "lacpdu transmit failure, error %d\n",
1707                     error));
1708         }
1709 }
1710
1711 static void
1712 lacp_sm_assert_ntt(struct lacp_port *lp)
1713 {
1714
1715         lp->lp_flags |= LACP_PORT_NTT;
1716 }
1717
1718 static void
1719 lacp_run_timers(struct lacp_port *lp)
1720 {
1721         int i;
1722
1723         for (i = 0; i < LACP_NTIMER; i++) {
1724                 KASSERT(lp->lp_timer[i] >= 0,
1725                     ("invalid timer value %d", lp->lp_timer[i]));
1726                 if (lp->lp_timer[i] == 0) {
1727                         continue;
1728                 } else if (--lp->lp_timer[i] <= 0) {
1729                         if (lacp_timer_funcs[i]) {
1730                                 (*lacp_timer_funcs[i])(lp);
1731                         }
1732                 }
1733         }
1734 }
1735
1736 int
1737 lacp_marker_input(struct lacp_port *lp, struct mbuf *m)
1738 {
1739         struct lacp_softc *lsc = lp->lp_lsc;
1740         struct lagg_port *lgp = lp->lp_lagg;
1741         struct lacp_port *lp2;
1742         struct markerdu *mdu;
1743         int error = 0;
1744         int pending = 0;
1745
1746         if (m->m_pkthdr.len != sizeof(*mdu)) {
1747                 goto bad;
1748         }
1749
1750         if ((m->m_flags & M_MCAST) == 0) {
1751                 goto bad;
1752         }
1753
1754         if (m->m_len < sizeof(*mdu)) {
1755                 m = m_pullup(m, sizeof(*mdu));
1756                 if (m == NULL) {
1757                         return (ENOMEM);
1758                 }
1759         }
1760
1761         mdu = mtod(m, struct markerdu *);
1762
1763         if (memcmp(&mdu->mdu_eh.ether_dhost,
1764             &ethermulticastaddr_slowprotocols, ETHER_ADDR_LEN)) {
1765                 goto bad;
1766         }
1767
1768         if (mdu->mdu_sph.sph_version != 1) {
1769                 goto bad;
1770         }
1771
1772         switch (mdu->mdu_tlv.tlv_type) {
1773         case MARKER_TYPE_INFO:
1774                 if (tlv_check(mdu, sizeof(*mdu), &mdu->mdu_tlv,
1775                     marker_info_tlv_template, TRUE)) {
1776                         goto bad;
1777                 }
1778                 mdu->mdu_tlv.tlv_type = MARKER_TYPE_RESPONSE;
1779                 memcpy(&mdu->mdu_eh.ether_dhost,
1780                     &ethermulticastaddr_slowprotocols, ETHER_ADDR_LEN);
1781                 memcpy(&mdu->mdu_eh.ether_shost,
1782                     lgp->lp_lladdr, ETHER_ADDR_LEN);
1783                 error = lagg_enqueue(lp->lp_ifp, m);
1784                 break;
1785
1786         case MARKER_TYPE_RESPONSE:
1787                 if (tlv_check(mdu, sizeof(*mdu), &mdu->mdu_tlv,
1788                     marker_response_tlv_template, TRUE)) {
1789                         goto bad;
1790                 }
1791                 LACP_DPRINTF((lp, "marker response, port=%u, sys=%6D, id=%u\n",
1792                     ntohs(mdu->mdu_info.mi_rq_port), mdu->mdu_info.mi_rq_system,
1793                     ":", ntohl(mdu->mdu_info.mi_rq_xid)));
1794
1795                 /* Verify that it is the last marker we sent out */
1796                 if (memcmp(&mdu->mdu_info, &lp->lp_marker,
1797                     sizeof(struct lacp_markerinfo)))
1798                         goto bad;
1799
1800                 LACP_LOCK(lsc);
1801                 lp->lp_flags &= ~LACP_PORT_MARK;
1802
1803                 if (lsc->lsc_suppress_distributing) {
1804                         /* Check if any ports are waiting for a response */
1805                         LIST_FOREACH(lp2, &lsc->lsc_ports, lp_next) {
1806                                 if (lp2->lp_flags & LACP_PORT_MARK) {
1807                                         pending = 1;
1808                                         break;
1809                                 }
1810                         }
1811
1812                         if (pending == 0) {
1813                                 /* All interface queues are clear */
1814                                 LACP_DPRINTF((NULL, "queue flush complete\n"));
1815                                 lsc->lsc_suppress_distributing = FALSE;
1816                         }
1817                 }
1818                 LACP_UNLOCK(lsc);
1819                 m_freem(m);
1820                 break;
1821
1822         default:
1823                 goto bad;
1824         }
1825
1826         return (error);
1827
1828 bad:
1829         LACP_DPRINTF((lp, "bad marker frame\n"));
1830         m_freem(m);
1831         return (EINVAL);
1832 }
1833
1834 static int
1835 tlv_check(const void *p, size_t size, const struct tlvhdr *tlv,
1836     const struct tlv_template *tmpl, boolean_t check_type)
1837 {
1838         while (/* CONSTCOND */ 1) {
1839                 if ((const char *)tlv - (const char *)p + sizeof(*tlv) > size) {
1840                         return (EINVAL);
1841                 }
1842                 if ((check_type && tlv->tlv_type != tmpl->tmpl_type) ||
1843                     tlv->tlv_length != tmpl->tmpl_length) {
1844                         return (EINVAL);
1845                 }
1846                 if (tmpl->tmpl_type == 0) {
1847                         break;
1848                 }
1849                 tlv = (const struct tlvhdr *)
1850                     ((const char *)tlv + tlv->tlv_length);
1851                 tmpl++;
1852         }
1853
1854         return (0);
1855 }
1856
1857 /* Debugging */
1858 const char *
1859 lacp_format_mac(const uint8_t *mac, char *buf, size_t buflen)
1860 {
1861         snprintf(buf, buflen, "%02X-%02X-%02X-%02X-%02X-%02X",
1862             (int)mac[0],
1863             (int)mac[1],
1864             (int)mac[2],
1865             (int)mac[3],
1866             (int)mac[4],
1867             (int)mac[5]);
1868
1869         return (buf);
1870 }
1871
1872 const char *
1873 lacp_format_systemid(const struct lacp_systemid *sysid,
1874     char *buf, size_t buflen)
1875 {
1876         char macbuf[LACP_MACSTR_MAX+1];
1877
1878         snprintf(buf, buflen, "%04X,%s",
1879             ntohs(sysid->lsi_prio),
1880             lacp_format_mac(sysid->lsi_mac, macbuf, sizeof(macbuf)));
1881
1882         return (buf);
1883 }
1884
1885 const char *
1886 lacp_format_portid(const struct lacp_portid *portid, char *buf, size_t buflen)
1887 {
1888         snprintf(buf, buflen, "%04X,%04X",
1889             ntohs(portid->lpi_prio),
1890             ntohs(portid->lpi_portno));
1891
1892         return (buf);
1893 }
1894
1895 const char *
1896 lacp_format_partner(const struct lacp_peerinfo *peer, char *buf, size_t buflen)
1897 {
1898         char sysid[LACP_SYSTEMIDSTR_MAX+1];
1899         char portid[LACP_PORTIDSTR_MAX+1];
1900
1901         snprintf(buf, buflen, "(%s,%04X,%s)",
1902             lacp_format_systemid(&peer->lip_systemid, sysid, sizeof(sysid)),
1903             ntohs(peer->lip_key),
1904             lacp_format_portid(&peer->lip_portid, portid, sizeof(portid)));
1905
1906         return (buf);
1907 }
1908
1909 const char *
1910 lacp_format_lagid(const struct lacp_peerinfo *a,
1911     const struct lacp_peerinfo *b, char *buf, size_t buflen)
1912 {
1913         char astr[LACP_PARTNERSTR_MAX+1];
1914         char bstr[LACP_PARTNERSTR_MAX+1];
1915
1916 #if 0
1917         /*
1918          * there's a convention to display small numbered peer
1919          * in the left.
1920          */
1921
1922         if (lacp_compare_peerinfo(a, b) > 0) {
1923                 const struct lacp_peerinfo *t;
1924
1925                 t = a;
1926                 a = b;
1927                 b = t;
1928         }
1929 #endif
1930
1931         snprintf(buf, buflen, "[%s,%s]",
1932             lacp_format_partner(a, astr, sizeof(astr)),
1933             lacp_format_partner(b, bstr, sizeof(bstr)));
1934
1935         return (buf);
1936 }
1937
1938 const char *
1939 lacp_format_lagid_aggregator(const struct lacp_aggregator *la,
1940     char *buf, size_t buflen)
1941 {
1942         if (la == NULL) {
1943                 return ("(none)");
1944         }
1945
1946         return (lacp_format_lagid(&la->la_actor, &la->la_partner, buf, buflen));
1947 }
1948
1949 const char *
1950 lacp_format_state(uint8_t state, char *buf, size_t buflen)
1951 {
1952         snprintf(buf, buflen, "%b", state, LACP_STATE_BITS);
1953         return (buf);
1954 }
1955
1956 static void
1957 lacp_dump_lacpdu(const struct lacpdu *du)
1958 {
1959         char buf[LACP_PARTNERSTR_MAX+1];
1960         char buf2[LACP_STATESTR_MAX+1];
1961
1962         printf("actor=%s\n",
1963             lacp_format_partner(&du->ldu_actor, buf, sizeof(buf)));
1964         printf("actor.state=%s\n",
1965             lacp_format_state(du->ldu_actor.lip_state, buf2, sizeof(buf2)));
1966         printf("partner=%s\n",
1967             lacp_format_partner(&du->ldu_partner, buf, sizeof(buf)));
1968         printf("partner.state=%s\n",
1969             lacp_format_state(du->ldu_partner.lip_state, buf2, sizeof(buf2)));
1970
1971         printf("maxdelay=%d\n", ntohs(du->ldu_collector.lci_maxdelay));
1972 }
1973
1974 static void
1975 lacp_dprintf(const struct lacp_port *lp, const char *fmt, ...)
1976 {
1977         va_list va;
1978
1979         if (lp) {
1980                 printf("%s: ", lp->lp_ifp->if_xname);
1981         }
1982
1983         va_start(va, fmt);
1984         vprintf(fmt, va);
1985         va_end(va);
1986 }