summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sbin/ifconfig/iflagg.c48
-rw-r--r--sys/net/ieee8023ad_lacp.c50
-rw-r--r--sys/net/ieee8023ad_lacp.h2
-rw-r--r--sys/net/if_lagg.c8
-rw-r--r--sys/net/if_lagg.h28
5 files changed, 133 insertions, 3 deletions
diff --git a/sbin/ifconfig/iflagg.c b/sbin/ifconfig/iflagg.c
index f8c3829..5eaea98 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 = "<unknown>";
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 0df94be..5f4906b 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 cb5f836..b0a67e0 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 0bf0c84..ce8d1d7 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 5467316..1c8072e 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 {
OpenPOWER on IntegriCloud