1 /*-
2 * Copyright (c) 2014, Bryan Venteicher <[email protected]>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice unmodified, this list of conditions, and the following
10 * disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include <sys/cdefs.h>
28 #include <sys/param.h>
29 #include <sys/ioctl.h>
30 #include <sys/socket.h>
31 #include <sys/sockio.h>
32
33 #include <stdlib.h>
34 #include <stdint.h>
35 #include <unistd.h>
36 #include <netdb.h>
37
38 #include <net/ethernet.h>
39 #include <net/if.h>
40 #include <net/if_vxlan.h>
41 #include <net/route.h>
42 #include <netinet/in.h>
43
44 #include <ctype.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <stdlib.h>
48 #include <unistd.h>
49 #include <err.h>
50 #include <errno.h>
51
52 #include "ifconfig.h"
53
54 static struct ifvxlanparam params = {
55 .vxlp_vni = VXLAN_VNI_MAX,
56 };
57
58 static int
get_val(const char * cp,u_long * valp)59 get_val(const char *cp, u_long *valp)
60 {
61 char *endptr;
62 u_long val;
63
64 errno = 0;
65 val = strtoul(cp, &endptr, 0);
66 if (cp[0] == '\0' || endptr[0] != '\0' || errno == ERANGE)
67 return (-1);
68
69 *valp = val;
70 return (0);
71 }
72
73 static int
do_cmd(if_ctx * ctx,u_long op,void * arg,size_t argsize,int set)74 do_cmd(if_ctx *ctx, u_long op, void *arg, size_t argsize, int set)
75 {
76 struct ifdrv ifd = {};
77
78 strlcpy(ifd.ifd_name, ctx->ifname, sizeof(ifd.ifd_name));
79 ifd.ifd_cmd = op;
80 ifd.ifd_len = argsize;
81 ifd.ifd_data = arg;
82
83 return (ioctl_ctx(ctx, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd));
84 }
85
86 static int
vxlan_exists(if_ctx * ctx)87 vxlan_exists(if_ctx *ctx)
88 {
89 struct ifvxlancfg cfg;
90
91 bzero(&cfg, sizeof(cfg));
92
93 return (do_cmd(ctx, VXLAN_CMD_GET_CONFIG, &cfg, sizeof(cfg), 0) != -1);
94 }
95
96 static void
vxlan_status(if_ctx * ctx)97 vxlan_status(if_ctx *ctx)
98 {
99 struct ifvxlancfg cfg;
100 char src[NI_MAXHOST], dst[NI_MAXHOST];
101 char srcport[NI_MAXSERV], dstport[NI_MAXSERV];
102 struct sockaddr *lsa, *rsa;
103 int vni, mc, ipv6;
104
105 bzero(&cfg, sizeof(cfg));
106
107 if (do_cmd(ctx, VXLAN_CMD_GET_CONFIG, &cfg, sizeof(cfg), 0) < 0)
108 return;
109
110 vni = cfg.vxlc_vni;
111 lsa = &cfg.vxlc_local_sa.sa;
112 rsa = &cfg.vxlc_remote_sa.sa;
113 ipv6 = rsa->sa_family == AF_INET6;
114
115 /* Just report nothing if the network identity isn't set yet. */
116 if (vni >= VXLAN_VNI_MAX)
117 return;
118
119 if (getnameinfo(lsa, lsa->sa_len, src, sizeof(src),
120 srcport, sizeof(srcport), NI_NUMERICHOST | NI_NUMERICSERV) != 0)
121 src[0] = srcport[0] = '\0';
122 if (getnameinfo(rsa, rsa->sa_len, dst, sizeof(dst),
123 dstport, sizeof(dstport), NI_NUMERICHOST | NI_NUMERICSERV) != 0)
124 dst[0] = dstport[0] = '\0';
125
126 if (!ipv6) {
127 struct sockaddr_in *sin = satosin(rsa);
128 mc = IN_MULTICAST(ntohl(sin->sin_addr.s_addr));
129 } else {
130 struct sockaddr_in6 *sin6 = satosin6(rsa);
131 mc = IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr);
132 }
133
134 printf("\tvxlan vni %d", vni);
135 printf(" local %s%s%s:%s", ipv6 ? "[" : "", src, ipv6 ? "]" : "",
136 srcport);
137 printf(" %s %s%s%s:%s", mc ? "group" : "remote", ipv6 ? "[" : "",
138 dst, ipv6 ? "]" : "", dstport);
139
140 if (ctx->args->verbose) {
141 printf("\n\t\tconfig: ");
142 printf("%slearning portrange %d-%d ttl %d",
143 cfg.vxlc_learn ? "" : "no", cfg.vxlc_port_min,
144 cfg.vxlc_port_max, cfg.vxlc_ttl);
145 printf("\n\t\tftable: ");
146 printf("cnt %d max %d timeout %d",
147 cfg.vxlc_ftable_cnt, cfg.vxlc_ftable_max,
148 cfg.vxlc_ftable_timeout);
149 }
150
151 putchar('\n');
152 }
153
154 #define _LOCAL_ADDR46 \
155 (VXLAN_PARAM_WITH_LOCAL_ADDR4 | VXLAN_PARAM_WITH_LOCAL_ADDR6)
156 #define _REMOTE_ADDR46 \
157 (VXLAN_PARAM_WITH_REMOTE_ADDR4 | VXLAN_PARAM_WITH_REMOTE_ADDR6)
158
159 static void
vxlan_check_params(void)160 vxlan_check_params(void)
161 {
162
163 if ((params.vxlp_with & _LOCAL_ADDR46) == _LOCAL_ADDR46)
164 errx(1, "cannot specify both local IPv4 and IPv6 addresses");
165 if ((params.vxlp_with & _REMOTE_ADDR46) == _REMOTE_ADDR46)
166 errx(1, "cannot specify both remote IPv4 and IPv6 addresses");
167 if ((params.vxlp_with & VXLAN_PARAM_WITH_LOCAL_ADDR4 &&
168 params.vxlp_with & VXLAN_PARAM_WITH_REMOTE_ADDR6) ||
169 (params.vxlp_with & VXLAN_PARAM_WITH_LOCAL_ADDR6 &&
170 params.vxlp_with & VXLAN_PARAM_WITH_REMOTE_ADDR4))
171 errx(1, "cannot mix IPv4 and IPv6 addresses");
172 }
173
174 #undef _LOCAL_ADDR46
175 #undef _REMOTE_ADDR46
176
177 static void
vxlan_create(if_ctx * ctx,struct ifreq * ifr)178 vxlan_create(if_ctx *ctx, struct ifreq *ifr)
179 {
180
181 vxlan_check_params();
182
183 ifr->ifr_data = (caddr_t) ¶ms;
184 ifcreate_ioctl(ctx, ifr);
185 }
186
187 static void
setvxlan_vni(if_ctx * ctx,const char * arg,int dummy __unused)188 setvxlan_vni(if_ctx *ctx, const char *arg, int dummy __unused)
189 {
190 struct ifvxlancmd cmd;
191 u_long val;
192
193 if (get_val(arg, &val) < 0 || val >= VXLAN_VNI_MAX)
194 errx(1, "invalid network identifier: %s", arg);
195
196 if (!vxlan_exists(ctx)) {
197 params.vxlp_with |= VXLAN_PARAM_WITH_VNI;
198 params.vxlp_vni = val;
199 return;
200 }
201
202 bzero(&cmd, sizeof(cmd));
203 cmd.vxlcmd_vni = val;
204
205 if (do_cmd(ctx, VXLAN_CMD_SET_VNI, &cmd, sizeof(cmd), 1) < 0)
206 err(1, "VXLAN_CMD_SET_VNI");
207 }
208
209 static void
setvxlan_local(if_ctx * ctx,const char * addr,int dummy __unused)210 setvxlan_local(if_ctx *ctx, const char *addr, int dummy __unused)
211 {
212 struct ifvxlancmd cmd;
213 struct addrinfo *ai;
214 #if (defined INET || defined INET6)
215 struct sockaddr *sa;
216 #endif
217 int error;
218
219 bzero(&cmd, sizeof(cmd));
220
221 if ((error = getaddrinfo(addr, NULL, NULL, &ai)) != 0)
222 errx(1, "error in parsing local address string: %s",
223 gai_strerror(error));
224
225 #if (defined INET || defined INET6)
226 sa = ai->ai_addr;
227 #endif
228
229 switch (ai->ai_family) {
230 #ifdef INET
231 case AF_INET: {
232 struct sockaddr_in *sin = satosin(sa);
233
234 if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
235 errx(1, "local address cannot be multicast");
236
237 cmd.vxlcmd_sa.in4 = *sin;
238 break;
239 }
240 #endif
241 #ifdef INET6
242 case AF_INET6: {
243 struct sockaddr_in6 *sin6 = satosin6(sa);
244
245 if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
246 errx(1, "local address cannot be multicast");
247
248 cmd.vxlcmd_sa.in6 = *sin6;
249 break;
250 }
251 #endif
252 default:
253 errx(1, "local address %s not supported", addr);
254 }
255
256 freeaddrinfo(ai);
257
258 if (!vxlan_exists(ctx)) {
259 if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) {
260 params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_ADDR4;
261 params.vxlp_local_sa.in4 = cmd.vxlcmd_sa.in4;
262 } else {
263 params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_ADDR6;
264 params.vxlp_local_sa.in6 = cmd.vxlcmd_sa.in6;
265 }
266 return;
267 }
268
269 if (do_cmd(ctx, VXLAN_CMD_SET_LOCAL_ADDR, &cmd, sizeof(cmd), 1) < 0)
270 err(1, "VXLAN_CMD_SET_LOCAL_ADDR");
271 }
272
273 static void
setvxlan_remote(if_ctx * ctx,const char * addr,int dummy __unused)274 setvxlan_remote(if_ctx *ctx, const char *addr, int dummy __unused)
275 {
276 struct ifvxlancmd cmd;
277 struct addrinfo *ai;
278 #if (defined INET || defined INET6)
279 struct sockaddr *sa;
280 #endif
281 int error;
282
283 bzero(&cmd, sizeof(cmd));
284
285 if ((error = getaddrinfo(addr, NULL, NULL, &ai)) != 0)
286 errx(1, "error in parsing remote address string: %s",
287 gai_strerror(error));
288
289 #if (defined INET || defined INET6)
290 sa = ai->ai_addr;
291 #endif
292
293 switch (ai->ai_family) {
294 #ifdef INET
295 case AF_INET: {
296 struct sockaddr_in *sin = satosin(sa);
297
298 if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
299 errx(1, "remote address cannot be multicast");
300
301 cmd.vxlcmd_sa.in4 = *sin;
302 break;
303 }
304 #endif
305 #ifdef INET6
306 case AF_INET6: {
307 struct sockaddr_in6 *sin6 = satosin6(sa);
308
309 if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
310 errx(1, "remote address cannot be multicast");
311
312 cmd.vxlcmd_sa.in6 = *sin6;
313 break;
314 }
315 #endif
316 default:
317 errx(1, "remote address %s not supported", addr);
318 }
319
320 freeaddrinfo(ai);
321
322 if (!vxlan_exists(ctx)) {
323 if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) {
324 params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR4;
325 params.vxlp_remote_sa.in4 = cmd.vxlcmd_sa.in4;
326 } else {
327 params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR6;
328 params.vxlp_remote_sa.in6 = cmd.vxlcmd_sa.in6;
329 }
330 return;
331 }
332
333 if (do_cmd(ctx, VXLAN_CMD_SET_REMOTE_ADDR, &cmd, sizeof(cmd), 1) < 0)
334 err(1, "VXLAN_CMD_SET_REMOTE_ADDR");
335 }
336
337 static void
setvxlan_group(if_ctx * ctx,const char * addr,int dummy __unused)338 setvxlan_group(if_ctx *ctx, const char *addr, int dummy __unused)
339 {
340 struct ifvxlancmd cmd;
341 struct addrinfo *ai;
342 #if (defined INET || defined INET6)
343 struct sockaddr *sa;
344 #endif
345 int error;
346
347 bzero(&cmd, sizeof(cmd));
348
349 if ((error = getaddrinfo(addr, NULL, NULL, &ai)) != 0)
350 errx(1, "error in parsing group address string: %s",
351 gai_strerror(error));
352
353 #if (defined INET || defined INET6)
354 sa = ai->ai_addr;
355 #endif
356
357 switch (ai->ai_family) {
358 #ifdef INET
359 case AF_INET: {
360 struct sockaddr_in *sin = satosin(sa);
361
362 if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
363 errx(1, "group address must be multicast");
364
365 cmd.vxlcmd_sa.in4 = *sin;
366 break;
367 }
368 #endif
369 #ifdef INET6
370 case AF_INET6: {
371 struct sockaddr_in6 *sin6 = satosin6(sa);
372
373 if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
374 errx(1, "group address must be multicast");
375
376 cmd.vxlcmd_sa.in6 = *sin6;
377 break;
378 }
379 #endif
380 default:
381 errx(1, "group address %s not supported", addr);
382 }
383
384 freeaddrinfo(ai);
385
386 if (!vxlan_exists(ctx)) {
387 if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) {
388 params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR4;
389 params.vxlp_remote_sa.in4 = cmd.vxlcmd_sa.in4;
390 } else {
391 params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR6;
392 params.vxlp_remote_sa.in6 = cmd.vxlcmd_sa.in6;
393 }
394 return;
395 }
396
397 if (do_cmd(ctx, VXLAN_CMD_SET_REMOTE_ADDR, &cmd, sizeof(cmd), 1) < 0)
398 err(1, "VXLAN_CMD_SET_REMOTE_ADDR");
399 }
400
401 static void
setvxlan_local_port(if_ctx * ctx,const char * arg,int dummy __unused)402 setvxlan_local_port(if_ctx *ctx, const char *arg, int dummy __unused)
403 {
404 struct ifvxlancmd cmd;
405 u_long val;
406
407 if (get_val(arg, &val) < 0 || val >= UINT16_MAX)
408 errx(1, "invalid local port: %s", arg);
409
410 if (!vxlan_exists(ctx)) {
411 params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_PORT;
412 params.vxlp_local_port = val;
413 return;
414 }
415
416 bzero(&cmd, sizeof(cmd));
417 cmd.vxlcmd_port = val;
418
419 if (do_cmd(ctx, VXLAN_CMD_SET_LOCAL_PORT, &cmd, sizeof(cmd), 1) < 0)
420 err(1, "VXLAN_CMD_SET_LOCAL_PORT");
421 }
422
423 static void
setvxlan_remote_port(if_ctx * ctx,const char * arg,int dummy __unused)424 setvxlan_remote_port(if_ctx *ctx, const char *arg, int dummy __unused)
425 {
426 struct ifvxlancmd cmd;
427 u_long val;
428
429 if (get_val(arg, &val) < 0 || val >= UINT16_MAX)
430 errx(1, "invalid remote port: %s", arg);
431
432 if (!vxlan_exists(ctx)) {
433 params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_PORT;
434 params.vxlp_remote_port = val;
435 return;
436 }
437
438 bzero(&cmd, sizeof(cmd));
439 cmd.vxlcmd_port = val;
440
441 if (do_cmd(ctx, VXLAN_CMD_SET_REMOTE_PORT, &cmd, sizeof(cmd), 1) < 0)
442 err(1, "VXLAN_CMD_SET_REMOTE_PORT");
443 }
444
445 static void
setvxlan_port_range(if_ctx * ctx,const char * arg1,const char * arg2)446 setvxlan_port_range(if_ctx *ctx, const char *arg1, const char *arg2)
447 {
448 struct ifvxlancmd cmd;
449 u_long min, max;
450
451 if (get_val(arg1, &min) < 0 || min >= UINT16_MAX)
452 errx(1, "invalid port range minimum: %s", arg1);
453 if (get_val(arg2, &max) < 0 || max >= UINT16_MAX)
454 errx(1, "invalid port range maximum: %s", arg2);
455 if (max < min)
456 errx(1, "invalid port range");
457
458 if (!vxlan_exists(ctx)) {
459 params.vxlp_with |= VXLAN_PARAM_WITH_PORT_RANGE;
460 params.vxlp_min_port = min;
461 params.vxlp_max_port = max;
462 return;
463 }
464
465 bzero(&cmd, sizeof(cmd));
466 cmd.vxlcmd_port_min = min;
467 cmd.vxlcmd_port_max = max;
468
469 if (do_cmd(ctx, VXLAN_CMD_SET_PORT_RANGE, &cmd, sizeof(cmd), 1) < 0)
470 err(1, "VXLAN_CMD_SET_PORT_RANGE");
471 }
472
473 static void
setvxlan_timeout(if_ctx * ctx,const char * arg,int dummy __unused)474 setvxlan_timeout(if_ctx *ctx, const char *arg, int dummy __unused)
475 {
476 struct ifvxlancmd cmd;
477 u_long val;
478
479 if (get_val(arg, &val) < 0 || (val & ~0xFFFFFFFF) != 0)
480 errx(1, "invalid timeout value: %s", arg);
481
482 if (!vxlan_exists(ctx)) {
483 params.vxlp_with |= VXLAN_PARAM_WITH_FTABLE_TIMEOUT;
484 params.vxlp_ftable_timeout = val & 0xFFFFFFFF;
485 return;
486 }
487
488 bzero(&cmd, sizeof(cmd));
489 cmd.vxlcmd_ftable_timeout = val & 0xFFFFFFFF;
490
491 if (do_cmd(ctx, VXLAN_CMD_SET_FTABLE_TIMEOUT, &cmd, sizeof(cmd), 1) < 0)
492 err(1, "VXLAN_CMD_SET_FTABLE_TIMEOUT");
493 }
494
495 static void
setvxlan_maxaddr(if_ctx * ctx,const char * arg,int dummy __unused)496 setvxlan_maxaddr(if_ctx *ctx, const char *arg, int dummy __unused)
497 {
498 struct ifvxlancmd cmd;
499 u_long val;
500
501 if (get_val(arg, &val) < 0 || (val & ~0xFFFFFFFF) != 0)
502 errx(1, "invalid maxaddr value: %s", arg);
503
504 if (!vxlan_exists(ctx)) {
505 params.vxlp_with |= VXLAN_PARAM_WITH_FTABLE_MAX;
506 params.vxlp_ftable_max = val & 0xFFFFFFFF;
507 return;
508 }
509
510 bzero(&cmd, sizeof(cmd));
511 cmd.vxlcmd_ftable_max = val & 0xFFFFFFFF;
512
513 if (do_cmd(ctx, VXLAN_CMD_SET_FTABLE_MAX, &cmd, sizeof(cmd), 1) < 0)
514 err(1, "VXLAN_CMD_SET_FTABLE_MAX");
515 }
516
517 static void
setvxlan_dev(if_ctx * ctx,const char * arg,int dummy __unused)518 setvxlan_dev(if_ctx *ctx, const char *arg, int dummy __unused)
519 {
520 struct ifvxlancmd cmd;
521
522 if (!vxlan_exists(ctx)) {
523 params.vxlp_with |= VXLAN_PARAM_WITH_MULTICAST_IF;
524 strlcpy(params.vxlp_mc_ifname, arg,
525 sizeof(params.vxlp_mc_ifname));
526 return;
527 }
528
529 bzero(&cmd, sizeof(cmd));
530 strlcpy(cmd.vxlcmd_ifname, arg, sizeof(cmd.vxlcmd_ifname));
531
532 if (do_cmd(ctx, VXLAN_CMD_SET_MULTICAST_IF, &cmd, sizeof(cmd), 1) < 0)
533 err(1, "VXLAN_CMD_SET_MULTICAST_IF");
534 }
535
536 static void
setvxlan_ttl(if_ctx * ctx,const char * arg,int dummy __unused)537 setvxlan_ttl(if_ctx *ctx, const char *arg, int dummy __unused)
538 {
539 struct ifvxlancmd cmd;
540 u_long val;
541
542 if (get_val(arg, &val) < 0 || val > 256)
543 errx(1, "invalid TTL value: %s", arg);
544
545 if (!vxlan_exists(ctx)) {
546 params.vxlp_with |= VXLAN_PARAM_WITH_TTL;
547 params.vxlp_ttl = val;
548 return;
549 }
550
551 bzero(&cmd, sizeof(cmd));
552 cmd.vxlcmd_ttl = val;
553
554 if (do_cmd(ctx, VXLAN_CMD_SET_TTL, &cmd, sizeof(cmd), 1) < 0)
555 err(1, "VXLAN_CMD_SET_TTL");
556 }
557
558 static void
setvxlan_learn(if_ctx * ctx,const char * arg __unused,int d)559 setvxlan_learn(if_ctx *ctx, const char *arg __unused, int d)
560 {
561 struct ifvxlancmd cmd;
562
563 if (!vxlan_exists(ctx)) {
564 params.vxlp_with |= VXLAN_PARAM_WITH_LEARN;
565 params.vxlp_learn = d;
566 return;
567 }
568
569 bzero(&cmd, sizeof(cmd));
570 if (d != 0)
571 cmd.vxlcmd_flags |= VXLAN_CMD_FLAG_LEARN;
572
573 if (do_cmd(ctx, VXLAN_CMD_SET_LEARN, &cmd, sizeof(cmd), 1) < 0)
574 err(1, "VXLAN_CMD_SET_LEARN");
575 }
576
577 static void
setvxlan_flush(if_ctx * ctx,const char * val __unused,int d)578 setvxlan_flush(if_ctx *ctx, const char *val __unused, int d)
579 {
580 struct ifvxlancmd cmd;
581
582 bzero(&cmd, sizeof(cmd));
583 if (d != 0)
584 cmd.vxlcmd_flags |= VXLAN_CMD_FLAG_FLUSH_ALL;
585
586 if (do_cmd(ctx, VXLAN_CMD_FLUSH, &cmd, sizeof(cmd), 1) < 0)
587 err(1, "VXLAN_CMD_FLUSH");
588 }
589
590 static struct cmd vxlan_cmds[] = {
591
592 DEF_CLONE_CMD_ARG("vni", setvxlan_vni),
593 DEF_CLONE_CMD_ARG("vxlanid", setvxlan_vni),
594 DEF_CLONE_CMD_ARG("vxlanlocal", setvxlan_local),
595 DEF_CLONE_CMD_ARG("vxlanremote", setvxlan_remote),
596 DEF_CLONE_CMD_ARG("vxlangroup", setvxlan_group),
597 DEF_CLONE_CMD_ARG("vxlanlocalport", setvxlan_local_port),
598 DEF_CLONE_CMD_ARG("vxlanremoteport", setvxlan_remote_port),
599 DEF_CLONE_CMD_ARG2("vxlanportrange", setvxlan_port_range),
600 DEF_CLONE_CMD_ARG("vxlantimeout", setvxlan_timeout),
601 DEF_CLONE_CMD_ARG("vxlanmaxaddr", setvxlan_maxaddr),
602 DEF_CLONE_CMD_ARG("vxlandev", setvxlan_dev),
603 DEF_CLONE_CMD_ARG("vxlanttl", setvxlan_ttl),
604 DEF_CLONE_CMD("vxlanlearn", 1, setvxlan_learn),
605 DEF_CLONE_CMD("-vxlanlearn", 0, setvxlan_learn),
606
607 DEF_CMD_ARG("vni", setvxlan_vni),
608 DEF_CMD_ARG("vxlanid", setvxlan_vni),
609 DEF_CMD_ARG("vxlanlocal", setvxlan_local),
610 DEF_CMD_ARG("vxlanremote", setvxlan_remote),
611 DEF_CMD_ARG("vxlangroup", setvxlan_group),
612 DEF_CMD_ARG("vxlanlocalport", setvxlan_local_port),
613 DEF_CMD_ARG("vxlanremoteport", setvxlan_remote_port),
614 DEF_CMD_ARG2("vxlanportrange", setvxlan_port_range),
615 DEF_CMD_ARG("vxlantimeout", setvxlan_timeout),
616 DEF_CMD_ARG("vxlanmaxaddr", setvxlan_maxaddr),
617 DEF_CMD_ARG("vxlandev", setvxlan_dev),
618 DEF_CMD_ARG("vxlanttl", setvxlan_ttl),
619 DEF_CMD("vxlanlearn", 1, setvxlan_learn),
620 DEF_CMD("-vxlanlearn", 0, setvxlan_learn),
621
622 DEF_CMD("vxlanflush", 0, setvxlan_flush),
623 DEF_CMD("vxlanflushall", 1, setvxlan_flush),
624
625 DEF_CMD("vxlanhwcsum", IFCAP_VXLAN_HWCSUM, setifcap),
626 DEF_CMD("-vxlanhwcsum", IFCAP_VXLAN_HWCSUM, clearifcap),
627 DEF_CMD("vxlanhwtso", IFCAP_VXLAN_HWTSO, setifcap),
628 DEF_CMD("-vxlanhwtso", IFCAP_VXLAN_HWTSO, clearifcap),
629 };
630
631 static struct afswtch af_vxlan = {
632 .af_name = "af_vxlan",
633 .af_af = AF_UNSPEC,
634 .af_other_status = vxlan_status,
635 };
636
637 static __constructor void
vxlan_ctor(void)638 vxlan_ctor(void)
639 {
640 size_t i;
641
642 for (i = 0; i < nitems(vxlan_cmds); i++)
643 cmd_register(&vxlan_cmds[i]);
644 af_register(&af_vxlan);
645 clone_setdefcallback_prefix("vxlan", vxlan_create);
646 }
647