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