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