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 #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(int sock,u_long op,void * arg,size_t argsize,int set)74 do_cmd(int sock, u_long op, void *arg, size_t argsize, int set)
75 {
76 struct ifdrv ifd;
77
78 bzero(&ifd, sizeof(ifd));
79
80 strlcpy(ifd.ifd_name, ifr.ifr_name, sizeof(ifd.ifd_name));
81 ifd.ifd_cmd = op;
82 ifd.ifd_len = argsize;
83 ifd.ifd_data = arg;
84
85 return (ioctl(sock, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd));
86 }
87
88 static int
vxlan_exists(int sock)89 vxlan_exists(int sock)
90 {
91 struct ifvxlancfg cfg;
92
93 bzero(&cfg, sizeof(cfg));
94
95 return (do_cmd(sock, VXLAN_CMD_GET_CONFIG, &cfg, sizeof(cfg), 0) != -1);
96 }
97
98 static void
vxlan_status(int s)99 vxlan_status(int s)
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(s, 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 = (struct sockaddr_in *)rsa;
130 mc = IN_MULTICAST(ntohl(sin->sin_addr.s_addr));
131 } else {
132 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)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 (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
vxlan_check_params(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
vxlan_cb(int s,void * arg)180 vxlan_cb(int s, void *arg)
181 {
182
183 }
184
185 static void
vxlan_create(int s,struct ifreq * ifr)186 vxlan_create(int s, struct ifreq *ifr)
187 {
188
189 vxlan_check_params();
190
191 ifr->ifr_data = (caddr_t) ¶ms;
192 ioctl_ifcreate(s, ifr);
193 }
194
195 static
DECL_CMD_FUNC(setvxlan_vni,arg,d)196 DECL_CMD_FUNC(setvxlan_vni, arg, d)
197 {
198 struct ifvxlancmd cmd;
199 u_long val;
200
201 if (get_val(arg, &val) < 0 || val >= VXLAN_VNI_MAX)
202 errx(1, "invalid network identifier: %s", arg);
203
204 if (!vxlan_exists(s)) {
205 params.vxlp_with |= VXLAN_PARAM_WITH_VNI;
206 params.vxlp_vni = val;
207 return;
208 }
209
210 bzero(&cmd, sizeof(cmd));
211 cmd.vxlcmd_vni = val;
212
213 if (do_cmd(s, VXLAN_CMD_SET_VNI, &cmd, sizeof(cmd), 1) < 0)
214 err(1, "VXLAN_CMD_SET_VNI");
215 }
216
217 static
DECL_CMD_FUNC(setvxlan_local,addr,d)218 DECL_CMD_FUNC(setvxlan_local, addr, d)
219 {
220 struct ifvxlancmd cmd;
221 struct addrinfo *ai;
222 struct sockaddr *sa;
223 int error;
224
225 bzero(&cmd, sizeof(cmd));
226
227 if ((error = getaddrinfo(addr, NULL, NULL, &ai)) != 0)
228 errx(1, "error in parsing local address string: %s",
229 gai_strerror(error));
230
231 sa = ai->ai_addr;
232
233 switch (ai->ai_family) {
234 #ifdef INET
235 case AF_INET: {
236 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
237
238 if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
239 errx(1, "local address cannot be multicast");
240
241 cmd.vxlcmd_sa.in4 = *sin;
242 break;
243 }
244 #endif
245 #ifdef INET6
246 case AF_INET6: {
247 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
248
249 if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
250 errx(1, "local address cannot be multicast");
251
252 cmd.vxlcmd_sa.in6 = *sin6;
253 break;
254 }
255 #endif
256 default:
257 errx(1, "local address %s not supported", addr);
258 }
259
260 freeaddrinfo(ai);
261
262 if (!vxlan_exists(s)) {
263 if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) {
264 params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_ADDR4;
265 params.vxlp_local_sa.in4 = cmd.vxlcmd_sa.in4;
266 } else {
267 params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_ADDR6;
268 params.vxlp_local_sa.in6 = cmd.vxlcmd_sa.in6;
269 }
270 return;
271 }
272
273 if (do_cmd(s, VXLAN_CMD_SET_LOCAL_ADDR, &cmd, sizeof(cmd), 1) < 0)
274 err(1, "VXLAN_CMD_SET_LOCAL_ADDR");
275 }
276
277 static
DECL_CMD_FUNC(setvxlan_remote,addr,d)278 DECL_CMD_FUNC(setvxlan_remote, addr, d)
279 {
280 struct ifvxlancmd cmd;
281 struct addrinfo *ai;
282 struct sockaddr *sa;
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 sa = ai->ai_addr;
292
293 switch (ai->ai_family) {
294 #ifdef INET
295 case AF_INET: {
296 struct sockaddr_in *sin = (struct sockaddr_in *)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 = (struct sockaddr_in6 *)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(s)) {
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(s, VXLAN_CMD_SET_REMOTE_ADDR, &cmd, sizeof(cmd), 1) < 0)
334 err(1, "VXLAN_CMD_SET_REMOTE_ADDR");
335 }
336
337 static
DECL_CMD_FUNC(setvxlan_group,addr,d)338 DECL_CMD_FUNC(setvxlan_group, addr, d)
339 {
340 struct ifvxlancmd cmd;
341 struct addrinfo *ai;
342 struct sockaddr *sa;
343 int error;
344
345 bzero(&cmd, sizeof(cmd));
346
347 if ((error = getaddrinfo(addr, NULL, NULL, &ai)) != 0)
348 errx(1, "error in parsing group address string: %s",
349 gai_strerror(error));
350
351 sa = ai->ai_addr;
352
353 switch (ai->ai_family) {
354 #ifdef INET
355 case AF_INET: {
356 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
357
358 if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
359 errx(1, "group address must be multicast");
360
361 cmd.vxlcmd_sa.in4 = *sin;
362 break;
363 }
364 #endif
365 #ifdef INET6
366 case AF_INET6: {
367 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
368
369 if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
370 errx(1, "group address must be multicast");
371
372 cmd.vxlcmd_sa.in6 = *sin6;
373 break;
374 }
375 #endif
376 default:
377 errx(1, "group address %s not supported", addr);
378 }
379
380 freeaddrinfo(ai);
381
382 if (!vxlan_exists(s)) {
383 if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) {
384 params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR4;
385 params.vxlp_remote_sa.in4 = cmd.vxlcmd_sa.in4;
386 } else {
387 params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR6;
388 params.vxlp_remote_sa.in6 = cmd.vxlcmd_sa.in6;
389 }
390 return;
391 }
392
393 if (do_cmd(s, VXLAN_CMD_SET_REMOTE_ADDR, &cmd, sizeof(cmd), 1) < 0)
394 err(1, "VXLAN_CMD_SET_REMOTE_ADDR");
395 }
396
397 static
DECL_CMD_FUNC(setvxlan_local_port,arg,d)398 DECL_CMD_FUNC(setvxlan_local_port, arg, d)
399 {
400 struct ifvxlancmd cmd;
401 u_long val;
402
403 if (get_val(arg, &val) < 0 || val >= UINT16_MAX)
404 errx(1, "invalid local port: %s", arg);
405
406 if (!vxlan_exists(s)) {
407 params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_PORT;
408 params.vxlp_local_port = val;
409 return;
410 }
411
412 bzero(&cmd, sizeof(cmd));
413 cmd.vxlcmd_port = val;
414
415 if (do_cmd(s, VXLAN_CMD_SET_LOCAL_PORT, &cmd, sizeof(cmd), 1) < 0)
416 err(1, "VXLAN_CMD_SET_LOCAL_PORT");
417 }
418
419 static
DECL_CMD_FUNC(setvxlan_remote_port,arg,d)420 DECL_CMD_FUNC(setvxlan_remote_port, arg, d)
421 {
422 struct ifvxlancmd cmd;
423 u_long val;
424
425 if (get_val(arg, &val) < 0 || val >= UINT16_MAX)
426 errx(1, "invalid remote port: %s", arg);
427
428 if (!vxlan_exists(s)) {
429 params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_PORT;
430 params.vxlp_remote_port = val;
431 return;
432 }
433
434 bzero(&cmd, sizeof(cmd));
435 cmd.vxlcmd_port = val;
436
437 if (do_cmd(s, VXLAN_CMD_SET_REMOTE_PORT, &cmd, sizeof(cmd), 1) < 0)
438 err(1, "VXLAN_CMD_SET_REMOTE_PORT");
439 }
440
441 static
DECL_CMD_FUNC2(setvxlan_port_range,arg1,arg2)442 DECL_CMD_FUNC2(setvxlan_port_range, arg1, arg2)
443 {
444 struct ifvxlancmd cmd;
445 u_long min, max;
446
447 if (get_val(arg1, &min) < 0 || min >= UINT16_MAX)
448 errx(1, "invalid port range minimum: %s", arg1);
449 if (get_val(arg2, &max) < 0 || max >= UINT16_MAX)
450 errx(1, "invalid port range maximum: %s", arg2);
451 if (max < min)
452 errx(1, "invalid port range");
453
454 if (!vxlan_exists(s)) {
455 params.vxlp_with |= VXLAN_PARAM_WITH_PORT_RANGE;
456 params.vxlp_min_port = min;
457 params.vxlp_max_port = max;
458 return;
459 }
460
461 bzero(&cmd, sizeof(cmd));
462 cmd.vxlcmd_port_min = min;
463 cmd.vxlcmd_port_max = max;
464
465 if (do_cmd(s, VXLAN_CMD_SET_PORT_RANGE, &cmd, sizeof(cmd), 1) < 0)
466 err(1, "VXLAN_CMD_SET_PORT_RANGE");
467 }
468
469 static
DECL_CMD_FUNC(setvxlan_timeout,arg,d)470 DECL_CMD_FUNC(setvxlan_timeout, arg, d)
471 {
472 struct ifvxlancmd cmd;
473 u_long val;
474
475 if (get_val(arg, &val) < 0 || (val & ~0xFFFFFFFF) != 0)
476 errx(1, "invalid timeout value: %s", arg);
477
478 if (!vxlan_exists(s)) {
479 params.vxlp_with |= VXLAN_PARAM_WITH_FTABLE_TIMEOUT;
480 params.vxlp_ftable_timeout = val & 0xFFFFFFFF;
481 return;
482 }
483
484 bzero(&cmd, sizeof(cmd));
485 cmd.vxlcmd_ftable_timeout = val & 0xFFFFFFFF;
486
487 if (do_cmd(s, VXLAN_CMD_SET_FTABLE_TIMEOUT, &cmd, sizeof(cmd), 1) < 0)
488 err(1, "VXLAN_CMD_SET_FTABLE_TIMEOUT");
489 }
490
491 static
DECL_CMD_FUNC(setvxlan_maxaddr,arg,d)492 DECL_CMD_FUNC(setvxlan_maxaddr, arg, d)
493 {
494 struct ifvxlancmd cmd;
495 u_long val;
496
497 if (get_val(arg, &val) < 0 || (val & ~0xFFFFFFFF) != 0)
498 errx(1, "invalid maxaddr value: %s", arg);
499
500 if (!vxlan_exists(s)) {
501 params.vxlp_with |= VXLAN_PARAM_WITH_FTABLE_MAX;
502 params.vxlp_ftable_max = val & 0xFFFFFFFF;
503 return;
504 }
505
506 bzero(&cmd, sizeof(cmd));
507 cmd.vxlcmd_ftable_max = val & 0xFFFFFFFF;
508
509 if (do_cmd(s, VXLAN_CMD_SET_FTABLE_MAX, &cmd, sizeof(cmd), 1) < 0)
510 err(1, "VXLAN_CMD_SET_FTABLE_MAX");
511 }
512
513 static
DECL_CMD_FUNC(setvxlan_dev,arg,d)514 DECL_CMD_FUNC(setvxlan_dev, arg, d)
515 {
516 struct ifvxlancmd cmd;
517
518 if (!vxlan_exists(s)) {
519 params.vxlp_with |= VXLAN_PARAM_WITH_MULTICAST_IF;
520 strlcpy(params.vxlp_mc_ifname, arg,
521 sizeof(params.vxlp_mc_ifname));
522 return;
523 }
524
525 bzero(&cmd, sizeof(cmd));
526 strlcpy(cmd.vxlcmd_ifname, arg, sizeof(cmd.vxlcmd_ifname));
527
528 if (do_cmd(s, VXLAN_CMD_SET_MULTICAST_IF, &cmd, sizeof(cmd), 1) < 0)
529 err(1, "VXLAN_CMD_SET_MULTICAST_IF");
530 }
531
532 static
DECL_CMD_FUNC(setvxlan_ttl,arg,d)533 DECL_CMD_FUNC(setvxlan_ttl, arg, d)
534 {
535 struct ifvxlancmd cmd;
536 u_long val;
537
538 if (get_val(arg, &val) < 0 || val > 256)
539 errx(1, "invalid TTL value: %s", arg);
540
541 if (!vxlan_exists(s)) {
542 params.vxlp_with |= VXLAN_PARAM_WITH_TTL;
543 params.vxlp_ttl = val;
544 return;
545 }
546
547 bzero(&cmd, sizeof(cmd));
548 cmd.vxlcmd_ttl = val;
549
550 if (do_cmd(s, VXLAN_CMD_SET_TTL, &cmd, sizeof(cmd), 1) < 0)
551 err(1, "VXLAN_CMD_SET_TTL");
552 }
553
554 static
DECL_CMD_FUNC(setvxlan_learn,arg,d)555 DECL_CMD_FUNC(setvxlan_learn, arg, d)
556 {
557 struct ifvxlancmd cmd;
558
559 if (!vxlan_exists(s)) {
560 params.vxlp_with |= VXLAN_PARAM_WITH_LEARN;
561 params.vxlp_learn = d;
562 return;
563 }
564
565 bzero(&cmd, sizeof(cmd));
566 if (d != 0)
567 cmd.vxlcmd_flags |= VXLAN_CMD_FLAG_LEARN;
568
569 if (do_cmd(s, VXLAN_CMD_SET_LEARN, &cmd, sizeof(cmd), 1) < 0)
570 err(1, "VXLAN_CMD_SET_LEARN");
571 }
572
573 static void
setvxlan_flush(const char * val,int d,int s,const struct afswtch * afp)574 setvxlan_flush(const char *val, int d, int s, const struct afswtch *afp)
575 {
576 struct ifvxlancmd cmd;
577
578 bzero(&cmd, sizeof(cmd));
579 if (d != 0)
580 cmd.vxlcmd_flags |= VXLAN_CMD_FLAG_FLUSH_ALL;
581
582 if (do_cmd(s, VXLAN_CMD_FLUSH, &cmd, sizeof(cmd), 1) < 0)
583 err(1, "VXLAN_CMD_FLUSH");
584 }
585
586 static struct cmd vxlan_cmds[] = {
587
588 DEF_CLONE_CMD_ARG("vni", setvxlan_vni),
589 DEF_CLONE_CMD_ARG("vxlanid", setvxlan_vni),
590 DEF_CLONE_CMD_ARG("vxlanlocal", setvxlan_local),
591 DEF_CLONE_CMD_ARG("vxlanremote", setvxlan_remote),
592 DEF_CLONE_CMD_ARG("vxlangroup", setvxlan_group),
593 DEF_CLONE_CMD_ARG("vxlanlocalport", setvxlan_local_port),
594 DEF_CLONE_CMD_ARG("vxlanremoteport", setvxlan_remote_port),
595 DEF_CLONE_CMD_ARG2("vxlanportrange", setvxlan_port_range),
596 DEF_CLONE_CMD_ARG("vxlantimeout", setvxlan_timeout),
597 DEF_CLONE_CMD_ARG("vxlanmaxaddr", setvxlan_maxaddr),
598 DEF_CLONE_CMD_ARG("vxlandev", setvxlan_dev),
599 DEF_CLONE_CMD_ARG("vxlanttl", setvxlan_ttl),
600 DEF_CLONE_CMD("vxlanlearn", 1, setvxlan_learn),
601 DEF_CLONE_CMD("-vxlanlearn", 0, setvxlan_learn),
602
603 DEF_CMD_ARG("vni", setvxlan_vni),
604 DEF_CMD_ARG("vxlanid", setvxlan_vni),
605 DEF_CMD_ARG("vxlanlocal", setvxlan_local),
606 DEF_CMD_ARG("vxlanremote", setvxlan_remote),
607 DEF_CMD_ARG("vxlangroup", setvxlan_group),
608 DEF_CMD_ARG("vxlanlocalport", setvxlan_local_port),
609 DEF_CMD_ARG("vxlanremoteport", setvxlan_remote_port),
610 DEF_CMD_ARG2("vxlanportrange", setvxlan_port_range),
611 DEF_CMD_ARG("vxlantimeout", setvxlan_timeout),
612 DEF_CMD_ARG("vxlanmaxaddr", setvxlan_maxaddr),
613 DEF_CMD_ARG("vxlandev", setvxlan_dev),
614 DEF_CMD_ARG("vxlanttl", setvxlan_ttl),
615 DEF_CMD("vxlanlearn", 1, setvxlan_learn),
616 DEF_CMD("-vxlanlearn", 0, setvxlan_learn),
617
618 DEF_CMD("vxlanflush", 0, setvxlan_flush),
619 DEF_CMD("vxlanflushall", 1, setvxlan_flush),
620
621 DEF_CMD("vxlanhwcsum", IFCAP_VXLAN_HWCSUM, setifcap),
622 DEF_CMD("-vxlanhwcsum", -IFCAP_VXLAN_HWCSUM, setifcap),
623 DEF_CMD("vxlanhwtso", IFCAP_VXLAN_HWTSO, setifcap),
624 DEF_CMD("-vxlanhwtso", -IFCAP_VXLAN_HWTSO, setifcap),
625 };
626
627 static struct afswtch af_vxlan = {
628 .af_name = "af_vxlan",
629 .af_af = AF_UNSPEC,
630 .af_other_status = vxlan_status,
631 };
632
633 static __constructor void
vxlan_ctor(void)634 vxlan_ctor(void)
635 {
636 size_t i;
637
638 for (i = 0; i < nitems(vxlan_cmds); i++)
639 cmd_register(&vxlan_cmds[i]);
640 af_register(&af_vxlan);
641 callback_register(vxlan_cb, NULL);
642 clone_setdefcallback_prefix("vxlan", vxlan_create);
643 }
644