From 9732189ca9738cb356e550d291e5bce78fc6a7ec Mon Sep 17 00:00:00 2001 From: Hiroki Sato Date: Thu, 2 Oct 2014 20:01:13 +0000 Subject: [PATCH] Separate option handling from SIOC[SG]LAGG to SIOC[SG]LAGGOPTS for backward compatibility with old ifconfig(8). --- sbin/ifconfig/iflagg.c | 49 +++++----- sys/net/if_lagg.c | 206 ++++++++++++++++++++--------------------- sys/net/if_lagg.h | 34 ++++--- 3 files changed, 150 insertions(+), 139 deletions(-) diff --git a/sbin/ifconfig/iflagg.c b/sbin/ifconfig/iflagg.c index edb6121634b1..9c478b3dfc5f 100644 --- a/sbin/ifconfig/iflagg.c +++ b/sbin/ifconfig/iflagg.c @@ -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 = ""; @@ -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 ")); diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c index 3de40edad046..67895de1895a 100644 --- a/sys/net/if_lagg.c +++ b/sys/net/if_lagg.c @@ -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; diff --git a/sys/net/if_lagg.h b/sys/net/if_lagg.h index 6c39d1c451e9..bbb3497f96cd 100644 --- a/sys/net/if_lagg.h +++ b/sys/net/if_lagg.h @@ -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 /*