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