Separate option handling from SIOC[SG]LAGG to SIOC[SG]LAGGOPTS for

backward compatibility with old ifconfig(8).
This commit is contained in:
Hiroki Sato 2014-10-02 20:01:13 +00:00
parent a85f6c3043
commit 9732189ca9
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=272446
3 changed files with 150 additions and 139 deletions

View File

@ -85,27 +85,27 @@ setlaggproto(const char *val, int d, int s, const struct afswtch *afp)
static void
setlaggflowidshift(const char *val, int d, int s, const struct afswtch *afp)
{
struct lagg_reqall ra;
struct lagg_reqopts ro;
bzero(&ra, sizeof(ra));
ra.ra_opts = LAGG_OPT_FLOWIDSHIFT;
strlcpy(ra.ra_ifname, name, sizeof(ra.ra_ifname));
ra.ra_flowid_shift = (int)strtol(val, NULL, 10);
if (ra.ra_flowid_shift & ~LAGG_OPT_FLOWIDSHIFT_MASK)
bzero(&ro, sizeof(ro));
ro.ro_opts = LAGG_OPT_FLOWIDSHIFT;
strlcpy(ro.ro_ifname, name, sizeof(ro.ro_ifname));
ro.ro_flowid_shift = (int)strtol(val, NULL, 10);
if (ro.ro_flowid_shift & ~LAGG_OPT_FLOWIDSHIFT_MASK)
errx(1, "Invalid flowid_shift option: %s", val);
if (ioctl(s, SIOCSLAGG, &ra) != 0)
err(1, "SIOCSLAGG");
if (ioctl(s, SIOCSLAGGOPTS, &ro) != 0)
err(1, "SIOCSLAGGOPTS");
}
static void
setlaggsetopt(const char *val, int d, int s, const struct afswtch *afp)
{
struct lagg_reqall ra;
struct lagg_reqopts ro;
bzero(&ra, sizeof(ra));
ra.ra_opts = d;
switch (ra.ra_opts) {
bzero(&ro, sizeof(ro));
ro.ro_opts = d;
switch (ro.ro_opts) {
case LAGG_OPT_USE_FLOWID:
case -LAGG_OPT_USE_FLOWID:
case LAGG_OPT_LACP_STRICT:
@ -118,10 +118,10 @@ setlaggsetopt(const char *val, int d, int s, const struct afswtch *afp)
default:
err(1, "Invalid lagg option");
}
strlcpy(ra.ra_ifname, name, sizeof(ra.ra_ifname));
strlcpy(ro.ro_ifname, name, sizeof(ro.ro_ifname));
if (ioctl(s, SIOCSLAGG, &ra) != 0)
err(1, "SIOCSLAGG");
if (ioctl(s, SIOCSLAGGOPTS, &ro) != 0)
err(1, "SIOCSLAGGOPTS");
}
static void
@ -186,6 +186,7 @@ lagg_status(int s)
struct lagg_protos lpr[] = LAGG_PROTOS;
struct lagg_reqport rp, rpbuf[LAGG_MAX_PORTS];
struct lagg_reqall ra;
struct lagg_reqopts ro;
struct lagg_reqflags rf;
struct lacp_opreq *lp;
const char *proto = "<unknown>";
@ -193,6 +194,7 @@ lagg_status(int s)
bzero(&rp, sizeof(rp));
bzero(&ra, sizeof(ra));
bzero(&ro, sizeof(ro));
strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname));
strlcpy(rp.rp_portname, name, sizeof(rp.rp_portname));
@ -204,6 +206,9 @@ lagg_status(int s)
ra.ra_size = sizeof(rpbuf);
ra.ra_port = rpbuf;
strlcpy(ro.ro_ifname, name, sizeof(ro.ro_ifname));
ioctl(s, SIOCGLAGGOPTS, &ro);
strlcpy(rf.rf_ifname, name, sizeof(rf.rf_ifname));
if (ioctl(s, SIOCGLAGGFLAGS, &rf) != 0)
rf.rf_flags = 0;
@ -242,20 +247,20 @@ lagg_status(int s)
if (verbose) {
printf("\tlagg options:\n");
printf("\t\tuse_flowid: %d\n",
(ra.ra_opts & LAGG_OPT_USE_FLOWID) ? 1 : 0);
printf("\t\tflowid_shift: %d\n", ra.ra_flowid_shift);
(ro.ro_opts & LAGG_OPT_USE_FLOWID) ? 1 : 0);
printf("\t\tflowid_shift: %d\n", ro.ro_flowid_shift);
switch (ra.ra_proto) {
case LAGG_PROTO_LACP:
printf("\t\tlacp_strict: %d\n",
(ra.ra_opts & LAGG_OPT_LACP_STRICT) ? 1 : 0);
(ro.ro_opts & LAGG_OPT_LACP_STRICT) ? 1 : 0);
printf("\t\tlacp_rxtest: %d\n",
(ra.ra_opts & LAGG_OPT_LACP_RXTEST) ? 1 : 0);
(ro.ro_opts & LAGG_OPT_LACP_RXTEST) ? 1 : 0);
printf("\t\tlacp_txtest: %d\n",
(ra.ra_opts & LAGG_OPT_LACP_TXTEST) ? 1 : 0);
(ro.ro_opts & LAGG_OPT_LACP_TXTEST) ? 1 : 0);
}
printf("\tlagg statistics:\n");
printf("\t\tactive ports: %d\n", ra.ra_active);
printf("\t\tflapping: %u\n", ra.ra_flapping);
printf("\t\tactive ports: %d\n", ro.ro_active);
printf("\t\tflapping: %u\n", ro.ro_flapping);
if (ra.ra_proto == LAGG_PROTO_LACP) {
printf("\tlag id: %s\n",
lacp_format_peer(lp, "\n\t\t "));

View File

@ -1189,6 +1189,7 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
struct lagg_softc *sc = (struct lagg_softc *)ifp->if_softc;
struct lagg_reqall *ra = (struct lagg_reqall *)data;
struct lagg_reqopts *ro = (struct lagg_reqopts *)data;
struct lagg_reqport *rp = (struct lagg_reqport *)data, rpbuf;
struct lagg_reqflags *rf = (struct lagg_reqflags *)data;
struct ifreq *ifr = (struct ifreq *)data;
@ -1215,31 +1216,6 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
LAGG_RLOCK(sc, &tracker);
ra->ra_proto = sc->sc_proto;
lagg_proto_request(sc, &ra->ra_psc);
ra->ra_opts = sc->sc_opts;
if (sc->sc_proto == LAGG_PROTO_LACP) {
struct lacp_softc *lsc;
lsc = (struct lacp_softc *)sc->sc_psc;
if (lsc->lsc_debug.lsc_tx_test != 0)
ra->ra_opts |= LAGG_OPT_LACP_TXTEST;
if (lsc->lsc_debug.lsc_rx_test != 0)
ra->ra_opts |= LAGG_OPT_LACP_RXTEST;
if (lsc->lsc_strict_mode != 0)
ra->ra_opts |= LAGG_OPT_LACP_STRICT;
ra->ra_active = sc->sc_active;
} else {
/*
* LACP tracks active links automatically,
* the others do not.
*/
ra->ra_active = 0;
SLIST_FOREACH(lp, &sc->sc_ports, lp_entries)
ra->ra_active += LAGG_PORTACTIVE(lp);
}
ra->ra_flapping = sc->sc_flapping;
ra->ra_flowid_shift = sc->flowid_shift;
count = 0;
buf = outbuf;
len = min(ra->ra_size, buflen);
@ -1260,88 +1236,9 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
free(outbuf, M_TEMP);
break;
case SIOCSLAGG:
/*
* Set options or protocol depending on
* ra->ra_opts and ra->ra_proto.
*/
error = priv_check(td, PRIV_NET_LAGG);
if (error)
break;
if (ra->ra_opts != 0) {
/*
* Set options. LACP options are stored in sc->sc_psc,
* not in sc_opts.
*/
int valid, lacp;
switch (ra->ra_opts) {
case LAGG_OPT_USE_FLOWID:
case -LAGG_OPT_USE_FLOWID:
case LAGG_OPT_FLOWIDSHIFT:
valid = 1;
lacp = 0;
break;
case LAGG_OPT_LACP_TXTEST:
case -LAGG_OPT_LACP_TXTEST:
case LAGG_OPT_LACP_RXTEST:
case -LAGG_OPT_LACP_RXTEST:
case LAGG_OPT_LACP_STRICT:
case -LAGG_OPT_LACP_STRICT:
valid = lacp = 1;
break;
default:
valid = lacp = 0;
break;
}
LAGG_WLOCK(sc);
if (valid == 0 ||
(lacp == 1 && sc->sc_proto != LAGG_PROTO_LACP)) {
/* Invalid combination of options specified. */
error = EINVAL;
LAGG_WUNLOCK(sc);
break; /* Return from SIOCSLAGG. */
}
/*
* Store new options into sc->sc_opts except for
* FLOWIDSHIFT and LACP options.
*/
if (lacp == 0) {
if (ra->ra_opts == LAGG_OPT_FLOWIDSHIFT)
sc->flowid_shift = ra->ra_flowid_shift;
else if (ra->ra_opts > 0)
sc->sc_opts |= ra->ra_opts;
else
sc->sc_opts &= ~ra->ra_opts;
} else {
struct lacp_softc *lsc;
lsc = (struct lacp_softc *)sc->sc_psc;
switch (ra->ra_opts) {
case LAGG_OPT_LACP_TXTEST:
lsc->lsc_debug.lsc_tx_test = 1;
break;
case -LAGG_OPT_LACP_TXTEST:
lsc->lsc_debug.lsc_tx_test = 0;
break;
case LAGG_OPT_LACP_RXTEST:
lsc->lsc_debug.lsc_rx_test = 1;
break;
case -LAGG_OPT_LACP_RXTEST:
lsc->lsc_debug.lsc_rx_test = 0;
break;
case LAGG_OPT_LACP_STRICT:
lsc->lsc_strict_mode = 1;
break;
case -LAGG_OPT_LACP_STRICT:
lsc->lsc_strict_mode = 0;
break;
}
}
LAGG_WUNLOCK(sc);
break; /* Return from SIOCSLAGG. */
}
if (ra->ra_proto < 1 || ra->ra_proto >= LAGG_PROTO_MAX) {
error = EPROTONOSUPPORT;
break;
@ -1351,6 +1248,107 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
lagg_proto_detach(sc);
lagg_proto_attach(sc, ra->ra_proto);
break;
case SIOCGLAGGOPTS:
ro->ro_opts = sc->sc_opts;
if (sc->sc_proto == LAGG_PROTO_LACP) {
struct lacp_softc *lsc;
lsc = (struct lacp_softc *)sc->sc_psc;
if (lsc->lsc_debug.lsc_tx_test != 0)
ro->ro_opts |= LAGG_OPT_LACP_TXTEST;
if (lsc->lsc_debug.lsc_rx_test != 0)
ro->ro_opts |= LAGG_OPT_LACP_RXTEST;
if (lsc->lsc_strict_mode != 0)
ro->ro_opts |= LAGG_OPT_LACP_STRICT;
ro->ro_active = sc->sc_active;
} else {
ro->ro_active = 0;
SLIST_FOREACH(lp, &sc->sc_ports, lp_entries)
ro->ro_active += LAGG_PORTACTIVE(lp);
}
ro->ro_flapping = sc->sc_flapping;
ro->ro_flowid_shift = sc->flowid_shift;
break;
case SIOCSLAGGOPTS:
error = priv_check(td, PRIV_NET_LAGG);
if (error)
break;
if (ro->ro_opts == 0)
break;
/*
* Set options. LACP options are stored in sc->sc_psc,
* not in sc_opts.
*/
int valid, lacp;
switch (ro->ro_opts) {
case LAGG_OPT_USE_FLOWID:
case -LAGG_OPT_USE_FLOWID:
case LAGG_OPT_FLOWIDSHIFT:
valid = 1;
lacp = 0;
break;
case LAGG_OPT_LACP_TXTEST:
case -LAGG_OPT_LACP_TXTEST:
case LAGG_OPT_LACP_RXTEST:
case -LAGG_OPT_LACP_RXTEST:
case LAGG_OPT_LACP_STRICT:
case -LAGG_OPT_LACP_STRICT:
valid = lacp = 1;
break;
default:
valid = lacp = 0;
break;
}
LAGG_WLOCK(sc);
if (valid == 0 ||
(lacp == 1 && sc->sc_proto != LAGG_PROTO_LACP)) {
/* Invalid combination of options specified. */
error = EINVAL;
LAGG_WUNLOCK(sc);
break; /* Return from SIOCSLAGGOPTS. */
}
/*
* Store new options into sc->sc_opts except for
* FLOWIDSHIFT and LACP options.
*/
if (lacp == 0) {
if (ro->ro_opts == LAGG_OPT_FLOWIDSHIFT)
sc->flowid_shift = ro->ro_flowid_shift;
else if (ro->ro_opts > 0)
sc->sc_opts |= ro->ro_opts;
else
sc->sc_opts &= ~ro->ro_opts;
} else {
struct lacp_softc *lsc;
lsc = (struct lacp_softc *)sc->sc_psc;
switch (ro->ro_opts) {
case LAGG_OPT_LACP_TXTEST:
lsc->lsc_debug.lsc_tx_test = 1;
break;
case -LAGG_OPT_LACP_TXTEST:
lsc->lsc_debug.lsc_tx_test = 0;
break;
case LAGG_OPT_LACP_RXTEST:
lsc->lsc_debug.lsc_rx_test = 1;
break;
case -LAGG_OPT_LACP_RXTEST:
lsc->lsc_debug.lsc_rx_test = 0;
break;
case LAGG_OPT_LACP_STRICT:
lsc->lsc_strict_mode = 1;
break;
case -LAGG_OPT_LACP_STRICT:
lsc->lsc_strict_mode = 0;
break;
}
}
LAGG_WUNLOCK(sc);
break;
case SIOCGLAGGFLAGS:
rf->rf_flags = sc->sc_flags;
break;

View File

@ -125,19 +125,6 @@ struct lagg_reqall {
struct lacp_opreq rpsc_lacp;
} ra_psc;
#define ra_lacpreq ra_psc.rpsc_lacp
int ra_opts; /* Option bitmap */
#define LAGG_OPT_NONE 0x00
#define LAGG_OPT_USE_FLOWID 0x01 /* use M_FLOWID */
/* Pseudo flags which are used in ra_opts but not stored into sc_opts. */
#define LAGG_OPT_FLOWIDSHIFT 0x02 /* Set flowid */
#define LAGG_OPT_FLOWIDSHIFT_MASK 0x1f /* flowid is uint32_t */
#define LAGG_OPT_LACP_STRICT 0x10 /* LACP strict mode */
#define LAGG_OPT_LACP_TXTEST 0x20 /* LACP debug: txtest */
#define LAGG_OPT_LACP_RXTEST 0x40 /* LACP debug: rxtest */
u_int ra_count; /* number of ports */
u_int ra_active; /* active port count */
u_int ra_flapping; /* number of flapping */
int ra_flowid_shift; /* shift the flowid */
};
#define SIOCGLAGG _IOWR('i', 143, struct lagg_reqall)
@ -151,6 +138,27 @@ struct lagg_reqflags {
#define SIOCGLAGGFLAGS _IOWR('i', 145, struct lagg_reqflags)
#define SIOCSLAGGHASH _IOW('i', 146, struct lagg_reqflags)
struct lagg_reqopts {
char ro_ifname[IFNAMSIZ]; /* name of the lagg */
int ro_opts; /* Option bitmap */
#define LAGG_OPT_NONE 0x00
#define LAGG_OPT_USE_FLOWID 0x01 /* use M_FLOWID */
/* Pseudo flags which are used in ro_opts but not stored into sc_opts. */
#define LAGG_OPT_FLOWIDSHIFT 0x02 /* Set flowid */
#define LAGG_OPT_FLOWIDSHIFT_MASK 0x1f /* flowid is uint32_t */
#define LAGG_OPT_LACP_STRICT 0x10 /* LACP strict mode */
#define LAGG_OPT_LACP_TXTEST 0x20 /* LACP debug: txtest */
#define LAGG_OPT_LACP_RXTEST 0x40 /* LACP debug: rxtest */
u_int ro_count; /* number of ports */
u_int ro_active; /* active port count */
u_int ro_flapping; /* number of flapping */
int ro_flowid_shift; /* shift the flowid */
};
#define SIOCGLAGGOPTS _IOWR('i', 152, struct lagg_reqopts)
#define SIOCSLAGGOPTS _IOW('i', 153, struct lagg_reqopts)
#ifdef _KERNEL
/*