On Mon, Aug 06, 2018 at 08:18:23PM -0700, Carlos Cardenas wrote:
> Howdy.
> 
> Attached is a patch from my work that started at g2k18 on adding
> administrative knobs to our LACP driver.
> 
> The driver now has a new ioctl (SIOCxTRUNKOPTS), which for now only
> has options for LACP:
> * Mode - Active or Passive (default Active)
> * Timeout - Fast or Slow (default Slow)
> * System Priority - 1(high) to 65535(low) (default 32768)
> * Port Priority - 1(high) to 65535(low) (default 32768)
> * IFQ Priority - 0 to NUM_QUEUES (default 6)
> 
> At the moment, ifconfig only has options for lacpmode and lacptimeout
> plumbed as those are the immediate need.
> 
> The approach taken for the options was to make them on a "trunk" vs a
> "port" as what's typically seen on various NOSes (JunOS, NXOS, etc...)
> as it's uncommon for a host to have one link "Passive" and the other
> "Active" in a given trunk.
> 
> Just like on a NOS, when applying lacpmode or lacptimeout, the settings
> are immediately applied to all existing ports in the trunk and to all
> future ports brought into the trunk.
> 
> When using lacpmode/lacptimeout, they can be used on the same line
> creating the trunk.
> 
> Here's an example hostname.trunk0:
> trunkproto lacp lacptimeout fast
> trunkport em0
> trunkport em1
> dhcp
> inet6 autoconf
> 
> Testing done:
> Arch - amd64
> - Kernel: bsd.rd and GENERIC.MP
> - NIC Driver: em and oce
> - NOS: JunOS 18.1
> - MLAG-SETUP: No
> 
> I would like to solicit testers with additional NIC drivers, NOSes, and
> MLAG setups to ensure there's no regressions.
> 
> Comments? Ok?

I've updated the ifconfig piece to be a bit cleaner (prompted by
deraadt).

+--+
Carlos
Index: sbin/ifconfig/ifconfig.8
===================================================================
RCS file: /home/los/cvs/src/sbin/ifconfig/ifconfig.8,v
retrieving revision 1.312
diff -u -p -r1.312 ifconfig.8
--- sbin/ifconfig/ifconfig.8    19 Jul 2018 19:16:36 -0000      1.312
+++ sbin/ifconfig/ifconfig.8    8 Aug 2018 17:42:56 -0000
@@ -1627,6 +1627,16 @@ Set the trunk protocol.
 Refer to
 .Xr trunk 4
 for a complete list of the available protocols.
+.It Cm lacpmode Ar mode
+Set the LACP trunk mode to either
+.Ar active
+or
+.Ar passive .
+.It Cm lacptimeout Ar speed
+Set the LACP timeout speed to either
+.Ar fast
+or
+.Ar slow .
 .El
 .Sh TUNNEL
 .nr nS 1
Index: sbin/ifconfig/ifconfig.c
===================================================================
RCS file: /home/los/cvs/src/sbin/ifconfig/ifconfig.c,v
retrieving revision 1.369
diff -u -p -r1.369 ifconfig.c
--- sbin/ifconfig/ifconfig.c    13 Jul 2018 08:41:32 -0000      1.369
+++ sbin/ifconfig/ifconfig.c    8 Aug 2018 17:42:56 -0000
@@ -170,7 +170,12 @@ int        shownet80211chans;
 int    shownet80211nodes;
 int    showclasses;
 
-struct ifencap;
+struct ifencap;
+
+const  char *lacpmodeactive = "active";
+const  char *lacpmodepassive = "passive";
+const  char *lacptimeoutfast = "fast";
+const  char *lacptimeoutslow = "slow";
 
 void   notealias(const char *, int);
 void   setifaddr(const char *, int);
@@ -252,6 +257,8 @@ void        setautoconf(const char *, int);
 void   settrunkport(const char *, int);
 void   unsettrunkport(const char *, int);
 void   settrunkproto(const char *, int);
+void   settrunklacpmode(const char *, int);
+void   settrunklacptimeout(const char *, int);
 void   trunk_status(void);
 void   list_cloners(void);
 
