iflagg.c revision 171247
11539Srgrimes/*-
21539Srgrimes */
31539Srgrimes
41539Srgrimes#ifndef lint
51539Srgrimesstatic const char rcsid[] =
61539Srgrimes  "$FreeBSD: head/sbin/ifconfig/iflagg.c 171247 2007-07-05 09:18:57Z thompsa $";
71539Srgrimes#endif /* not lint */
81539Srgrimes
91539Srgrimes#include <sys/param.h>
101539Srgrimes#include <sys/ioctl.h>
111539Srgrimes#include <sys/socket.h>
121539Srgrimes#include <sys/sockio.h>
131539Srgrimes
141539Srgrimes#include <stdlib.h>
151539Srgrimes#include <unistd.h>
161539Srgrimes
171539Srgrimes#include <net/ethernet.h>
181539Srgrimes#include <net/if.h>
191539Srgrimes#include <net/if_lagg.h>
201539Srgrimes#include <net/route.h>
211539Srgrimes
221539Srgrimes#include <ctype.h>
231539Srgrimes#include <stdio.h>
241539Srgrimes#include <string.h>
251539Srgrimes#include <stdlib.h>
261539Srgrimes#include <unistd.h>
271539Srgrimes#include <err.h>
281539Srgrimes#include <errno.h>
291539Srgrimes
301539Srgrimes#include "ifconfig.h"
311539Srgrimes
321539Srgrimeschar lacpbuf[120];	/* LACP peer '[(a,a,a),(p,p,p)]' */
3323657Speter
3455031Sbdestatic void
351539Srgrimessetlaggport(const char *val, int d, int s, const struct afswtch *afp)
361539Srgrimes{
371539Srgrimes	struct lagg_reqport rp;
387865Sbde
391539Srgrimes	bzero(&rp, sizeof(rp));
4033861Sbde	strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname));
4133861Sbde	strlcpy(rp.rp_portname, val, sizeof(rp.rp_portname));
421539Srgrimes
4326636Sache	if (ioctl(s, SIOCSLAGGPORT, &rp))
4426636Sache		err(1, "SIOCSLAGGPORT");
4515483Sbde}
4615483Sbde
4715483Sbdestatic void
4815483Sbdeunsetlaggport(const char *val, int d, int s, const struct afswtch *afp)
4915483Sbde{
5015483Sbde	struct lagg_reqport rp;
511539Srgrimes
521539Srgrimes	bzero(&rp, sizeof(rp));
531539Srgrimes	strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname));
541539Srgrimes	strlcpy(rp.rp_portname, val, sizeof(rp.rp_portname));
551539Srgrimes
561539Srgrimes	if (ioctl(s, SIOCSLAGGDELPORT, &rp))
571539Srgrimes		err(1, "SIOCSLAGGDELPORT");
581539Srgrimes}
591539Srgrimes
601539Srgrimesstatic void
611539Srgrimessetlaggproto(const char *val, int d, int s, const struct afswtch *afp)
621539Srgrimes{
631539Srgrimes	struct lagg_protos lpr[] = LAGG_PROTOS;
641539Srgrimes	struct lagg_reqall ra;
651539Srgrimes	int i;
661539Srgrimes
671539Srgrimes	bzero(&ra, sizeof(ra));
681539Srgrimes	ra.ra_proto = LAGG_PROTO_MAX;
691539Srgrimes
701539Srgrimes	for (i = 0; i < (sizeof(lpr) / sizeof(lpr[0])); i++) {
7187071Sbde		if (strcmp(val, lpr[i].lpr_name) == 0) {
7286368Smike			ra.ra_proto = lpr[i].lpr_proto;
7386368Smike			break;
7486368Smike		}
7586368Smike	}
7686368Smike	if (ra.ra_proto == LAGG_PROTO_MAX)
7786368Smike		errx(1, "Invalid aggregation protocol: %s", val);
7887071Sbde
7986368Smike	strlcpy(ra.ra_ifname, name, sizeof(ra.ra_ifname));
801539Srgrimes	if (ioctl(s, SIOCSLAGG, &ra) != 0)
811539Srgrimes		err(1, "SIOCSLAGG");
821539Srgrimes}
831539Srgrimes
841539Srgrimesstatic char *
851539Srgrimeslacp_format_mac(const uint8_t *mac, char *buf, size_t buflen)
861539Srgrimes{
871539Srgrimes	snprintf(buf, buflen, "%02X-%02X-%02X-%02X-%02X-%02X",
881539Srgrimes	    (int)mac[0], (int)mac[1], (int)mac[2], (int)mac[3],
891539Srgrimes	    (int)mac[4], (int)mac[5]);
901539Srgrimes
911539Srgrimes	return (buf);
921539Srgrimes}
9393032Simp
9493032Simpstatic char *
9593032Simplacp_format_peer(struct lacp_opreq *req, const char *sep)
9693032Simp{
9793032Simp	char macbuf1[20];
9893032Simp	char macbuf2[20];
9993032Simp
10093032Simp	snprintf(lacpbuf, sizeof(lacpbuf),
10193032Simp	    "[(%04X,%s,%04X,%04X,%04X),%s(%04X,%s,%04X,%04X,%04X)]",
10293032Simp	    req->actor_prio,
10393032Simp	    lacp_format_mac(req->actor_mac, macbuf1, sizeof(macbuf1)),
10493032Simp	    req->actor_key, req->actor_portprio, req->actor_portno, sep,
10593032Simp	    req->partner_prio,
10693032Simp	    lacp_format_mac(req->partner_mac, macbuf2, sizeof(macbuf2)),
10793032Simp	    req->partner_key, req->partner_portprio, req->partner_portno);
10893032Simp
10993032Simp	return(lacpbuf);
11093032Simp}
11193032Simp
11293032Simpstatic void
11393032Simplagg_status(int s)
11493032Simp{
11593032Simp	struct lagg_protos lpr[] = LAGG_PROTOS;
1161539Srgrimes	struct lagg_reqport rp, rpbuf[LAGG_MAX_PORTS];
11793032Simp	struct lagg_reqall ra;
11893032Simp	struct lacp_opreq *lp;
1191539Srgrimes	const char *proto = "<unknown>";
12093032Simp	int i, isport = 0;
12193032Simp
12293032Simp	bzero(&rp, sizeof(rp));
12393032Simp	bzero(&ra, sizeof(ra));
12493032Simp
1251539Srgrimes	strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname));
1267865Sbde	strlcpy(rp.rp_portname, name, sizeof(rp.rp_portname));
12769201Sphk
12893032Simp	if (ioctl(s, SIOCGLAGGPORT, &rp) == 0)
12969201Sphk		isport = 1;
13093032Simp
13193032Simp	strlcpy(ra.ra_ifname, name, sizeof(ra.ra_ifname));
1321539Srgrimes	ra.ra_size = sizeof(rpbuf);
13393032Simp	ra.ra_port = rpbuf;
13493032Simp
13593032Simp	if (ioctl(s, SIOCGLAGG, &ra) == 0) {
13693032Simp		lp = (struct lacp_opreq *)&ra.ra_lacpreq;
13793032Simp
13893032Simp		for (i = 0; i < (sizeof(lpr) / sizeof(lpr[0])); i++) {
13993032Simp			if (ra.ra_proto == lpr[i].lpr_proto) {
1407865Sbde				proto = lpr[i].lpr_name;
14193032Simp				break;
14293032Simp			}
1434749Sats		}
14493032Simp
1451539Srgrimes		printf("\tlaggproto %s", proto);
14641927Sdt		if (isport)
14793032Simp			printf(" laggdev %s", rp.rp_ifname);
14893032Simp		putchar('\n');
14993032Simp		if (verbose && ra.ra_proto == LAGG_PROTO_LACP)
15087086Sbde			printf("\tlag id: %s\n",
15187086Sbde			    lacp_format_peer(lp, "\n\t\t "));
15293032Simp
15387086Sbde		for (i = 0; i < ra.ra_ports; i++) {
15493032Simp			lp = (struct lacp_opreq *)&rpbuf[i].rp_lacpreq;
15593032Simp			printf("\tlaggport: %s ", rpbuf[i].rp_portname);
15693032Simp			printb("flags", rpbuf[i].rp_flags, LAGG_PORT_BITS);
15793032Simp			if (verbose && ra.ra_proto == LAGG_PROTO_LACP)
15893032Simp				printf(" state=%X", lp->actor_state);
15993032Simp			putchar('\n');
16093032Simp			if (verbose && ra.ra_proto == LAGG_PROTO_LACP)
16193032Simp				printf("\t\t%s\n",
16293032Simp				    lacp_format_peer(lp, "\n\t\t "));
16393032Simp		}
16493032Simp
1651539Srgrimes		if (0 /* XXX */) {
16693032Simp			printf("\tsupported aggregation protocols:\n");
16793032Simp			for (i = 0; i < (sizeof(lpr) / sizeof(lpr[0])); i++)
16893032Simp				printf("\t\tlaggproto %s\n", lpr[i].lpr_name);
16988399Smike		}
17093032Simp	} else if (isport)
1711539Srgrimes		printf("\tlagg: laggdev %s\n", rp.rp_ifname);
17293032Simp}
17393032Simp
17487071Sbdestatic struct cmd lagg_cmds[] = {
17587071Sbde	DEF_CMD_ARG("laggport",		setlaggport),
17693032Simp	DEF_CMD_ARG("-laggport",	unsetlaggport),
17793032Simp	DEF_CMD_ARG("laggproto",	setlaggproto),
17887071Sbde};
17993032Simpstatic struct afswtch af_lagg = {
18093032Simp	.af_name	= "af_lagg",
18193032Simp	.af_af		= AF_UNSPEC,
18293032Simp	.af_other_status = lagg_status,
18393032Simp};
18493032Simp
18593032Simpstatic __constructor void
18693032Simplagg_ctor(void)
18793032Simp{
18893032Simp#define	N(a)	(sizeof(a) / sizeof(a[0]))
18993032Simp	int i;
19093032Simp
19193032Simp	for (i = 0; i < N(lagg_cmds);  i++)
19293032Simp		cmd_register(&lagg_cmds[i]);
19387071Sbde	af_register(&af_lagg);
19487071Sbde#undef N
19593032Simp}
19687071Sbde