1 /*- 2 * $FreeBSD: head/sbin/ifconfig/iflagg.c 249897 2013-04-25 16:34:04Z glebius $ 3 */ 4 5 #include <sys/param.h> 6 #include <sys/ioctl.h> 7 #include <sys/socket.h> 8 #include <sys/sockio.h> 9 10 #include <stdlib.h> 11 #include <unistd.h> 12 13 #include <net/ethernet.h> 14 #include <net/if.h> 15 #include <net/lagg/if_lagg.h> 16 #include <net/route.h> 17 18 #include <ctype.h> 19 #include <stdio.h> 20 #include <string.h> 21 #include <err.h> 22 #include <errno.h> 23 24 #include "ifconfig.h" 25 26 char lacpbuf[120]; /* LACP peer '[(a,a,a),(p,p,p)]' */ 27 28 static void 29 setlaggport(const char *val, int d, int s, const struct afswtch *afp) 30 { 31 struct lagg_reqport rp; 32 33 bzero(&rp, sizeof(rp)); 34 strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname)); 35 strlcpy(rp.rp_portname, val, sizeof(rp.rp_portname)); 36 37 /* Don't choke if the port is already in this lagg. */ 38 if (ioctl(s, SIOCSLAGGPORT, &rp) && errno != EEXIST) 39 err(1, "SIOCSLAGGPORT"); 40 } 41 42 static void 43 unsetlaggport(const char *val, int d, int s, const struct afswtch *afp) 44 { 45 struct lagg_reqport rp; 46 47 bzero(&rp, sizeof(rp)); 48 strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname)); 49 strlcpy(rp.rp_portname, val, sizeof(rp.rp_portname)); 50 51 if (ioctl(s, SIOCSLAGGDELPORT, &rp)) 52 err(1, "SIOCSLAGGDELPORT"); 53 } 54 55 static void 56 setlaggproto(const char *val, int d, int s, const struct afswtch *afp) 57 { 58 struct lagg_protos lpr[] = LAGG_PROTOS; 59 struct lagg_reqall ra; 60 int i; 61 62 bzero(&ra, sizeof(ra)); 63 ra.ra_proto = LAGG_PROTO_MAX; 64 65 for (i = 0; i < (NELEM(lpr)); i++) { 66 if (strcmp(val, lpr[i].lpr_name) == 0) { 67 ra.ra_proto = lpr[i].lpr_proto; 68 break; 69 } 70 } 71 if (ra.ra_proto == LAGG_PROTO_MAX) 72 errx(1, "Invalid aggregation protocol: %s", val); 73 74 strlcpy(ra.ra_ifname, name, sizeof(ra.ra_ifname)); 75 if (ioctl(s, SIOCSLAGG, &ra) != 0) 76 err(1, "SIOCSLAGG"); 77 } 78 79 static void 80 setlagghash(const char *val, int d, int s, const struct afswtch *afp) 81 { 82 struct lagg_reqflags rf; 83 char *str, *tmp, *tok; 84 85 86 rf.rf_flags = 0; 87 str = tmp = strdup(val); 88 while ((tok = strsep(&tmp, ",")) != NULL) { 89 if (strcmp(tok, "l2") == 0) 90 rf.rf_flags |= LAGG_F_HASHL2; 91 else if (strcmp(tok, "l3") == 0) 92 rf.rf_flags |= LAGG_F_HASHL3; 93 else if (strcmp(tok, "l4") == 0) 94 rf.rf_flags |= LAGG_F_HASHL4; 95 else 96 errx(1, "Invalid lagghash option: %s", tok); 97 } 98 free(str); 99 if (rf.rf_flags == 0) 100 errx(1, "No lagghash options supplied"); 101 102 strlcpy(rf.rf_ifname, name, sizeof(rf.rf_ifname)); 103 if (ioctl(s, SIOCSLAGGHASH, &rf)) 104 err(1, "SIOCSLAGGHASH"); 105 } 106 107 static char * 108 lacp_format_mac(const uint8_t *mac, char *buf, size_t buflen) 109 { 110 snprintf(buf, buflen, "%02X-%02X-%02X-%02X-%02X-%02X", 111 (int)mac[0], (int)mac[1], (int)mac[2], (int)mac[3], 112 (int)mac[4], (int)mac[5]); 113 114 return (buf); 115 } 116 117 static char * 118 lacp_format_peer(struct lacp_opreq *req, const char *sep) 119 { 120 char macbuf1[20]; 121 char macbuf2[20]; 122 123 snprintf(lacpbuf, sizeof(lacpbuf), 124 "[(%04X,%s,%04X,%04X,%04X),%s(%04X,%s,%04X,%04X,%04X)]", 125 req->actor_prio, 126 lacp_format_mac(req->actor_mac, macbuf1, sizeof(macbuf1)), 127 req->actor_key, req->actor_portprio, req->actor_portno, sep, 128 req->partner_prio, 129 lacp_format_mac(req->partner_mac, macbuf2, sizeof(macbuf2)), 130 req->partner_key, req->partner_portprio, req->partner_portno); 131 132 return(lacpbuf); 133 } 134 135 static void 136 lagg_status(int s) 137 { 138 struct lagg_protos lpr[] = LAGG_PROTOS; 139 struct lagg_reqport rp, rpbuf[LAGG_MAX_PORTS]; 140 struct lagg_reqall ra; 141 struct lagg_reqflags rf; 142 struct lacp_opreq *lp; 143 const char *proto = "<unknown>"; 144 int i, isport = 0; 145 146 bzero(&rp, sizeof(rp)); 147 bzero(&ra, sizeof(ra)); 148 149 strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname)); 150 strlcpy(rp.rp_portname, name, sizeof(rp.rp_portname)); 151 152 if (ioctl(s, SIOCGLAGGPORT, &rp) == 0) 153 isport = 1; 154 155 strlcpy(ra.ra_ifname, name, sizeof(ra.ra_ifname)); 156 ra.ra_size = sizeof(rpbuf); 157 ra.ra_port = rpbuf; 158 159 strlcpy(rf.rf_ifname, name, sizeof(rf.rf_ifname)); 160 if (ioctl(s, SIOCGLAGGFLAGS, &rf) != 0) 161 rf.rf_flags = 0; 162 163 if (ioctl(s, SIOCGLAGG, &ra) == 0) { 164 lp = (struct lacp_opreq *)&ra.ra_lacpreq; 165 166 for (i = 0; i < (NELEM(lpr)); i++) { 167 if (ra.ra_proto == lpr[i].lpr_proto) { 168 proto = lpr[i].lpr_name; 169 break; 170 } 171 } 172 173 printf("\tlaggproto %s", proto); 174 if (rf.rf_flags & LAGG_F_HASHMASK) { 175 const char *sep = ""; 176 177 printf(" lagghash "); 178 if (rf.rf_flags & LAGG_F_HASHL2) { 179 printf("%sl2", sep); 180 sep = ","; 181 } 182 if (rf.rf_flags & LAGG_F_HASHL3) { 183 printf("%sl3", sep); 184 sep = ","; 185 } 186 if (rf.rf_flags & LAGG_F_HASHL4) { 187 printf("%sl4", sep); 188 sep = ","; 189 } 190 } 191 if (isport) 192 printf(" laggdev %s", rp.rp_ifname); 193 putchar('\n'); 194 if (verbose && ra.ra_proto == LAGG_PROTO_LACP) 195 printf("\tlag id: %s\n", 196 lacp_format_peer(lp, "\n\t\t ")); 197 198 for (i = 0; i < ra.ra_ports; i++) { 199 lp = (struct lacp_opreq *)&rpbuf[i].rp_lacpreq; 200 printf("\tlaggport: %s ", rpbuf[i].rp_portname); 201 printb("flags", rpbuf[i].rp_flags, LAGG_PORT_BITS); 202 if (verbose && ra.ra_proto == LAGG_PROTO_LACP) 203 printf(" state=%X", lp->actor_state); 204 putchar('\n'); 205 if (verbose && ra.ra_proto == LAGG_PROTO_LACP) 206 printf("\t\t%s\n", 207 lacp_format_peer(lp, "\n\t\t ")); 208 } 209 210 if (0 /* XXX */) { 211 printf("\tsupported aggregation protocols:\n"); 212 for (i = 0; i < (NELEM(lpr)); i++) 213 printf("\t\tlaggproto %s\n", lpr[i].lpr_name); 214 } 215 } 216 } 217 218 static struct cmd lagg_cmds[] = { 219 DEF_CMD_ARG("laggport", setlaggport), 220 DEF_CMD_ARG("-laggport", unsetlaggport), 221 DEF_CMD_ARG("laggproto", setlaggproto), 222 DEF_CMD_ARG("lagghash", setlagghash), 223 }; 224 static struct afswtch af_lagg = { 225 .af_name = "af_lagg", 226 .af_af = AF_UNSPEC, 227 .af_other_status = lagg_status, 228 }; 229 230 static __constructor(101) void 231 lagg_ctor(void) 232 { 233 #define N(a) (sizeof(a) / sizeof(a[0])) 234 int i; 235 236 for (i = 0; i < N(lagg_cmds); i++) 237 cmd_register(&lagg_cmds[i]); 238 af_register(&af_lagg); 239 #undef N 240 } 241