From b3d37ca5f81f684ee24495c24dca37d6c4ee0c79 Mon Sep 17 00:00:00 2001 From: Andrew Thompson Date: Thu, 5 Jul 2007 09:18:57 +0000 Subject: [PATCH] Allow the LACP state to be queried from userland which at the moment is the actor and partner peer info. Print out the active aggregator and per port data in verbose mode from ifconfig. Approved by: re (mux) --- sbin/ifconfig/iflagg.c | 48 ++++++++++++++++++++++++++++++++++--- sys/net/ieee8023ad_lacp.c | 50 +++++++++++++++++++++++++++++++++++++++ sys/net/ieee8023ad_lacp.h | 2 ++ sys/net/if_lagg.c | 8 +++++++ sys/net/if_lagg.h | 28 ++++++++++++++++++++++ 5 files changed, 133 insertions(+), 3 deletions(-) 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 {