]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sbin/ifconfig/iflagg.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sbin / ifconfig / iflagg.c
1 /*-
2  */
3
4 #ifndef lint
5 static const char rcsid[] =
6   "$FreeBSD$";
7 #endif /* not lint */
8
9 #include <sys/param.h>
10 #include <sys/ioctl.h>
11 #include <sys/socket.h>
12 #include <sys/sockio.h>
13
14 #include <stdlib.h>
15 #include <unistd.h>
16
17 #include <net/ethernet.h>
18 #include <net/if.h>
19 #include <net/if_lagg.h>
20 #include <net/route.h>
21
22 #include <ctype.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <err.h>
28 #include <errno.h>
29
30 #include "ifconfig.h"
31
32 char lacpbuf[120];      /* LACP peer '[(a,a,a),(p,p,p)]' */
33
34 static void
35 setlaggport(const char *val, int d, int s, const struct afswtch *afp)
36 {
37         struct lagg_reqport rp;
38
39         bzero(&rp, sizeof(rp));
40         strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname));
41         strlcpy(rp.rp_portname, val, sizeof(rp.rp_portname));
42
43         if (ioctl(s, SIOCSLAGGPORT, &rp))
44                 err(1, "SIOCSLAGGPORT");
45 }
46
47 static void
48 unsetlaggport(const char *val, int d, int s, const struct afswtch *afp)
49 {
50         struct lagg_reqport rp;
51
52         bzero(&rp, sizeof(rp));
53         strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname));
54         strlcpy(rp.rp_portname, val, sizeof(rp.rp_portname));
55
56         if (ioctl(s, SIOCSLAGGDELPORT, &rp))
57                 err(1, "SIOCSLAGGDELPORT");
58 }
59
60 static void
61 setlaggproto(const char *val, int d, int s, const struct afswtch *afp)
62 {
63         struct lagg_protos lpr[] = LAGG_PROTOS;
64         struct lagg_reqall ra;
65         int i;
66
67         bzero(&ra, sizeof(ra));
68         ra.ra_proto = LAGG_PROTO_MAX;
69
70         for (i = 0; i < (sizeof(lpr) / sizeof(lpr[0])); i++) {
71                 if (strcmp(val, lpr[i].lpr_name) == 0) {
72                         ra.ra_proto = lpr[i].lpr_proto;
73                         break;
74                 }
75         }
76         if (ra.ra_proto == LAGG_PROTO_MAX)
77                 errx(1, "Invalid aggregation protocol: %s", val);
78
79         strlcpy(ra.ra_ifname, name, sizeof(ra.ra_ifname));
80         if (ioctl(s, SIOCSLAGG, &ra) != 0)
81                 err(1, "SIOCSLAGG");
82 }
83
84 static char *
85 lacp_format_mac(const uint8_t *mac, char *buf, size_t buflen)
86 {
87         snprintf(buf, buflen, "%02X-%02X-%02X-%02X-%02X-%02X",
88             (int)mac[0], (int)mac[1], (int)mac[2], (int)mac[3],
89             (int)mac[4], (int)mac[5]);
90
91         return (buf);
92 }
93
94 static char *
95 lacp_format_peer(struct lacp_opreq *req, const char *sep)
96 {
97         char macbuf1[20];
98         char macbuf2[20];
99
100         snprintf(lacpbuf, sizeof(lacpbuf),
101             "[(%04X,%s,%04X,%04X,%04X),%s(%04X,%s,%04X,%04X,%04X)]",
102             req->actor_prio,
103             lacp_format_mac(req->actor_mac, macbuf1, sizeof(macbuf1)),
104             req->actor_key, req->actor_portprio, req->actor_portno, sep,
105             req->partner_prio,
106             lacp_format_mac(req->partner_mac, macbuf2, sizeof(macbuf2)),
107             req->partner_key, req->partner_portprio, req->partner_portno);
108
109         return(lacpbuf);
110 }
111
112 static void
113 lagg_status(int s)
114 {
115         struct lagg_protos lpr[] = LAGG_PROTOS;
116         struct lagg_reqport rp, rpbuf[LAGG_MAX_PORTS];
117         struct lagg_reqall ra;
118         struct lacp_opreq *lp;
119         const char *proto = "<unknown>";
120         int i, isport = 0;
121
122         bzero(&rp, sizeof(rp));
123         bzero(&ra, sizeof(ra));
124
125         strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname));
126         strlcpy(rp.rp_portname, name, sizeof(rp.rp_portname));
127
128         if (ioctl(s, SIOCGLAGGPORT, &rp) == 0)
129                 isport = 1;
130
131         strlcpy(ra.ra_ifname, name, sizeof(ra.ra_ifname));
132         ra.ra_size = sizeof(rpbuf);
133         ra.ra_port = rpbuf;
134
135         if (ioctl(s, SIOCGLAGG, &ra) == 0) {
136                 lp = (struct lacp_opreq *)&ra.ra_lacpreq;
137
138                 for (i = 0; i < (sizeof(lpr) / sizeof(lpr[0])); i++) {
139                         if (ra.ra_proto == lpr[i].lpr_proto) {
140                                 proto = lpr[i].lpr_name;
141                                 break;
142                         }
143                 }
144
145                 printf("\tlaggproto %s", proto);
146                 if (isport)
147                         printf(" laggdev %s", rp.rp_ifname);
148                 putchar('\n');
149                 if (verbose && ra.ra_proto == LAGG_PROTO_LACP)
150                         printf("\tlag id: %s\n",
151                             lacp_format_peer(lp, "\n\t\t "));
152
153                 for (i = 0; i < ra.ra_ports; i++) {
154                         lp = (struct lacp_opreq *)&rpbuf[i].rp_lacpreq;
155                         printf("\tlaggport: %s ", rpbuf[i].rp_portname);
156                         printb("flags", rpbuf[i].rp_flags, LAGG_PORT_BITS);
157                         if (verbose && ra.ra_proto == LAGG_PROTO_LACP)
158                                 printf(" state=%X", lp->actor_state);
159                         putchar('\n');
160                         if (verbose && ra.ra_proto == LAGG_PROTO_LACP)
161                                 printf("\t\t%s\n",
162                                     lacp_format_peer(lp, "\n\t\t "));
163                 }
164
165                 if (0 /* XXX */) {
166                         printf("\tsupported aggregation protocols:\n");
167                         for (i = 0; i < (sizeof(lpr) / sizeof(lpr[0])); i++)
168                                 printf("\t\tlaggproto %s\n", lpr[i].lpr_name);
169                 }
170         }
171 }
172
173 static struct cmd lagg_cmds[] = {
174         DEF_CMD_ARG("laggport",         setlaggport),
175         DEF_CMD_ARG("-laggport",        unsetlaggport),
176         DEF_CMD_ARG("laggproto",        setlaggproto),
177 };
178 static struct afswtch af_lagg = {
179         .af_name        = "af_lagg",
180         .af_af          = AF_UNSPEC,
181         .af_other_status = lagg_status,
182 };
183
184 static __constructor void
185 lagg_ctor(void)
186 {
187 #define N(a)    (sizeof(a) / sizeof(a[0]))
188         int i;
189
190         for (i = 0; i < N(lagg_cmds);  i++)
191                 cmd_register(&lagg_cmds[i]);
192         af_register(&af_lagg);
193 #undef N
194 }