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 56static struct ifvxlanparam params = { 57 .vxlp_vni = VXLAN_VNI_MAX, 58}; 59 60static int 61get_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 75static int 76do_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 90static int 91vxlan_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 100static void 101vxlan_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 163static void 164vxlan_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 181static void 182vxlan_cb(int s, void *arg) 183{ 184 185} 186 187static void 188vxlan_create(int s, struct ifreq *ifr) 189{ 190 191 vxlan_check_params(); 192 193 ifr->ifr_data = (caddr_t) ¶ms; 194 ioctl_ifcreate(s, ifr); 195} 196 197static 198DECL_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 219static 220DECL_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 279static 280DECL_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 339static 340DECL_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 399static 400DECL_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 421static 422DECL_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 443static 444DECL_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 471static 472DECL_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 493static 494DECL_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 515static 516DECL_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 534static 535DECL_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 556static 557DECL_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 575static void 576setvxlan_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 588static 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 629static struct afswtch af_vxlan = { 630 .af_name = "af_vxlan", 631 .af_af = AF_UNSPEC, 632 .af_other_status = vxlan_status, 633}; 634 635static __constructor void 636vxlan_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("vxlan", vxlan_create); 645} 646