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