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