@@ -408,6 +415,8 @@ const struct        cmd {
        { "trunkport",  NEXTARG,        0,              settrunkport },
        { "-trunkport", NEXTARG,        0,              unsettrunkport },
        { "trunkproto", NEXTARG,        0,              settrunkproto },
+       { "lacpmode",   NEXTARG,        0,              settrunklacpmode },
+       { "lacptimeout", NEXTARG,       0,              settrunklacptimeout },
        { "anycast",    IN6_IFF_ANYCAST,        0,      setia6flags },
        { "-anycast",   -IN6_IFF_ANYCAST,       0,      setia6flags },
        { "tentative",  IN6_IFF_TENTATIVE,      0,      setia6flags },
@@ -3990,6 +3999,72 @@ settrunkproto(const char *val, int d)
        strlcpy(ra.ra_ifname, name, sizeof(ra.ra_ifname));
        if (ioctl(s, SIOCSTRUNK, &ra) != 0)
                err(1, "SIOCSTRUNK");
+}
+
+void
+settrunklacpmode(const char *val, int d)
+{
+       struct trunk_reqall ra;
+       struct trunk_opts tops;
+
+       bzero(&ra, sizeof(ra));
+       strlcpy(ra.ra_ifname, name, sizeof(ra.ra_ifname));
+
+       if (ioctl(s, SIOCGTRUNK, &ra) != 0)
+               err(1, "SIOCGTRUNK");
+
+       if (ra.ra_proto != TRUNK_PROTO_LACP)
+               errx(1, "Invalid option for trunk: %s", name);
+
+       if (strcmp(val, lacpmodeactive) != 0 &&
+           strcmp(val, lacpmodepassive) != 0)
+               errx(1, "Invalid lacpmode option for trunk: %s", name);
+
+       bzero(&tops, sizeof(tops));
+       strlcpy(tops.to_ifname, name, sizeof(tops.to_ifname));
+       tops.to_proto = TRUNK_PROTO_LACP;
+       tops.to_opts |= TRUNK_OPT_LACP_MODE;
+
+       if (strcmp(val, lacpmodeactive) == 0)
+               tops.to_lacpopts.lacp_mode = 1;
+       else
+               tops.to_lacpopts.lacp_mode = 0;
+
+       if (ioctl(s, SIOCSTRUNKOPTS, &tops) != 0)
+               err(1, "SIOCSTRUNKOPTS");
+}
+
+void
+settrunklacptimeout(const char *val, int d)
+{
+       struct trunk_reqall ra;
+       struct trunk_opts tops;
+
+       bzero(&ra, sizeof(ra));
+       strlcpy(ra.ra_ifname, name, sizeof(ra.ra_ifname));
+
+       if (ioctl(s, SIOCGTRUNK, &ra) != 0)
+               err(1, "SIOCGTRUNK");
+
+       if (ra.ra_proto != TRUNK_PROTO_LACP)
+               errx(1, "Invalid option for trunk: %s", name);
+
+       if (strcmp(val, lacptimeoutfast) != 0 &&
+           strcmp(val, lacptimeoutslow) != 0)
+               errx(1, "Invalid lacptimeout option for trunk: %s", name);
+
+       bzero(&tops, sizeof(tops));
+       strlcpy(tops.to_ifname, name, sizeof(tops.to_ifname));
+       tops.to_proto = TRUNK_PROTO_LACP;
+       tops.to_opts |= TRUNK_OPT_LACP_TIMEOUT;
+
+       if (strcmp(val, lacptimeoutfast) == 0)
+               tops.to_lacpopts.lacp_timeout = 1;
+       else
+               tops.to_lacpopts.lacp_timeout = 0;
+
+       if (ioctl(s, SIOCSTRUNKOPTS, &tops) != 0)
+               err(1, "SIOCSTRUNKOPTS");
 }
 
 void
