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