LCOV - code coverage report
Current view: top level - net - trunklacp.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 736 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 63 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13