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