diff --git a/sbin/ifconfig/iflagg.c b/sbin/ifconfig/iflagg.c index f8c3829af25c..5eaea98b34e1 100644 --- a/sbin/ifconfig/iflagg.c +++ b/sbin/ifconfig/iflagg.c @@ -29,6 +29,8 @@ static const char rcsid[] = #include "ifconfig.h" +char lacpbuf[120]; /* LACP peer '[(a,a,a),(p,p,p)]' */ + static void setlaggport(const char *val, int d, int s, const struct afswtch *afp) { @@ -79,12 +81,41 @@ setlaggproto(const char *val, int d, int s, const struct afswtch *afp) err(1, "SIOCSLAGG"); } +static char * +lacp_format_mac(const uint8_t *mac, char *buf, size_t buflen) +{ + snprintf(buf, buflen, "%02X-%02X-%02X-%02X-%02X-%02X", + (int)mac[0], (int)mac[1], (int)mac[2], (int)mac[3], + (int)mac[4], (int)mac[5]); + + return (buf); +} + +static char * +lacp_format_peer(struct lacp_opreq *req, const char *sep) +{ + char macbuf1[20]; + char macbuf2[20]; + + snprintf(lacpbuf, sizeof(lacpbuf), + "[(%04X,%s,%04X,%04X,%04X),%s(%04X,%s,%04X,%04X,%04X)]", + req->actor_prio, + lacp_format_mac(req->actor_mac, macbuf1, sizeof(macbuf1)), + req->actor_key, req->actor_portprio, req->actor_portno, sep, + req->partner_prio, + lacp_format_mac(req->partner_mac, macbuf2, sizeof(macbuf2)), + req->partner_key, req->partner_portprio, req->partner_portno); + + return(lacpbuf); +} + static void lagg_status(int s) { struct lagg_protos lpr[] = LAGG_PROTOS; struct lagg_reqport rp, rpbuf[LAGG_MAX_PORTS]; struct lagg_reqall ra; + struct lacp_opreq *lp; const char *proto = ""; int i, isport = 0; @@ -102,6 +133,8 @@ lagg_status(int s) ra.ra_port = rpbuf; if (ioctl(s, SIOCGLAGG, &ra) == 0) { + lp = (struct lacp_opreq *)&ra.ra_lacpreq; + for (i = 0; i < (sizeof(lpr) / sizeof(lpr[0])); i++) { if (ra.ra_proto == lpr[i].lpr_proto) { proto = lpr[i].lpr_name; @@ -109,15 +142,24 @@ lagg_status(int s) } } - printf("\tlagg: laggproto %s", proto); + printf("\tlaggproto %s", proto); if (isport) printf(" laggdev %s", rp.rp_ifname); putchar('\n'); + if (verbose && ra.ra_proto == LAGG_PROTO_LACP) + printf("\tlag id: %s\n", + lacp_format_peer(lp, "\n\t\t ")); for (i = 0; i < ra.ra_ports; i++) { - printf("\t\tlaggport %s ", rpbuf[i].rp_portname); - printb("", rpbuf[i].rp_flags, LAGG_PORT_BITS); + lp = (struct lacp_opreq *)&rpbuf[i].rp_lacpreq; + printf("\tlaggport: %s ", rpbuf[i].rp_portname); + printb("flags", rpbuf[i].rp_flags, LAGG_PORT_BITS); + if (verbose && ra.ra_proto == LAGG_PROTO_LACP) + printf(" state=%X", lp->actor_state); putchar('\n'); + if (verbose && ra.ra_proto == LAGG_PROTO_LACP) + printf("\t\t%s\n", + lacp_format_peer(lp, "\n\t\t ")); } if (0 /* XXX */) { diff --git a/sys/net/ieee8023ad_lacp.c b/sys/net/ieee8023ad_lacp.c index 0df94be13516..5f4906b73178 100644 --- a/sys/net/ieee8023ad_lacp.c +++ b/sys/net/ieee8023ad_lacp.c @@ -611,6 +611,56 @@ lacp_port_isactive(struct lagg_port *lgp) return (0); } +void +lacp_req(struct lagg_softc *sc, caddr_t data) +{ + struct lacp_opreq *req = (struct lacp_opreq *)data; + struct lacp_softc *lsc = LACP_SOFTC(sc); + struct lacp_aggregator *la = lsc->lsc_active_aggregator; + + bzero(req, sizeof(struct lacp_opreq)); + if (la != NULL) { + req->actor_prio = ntohs(la->la_actor.lip_systemid.lsi_prio); + memcpy(&req->actor_mac, &la->la_actor.lip_systemid.lsi_mac, + ETHER_ADDR_LEN); + req->actor_key = ntohs(la->la_actor.lip_key); + req->actor_portprio = ntohs(la->la_actor.lip_portid.lpi_prio); + req->actor_portno = ntohs(la->la_actor.lip_portid.lpi_portno); + req->actor_state = la->la_actor.lip_state; + + req->partner_prio = ntohs(la->la_partner.lip_systemid.lsi_prio); + memcpy(&req->partner_mac, &la->la_partner.lip_systemid.lsi_mac, + ETHER_ADDR_LEN); + req->partner_key = ntohs(la->la_partner.lip_key); + req->partner_portprio = ntohs(la->la_partner.lip_portid.lpi_prio); + req->partner_portno = ntohs(la->la_partner.lip_portid.lpi_portno); + req->partner_state = la->la_partner.lip_state; + } +} + +void +lacp_portreq(struct lagg_port *lgp, caddr_t data) +{ + struct lacp_opreq *req = (struct lacp_opreq *)data; + struct lacp_port *lp = LACP_PORT(lgp); + + req->actor_prio = ntohs(lp->lp_actor.lip_systemid.lsi_prio); + memcpy(&req->actor_mac, &lp->lp_actor.lip_systemid.lsi_mac, + ETHER_ADDR_LEN); + req->actor_key = ntohs(lp->lp_actor.lip_key); + req->actor_portprio = ntohs(lp->lp_actor.lip_portid.lpi_prio); + req->actor_portno = ntohs(lp->lp_actor.lip_portid.lpi_portno); + req->actor_state = lp->lp_actor.lip_state; + + req->partner_prio = ntohs(lp->lp_partner.lip_systemid.lsi_prio); + memcpy(&req->partner_mac, &lp->lp_partner.lip_systemid.lsi_mac, + ETHER_ADDR_LEN); + req->partner_key = ntohs(lp->lp_partner.lip_key); + req->partner_portprio = ntohs(lp->lp_partner.lip_portid.lpi_prio); + req->partner_portno = ntohs(lp->lp_partner.lip_portid.lpi_portno); + req->partner_state = lp->lp_partner.lip_state; +} + static void lacp_disable_collecting(struct lacp_port *lp) { diff --git a/sys/net/ieee8023ad_lacp.h b/sys/net/ieee8023ad_lacp.h index cb5f836b3b99..b0a67e085ce8 100644 --- a/sys/net/ieee8023ad_lacp.h +++ b/sys/net/ieee8023ad_lacp.h @@ -270,6 +270,8 @@ int lacp_port_create(struct lagg_port *); void lacp_port_destroy(struct lagg_port *); void lacp_linkstate(struct lagg_port *); int lacp_port_isactive(struct lagg_port *); +void lacp_req(struct lagg_softc *, caddr_t); +void lacp_portreq(struct lagg_port *, caddr_t); /* following constants don't include terminating NUL */ #define LACP_MACSTR_MAX (2*6 + 5) diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c index 0bf0c84fa212..ce8d1d753a94 100644 --- a/sys/net/if_lagg.c +++ b/sys/net/if_lagg.c @@ -686,6 +686,8 @@ lagg_port2req(struct lagg_port *lp, struct lagg_reqport *rp) strlcpy(rp->rp_portname, lp->lp_ifp->if_xname, sizeof(rp->rp_portname)); rp->rp_prio = lp->lp_prio; rp->rp_flags = lp->lp_flags; + if (sc->sc_portreq != NULL) + (*sc->sc_portreq)(lp, (caddr_t)&rp->rp_psc); /* Add protocol specific flags */ switch (sc->sc_proto) { @@ -768,6 +770,8 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) case SIOCGLAGG: ra->ra_proto = sc->sc_proto; ra->ra_ports = i = 0; + if (sc->sc_req != NULL) + (*sc->sc_req)(sc, (caddr_t)&ra->ra_psc); lp = SLIST_FIRST(&sc->sc_ports); while (lp && ra->ra_size >= i + sizeof(struct lagg_reqport)) { @@ -802,6 +806,8 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) sc->sc_init = NULL; sc->sc_stop = NULL; sc->sc_lladdr = NULL; + sc->sc_req = NULL; + sc->sc_portreq = NULL; } if (error != 0) break; @@ -1532,6 +1538,8 @@ lagg_lacp_attach(struct lagg_softc *sc) sc->sc_init = lacp_init; sc->sc_stop = lacp_stop; sc->sc_lladdr = lagg_lacp_lladdr; + sc->sc_req = lacp_req; + sc->sc_portreq = lacp_portreq; error = lacp_attach(sc); if (error) diff --git a/sys/net/if_lagg.h b/sys/net/if_lagg.h index 5467316d5d2d..1c8072e3d580 100644 --- a/sys/net/if_lagg.h +++ b/sys/net/if_lagg.h @@ -69,12 +69,34 @@ struct lagg_protos { * lagg ioctls. */ +/* + * LACP current operational parameters structure. + */ +struct lacp_opreq { + uint16_t actor_prio; + uint8_t actor_mac[ETHER_ADDR_LEN]; + uint16_t actor_key; + uint16_t actor_portprio; + uint16_t actor_portno; + uint8_t actor_state; + uint16_t partner_prio; + uint8_t partner_mac[ETHER_ADDR_LEN]; + uint16_t partner_key; + uint16_t partner_portprio; + uint16_t partner_portno; + uint8_t partner_state; +}; + /* lagg port settings */ struct lagg_reqport { char rp_ifname[IFNAMSIZ]; /* name of the lagg */ char rp_portname[IFNAMSIZ]; /* name of the port */ u_int32_t rp_prio; /* port priority */ u_int32_t rp_flags; /* port flags */ + union { + struct lacp_opreq rpsc_lacp; + } rp_psc; +#define rp_lacpreq rp_psc.rpsc_lacp }; #define SIOCGLAGGPORT _IOWR('i', 140, struct lagg_reqport) @@ -89,6 +111,10 @@ struct lagg_reqall { size_t ra_size; /* size of buffer */ struct lagg_reqport *ra_port; /* allocated buffer */ int ra_ports; /* total port count */ + union { + struct lacp_opreq rpsc_lacp; + } ra_psc; +#define ra_lacpreq ra_psc.rpsc_lacp }; #define SIOCGLAGG _IOWR('i', 143, struct lagg_reqall) @@ -170,6 +196,8 @@ struct lagg_softc { void (*sc_init)(struct lagg_softc *); void (*sc_stop)(struct lagg_softc *); void (*sc_lladdr)(struct lagg_softc *); + void (*sc_req)(struct lagg_softc *, caddr_t); + void (*sc_portreq)(struct lagg_port *, caddr_t); }; struct lagg_port {