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?
+--+
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 6 Aug 2018 18:24:11 -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 6 Aug 2018 18:24:11 -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,77 @@ 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) {
+ printf("proto: %d\n", ra.ra_proto);
+ errx(1, "Invalid option for trunk: %s", name);
+ } else {
+ 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) {
+ printf("proto: %d\n", ra.ra_proto);
+ errx(1, "Invalid option for trunk: %s", name);
+ } else {
+ 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 6 Aug 2018 18:24:11 -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 6 Aug 2018 18:24:11 -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 6 Aug 2018 18:24:11 -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 6 Aug 2018 18:24:11 -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 6 Aug 2018 18:24:12 -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