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