Index: sys/net/if_trunk.c
===================================================================
RCS file: /home/los/cvs/src/sys/net/if_trunk.c,v
retrieving revision 1.136
diff -u -p -r1.136 if_trunk.c
--- sys/net/if_trunk.c  19 Feb 2018 08:59:52 -0000      1.136
+++ sys/net/if_trunk.c  8 Aug 2018 17:42:56 -0000
@@ -604,8 +604,11 @@ trunk_ioctl(struct ifnet *ifp, u_long cm
        struct trunk_softc *tr = (struct trunk_softc *)ifp->if_softc;
        struct trunk_reqall *ra = (struct trunk_reqall *)data;
        struct trunk_reqport *rp = (struct trunk_reqport *)data, rpbuf;
+       struct trunk_opts *tro = (struct trunk_opts *)data;
        struct ifreq *ifr = (struct ifreq *)data;
+       struct lacp_softc *lsc;
        struct trunk_port *tp;
+       struct lacp_port *lp;
        struct ifnet *tpif;
        int i, error = 0;
 
@@ -670,6 +673,94 @@ trunk_ioctl(struct ifnet *ifp, u_long cm
                        }
                }
                error = EPROTONOSUPPORT;
+               break;
+       case SIOCGTRUNKOPTS:
+               /* Only LACP trunks have options atm */
+               if (tro->to_proto != TRUNK_PROTO_LACP) {
+                       error = EPROTONOSUPPORT;
+                       break;
+               }
+               lsc = LACP_SOFTC(tr);
+               tro->to_lacpopts.lacp_mode = lsc->lsc_mode;
+               tro->to_lacpopts.lacp_timeout = lsc->lsc_timeout;
+               tro->to_lacpopts.lacp_prio = lsc->lsc_sys_prio;
+               tro->to_lacpopts.lacp_portprio = lsc->lsc_port_prio;
+               tro->to_lacpopts.lacp_ifqprio = lsc->lsc_ifq_prio;
+               break;
+       case SIOCSTRUNKOPTS:
+               if ((error = suser(curproc)) != 0) {
+                       error = EPERM;
+                       break;
+               }
+               /* Only LACP trunks have options atm */
+               if (tro->to_proto != TRUNK_PROTO_LACP) {
+                       error = EPROTONOSUPPORT;
+                       break;
+               }
+               lsc = LACP_SOFTC(tr);
+               switch(tro->to_opts) {
+                       case TRUNK_OPT_LACP_MODE:
+                               /*
+                                * Ensure mode changes occur immediately
+                                * on all ports
+                                */
+                               lsc->lsc_mode = tro->to_lacpopts.lacp_mode;
+                               if (lsc->lsc_mode == 0) {
+                                       LIST_FOREACH(lp, &lsc->lsc_ports,
+                                           lp_next)
+                                               lp->lp_state &=
+                                                   ~LACP_STATE_ACTIVITY;
+                               } else {
+                                       LIST_FOREACH(lp, &lsc->lsc_ports,
+                                           lp_next)
+                                               lp->lp_state |=
+                                                   LACP_STATE_ACTIVITY;
+                               }
+                               break;
+                       case TRUNK_OPT_LACP_TIMEOUT:
+                               /*
+                                * Ensure timeout changes occur immediately
+                                * on all ports
+                                */
+                               lsc->lsc_timeout =
+                                   tro->to_lacpopts.lacp_timeout;
+                               if (lsc->lsc_timeout == 0) {
+                                       LIST_FOREACH(lp, &lsc->lsc_ports,
+                                           lp_next)
+                                               lp->lp_state &=
+                                                   ~LACP_STATE_TIMEOUT;
+                               } else {
+                                       LIST_FOREACH(lp, &lsc->lsc_ports,
+                                           lp_next)
+                                               lp->lp_state |=
+                                                   LACP_STATE_TIMEOUT;
+                               }
+                               break;
+                       case TRUNK_OPT_LACP_SYS_PRIO:
+                               if (tro->to_lacpopts.lacp_prio == 0) {
+                                       error = EINVAL; 
+                                       break;
+                               }
+                               lsc->lsc_sys_prio = tro->to_lacpopts.lacp_prio;
+                               break;
+                       case TRUNK_OPT_LACP_PORT_PRIO:
+                               if (tro->to_lacpopts.lacp_portprio == 0) {
+                                       error = EINVAL; 
+                                       break;
+                               }
+                               lsc->lsc_port_prio =
+                                   tro->to_lacpopts.lacp_portprio;
+                               break;
+                       case TRUNK_OPT_LACP_IFQ_PRIO:
+                               if (tro->to_lacpopts.lacp_ifqprio >
+                                   IFQ_MAXPRIO) {
+                                       error = EINVAL; 
+                                       break;
+                               }
+                               lsc->lsc_ifq_prio =
+                                   tro->to_lacpopts.lacp_ifqprio;
+                               break;
+               }
                break;
        case SIOCGTRUNKPORT:
                if (rp->rp_portname[0] == '\0' ||
Index: sys/net/if_trunk.h
===================================================================
RCS file: /home/los/cvs/src/sys/net/if_trunk.h,v
retrieving revision 1.25
diff -u -p -r1.25 if_trunk.h
--- sys/net/if_trunk.h  23 Sep 2015 12:40:12 -0000      1.25
+++ sys/net/if_trunk.h  8 Aug 2018 17:42:56 -0000
@@ -121,6 +121,36 @@ struct trunk_reqall {
 #define SIOCGTRUNK             _IOWR('i', 143, struct trunk_reqall)
 #define SIOCSTRUNK              _IOW('i', 144, struct trunk_reqall)
 
+/* LACP administrative options */
+struct lacp_adminopts {
+       u_int8_t                lacp_mode;              /* active or passive */
+       u_int8_t                lacp_timeout;           /* fast or slow */
+       u_int16_t               lacp_prio;              /* system priority */
+       u_int16_t               lacp_portprio;          /* port priority */
+       u_int8_t                lacp_ifqprio;           /* ifq priority */
+};
+
+/* Trunk administrative options */
+struct trunk_opts {
+       char                    to_ifname[IFNAMSIZ];    /* name of the trunk */
+       u_int                   to_proto;               /* trunk protocol */
+       int                     to_opts;                /* option bitmap */
+#define TRUNK_OPT_NONE                 0x00
+#define TRUNK_OPT_LACP_MODE            0x01            /* set active bit */
+#define TRUNK_OPT_LACP_TIMEOUT         0x02            /* set timeout bit */
+#define TRUNK_OPT_LACP_SYS_PRIO                0x04            /* set sys_prio 
bit */
+#define TRUNK_OPT_LACP_PORT_PRIO       0x08            /* set port_prio bit */
+#define TRUNK_OPT_LACP_IFQ_PRIO                0x10            /* set ifq_prio 
bit */
+
+       union {
+               struct lacp_adminopts rpsc_lacp;
+       } to_psc;
+#define to_lacpopts    to_psc.rpsc_lacp
+};
+
+#define SIOCGTRUNKOPTS         _IOWR('i', 145, struct trunk_opts)
+#define SIOCSTRUNKOPTS          _IOW('i', 146, struct trunk_opts)
+
 #ifdef _KERNEL
 /*
  * Internal kernel part
Index: sys/net/trunklacp.c
===================================================================
RCS file: /home/los/cvs/src/sys/net/trunklacp.c,v
retrieving revision 1.29
diff -u -p -r1.29 trunklacp.c
--- sys/net/trunklacp.c 24 Jan 2017 10:08:30 -0000      1.29
+++ sys/net/trunklacp.c 8 Aug 2018 17:42:56 -0000
@@ -58,14 +58,6 @@
 #include <net/bpf.h>
 #endif
 
-/*
- * actor system priority and port priority.
- * XXX should be configurable.
- */
-#define        LACP_SYSTEM_PRIO        0x8000
-#define        LACP_PORT_PRIO          0x8000
-#define        LACP_IFQ_PRIO           6
-
 const u_int8_t ethermulticastaddr_slowprotocols[ETHER_ADDR_LEN] =
     { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x02 };
 
@@ -93,6 +85,8 @@ const struct tlv_template marker_respons
 
 typedef void (*lacp_timer_func_t)(struct lacp_port *);
 
+void           lacp_default_partner(struct lacp_softc *,
+                   struct lacp_peerinfo *);
 void           lacp_fill_actorinfo(struct lacp_port *, struct lacp_peerinfo *);
 void           lacp_fill_markerinfo(struct lacp_port *,
                    struct lacp_markerinfo *);
@@ -197,31 +191,22 @@ void              lacp_dprintf(const struct lacp_por
 #define LACP_DPRINTF(a) /* nothing */
 #endif
 
-/*
- * partner administration variables.
- * XXX should be configurable.
- */
-
-const struct lacp_peerinfo lacp_partner_admin = {
-       { 0xffff },     /* lip_systemid.lsi_prio */
-       0,              /* lip_key */
-       { 0xffff },     /* lip_portid.lpi_prio */
-#if 1
-       /* optimistic lip_state */
-       LACP_STATE_SYNC | LACP_STATE_AGGREGATION |
-           LACP_STATE_COLLECTING | LACP_STATE_DISTRIBUTING
-#else
-       /* pessimistic lip_state */
-       0
-#endif
-};
-
 const lacp_timer_func_t lacp_timer_funcs[LACP_NTIMER] = {
        [LACP_TIMER_CURRENT_WHILE] = lacp_sm_rx_timer,
        [LACP_TIMER_PERIODIC] = lacp_sm_ptx_timer,
        [LACP_TIMER_WAIT_WHILE] = lacp_sm_mux_timer,
 };
 
+void
+lacp_default_partner(struct lacp_softc *lsc, struct lacp_peerinfo *peer)
+{
+       peer->lip_systemid.lsi_prio = lsc->lsc_sys_prio;
+       peer->lip_key = 0;
+       peer->lip_portid.lpi_prio = lsc->lsc_port_prio;
+       peer->lip_state = LACP_STATE_SYNC | LACP_STATE_AGGREGATION |
+           LACP_STATE_COLLECTING | LACP_STATE_DISTRIBUTING;
+}
+
 int
 lacp_input(struct trunk_port *tp, struct mbuf *m)
 {
@@ -351,13 +336,14 @@ bad:
 void
 lacp_fill_actorinfo(struct lacp_port *lp, struct lacp_peerinfo *info)
 {
+       struct lacp_softc *lsc = lp->lp_lsc;
        struct trunk_port *tp = lp->lp_trunk;
        struct trunk_softc *sc = tp->tp_trunk;
 
-       info->lip_systemid.lsi_prio = htons(LACP_SYSTEM_PRIO);
+       info->lip_systemid.lsi_prio = htons(lsc->lsc_sys_prio);
        memcpy(&info->lip_systemid.lsi_mac,
            sc->tr_ac.ac_enaddr, ETHER_ADDR_LEN);
-       info->lip_portid.lpi_prio = htons(LACP_PORT_PRIO);
+       info->lip_portid.lpi_prio = htons(lsc->lsc_port_prio);
        info->lip_portid.lpi_portno = htons(lp->lp_ifp->if_index);
        info->lip_state = lp->lp_state;
 }
@@ -376,6 +362,7 @@ lacp_fill_markerinfo(struct lacp_port *l
 int
 lacp_xmit_lacpdu(struct lacp_port *lp)
 {
+       struct lacp_softc *lsc = lp->lp_lsc;
        struct trunk_port *tp = lp->lp_trunk;
        struct mbuf *m;
        struct lacpdu *du;
@@ -385,7 +372,7 @@ lacp_xmit_lacpdu(struct lacp_port *lp)
        if (m == NULL)
                return (ENOMEM);
        m->m_len = m->m_pkthdr.len = sizeof(*du);
-       m->m_pkthdr.pf.prio = LACP_IFQ_PRIO;
+       m->m_pkthdr.pf.prio = lsc->lsc_ifq_prio;
 
        du = mtod(m, struct lacpdu *);
        memset(du, 0, sizeof(*du));
@@ -427,6 +414,7 @@ lacp_xmit_lacpdu(struct lacp_port *lp)
 int
 lacp_xmit_marker(struct lacp_port *lp)
 {
+       struct lacp_softc *lsc = lp->lp_lsc;
        struct trunk_port *tp = lp->lp_trunk;
        struct mbuf *m;
        struct markerdu *mdu;
@@ -436,7 +424,7 @@ lacp_xmit_marker(struct lacp_port *lp)
        if (m == NULL)
                return (ENOMEM);
        m->m_len = m->m_pkthdr.len = sizeof(*mdu);
-       m->m_pkthdr.pf.prio = LACP_IFQ_PRIO;
+       m->m_pkthdr.pf.prio = lsc->lsc_ifq_prio;
 
        mdu = mtod(m, struct markerdu *);
        memset(mdu, 0, sizeof(*mdu));
@@ -522,9 +510,6 @@ lacp_port_create(struct trunk_port *tp)
        struct ifreq ifr;
        int error;
 
-       int active = 1; /* XXX should be configurable */
-       int fast = 0; /* XXX should be configurable */
-
        bzero(&ifr, sizeof(ifr));
        ifr.ifr_addr.sa_family = AF_UNSPEC;
        ifr.ifr_addr.sa_len = ETHER_ADDR_LEN;
@@ -554,8 +539,8 @@ lacp_port_create(struct trunk_port *tp)
        lacp_fill_actorinfo(lp, &lp->lp_actor);
        lacp_fill_markerinfo(lp, &lp->lp_marker);
        lp->lp_state =
-           (active ? LACP_STATE_ACTIVITY : 0) |
-           (fast ? LACP_STATE_TIMEOUT : 0);
+           (lsc->lsc_mode ? LACP_STATE_ACTIVITY : 0) |
+           (lsc->lsc_timeout ? LACP_STATE_TIMEOUT : 0);
        lp->lp_aggregator = NULL;
        lacp_sm_rx_set_expired(lp);
 
@@ -764,6 +749,13 @@ lacp_attach(struct trunk_softc *sc)
        TAILQ_INIT(&lsc->lsc_aggregators);
        LIST_INIT(&lsc->lsc_ports);
 
+       /* set default admin values */
+       lsc->lsc_mode = LACP_DEFAULT_MODE;
+       lsc->lsc_timeout = LACP_DEFAULT_TIMEOUT;
+       lsc->lsc_sys_prio = LACP_DEFAULT_SYSTEM_PRIO;
+       lsc->lsc_port_prio = LACP_DEFAULT_PORT_PRIO;
+       lsc->lsc_ifq_prio = LACP_DEFAULT_IFQ_PRIO;
+
        timeout_set(&lsc->lsc_transit_callout, lacp_transit_expire, lsc);
        timeout_set(&lsc->lsc_callout, lacp_tick, lsc);
        task_set(&lsc->lsc_input, lacp_input_process, lsc);
@@ -1555,12 +1547,15 @@ lacp_sm_rx_update_ntt(struct lacp_port *
 void
 lacp_sm_rx_record_default(struct lacp_port *lp)
 {
+       struct lacp_softc *lsc;
        u_int8_t oldpstate;
 
+       lsc = lp->lp_lsc;
+
        /* LACP_DPRINTF((lp, "%s\n", __func__)); */
 
        oldpstate = lp->lp_partner.lip_state;
-       lp->lp_partner = lacp_partner_admin;
+       lacp_default_partner(lsc, &(lp->lp_partner));
        lp->lp_state |= LACP_STATE_DEFAULTED;
        lacp_sm_ptx_update_timeout(lp, oldpstate);
 }
@@ -1590,9 +1585,14 @@ lacp_sm_rx_update_selected(struct lacp_p
 void
 lacp_sm_rx_update_default_selected(struct lacp_port *lp)
 {
+       struct lacp_softc *lsc;
+       struct lacp_peerinfo peer;
+
+       lsc = lp->lp_lsc;
+       lacp_default_partner(lsc, &peer);
        /* LACP_DPRINTF((lp, "%s\n", __func__)); */
 
-       lacp_sm_rx_update_selected_from_peerinfo(lp, &lacp_partner_admin);
+       lacp_sm_rx_update_selected_from_peerinfo(lp, &peer);
 }
 
 /* transmit machine */
Index: sys/net/trunklacp.h
===================================================================
RCS file: /home/los/cvs/src/sys/net/trunklacp.h,v
retrieving revision 1.13
diff -u -p -r1.13 trunklacp.h
--- sys/net/trunklacp.h 12 May 2018 02:02:34 -0000      1.13
+++ sys/net/trunklacp.h 8 Aug 2018 17:42:56 -0000
@@ -39,6 +39,19 @@
 #define        SLOWPROTOCOLS_SUBTYPE_LACP      1
 #define        SLOWPROTOCOLS_SUBTYPE_MARKER    2
 
+/*
+ * default administrative values
+ */
+#define        LACP_DEFAULT_MODE               1 /* Active Mode */
+#define        LACP_DEFAULT_TIMEOUT            0 /* Slow Timeout */
+#define        LACP_DEFAULT_SYSTEM_PRIO        0x8000 /* Medium Priority */
+#define        LACP_LOW_SYSTEM_PRIO            0xffff
+#define        LACP_HIGH_SYSTEM_PRIO           0x0001
+#define        LACP_DEFAULT_PORT_PRIO          0x8000 /* Medium Priority */
+#define        LACP_LOW_PORT_PRIO              0xffff
+#define        LACP_HIGH_PORT_PRIO             0x0001
+#define        LACP_DEFAULT_IFQ_PRIO           6
+
 struct slowprothdr {
        u_int8_t                sph_subtype;
        u_int8_t                sph_version;
@@ -221,6 +234,14 @@ struct lacp_aggregator {
        int                     la_pending; /* number of ports in wait_while */
 };
 
+struct lacp_admin_def {
+       u_int8_t                lad_mode; /* active or passive */
+       u_int8_t                lad_timeout; /* fast or slow */
+       u_int16_t               lad_prio; /* system priority */
+       u_int16_t               lad_portprio; /* port priority */
+       u_int8_t                lad_ifqprio; /* ifq priority */
+};
+
 struct lacp_softc {
        struct trunk_softc      *lsc_softc;
        struct lacp_aggregator  *lsc_active_aggregator;
@@ -233,6 +254,12 @@ struct lacp_softc {
        volatile u_int          lsc_activemap;
        SIPHASH_KEY             lsc_hashkey;
        struct task             lsc_input;
+       struct lacp_admin_def   lsc_admin_defaults;
+#define lsc_mode               lsc_admin_defaults.lad_mode
+#define lsc_timeout            lsc_admin_defaults.lad_timeout
+#define lsc_sys_prio   lsc_admin_defaults.lad_prio
+#define lsc_port_prio  lsc_admin_defaults.lad_portprio
+#define lsc_ifq_prio   lsc_admin_defaults.lad_ifqprio
 };
 
 #define        LACP_TYPE_ACTORINFO     1
Index: share/man/man4/trunk.4
===================================================================
RCS file: /home/los/cvs/src/share/man/man4/trunk.4,v
retrieving revision 1.29
diff -u -p -r1.29 trunk.4
--- share/man/man4/trunk.4      13 Mar 2015 19:58:41 -0000      1.29
+++ share/man/man4/trunk.4      8 Aug 2018 17:42:56 -0000
@@ -144,10 +144,8 @@ such as
 duplicate address detection (DAD)
 cannot properly deal with duplicate packets.
 .Pp
-There is no way to configure LACP administrative variables, including
-system and port priorities.
-The current implementation always performs active-mode LACP and uses
-0x8000 as system and port priorities.
+The current LACP implementation defaults to active-mode LACP, slow timeout,
+and uses 0x8000 (medium priority) as system and port priorities.
 .Pp
 The
 .Nm

Reply via email to