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 "opt_inet.h" 28#include "opt_inet6.h" 29 30#include <sys/cdefs.h> 31__FBSDID("$FreeBSD: stable/11/sys/net/if_vxlan.c 346783 2019-04-27 04:39:41Z kevans $"); 32 33#include <sys/param.h> 34#include <sys/eventhandler.h> 35#include <sys/kernel.h> 36#include <sys/lock.h> 37#include <sys/hash.h> 38#include <sys/malloc.h> 39#include <sys/mbuf.h> 40#include <sys/module.h> 41#include <sys/refcount.h> 42#include <sys/rmlock.h> 43#include <sys/priv.h> 44#include <sys/proc.h> 45#include <sys/queue.h> 46#include <sys/sbuf.h> 47#include <sys/socket.h> 48#include <sys/socketvar.h> 49#include <sys/sockio.h> 50#include <sys/sysctl.h> 51#include <sys/systm.h> 52 53#include <net/bpf.h> 54#include <net/ethernet.h> 55#include <net/if.h> 56#include <net/if_var.h> 57#include <net/if_clone.h> 58#include <net/if_dl.h> 59#include <net/if_media.h> 60#include <net/if_types.h> 61#include <net/if_vxlan.h> 62#include <net/netisr.h> 63 64#include <netinet/in.h> 65#include <netinet/in_systm.h> 66#include <netinet/in_var.h> 67#include <netinet/in_pcb.h> 68#include <netinet/ip.h> 69#include <netinet/ip6.h> 70#include <netinet/ip_var.h> 71#include <netinet/udp.h> 72#include <netinet/udp_var.h> 73 74#include <netinet6/ip6_var.h> 75#include <netinet6/scope6_var.h> 76 77struct vxlan_softc; 78LIST_HEAD(vxlan_softc_head, vxlan_softc); 79 80struct vxlan_socket_mc_info { 81 union vxlan_sockaddr vxlsomc_saddr; 82 union vxlan_sockaddr vxlsomc_gaddr; 83 int vxlsomc_ifidx; 84 int vxlsomc_users; 85}; 86 87#define VXLAN_SO_MC_MAX_GROUPS 32 88 89#define VXLAN_SO_VNI_HASH_SHIFT 6 90#define VXLAN_SO_VNI_HASH_SIZE (1 << VXLAN_SO_VNI_HASH_SHIFT) 91#define VXLAN_SO_VNI_HASH(_vni) ((_vni) % VXLAN_SO_VNI_HASH_SIZE) 92 93struct vxlan_socket { 94 struct socket *vxlso_sock; 95 struct rmlock vxlso_lock; 96 u_int vxlso_refcnt; 97 union vxlan_sockaddr vxlso_laddr; 98 LIST_ENTRY(vxlan_socket) vxlso_entry; 99 struct vxlan_softc_head vxlso_vni_hash[VXLAN_SO_VNI_HASH_SIZE]; 100 struct vxlan_socket_mc_info vxlso_mc[VXLAN_SO_MC_MAX_GROUPS]; 101}; 102 103#define VXLAN_SO_RLOCK(_vso, _p) rm_rlock(&(_vso)->vxlso_lock, (_p)) 104#define VXLAN_SO_RUNLOCK(_vso, _p) rm_runlock(&(_vso)->vxlso_lock, (_p)) 105#define VXLAN_SO_WLOCK(_vso) rm_wlock(&(_vso)->vxlso_lock) 106#define VXLAN_SO_WUNLOCK(_vso) rm_wunlock(&(_vso)->vxlso_lock) 107#define VXLAN_SO_LOCK_ASSERT(_vso) \ 108 rm_assert(&(_vso)->vxlso_lock, RA_LOCKED) 109#define VXLAN_SO_LOCK_WASSERT(_vso) \ 110 rm_assert(&(_vso)->vxlso_lock, RA_WLOCKED) 111 112#define VXLAN_SO_ACQUIRE(_vso) refcount_acquire(&(_vso)->vxlso_refcnt) 113#define VXLAN_SO_RELEASE(_vso) refcount_release(&(_vso)->vxlso_refcnt) 114 115struct vxlan_ftable_entry { 116 LIST_ENTRY(vxlan_ftable_entry) vxlfe_hash; 117 uint16_t vxlfe_flags; 118 uint8_t vxlfe_mac[ETHER_ADDR_LEN]; 119 union vxlan_sockaddr vxlfe_raddr; 120 time_t vxlfe_expire; 121}; 122 123#define VXLAN_FE_FLAG_DYNAMIC 0x01 124#define VXLAN_FE_FLAG_STATIC 0x02 125 126#define VXLAN_FE_IS_DYNAMIC(_fe) \ 127 ((_fe)->vxlfe_flags & VXLAN_FE_FLAG_DYNAMIC) 128 129#define VXLAN_SC_FTABLE_SHIFT 9 130#define VXLAN_SC_FTABLE_SIZE (1 << VXLAN_SC_FTABLE_SHIFT) 131#define VXLAN_SC_FTABLE_MASK (VXLAN_SC_FTABLE_SIZE - 1) 132#define VXLAN_SC_FTABLE_HASH(_sc, _mac) \ 133 (vxlan_mac_hash(_sc, _mac) % VXLAN_SC_FTABLE_SIZE) 134 135LIST_HEAD(vxlan_ftable_head, vxlan_ftable_entry); 136 137struct vxlan_statistics { 138 uint32_t ftable_nospace; 139 uint32_t ftable_lock_upgrade_failed; 140}; 141 142struct vxlan_softc { 143 struct ifnet *vxl_ifp; 144 struct vxlan_socket *vxl_sock; 145 uint32_t vxl_vni; 146 union vxlan_sockaddr vxl_src_addr; 147 union vxlan_sockaddr vxl_dst_addr; 148 uint32_t vxl_flags; 149#define VXLAN_FLAG_INIT 0x0001 150#define VXLAN_FLAG_TEARDOWN 0x0002 151#define VXLAN_FLAG_LEARN 0x0004 152 153 uint32_t vxl_port_hash_key; 154 uint16_t vxl_min_port; 155 uint16_t vxl_max_port; 156 uint8_t vxl_ttl; 157 158 /* Lookup table from MAC address to forwarding entry. */ 159 uint32_t vxl_ftable_cnt; 160 uint32_t vxl_ftable_max; 161 uint32_t vxl_ftable_timeout; 162 uint32_t vxl_ftable_hash_key; 163 struct vxlan_ftable_head *vxl_ftable; 164 165 /* Derived from vxl_dst_addr. */ 166 struct vxlan_ftable_entry vxl_default_fe; 167 168 struct ip_moptions *vxl_im4o; 169 struct ip6_moptions *vxl_im6o; 170 171 struct rmlock vxl_lock; 172 volatile u_int vxl_refcnt; 173 174 int vxl_unit; 175 int vxl_vso_mc_index; 176 struct vxlan_statistics vxl_stats; 177 struct sysctl_oid *vxl_sysctl_node; 178 struct sysctl_ctx_list vxl_sysctl_ctx; 179 struct callout vxl_callout; 180 struct ether_addr vxl_hwaddr; 181 int vxl_mc_ifindex; 182 struct ifnet *vxl_mc_ifp; 183 struct ifmedia vxl_media; 184 char vxl_mc_ifname[IFNAMSIZ]; 185 LIST_ENTRY(vxlan_softc) vxl_entry; 186 LIST_ENTRY(vxlan_softc) vxl_ifdetach_list; 187}; 188 189#define VXLAN_RLOCK(_sc, _p) rm_rlock(&(_sc)->vxl_lock, (_p)) 190#define VXLAN_RUNLOCK(_sc, _p) rm_runlock(&(_sc)->vxl_lock, (_p)) 191#define VXLAN_WLOCK(_sc) rm_wlock(&(_sc)->vxl_lock) 192#define VXLAN_WUNLOCK(_sc) rm_wunlock(&(_sc)->vxl_lock) 193#define VXLAN_LOCK_WOWNED(_sc) rm_wowned(&(_sc)->vxl_lock) 194#define VXLAN_LOCK_ASSERT(_sc) rm_assert(&(_sc)->vxl_lock, RA_LOCKED) 195#define VXLAN_LOCK_WASSERT(_sc) rm_assert(&(_sc)->vxl_lock, RA_WLOCKED) 196#define VXLAN_UNLOCK(_sc, _p) do { \ 197 if (VXLAN_LOCK_WOWNED(_sc)) \ 198 VXLAN_WUNLOCK(_sc); \ 199 else \ 200 VXLAN_RUNLOCK(_sc, _p); \ 201} while (0) 202 203#define VXLAN_ACQUIRE(_sc) refcount_acquire(&(_sc)->vxl_refcnt) 204#define VXLAN_RELEASE(_sc) refcount_release(&(_sc)->vxl_refcnt) 205 206#define satoconstsin(sa) ((const struct sockaddr_in *)(sa)) 207#define satoconstsin6(sa) ((const struct sockaddr_in6 *)(sa)) 208 209struct vxlanudphdr { 210 struct udphdr vxlh_udp; 211 struct vxlan_header vxlh_hdr; 212} __packed; 213 214static int vxlan_ftable_addr_cmp(const uint8_t *, const uint8_t *); 215static void vxlan_ftable_init(struct vxlan_softc *); 216static void vxlan_ftable_fini(struct vxlan_softc *); 217static void vxlan_ftable_flush(struct vxlan_softc *, int); 218static void vxlan_ftable_expire(struct vxlan_softc *); 219static int vxlan_ftable_update_locked(struct vxlan_softc *, 220 const union vxlan_sockaddr *, const uint8_t *, 221 struct rm_priotracker *); 222static int vxlan_ftable_learn(struct vxlan_softc *, 223 const struct sockaddr *, const uint8_t *); 224static int vxlan_ftable_sysctl_dump(SYSCTL_HANDLER_ARGS); 225 226static struct vxlan_ftable_entry * 227 vxlan_ftable_entry_alloc(void); 228static void vxlan_ftable_entry_free(struct vxlan_ftable_entry *); 229static void vxlan_ftable_entry_init(struct vxlan_softc *, 230 struct vxlan_ftable_entry *, const uint8_t *, 231 const struct sockaddr *, uint32_t); 232static void vxlan_ftable_entry_destroy(struct vxlan_softc *, 233 struct vxlan_ftable_entry *); 234static int vxlan_ftable_entry_insert(struct vxlan_softc *, 235 struct vxlan_ftable_entry *); 236static struct vxlan_ftable_entry * 237 vxlan_ftable_entry_lookup(struct vxlan_softc *, 238 const uint8_t *); 239static void vxlan_ftable_entry_dump(struct vxlan_ftable_entry *, 240 struct sbuf *); 241 242static struct vxlan_socket * 243 vxlan_socket_alloc(const union vxlan_sockaddr *); 244static void vxlan_socket_destroy(struct vxlan_socket *); 245static void vxlan_socket_release(struct vxlan_socket *); 246static struct vxlan_socket * 247 vxlan_socket_lookup(union vxlan_sockaddr *vxlsa); 248static void vxlan_socket_insert(struct vxlan_socket *); 249static int vxlan_socket_init(struct vxlan_socket *, struct ifnet *); 250static int vxlan_socket_bind(struct vxlan_socket *, struct ifnet *); 251static int vxlan_socket_create(struct ifnet *, int, 252 const union vxlan_sockaddr *, struct vxlan_socket **); 253static void vxlan_socket_ifdetach(struct vxlan_socket *, 254 struct ifnet *, struct vxlan_softc_head *); 255 256static struct vxlan_socket * 257 vxlan_socket_mc_lookup(const union vxlan_sockaddr *); 258static int vxlan_sockaddr_mc_info_match( 259 const struct vxlan_socket_mc_info *, 260 const union vxlan_sockaddr *, 261 const union vxlan_sockaddr *, int); 262static int vxlan_socket_mc_join_group(struct vxlan_socket *, 263 const union vxlan_sockaddr *, const union vxlan_sockaddr *, 264 int *, union vxlan_sockaddr *); 265static int vxlan_socket_mc_leave_group(struct vxlan_socket *, 266 const union vxlan_sockaddr *, 267 const union vxlan_sockaddr *, int); 268static int vxlan_socket_mc_add_group(struct vxlan_socket *, 269 const union vxlan_sockaddr *, const union vxlan_sockaddr *, 270 int, int *); 271static void vxlan_socket_mc_release_group_by_idx(struct vxlan_socket *, 272 int); 273 274static struct vxlan_softc * 275 vxlan_socket_lookup_softc_locked(struct vxlan_socket *, 276 uint32_t); 277static struct vxlan_softc * 278 vxlan_socket_lookup_softc(struct vxlan_socket *, uint32_t); 279static int vxlan_socket_insert_softc(struct vxlan_socket *, 280 struct vxlan_softc *); 281static void vxlan_socket_remove_softc(struct vxlan_socket *, 282 struct vxlan_softc *); 283 284static struct ifnet * 285 vxlan_multicast_if_ref(struct vxlan_softc *, int); 286static void vxlan_free_multicast(struct vxlan_softc *); 287static int vxlan_setup_multicast_interface(struct vxlan_softc *); 288 289static int vxlan_setup_multicast(struct vxlan_softc *); 290static int vxlan_setup_socket(struct vxlan_softc *); 291static void vxlan_setup_interface(struct vxlan_softc *); 292static int vxlan_valid_init_config(struct vxlan_softc *); 293static void vxlan_init_wait(struct vxlan_softc *); 294static void vxlan_init_complete(struct vxlan_softc *); 295static void vxlan_init(void *); 296static void vxlan_release(struct vxlan_softc *); 297static void vxlan_teardown_wait(struct vxlan_softc *); 298static void vxlan_teardown_complete(struct vxlan_softc *); 299static void vxlan_teardown_locked(struct vxlan_softc *); 300static void vxlan_teardown(struct vxlan_softc *); 301static void vxlan_ifdetach(struct vxlan_softc *, struct ifnet *, 302 struct vxlan_softc_head *); 303static void vxlan_timer(void *); 304 305static int vxlan_ctrl_get_config(struct vxlan_softc *, void *); 306static int vxlan_ctrl_set_vni(struct vxlan_softc *, void *); 307static int vxlan_ctrl_set_local_addr(struct vxlan_softc *, void *); 308static int vxlan_ctrl_set_remote_addr(struct vxlan_softc *, void *); 309static int vxlan_ctrl_set_local_port(struct vxlan_softc *, void *); 310static int vxlan_ctrl_set_remote_port(struct vxlan_softc *, void *); 311static int vxlan_ctrl_set_port_range(struct vxlan_softc *, void *); 312static int vxlan_ctrl_set_ftable_timeout(struct vxlan_softc *, void *); 313static int vxlan_ctrl_set_ftable_max(struct vxlan_softc *, void *); 314static int vxlan_ctrl_set_multicast_if(struct vxlan_softc * , void *); 315static int vxlan_ctrl_set_ttl(struct vxlan_softc *, void *); 316static int vxlan_ctrl_set_learn(struct vxlan_softc *, void *); 317static int vxlan_ctrl_ftable_entry_add(struct vxlan_softc *, void *); 318static int vxlan_ctrl_ftable_entry_rem(struct vxlan_softc *, void *); 319static int vxlan_ctrl_flush(struct vxlan_softc *, void *); 320static int vxlan_ioctl_drvspec(struct vxlan_softc *, 321 struct ifdrv *, int); 322static int vxlan_ioctl_ifflags(struct vxlan_softc *); 323static int vxlan_ioctl(struct ifnet *, u_long, caddr_t); 324 325#if defined(INET) || defined(INET6) 326static uint16_t vxlan_pick_source_port(struct vxlan_softc *, struct mbuf *); 327static void vxlan_encap_header(struct vxlan_softc *, struct mbuf *, 328 int, uint16_t, uint16_t); 329#endif 330static int vxlan_encap4(struct vxlan_softc *, 331 const union vxlan_sockaddr *, struct mbuf *); 332static int vxlan_encap6(struct vxlan_softc *, 333 const union vxlan_sockaddr *, struct mbuf *); 334static int vxlan_transmit(struct ifnet *, struct mbuf *); 335static void vxlan_qflush(struct ifnet *); 336static void vxlan_rcv_udp_packet(struct mbuf *, int, struct inpcb *, 337 const struct sockaddr *, void *); 338static int vxlan_input(struct vxlan_socket *, uint32_t, struct mbuf **, 339 const struct sockaddr *); 340 341static void vxlan_set_default_config(struct vxlan_softc *); 342static int vxlan_set_user_config(struct vxlan_softc *, 343 struct ifvxlanparam *); 344static int vxlan_clone_create(struct if_clone *, int, caddr_t); 345static void vxlan_clone_destroy(struct ifnet *); 346 347static uint32_t vxlan_mac_hash(struct vxlan_softc *, const uint8_t *); 348static int vxlan_media_change(struct ifnet *); 349static void vxlan_media_status(struct ifnet *, struct ifmediareq *); 350 351static int vxlan_sockaddr_cmp(const union vxlan_sockaddr *, 352 const struct sockaddr *); 353static void vxlan_sockaddr_copy(union vxlan_sockaddr *, 354 const struct sockaddr *); 355static int vxlan_sockaddr_in_equal(const union vxlan_sockaddr *, 356 const struct sockaddr *); 357static void vxlan_sockaddr_in_copy(union vxlan_sockaddr *, 358 const struct sockaddr *); 359static int vxlan_sockaddr_supported(const union vxlan_sockaddr *, int); 360static int vxlan_sockaddr_in_any(const union vxlan_sockaddr *); 361static int vxlan_sockaddr_in_multicast(const union vxlan_sockaddr *); 362static int vxlan_sockaddr_in6_embedscope(union vxlan_sockaddr *); 363 364static int vxlan_can_change_config(struct vxlan_softc *); 365static int vxlan_check_vni(uint32_t); 366static int vxlan_check_ttl(int); 367static int vxlan_check_ftable_timeout(uint32_t); 368static int vxlan_check_ftable_max(uint32_t); 369 370static void vxlan_sysctl_setup(struct vxlan_softc *); 371static void vxlan_sysctl_destroy(struct vxlan_softc *); 372static int vxlan_tunable_int(struct vxlan_softc *, const char *, int); 373 374static void vxlan_ifdetach_event(void *, struct ifnet *); 375static void vxlan_load(void); 376static void vxlan_unload(void); 377static int vxlan_modevent(module_t, int, void *); 378 379static const char vxlan_name[] = "vxlan"; 380static MALLOC_DEFINE(M_VXLAN, vxlan_name, 381 "Virtual eXtensible LAN Interface"); 382static struct if_clone *vxlan_cloner; 383 384static struct mtx vxlan_list_mtx; 385#define VXLAN_LIST_LOCK() mtx_lock(&vxlan_list_mtx) 386#define VXLAN_LIST_UNLOCK() mtx_unlock(&vxlan_list_mtx) 387 388static LIST_HEAD(, vxlan_socket) vxlan_socket_list; 389 390static eventhandler_tag vxlan_ifdetach_event_tag; 391 392SYSCTL_DECL(_net_link); 393SYSCTL_NODE(_net_link, OID_AUTO, vxlan, CTLFLAG_RW, 0, 394 "Virtual eXtensible Local Area Network"); 395 396static int vxlan_legacy_port = 0; 397TUNABLE_INT("net.link.vxlan.legacy_port", &vxlan_legacy_port); 398static int vxlan_reuse_port = 0; 399TUNABLE_INT("net.link.vxlan.reuse_port", &vxlan_reuse_port); 400 401/* Default maximum number of addresses in the forwarding table. */ 402#ifndef VXLAN_FTABLE_MAX 403#define VXLAN_FTABLE_MAX 2000 404#endif 405 406/* Timeout (in seconds) of addresses learned in the forwarding table. */ 407#ifndef VXLAN_FTABLE_TIMEOUT 408#define VXLAN_FTABLE_TIMEOUT (20 * 60) 409#endif 410 411/* 412 * Maximum timeout (in seconds) of addresses learned in the forwarding 413 * table. 414 */ 415#ifndef VXLAN_FTABLE_MAX_TIMEOUT 416#define VXLAN_FTABLE_MAX_TIMEOUT (60 * 60 * 24) 417#endif 418 419/* Number of seconds between pruning attempts of the forwarding table. */ 420#ifndef VXLAN_FTABLE_PRUNE 421#define VXLAN_FTABLE_PRUNE (5 * 60) 422#endif 423 424static int vxlan_ftable_prune_period = VXLAN_FTABLE_PRUNE; 425 426struct vxlan_control { 427 int (*vxlc_func)(struct vxlan_softc *, void *); 428 int vxlc_argsize; 429 int vxlc_flags; 430#define VXLAN_CTRL_FLAG_COPYIN 0x01 431#define VXLAN_CTRL_FLAG_COPYOUT 0x02 432#define VXLAN_CTRL_FLAG_SUSER 0x04 433}; 434 435static const struct vxlan_control vxlan_control_table[] = { 436 [VXLAN_CMD_GET_CONFIG] = 437 { vxlan_ctrl_get_config, sizeof(struct ifvxlancfg), 438 VXLAN_CTRL_FLAG_COPYOUT 439 }, 440 441 [VXLAN_CMD_SET_VNI] = 442 { vxlan_ctrl_set_vni, sizeof(struct ifvxlancmd), 443 VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER, 444 }, 445 446 [VXLAN_CMD_SET_LOCAL_ADDR] = 447 { vxlan_ctrl_set_local_addr, sizeof(struct ifvxlancmd), 448 VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER, 449 }, 450 451 [VXLAN_CMD_SET_REMOTE_ADDR] = 452 { vxlan_ctrl_set_remote_addr, sizeof(struct ifvxlancmd), 453 VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER, 454 }, 455 456 [VXLAN_CMD_SET_LOCAL_PORT] = 457 { vxlan_ctrl_set_local_port, sizeof(struct ifvxlancmd), 458 VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER, 459 }, 460 461 [VXLAN_CMD_SET_REMOTE_PORT] = 462 { vxlan_ctrl_set_remote_port, sizeof(struct ifvxlancmd), 463 VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER, 464 }, 465 466 [VXLAN_CMD_SET_PORT_RANGE] = 467 { vxlan_ctrl_set_port_range, sizeof(struct ifvxlancmd), 468 VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER, 469 }, 470 471 [VXLAN_CMD_SET_FTABLE_TIMEOUT] = 472 { vxlan_ctrl_set_ftable_timeout, sizeof(struct ifvxlancmd), 473 VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER, 474 }, 475 476 [VXLAN_CMD_SET_FTABLE_MAX] = 477 { vxlan_ctrl_set_ftable_max, sizeof(struct ifvxlancmd), 478 VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER, 479 }, 480 481 [VXLAN_CMD_SET_MULTICAST_IF] = 482 { vxlan_ctrl_set_multicast_if, sizeof(struct ifvxlancmd), 483 VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER, 484 }, 485 486 [VXLAN_CMD_SET_TTL] = 487 { vxlan_ctrl_set_ttl, sizeof(struct ifvxlancmd), 488 VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER, 489 }, 490 491 [VXLAN_CMD_SET_LEARN] = 492 { vxlan_ctrl_set_learn, sizeof(struct ifvxlancmd), 493 VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER, 494 }, 495 496 [VXLAN_CMD_FTABLE_ENTRY_ADD] = 497 { vxlan_ctrl_ftable_entry_add, sizeof(struct ifvxlancmd), 498 VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER, 499 }, 500 501 [VXLAN_CMD_FTABLE_ENTRY_REM] = 502 { vxlan_ctrl_ftable_entry_rem, sizeof(struct ifvxlancmd), 503 VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER, 504 }, 505 506 [VXLAN_CMD_FLUSH] = 507 { vxlan_ctrl_flush, sizeof(struct ifvxlancmd), 508 VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER, 509 }, 510}; 511 512static const int vxlan_control_table_size = nitems(vxlan_control_table); 513 514static int 515vxlan_ftable_addr_cmp(const uint8_t *a, const uint8_t *b) 516{ 517 int i, d; 518 519 for (i = 0, d = 0; i < ETHER_ADDR_LEN && d == 0; i++) 520 d = ((int)a[i]) - ((int)b[i]); 521 522 return (d); 523} 524 525static void 526vxlan_ftable_init(struct vxlan_softc *sc) 527{ 528 int i; 529 530 sc->vxl_ftable = malloc(sizeof(struct vxlan_ftable_head) * 531 VXLAN_SC_FTABLE_SIZE, M_VXLAN, M_ZERO | M_WAITOK); 532 533 for (i = 0; i < VXLAN_SC_FTABLE_SIZE; i++) 534 LIST_INIT(&sc->vxl_ftable[i]); 535 sc->vxl_ftable_hash_key = arc4random(); 536} 537 538static void 539vxlan_ftable_fini(struct vxlan_softc *sc) 540{ 541 int i; 542 543 for (i = 0; i < VXLAN_SC_FTABLE_SIZE; i++) { 544 KASSERT(LIST_EMPTY(&sc->vxl_ftable[i]), 545 ("%s: vxlan %p ftable[%d] not empty", __func__, sc, i)); 546 } 547 MPASS(sc->vxl_ftable_cnt == 0); 548 549 free(sc->vxl_ftable, M_VXLAN); 550 sc->vxl_ftable = NULL; 551} 552 553static void 554vxlan_ftable_flush(struct vxlan_softc *sc, int all) 555{ 556 struct vxlan_ftable_entry *fe, *tfe; 557 int i; 558 559 for (i = 0; i < VXLAN_SC_FTABLE_SIZE; i++) { 560 LIST_FOREACH_SAFE(fe, &sc->vxl_ftable[i], vxlfe_hash, tfe) { 561 if (all || VXLAN_FE_IS_DYNAMIC(fe)) 562 vxlan_ftable_entry_destroy(sc, fe); 563 } 564 } 565} 566 567static void 568vxlan_ftable_expire(struct vxlan_softc *sc) 569{ 570 struct vxlan_ftable_entry *fe, *tfe; 571 int i; 572 573 VXLAN_LOCK_WASSERT(sc); 574 575 for (i = 0; i < VXLAN_SC_FTABLE_SIZE; i++) { 576 LIST_FOREACH_SAFE(fe, &sc->vxl_ftable[i], vxlfe_hash, tfe) { 577 if (VXLAN_FE_IS_DYNAMIC(fe) && 578 time_uptime >= fe->vxlfe_expire) 579 vxlan_ftable_entry_destroy(sc, fe); 580 } 581 } 582} 583 584static int 585vxlan_ftable_update_locked(struct vxlan_softc *sc, 586 const union vxlan_sockaddr *vxlsa, const uint8_t *mac, 587 struct rm_priotracker *tracker) 588{ 589 struct vxlan_ftable_entry *fe; 590 int error; 591 592 VXLAN_LOCK_ASSERT(sc); 593 594again: 595 /* 596 * A forwarding entry for this MAC address might already exist. If 597 * so, update it, otherwise create a new one. We may have to upgrade 598 * the lock if we have to change or create an entry. 599 */ 600 fe = vxlan_ftable_entry_lookup(sc, mac); 601 if (fe != NULL) { 602 fe->vxlfe_expire = time_uptime + sc->vxl_ftable_timeout; 603 604 if (!VXLAN_FE_IS_DYNAMIC(fe) || 605 vxlan_sockaddr_in_equal(&fe->vxlfe_raddr, &vxlsa->sa)) 606 return (0); 607 if (!VXLAN_LOCK_WOWNED(sc)) { 608 VXLAN_RUNLOCK(sc, tracker); 609 VXLAN_WLOCK(sc); 610 sc->vxl_stats.ftable_lock_upgrade_failed++; 611 goto again; 612 } 613 vxlan_sockaddr_in_copy(&fe->vxlfe_raddr, &vxlsa->sa); 614 return (0); 615 } 616 617 if (!VXLAN_LOCK_WOWNED(sc)) { 618 VXLAN_RUNLOCK(sc, tracker); 619 VXLAN_WLOCK(sc); 620 sc->vxl_stats.ftable_lock_upgrade_failed++; 621 goto again; 622 } 623 624 if (sc->vxl_ftable_cnt >= sc->vxl_ftable_max) { 625 sc->vxl_stats.ftable_nospace++; 626 return (ENOSPC); 627 } 628 629 fe = vxlan_ftable_entry_alloc(); 630 if (fe == NULL) 631 return (ENOMEM); 632 633 vxlan_ftable_entry_init(sc, fe, mac, &vxlsa->sa, VXLAN_FE_FLAG_DYNAMIC); 634 635 /* The prior lookup failed, so the insert should not. */ 636 error = vxlan_ftable_entry_insert(sc, fe); 637 MPASS(error == 0); 638 639 return (0); 640} 641 642static int 643vxlan_ftable_learn(struct vxlan_softc *sc, const struct sockaddr *sa, 644 const uint8_t *mac) 645{ 646 struct rm_priotracker tracker; 647 union vxlan_sockaddr vxlsa; 648 int error; 649 650 /* 651 * The source port may be randomly selected by the remote host, so 652 * use the port of the default destination address. 653 */ 654 vxlan_sockaddr_copy(&vxlsa, sa); 655 vxlsa.in4.sin_port = sc->vxl_dst_addr.in4.sin_port; 656 657 if (VXLAN_SOCKADDR_IS_IPV6(&vxlsa)) { 658 error = vxlan_sockaddr_in6_embedscope(&vxlsa); 659 if (error) 660 return (error); 661 } 662 663 VXLAN_RLOCK(sc, &tracker); 664 error = vxlan_ftable_update_locked(sc, &vxlsa, mac, &tracker); 665 VXLAN_UNLOCK(sc, &tracker); 666 667 return (error); 668} 669 670static int 671vxlan_ftable_sysctl_dump(SYSCTL_HANDLER_ARGS) 672{ 673 struct rm_priotracker tracker; 674 struct sbuf sb; 675 struct vxlan_softc *sc; 676 struct vxlan_ftable_entry *fe; 677 size_t size; 678 int i, error; 679 680 /* 681 * This is mostly intended for debugging during development. It is 682 * not practical to dump an entire large table this way. 683 */ 684 685 sc = arg1; 686 size = PAGE_SIZE; /* Calculate later. */ 687 688 sbuf_new(&sb, NULL, size, SBUF_FIXEDLEN); 689 sbuf_putc(&sb, '\n'); 690 691 VXLAN_RLOCK(sc, &tracker); 692 for (i = 0; i < VXLAN_SC_FTABLE_SIZE; i++) { 693 LIST_FOREACH(fe, &sc->vxl_ftable[i], vxlfe_hash) { 694 if (sbuf_error(&sb) != 0) 695 break; 696 vxlan_ftable_entry_dump(fe, &sb); 697 } 698 } 699 VXLAN_RUNLOCK(sc, &tracker); 700 701 if (sbuf_len(&sb) == 1) 702 sbuf_setpos(&sb, 0); 703 704 sbuf_finish(&sb); 705 error = sysctl_handle_string(oidp, sbuf_data(&sb), sbuf_len(&sb), req); 706 sbuf_delete(&sb); 707 708 return (error); 709} 710 711static struct vxlan_ftable_entry * 712vxlan_ftable_entry_alloc(void) 713{ 714 struct vxlan_ftable_entry *fe; 715 716 fe = malloc(sizeof(*fe), M_VXLAN, M_ZERO | M_NOWAIT); 717 718 return (fe); 719} 720 721static void 722vxlan_ftable_entry_free(struct vxlan_ftable_entry *fe) 723{ 724 725 free(fe, M_VXLAN); 726} 727 728static void 729vxlan_ftable_entry_init(struct vxlan_softc *sc, struct vxlan_ftable_entry *fe, 730 const uint8_t *mac, const struct sockaddr *sa, uint32_t flags) 731{ 732 733 fe->vxlfe_flags = flags; 734 fe->vxlfe_expire = time_uptime + sc->vxl_ftable_timeout; 735 memcpy(fe->vxlfe_mac, mac, ETHER_ADDR_LEN); 736 vxlan_sockaddr_copy(&fe->vxlfe_raddr, sa); 737} 738 739static void 740vxlan_ftable_entry_destroy(struct vxlan_softc *sc, 741 struct vxlan_ftable_entry *fe) 742{ 743 744 sc->vxl_ftable_cnt--; 745 LIST_REMOVE(fe, vxlfe_hash); 746 vxlan_ftable_entry_free(fe); 747} 748 749static int 750vxlan_ftable_entry_insert(struct vxlan_softc *sc, 751 struct vxlan_ftable_entry *fe) 752{ 753 struct vxlan_ftable_entry *lfe; 754 uint32_t hash; 755 int dir; 756 757 VXLAN_LOCK_WASSERT(sc); 758 hash = VXLAN_SC_FTABLE_HASH(sc, fe->vxlfe_mac); 759 760 lfe = LIST_FIRST(&sc->vxl_ftable[hash]); 761 if (lfe == NULL) { 762 LIST_INSERT_HEAD(&sc->vxl_ftable[hash], fe, vxlfe_hash); 763 goto out; 764 } 765 766 do { 767 dir = vxlan_ftable_addr_cmp(fe->vxlfe_mac, lfe->vxlfe_mac); 768 if (dir == 0) 769 return (EEXIST); 770 if (dir > 0) { 771 LIST_INSERT_BEFORE(lfe, fe, vxlfe_hash); 772 goto out; 773 } else if (LIST_NEXT(lfe, vxlfe_hash) == NULL) { 774 LIST_INSERT_AFTER(lfe, fe, vxlfe_hash); 775 goto out; 776 } else 777 lfe = LIST_NEXT(lfe, vxlfe_hash); 778 } while (lfe != NULL); 779 780out: 781 sc->vxl_ftable_cnt++; 782 783 return (0); 784} 785 786static struct vxlan_ftable_entry * 787vxlan_ftable_entry_lookup(struct vxlan_softc *sc, const uint8_t *mac) 788{ 789 struct vxlan_ftable_entry *fe; 790 uint32_t hash; 791 int dir; 792 793 VXLAN_LOCK_ASSERT(sc); 794 hash = VXLAN_SC_FTABLE_HASH(sc, mac); 795 796 LIST_FOREACH(fe, &sc->vxl_ftable[hash], vxlfe_hash) { 797 dir = vxlan_ftable_addr_cmp(mac, fe->vxlfe_mac); 798 if (dir == 0) 799 return (fe); 800 if (dir > 0) 801 break; 802 } 803 804 return (NULL); 805} 806 807static void 808vxlan_ftable_entry_dump(struct vxlan_ftable_entry *fe, struct sbuf *sb) 809{ 810 char buf[64]; 811 const union vxlan_sockaddr *sa; 812 const void *addr; 813 int i, len, af, width; 814 815 sa = &fe->vxlfe_raddr; 816 af = sa->sa.sa_family; 817 len = sbuf_len(sb); 818 819 sbuf_printf(sb, "%c 0x%02X ", VXLAN_FE_IS_DYNAMIC(fe) ? 'D' : 'S', 820 fe->vxlfe_flags); 821 822 for (i = 0; i < ETHER_ADDR_LEN - 1; i++) 823 sbuf_printf(sb, "%02X:", fe->vxlfe_mac[i]); 824 sbuf_printf(sb, "%02X ", fe->vxlfe_mac[i]); 825 826 if (af == AF_INET) { 827 addr = &sa->in4.sin_addr; 828 width = INET_ADDRSTRLEN - 1; 829 } else { 830 addr = &sa->in6.sin6_addr; 831 width = INET6_ADDRSTRLEN - 1; 832 } 833 inet_ntop(af, addr, buf, sizeof(buf)); 834 sbuf_printf(sb, "%*s ", width, buf); 835 836 sbuf_printf(sb, "%08jd", (intmax_t)fe->vxlfe_expire); 837 838 sbuf_putc(sb, '\n'); 839 840 /* Truncate a partial line. */ 841 if (sbuf_error(sb) != 0) 842 sbuf_setpos(sb, len); 843} 844 845static struct vxlan_socket * 846vxlan_socket_alloc(const union vxlan_sockaddr *sa) 847{ 848 struct vxlan_socket *vso; 849 int i; 850 851 vso = malloc(sizeof(*vso), M_VXLAN, M_WAITOK | M_ZERO); 852 rm_init(&vso->vxlso_lock, "vxlansorm"); 853 refcount_init(&vso->vxlso_refcnt, 0); 854 for (i = 0; i < VXLAN_SO_VNI_HASH_SIZE; i++) 855 LIST_INIT(&vso->vxlso_vni_hash[i]); 856 vso->vxlso_laddr = *sa; 857 858 return (vso); 859} 860 861static void 862vxlan_socket_destroy(struct vxlan_socket *vso) 863{ 864 struct socket *so; 865 struct vxlan_socket_mc_info *mc; 866 int i; 867 868 for (i = 0; i < VXLAN_SO_MC_MAX_GROUPS; i++) { 869 mc = &vso->vxlso_mc[i]; 870 KASSERT(mc->vxlsomc_gaddr.sa.sa_family == AF_UNSPEC, 871 ("%s: socket %p mc[%d] still has address", 872 __func__, vso, i)); 873 } 874 875 for (i = 0; i < VXLAN_SO_VNI_HASH_SIZE; i++) { 876 KASSERT(LIST_EMPTY(&vso->vxlso_vni_hash[i]), 877 ("%s: socket %p vni_hash[%d] not empty", 878 __func__, vso, i)); 879 } 880 881 so = vso->vxlso_sock; 882 if (so != NULL) { 883 vso->vxlso_sock = NULL; 884 soclose(so); 885 } 886 887 rm_destroy(&vso->vxlso_lock); 888 free(vso, M_VXLAN); 889} 890 891static void 892vxlan_socket_release(struct vxlan_socket *vso) 893{ 894 int destroy; 895 896 VXLAN_LIST_LOCK(); 897 destroy = VXLAN_SO_RELEASE(vso); 898 if (destroy != 0) 899 LIST_REMOVE(vso, vxlso_entry); 900 VXLAN_LIST_UNLOCK(); 901 902 if (destroy != 0) 903 vxlan_socket_destroy(vso); 904} 905 906static struct vxlan_socket * 907vxlan_socket_lookup(union vxlan_sockaddr *vxlsa) 908{ 909 struct vxlan_socket *vso; 910 911 VXLAN_LIST_LOCK(); 912 LIST_FOREACH(vso, &vxlan_socket_list, vxlso_entry) { 913 if (vxlan_sockaddr_cmp(&vso->vxlso_laddr, &vxlsa->sa) == 0) { 914 VXLAN_SO_ACQUIRE(vso); 915 break; 916 } 917 } 918 VXLAN_LIST_UNLOCK(); 919 920 return (vso); 921} 922 923static void 924vxlan_socket_insert(struct vxlan_socket *vso) 925{ 926 927 VXLAN_LIST_LOCK(); 928 VXLAN_SO_ACQUIRE(vso); 929 LIST_INSERT_HEAD(&vxlan_socket_list, vso, vxlso_entry); 930 VXLAN_LIST_UNLOCK(); 931} 932 933static int 934vxlan_socket_init(struct vxlan_socket *vso, struct ifnet *ifp) 935{ 936 struct thread *td; 937 int error; 938 939 td = curthread; 940 941 error = socreate(vso->vxlso_laddr.sa.sa_family, &vso->vxlso_sock, 942 SOCK_DGRAM, IPPROTO_UDP, td->td_ucred, td); 943 if (error) { 944 if_printf(ifp, "cannot create socket: %d\n", error); 945 return (error); 946 } 947 948 error = udp_set_kernel_tunneling(vso->vxlso_sock, 949 vxlan_rcv_udp_packet, NULL, vso); 950 if (error) { 951 if_printf(ifp, "cannot set tunneling function: %d\n", error); 952 return (error); 953 } 954 955 if (vxlan_reuse_port != 0) { 956 struct sockopt sopt; 957 int val = 1; 958 959 bzero(&sopt, sizeof(sopt)); 960 sopt.sopt_dir = SOPT_SET; 961 sopt.sopt_level = IPPROTO_IP; 962 sopt.sopt_name = SO_REUSEPORT; 963 sopt.sopt_val = &val; 964 sopt.sopt_valsize = sizeof(val); 965 error = sosetopt(vso->vxlso_sock, &sopt); 966 if (error) { 967 if_printf(ifp, 968 "cannot set REUSEADDR socket opt: %d\n", error); 969 return (error); 970 } 971 } 972 973 return (0); 974} 975 976static int 977vxlan_socket_bind(struct vxlan_socket *vso, struct ifnet *ifp) 978{ 979 union vxlan_sockaddr laddr; 980 struct thread *td; 981 int error; 982 983 td = curthread; 984 laddr = vso->vxlso_laddr; 985 986 error = sobind(vso->vxlso_sock, &laddr.sa, td); 987 if (error) { 988 if (error != EADDRINUSE) 989 if_printf(ifp, "cannot bind socket: %d\n", error); 990 return (error); 991 } 992 993 return (0); 994} 995 996static int 997vxlan_socket_create(struct ifnet *ifp, int multicast, 998 const union vxlan_sockaddr *saddr, struct vxlan_socket **vsop) 999{ 1000 union vxlan_sockaddr laddr; 1001 struct vxlan_socket *vso; 1002 int error; 1003 1004 laddr = *saddr; 1005 1006 /* 1007 * If this socket will be multicast, then only the local port 1008 * must be specified when binding. 1009 */ 1010 if (multicast != 0) { 1011 if (VXLAN_SOCKADDR_IS_IPV4(&laddr)) 1012 laddr.in4.sin_addr.s_addr = INADDR_ANY; 1013#ifdef INET6 1014 else 1015 laddr.in6.sin6_addr = in6addr_any; 1016#endif 1017 } 1018 1019 vso = vxlan_socket_alloc(&laddr); 1020 if (vso == NULL) 1021 return (ENOMEM); 1022 1023 error = vxlan_socket_init(vso, ifp); 1024 if (error) 1025 goto fail; 1026 1027 error = vxlan_socket_bind(vso, ifp); 1028 if (error) 1029 goto fail; 1030 1031 /* 1032 * There is a small window between the bind completing and 1033 * inserting the socket, so that a concurrent create may fail. 1034 * Let's not worry about that for now. 1035 */ 1036 vxlan_socket_insert(vso); 1037 *vsop = vso; 1038 1039 return (0); 1040 1041fail: 1042 vxlan_socket_destroy(vso); 1043 1044 return (error); 1045} 1046 1047static void 1048vxlan_socket_ifdetach(struct vxlan_socket *vso, struct ifnet *ifp, 1049 struct vxlan_softc_head *list) 1050{ 1051 struct rm_priotracker tracker; 1052 struct vxlan_softc *sc; 1053 int i; 1054 1055 VXLAN_SO_RLOCK(vso, &tracker); 1056 for (i = 0; i < VXLAN_SO_VNI_HASH_SIZE; i++) { 1057 LIST_FOREACH(sc, &vso->vxlso_vni_hash[i], vxl_entry) 1058 vxlan_ifdetach(sc, ifp, list); 1059 } 1060 VXLAN_SO_RUNLOCK(vso, &tracker); 1061} 1062 1063static struct vxlan_socket * 1064vxlan_socket_mc_lookup(const union vxlan_sockaddr *vxlsa) 1065{ 1066 union vxlan_sockaddr laddr; 1067 struct vxlan_socket *vso; 1068 1069 laddr = *vxlsa; 1070 1071 if (VXLAN_SOCKADDR_IS_IPV4(&laddr)) 1072 laddr.in4.sin_addr.s_addr = INADDR_ANY; 1073#ifdef INET6 1074 else 1075 laddr.in6.sin6_addr = in6addr_any; 1076#endif 1077 1078 vso = vxlan_socket_lookup(&laddr); 1079 1080 return (vso); 1081} 1082 1083static int 1084vxlan_sockaddr_mc_info_match(const struct vxlan_socket_mc_info *mc, 1085 const union vxlan_sockaddr *group, const union vxlan_sockaddr *local, 1086 int ifidx) 1087{ 1088 1089 if (!vxlan_sockaddr_in_any(local) && 1090 !vxlan_sockaddr_in_equal(&mc->vxlsomc_saddr, &local->sa)) 1091 return (0); 1092 if (!vxlan_sockaddr_in_equal(&mc->vxlsomc_gaddr, &group->sa)) 1093 return (0); 1094 if (ifidx != 0 && ifidx != mc->vxlsomc_ifidx) 1095 return (0); 1096 1097 return (1); 1098} 1099 1100static int 1101vxlan_socket_mc_join_group(struct vxlan_socket *vso, 1102 const union vxlan_sockaddr *group, const union vxlan_sockaddr *local, 1103 int *ifidx, union vxlan_sockaddr *source) 1104{ 1105 struct sockopt sopt; 1106 int error; 1107 1108 *source = *local; 1109 1110 if (VXLAN_SOCKADDR_IS_IPV4(group)) { 1111 struct ip_mreq mreq; 1112 1113 mreq.imr_multiaddr = group->in4.sin_addr; 1114 mreq.imr_interface = local->in4.sin_addr; 1115 1116 bzero(&sopt, sizeof(sopt)); 1117 sopt.sopt_dir = SOPT_SET; 1118 sopt.sopt_level = IPPROTO_IP; 1119 sopt.sopt_name = IP_ADD_MEMBERSHIP; 1120 sopt.sopt_val = &mreq; 1121 sopt.sopt_valsize = sizeof(mreq); 1122 error = sosetopt(vso->vxlso_sock, &sopt); 1123 if (error) 1124 return (error); 1125 1126 /* 1127 * BMV: Ideally, there would be a formal way for us to get 1128 * the local interface that was selected based on the 1129 * imr_interface address. We could then update *ifidx so 1130 * vxlan_sockaddr_mc_info_match() would return a match for 1131 * later creates that explicitly set the multicast interface. 1132 * 1133 * If we really need to, we can of course look in the INP's 1134 * membership list: 1135 * sotoinpcb(vso->vxlso_sock)->inp_moptions-> 1136 * imo_membership[]->inm_ifp 1137 * similarly to imo_match_group(). 1138 */ 1139 source->in4.sin_addr = local->in4.sin_addr; 1140 1141 } else if (VXLAN_SOCKADDR_IS_IPV6(group)) { 1142 struct ipv6_mreq mreq; 1143 1144 mreq.ipv6mr_multiaddr = group->in6.sin6_addr; 1145 mreq.ipv6mr_interface = *ifidx; 1146 1147 bzero(&sopt, sizeof(sopt)); 1148 sopt.sopt_dir = SOPT_SET; 1149 sopt.sopt_level = IPPROTO_IPV6; 1150 sopt.sopt_name = IPV6_JOIN_GROUP; 1151 sopt.sopt_val = &mreq; 1152 sopt.sopt_valsize = sizeof(mreq); 1153 error = sosetopt(vso->vxlso_sock, &sopt); 1154 if (error) 1155 return (error); 1156 1157 /* 1158 * BMV: As with IPv4, we would really like to know what 1159 * interface in6p_lookup_mcast_ifp() selected. 1160 */ 1161 } else 1162 error = EAFNOSUPPORT; 1163 1164 return (error); 1165} 1166 1167static int 1168vxlan_socket_mc_leave_group(struct vxlan_socket *vso, 1169 const union vxlan_sockaddr *group, const union vxlan_sockaddr *source, 1170 int ifidx) 1171{ 1172 struct sockopt sopt; 1173 int error; 1174 1175 bzero(&sopt, sizeof(sopt)); 1176 sopt.sopt_dir = SOPT_SET; 1177 1178 if (VXLAN_SOCKADDR_IS_IPV4(group)) { 1179 struct ip_mreq mreq; 1180 1181 mreq.imr_multiaddr = group->in4.sin_addr; 1182 mreq.imr_interface = source->in4.sin_addr; 1183 1184 sopt.sopt_level = IPPROTO_IP; 1185 sopt.sopt_name = IP_DROP_MEMBERSHIP; 1186 sopt.sopt_val = &mreq; 1187 sopt.sopt_valsize = sizeof(mreq); 1188 error = sosetopt(vso->vxlso_sock, &sopt); 1189 1190 } else if (VXLAN_SOCKADDR_IS_IPV6(group)) { 1191 struct ipv6_mreq mreq; 1192 1193 mreq.ipv6mr_multiaddr = group->in6.sin6_addr; 1194 mreq.ipv6mr_interface = ifidx; 1195 1196 sopt.sopt_level = IPPROTO_IPV6; 1197 sopt.sopt_name = IPV6_LEAVE_GROUP; 1198 sopt.sopt_val = &mreq; 1199 sopt.sopt_valsize = sizeof(mreq); 1200 error = sosetopt(vso->vxlso_sock, &sopt); 1201 1202 } else 1203 error = EAFNOSUPPORT; 1204 1205 return (error); 1206} 1207 1208static int 1209vxlan_socket_mc_add_group(struct vxlan_socket *vso, 1210 const union vxlan_sockaddr *group, const union vxlan_sockaddr *local, 1211 int ifidx, int *idx) 1212{ 1213 union vxlan_sockaddr source; 1214 struct vxlan_socket_mc_info *mc; 1215 int i, empty, error; 1216 1217 /* 1218 * Within a socket, the same multicast group may be used by multiple 1219 * interfaces, each with a different network identifier. But a socket 1220 * may only join a multicast group once, so keep track of the users 1221 * here. 1222 */ 1223 1224 VXLAN_SO_WLOCK(vso); 1225 for (empty = 0, i = 0; i < VXLAN_SO_MC_MAX_GROUPS; i++) { 1226 mc = &vso->vxlso_mc[i]; 1227 1228 if (mc->vxlsomc_gaddr.sa.sa_family == AF_UNSPEC) { 1229 empty++; 1230 continue; 1231 } 1232 1233 if (vxlan_sockaddr_mc_info_match(mc, group, local, ifidx)) 1234 goto out; 1235 } 1236 VXLAN_SO_WUNLOCK(vso); 1237 1238 if (empty == 0) 1239 return (ENOSPC); 1240 1241 error = vxlan_socket_mc_join_group(vso, group, local, &ifidx, &source); 1242 if (error) 1243 return (error); 1244 1245 VXLAN_SO_WLOCK(vso); 1246 for (i = 0; i < VXLAN_SO_MC_MAX_GROUPS; i++) { 1247 mc = &vso->vxlso_mc[i]; 1248 1249 if (mc->vxlsomc_gaddr.sa.sa_family == AF_UNSPEC) { 1250 vxlan_sockaddr_copy(&mc->vxlsomc_gaddr, &group->sa); 1251 vxlan_sockaddr_copy(&mc->vxlsomc_saddr, &source.sa); 1252 mc->vxlsomc_ifidx = ifidx; 1253 goto out; 1254 } 1255 } 1256 VXLAN_SO_WUNLOCK(vso); 1257 1258 error = vxlan_socket_mc_leave_group(vso, group, &source, ifidx); 1259 MPASS(error == 0); 1260 1261 return (ENOSPC); 1262 1263out: 1264 mc->vxlsomc_users++; 1265 VXLAN_SO_WUNLOCK(vso); 1266 1267 *idx = i; 1268 1269 return (0); 1270} 1271 1272static void 1273vxlan_socket_mc_release_group_by_idx(struct vxlan_socket *vso, int idx) 1274{ 1275 union vxlan_sockaddr group, source; 1276 struct vxlan_socket_mc_info *mc; 1277 int ifidx, leave; 1278 1279 KASSERT(idx >= 0 && idx < VXLAN_SO_MC_MAX_GROUPS, 1280 ("%s: vso %p idx %d out of bounds", __func__, vso, idx)); 1281 1282 leave = 0; 1283 mc = &vso->vxlso_mc[idx]; 1284 1285 VXLAN_SO_WLOCK(vso); 1286 mc->vxlsomc_users--; 1287 if (mc->vxlsomc_users == 0) { 1288 group = mc->vxlsomc_gaddr; 1289 source = mc->vxlsomc_saddr; 1290 ifidx = mc->vxlsomc_ifidx; 1291 bzero(mc, sizeof(*mc)); 1292 leave = 1; 1293 } 1294 VXLAN_SO_WUNLOCK(vso); 1295 1296 if (leave != 0) { 1297 /* 1298 * Our socket's membership in this group may have already 1299 * been removed if we joined through an interface that's 1300 * been detached. 1301 */ 1302 vxlan_socket_mc_leave_group(vso, &group, &source, ifidx); 1303 } 1304} 1305 1306static struct vxlan_softc * 1307vxlan_socket_lookup_softc_locked(struct vxlan_socket *vso, uint32_t vni) 1308{ 1309 struct vxlan_softc *sc; 1310 uint32_t hash; 1311 1312 VXLAN_SO_LOCK_ASSERT(vso); 1313 hash = VXLAN_SO_VNI_HASH(vni); 1314 1315 LIST_FOREACH(sc, &vso->vxlso_vni_hash[hash], vxl_entry) { 1316 if (sc->vxl_vni == vni) { 1317 VXLAN_ACQUIRE(sc); 1318 break; 1319 } 1320 } 1321 1322 return (sc); 1323} 1324 1325static struct vxlan_softc * 1326vxlan_socket_lookup_softc(struct vxlan_socket *vso, uint32_t vni) 1327{ 1328 struct rm_priotracker tracker; 1329 struct vxlan_softc *sc; 1330 1331 VXLAN_SO_RLOCK(vso, &tracker); 1332 sc = vxlan_socket_lookup_softc_locked(vso, vni); 1333 VXLAN_SO_RUNLOCK(vso, &tracker); 1334 1335 return (sc); 1336} 1337 1338static int 1339vxlan_socket_insert_softc(struct vxlan_socket *vso, struct vxlan_softc *sc) 1340{ 1341 struct vxlan_softc *tsc; 1342 uint32_t vni, hash; 1343 1344 vni = sc->vxl_vni; 1345 hash = VXLAN_SO_VNI_HASH(vni); 1346 1347 VXLAN_SO_WLOCK(vso); 1348 tsc = vxlan_socket_lookup_softc_locked(vso, vni); 1349 if (tsc != NULL) { 1350 VXLAN_SO_WUNLOCK(vso); 1351 vxlan_release(tsc); 1352 return (EEXIST); 1353 } 1354 1355 VXLAN_ACQUIRE(sc); 1356 LIST_INSERT_HEAD(&vso->vxlso_vni_hash[hash], sc, vxl_entry); 1357 VXLAN_SO_WUNLOCK(vso); 1358 1359 return (0); 1360} 1361 1362static void 1363vxlan_socket_remove_softc(struct vxlan_socket *vso, struct vxlan_softc *sc) 1364{ 1365 1366 VXLAN_SO_WLOCK(vso); 1367 LIST_REMOVE(sc, vxl_entry); 1368 VXLAN_SO_WUNLOCK(vso); 1369 1370 vxlan_release(sc); 1371} 1372 1373static struct ifnet * 1374vxlan_multicast_if_ref(struct vxlan_softc *sc, int ipv4) 1375{ 1376 struct ifnet *ifp; 1377 1378 VXLAN_LOCK_ASSERT(sc); 1379 1380 if (ipv4 && sc->vxl_im4o != NULL) 1381 ifp = sc->vxl_im4o->imo_multicast_ifp; 1382 else if (!ipv4 && sc->vxl_im6o != NULL) 1383 ifp = sc->vxl_im6o->im6o_multicast_ifp; 1384 else 1385 ifp = NULL; 1386 1387 if (ifp != NULL) 1388 if_ref(ifp); 1389 1390 return (ifp); 1391} 1392 1393static void 1394vxlan_free_multicast(struct vxlan_softc *sc) 1395{ 1396 1397 if (sc->vxl_mc_ifp != NULL) { 1398 if_rele(sc->vxl_mc_ifp); 1399 sc->vxl_mc_ifp = NULL; 1400 sc->vxl_mc_ifindex = 0; 1401 } 1402 1403 if (sc->vxl_im4o != NULL) { 1404 free(sc->vxl_im4o, M_VXLAN); 1405 sc->vxl_im4o = NULL; 1406 } 1407 1408 if (sc->vxl_im6o != NULL) { 1409 free(sc->vxl_im6o, M_VXLAN); 1410 sc->vxl_im6o = NULL; 1411 } 1412} 1413 1414static int 1415vxlan_setup_multicast_interface(struct vxlan_softc *sc) 1416{ 1417 struct ifnet *ifp; 1418 1419 ifp = ifunit_ref(sc->vxl_mc_ifname); 1420 if (ifp == NULL) { 1421 if_printf(sc->vxl_ifp, "multicast interface %s does " 1422 "not exist\n", sc->vxl_mc_ifname); 1423 return (ENOENT); 1424 } 1425 1426 if ((ifp->if_flags & IFF_MULTICAST) == 0) { 1427 if_printf(sc->vxl_ifp, "interface %s does not support " 1428 "multicast\n", sc->vxl_mc_ifname); 1429 if_rele(ifp); 1430 return (ENOTSUP); 1431 } 1432 1433 sc->vxl_mc_ifp = ifp; 1434 sc->vxl_mc_ifindex = ifp->if_index; 1435 1436 return (0); 1437} 1438 1439static int 1440vxlan_setup_multicast(struct vxlan_softc *sc) 1441{ 1442 const union vxlan_sockaddr *group; 1443 int error; 1444 1445 group = &sc->vxl_dst_addr; 1446 error = 0; 1447 1448 if (sc->vxl_mc_ifname[0] != '\0') { 1449 error = vxlan_setup_multicast_interface(sc); 1450 if (error) 1451 return (error); 1452 } 1453 1454 /* 1455 * Initialize an multicast options structure that is sufficiently 1456 * populated for use in the respective IP output routine. This 1457 * structure is typically stored in the socket, but our sockets 1458 * may be shared among multiple interfaces. 1459 */ 1460 if (VXLAN_SOCKADDR_IS_IPV4(group)) { 1461 sc->vxl_im4o = malloc(sizeof(struct ip_moptions), M_VXLAN, 1462 M_ZERO | M_WAITOK); 1463 sc->vxl_im4o->imo_multicast_ifp = sc->vxl_mc_ifp; 1464 sc->vxl_im4o->imo_multicast_ttl = sc->vxl_ttl; 1465 sc->vxl_im4o->imo_multicast_vif = -1; 1466 } else if (VXLAN_SOCKADDR_IS_IPV6(group)) { 1467 sc->vxl_im6o = malloc(sizeof(struct ip6_moptions), M_VXLAN, 1468 M_ZERO | M_WAITOK); 1469 sc->vxl_im6o->im6o_multicast_ifp = sc->vxl_mc_ifp; 1470 sc->vxl_im6o->im6o_multicast_hlim = sc->vxl_ttl; 1471 } 1472 1473 return (error); 1474} 1475 1476static int 1477vxlan_setup_socket(struct vxlan_softc *sc) 1478{ 1479 struct vxlan_socket *vso; 1480 struct ifnet *ifp; 1481 union vxlan_sockaddr *saddr, *daddr; 1482 int multicast, error; 1483 1484 vso = NULL; 1485 ifp = sc->vxl_ifp; 1486 saddr = &sc->vxl_src_addr; 1487 daddr = &sc->vxl_dst_addr; 1488 1489 multicast = vxlan_sockaddr_in_multicast(daddr); 1490 MPASS(multicast != -1); 1491 sc->vxl_vso_mc_index = -1; 1492 1493 /* 1494 * Try to create the socket. If that fails, attempt to use an 1495 * existing socket. 1496 */ 1497 error = vxlan_socket_create(ifp, multicast, saddr, &vso); 1498 if (error) { 1499 if (multicast != 0) 1500 vso = vxlan_socket_mc_lookup(saddr); 1501 else 1502 vso = vxlan_socket_lookup(saddr); 1503 1504 if (vso == NULL) { 1505 if_printf(ifp, "cannot create socket (error: %d), " 1506 "and no existing socket found\n", error); 1507 goto out; 1508 } 1509 } 1510 1511 if (multicast != 0) { 1512 error = vxlan_setup_multicast(sc); 1513 if (error) 1514 goto out; 1515 1516 error = vxlan_socket_mc_add_group(vso, daddr, saddr, 1517 sc->vxl_mc_ifindex, &sc->vxl_vso_mc_index); 1518 if (error) 1519 goto out; 1520 } 1521 1522 sc->vxl_sock = vso; 1523 error = vxlan_socket_insert_softc(vso, sc); 1524 if (error) { 1525 sc->vxl_sock = NULL; 1526 if_printf(ifp, "network identifier %d already exists in " 1527 "this socket\n", sc->vxl_vni); 1528 goto out; 1529 } 1530 1531 return (0); 1532 1533out: 1534 if (vso != NULL) { 1535 if (sc->vxl_vso_mc_index != -1) { 1536 vxlan_socket_mc_release_group_by_idx(vso, 1537 sc->vxl_vso_mc_index); 1538 sc->vxl_vso_mc_index = -1; 1539 } 1540 if (multicast != 0) 1541 vxlan_free_multicast(sc); 1542 vxlan_socket_release(vso); 1543 } 1544 1545 return (error); 1546} 1547 1548static void 1549vxlan_setup_interface(struct vxlan_softc *sc) 1550{ 1551 struct ifnet *ifp; 1552 1553 ifp = sc->vxl_ifp; 1554 ifp->if_hdrlen = ETHER_HDR_LEN + sizeof(struct vxlanudphdr); 1555 1556 if (VXLAN_SOCKADDR_IS_IPV4(&sc->vxl_dst_addr) != 0) 1557 ifp->if_hdrlen += sizeof(struct ip); 1558 else if (VXLAN_SOCKADDR_IS_IPV6(&sc->vxl_dst_addr) != 0) 1559 ifp->if_hdrlen += sizeof(struct ip6_hdr); 1560} 1561 1562static int 1563vxlan_valid_init_config(struct vxlan_softc *sc) 1564{ 1565 const char *reason; 1566 1567 if (vxlan_check_vni(sc->vxl_vni) != 0) { 1568 reason = "invalid virtual network identifier specified"; 1569 goto fail; 1570 } 1571 1572 if (vxlan_sockaddr_supported(&sc->vxl_src_addr, 1) == 0) { 1573 reason = "source address type is not supported"; 1574 goto fail; 1575 } 1576 1577 if (vxlan_sockaddr_supported(&sc->vxl_dst_addr, 0) == 0) { 1578 reason = "destination address type is not supported"; 1579 goto fail; 1580 } 1581 1582 if (vxlan_sockaddr_in_any(&sc->vxl_dst_addr) != 0) { 1583 reason = "no valid destination address specified"; 1584 goto fail; 1585 } 1586 1587 if (vxlan_sockaddr_in_multicast(&sc->vxl_dst_addr) == 0 && 1588 sc->vxl_mc_ifname[0] != '\0') { 1589 reason = "can only specify interface with a group address"; 1590 goto fail; 1591 } 1592 1593 if (vxlan_sockaddr_in_any(&sc->vxl_src_addr) == 0) { 1594 if (VXLAN_SOCKADDR_IS_IPV4(&sc->vxl_src_addr) ^ 1595 VXLAN_SOCKADDR_IS_IPV4(&sc->vxl_dst_addr)) { 1596 reason = "source and destination address must both " 1597 "be either IPv4 or IPv6"; 1598 goto fail; 1599 } 1600 } 1601 1602 if (sc->vxl_src_addr.in4.sin_port == 0) { 1603 reason = "local port not specified"; 1604 goto fail; 1605 } 1606 1607 if (sc->vxl_dst_addr.in4.sin_port == 0) { 1608 reason = "remote port not specified"; 1609 goto fail; 1610 } 1611 1612 return (0); 1613 1614fail: 1615 if_printf(sc->vxl_ifp, "cannot initialize interface: %s\n", reason); 1616 return (EINVAL); 1617} 1618 1619static void 1620vxlan_init_wait(struct vxlan_softc *sc) 1621{ 1622 1623 VXLAN_LOCK_WASSERT(sc); 1624 while (sc->vxl_flags & VXLAN_FLAG_INIT) 1625 rm_sleep(sc, &sc->vxl_lock, 0, "vxlint", hz); 1626} 1627 1628static void 1629vxlan_init_complete(struct vxlan_softc *sc) 1630{ 1631 1632 VXLAN_WLOCK(sc); 1633 sc->vxl_flags &= ~VXLAN_FLAG_INIT; 1634 wakeup(sc); 1635 VXLAN_WUNLOCK(sc); 1636} 1637 1638static void 1639vxlan_init(void *xsc) 1640{ 1641 static const uint8_t empty_mac[ETHER_ADDR_LEN]; 1642 struct vxlan_softc *sc; 1643 struct ifnet *ifp; 1644 1645 sc = xsc; 1646 ifp = sc->vxl_ifp; 1647 1648 VXLAN_WLOCK(sc); 1649 if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 1650 VXLAN_WUNLOCK(sc); 1651 return; 1652 } 1653 sc->vxl_flags |= VXLAN_FLAG_INIT; 1654 VXLAN_WUNLOCK(sc); 1655 1656 if (vxlan_valid_init_config(sc) != 0) 1657 goto out; 1658 1659 vxlan_setup_interface(sc); 1660 1661 if (vxlan_setup_socket(sc) != 0) 1662 goto out; 1663 1664 /* Initialize the default forwarding entry. */ 1665 vxlan_ftable_entry_init(sc, &sc->vxl_default_fe, empty_mac, 1666 &sc->vxl_dst_addr.sa, VXLAN_FE_FLAG_STATIC); 1667 1668 VXLAN_WLOCK(sc); 1669 ifp->if_drv_flags |= IFF_DRV_RUNNING; 1670 callout_reset(&sc->vxl_callout, vxlan_ftable_prune_period * hz, 1671 vxlan_timer, sc); 1672 VXLAN_WUNLOCK(sc); 1673 1674 if_link_state_change(ifp, LINK_STATE_UP); 1675out: 1676 vxlan_init_complete(sc); 1677} 1678 1679static void 1680vxlan_release(struct vxlan_softc *sc) 1681{ 1682 1683 /* 1684 * The softc may be destroyed as soon as we release our reference, 1685 * so we cannot serialize the wakeup with the softc lock. We use a 1686 * timeout in our sleeps so a missed wakeup is unfortunate but not 1687 * fatal. 1688 */ 1689 if (VXLAN_RELEASE(sc) != 0) 1690 wakeup(sc); 1691} 1692 1693static void 1694vxlan_teardown_wait(struct vxlan_softc *sc) 1695{ 1696 1697 VXLAN_LOCK_WASSERT(sc); 1698 while (sc->vxl_flags & VXLAN_FLAG_TEARDOWN) 1699 rm_sleep(sc, &sc->vxl_lock, 0, "vxltrn", hz); 1700} 1701 1702static void 1703vxlan_teardown_complete(struct vxlan_softc *sc) 1704{ 1705 1706 VXLAN_WLOCK(sc); 1707 sc->vxl_flags &= ~VXLAN_FLAG_TEARDOWN; 1708 wakeup(sc); 1709 VXLAN_WUNLOCK(sc); 1710} 1711 1712static void 1713vxlan_teardown_locked(struct vxlan_softc *sc) 1714{ 1715 struct ifnet *ifp; 1716 struct vxlan_socket *vso; 1717 1718 ifp = sc->vxl_ifp; 1719 1720 VXLAN_LOCK_WASSERT(sc); 1721 MPASS(sc->vxl_flags & VXLAN_FLAG_TEARDOWN); 1722 1723 ifp->if_flags &= ~IFF_UP; 1724 ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1725 callout_stop(&sc->vxl_callout); 1726 vso = sc->vxl_sock; 1727 sc->vxl_sock = NULL; 1728 1729 VXLAN_WUNLOCK(sc); 1730 if_link_state_change(ifp, LINK_STATE_DOWN); 1731 1732 if (vso != NULL) { 1733 vxlan_socket_remove_softc(vso, sc); 1734 1735 if (sc->vxl_vso_mc_index != -1) { 1736 vxlan_socket_mc_release_group_by_idx(vso, 1737 sc->vxl_vso_mc_index); 1738 sc->vxl_vso_mc_index = -1; 1739 } 1740 } 1741 1742 VXLAN_WLOCK(sc); 1743 while (sc->vxl_refcnt != 0) 1744 rm_sleep(sc, &sc->vxl_lock, 0, "vxldrn", hz); 1745 VXLAN_WUNLOCK(sc); 1746 1747 callout_drain(&sc->vxl_callout); 1748 1749 vxlan_free_multicast(sc); 1750 if (vso != NULL) 1751 vxlan_socket_release(vso); 1752 1753 vxlan_teardown_complete(sc); 1754} 1755 1756static void 1757vxlan_teardown(struct vxlan_softc *sc) 1758{ 1759 1760 VXLAN_WLOCK(sc); 1761 if (sc->vxl_flags & VXLAN_FLAG_TEARDOWN) { 1762 vxlan_teardown_wait(sc); 1763 VXLAN_WUNLOCK(sc); 1764 return; 1765 } 1766 1767 sc->vxl_flags |= VXLAN_FLAG_TEARDOWN; 1768 vxlan_teardown_locked(sc); 1769} 1770 1771static void 1772vxlan_ifdetach(struct vxlan_softc *sc, struct ifnet *ifp, 1773 struct vxlan_softc_head *list) 1774{ 1775 1776 VXLAN_WLOCK(sc); 1777 1778 if (sc->vxl_mc_ifp != ifp) 1779 goto out; 1780 if (sc->vxl_flags & VXLAN_FLAG_TEARDOWN) 1781 goto out; 1782 1783 sc->vxl_flags |= VXLAN_FLAG_TEARDOWN; 1784 LIST_INSERT_HEAD(list, sc, vxl_ifdetach_list); 1785 1786out: 1787 VXLAN_WUNLOCK(sc); 1788} 1789 1790static void 1791vxlan_timer(void *xsc) 1792{ 1793 struct vxlan_softc *sc; 1794 1795 sc = xsc; 1796 VXLAN_LOCK_WASSERT(sc); 1797 1798 vxlan_ftable_expire(sc); 1799 callout_schedule(&sc->vxl_callout, vxlan_ftable_prune_period * hz); 1800} 1801 1802static int 1803vxlan_ioctl_ifflags(struct vxlan_softc *sc) 1804{ 1805 struct ifnet *ifp; 1806 1807 ifp = sc->vxl_ifp; 1808 1809 if (ifp->if_flags & IFF_UP) { 1810 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 1811 vxlan_init(sc); 1812 } else { 1813 if (ifp->if_drv_flags & IFF_DRV_RUNNING) 1814 vxlan_teardown(sc); 1815 } 1816 1817 return (0); 1818} 1819 1820static int 1821vxlan_ctrl_get_config(struct vxlan_softc *sc, void *arg) 1822{ 1823 struct rm_priotracker tracker; 1824 struct ifvxlancfg *cfg; 1825 1826 cfg = arg; 1827 bzero(cfg, sizeof(*cfg)); 1828 1829 VXLAN_RLOCK(sc, &tracker); 1830 cfg->vxlc_vni = sc->vxl_vni; 1831 memcpy(&cfg->vxlc_local_sa, &sc->vxl_src_addr, 1832 sizeof(union vxlan_sockaddr)); 1833 memcpy(&cfg->vxlc_remote_sa, &sc->vxl_dst_addr, 1834 sizeof(union vxlan_sockaddr)); 1835 cfg->vxlc_mc_ifindex = sc->vxl_mc_ifindex; 1836 cfg->vxlc_ftable_cnt = sc->vxl_ftable_cnt; 1837 cfg->vxlc_ftable_max = sc->vxl_ftable_max; 1838 cfg->vxlc_ftable_timeout = sc->vxl_ftable_timeout; 1839 cfg->vxlc_port_min = sc->vxl_min_port; 1840 cfg->vxlc_port_max = sc->vxl_max_port; 1841 cfg->vxlc_learn = (sc->vxl_flags & VXLAN_FLAG_LEARN) != 0; 1842 cfg->vxlc_ttl = sc->vxl_ttl; 1843 VXLAN_RUNLOCK(sc, &tracker); 1844 1845#ifdef INET6 1846 if (VXLAN_SOCKADDR_IS_IPV6(&cfg->vxlc_local_sa)) 1847 sa6_recoverscope(&cfg->vxlc_local_sa.in6); 1848 if (VXLAN_SOCKADDR_IS_IPV6(&cfg->vxlc_remote_sa)) 1849 sa6_recoverscope(&cfg->vxlc_remote_sa.in6); 1850#endif 1851 1852 return (0); 1853} 1854 1855static int 1856vxlan_ctrl_set_vni(struct vxlan_softc *sc, void *arg) 1857{ 1858 struct ifvxlancmd *cmd; 1859 int error; 1860 1861 cmd = arg; 1862 1863 if (vxlan_check_vni(cmd->vxlcmd_vni) != 0) 1864 return (EINVAL); 1865 1866 VXLAN_WLOCK(sc); 1867 if (vxlan_can_change_config(sc)) { 1868 sc->vxl_vni = cmd->vxlcmd_vni; 1869 error = 0; 1870 } else 1871 error = EBUSY; 1872 VXLAN_WUNLOCK(sc); 1873 1874 return (error); 1875} 1876 1877static int 1878vxlan_ctrl_set_local_addr(struct vxlan_softc *sc, void *arg) 1879{ 1880 struct ifvxlancmd *cmd; 1881 union vxlan_sockaddr *vxlsa; 1882 int error; 1883 1884 cmd = arg; 1885 vxlsa = &cmd->vxlcmd_sa; 1886 1887 if (!VXLAN_SOCKADDR_IS_IPV46(vxlsa)) 1888 return (EINVAL); 1889 if (vxlan_sockaddr_in_multicast(vxlsa) != 0) 1890 return (EINVAL); 1891 if (VXLAN_SOCKADDR_IS_IPV6(vxlsa)) { 1892 error = vxlan_sockaddr_in6_embedscope(vxlsa); 1893 if (error) 1894 return (error); 1895 } 1896 1897 VXLAN_WLOCK(sc); 1898 if (vxlan_can_change_config(sc)) { 1899 vxlan_sockaddr_in_copy(&sc->vxl_src_addr, &vxlsa->sa); 1900 error = 0; 1901 } else 1902 error = EBUSY; 1903 VXLAN_WUNLOCK(sc); 1904 1905 return (error); 1906} 1907 1908static int 1909vxlan_ctrl_set_remote_addr(struct vxlan_softc *sc, void *arg) 1910{ 1911 struct ifvxlancmd *cmd; 1912 union vxlan_sockaddr *vxlsa; 1913 int error; 1914 1915 cmd = arg; 1916 vxlsa = &cmd->vxlcmd_sa; 1917 1918 if (!VXLAN_SOCKADDR_IS_IPV46(vxlsa)) 1919 return (EINVAL); 1920 if (VXLAN_SOCKADDR_IS_IPV6(vxlsa)) { 1921 error = vxlan_sockaddr_in6_embedscope(vxlsa); 1922 if (error) 1923 return (error); 1924 } 1925 1926 VXLAN_WLOCK(sc); 1927 if (vxlan_can_change_config(sc)) { 1928 vxlan_sockaddr_in_copy(&sc->vxl_dst_addr, &vxlsa->sa); 1929 error = 0; 1930 } else 1931 error = EBUSY; 1932 VXLAN_WUNLOCK(sc); 1933 1934 return (error); 1935} 1936 1937static int 1938vxlan_ctrl_set_local_port(struct vxlan_softc *sc, void *arg) 1939{ 1940 struct ifvxlancmd *cmd; 1941 int error; 1942 1943 cmd = arg; 1944 1945 if (cmd->vxlcmd_port == 0) 1946 return (EINVAL); 1947 1948 VXLAN_WLOCK(sc); 1949 if (vxlan_can_change_config(sc)) { 1950 sc->vxl_src_addr.in4.sin_port = htons(cmd->vxlcmd_port); 1951 error = 0; 1952 } else 1953 error = EBUSY; 1954 VXLAN_WUNLOCK(sc); 1955 1956 return (error); 1957} 1958 1959static int 1960vxlan_ctrl_set_remote_port(struct vxlan_softc *sc, void *arg) 1961{ 1962 struct ifvxlancmd *cmd; 1963 int error; 1964 1965 cmd = arg; 1966 1967 if (cmd->vxlcmd_port == 0) 1968 return (EINVAL); 1969 1970 VXLAN_WLOCK(sc); 1971 if (vxlan_can_change_config(sc)) { 1972 sc->vxl_dst_addr.in4.sin_port = htons(cmd->vxlcmd_port); 1973 error = 0; 1974 } else 1975 error = EBUSY; 1976 VXLAN_WUNLOCK(sc); 1977 1978 return (error); 1979} 1980 1981static int 1982vxlan_ctrl_set_port_range(struct vxlan_softc *sc, void *arg) 1983{ 1984 struct ifvxlancmd *cmd; 1985 uint16_t min, max; 1986 int error; 1987 1988 cmd = arg; 1989 min = cmd->vxlcmd_port_min; 1990 max = cmd->vxlcmd_port_max; 1991 1992 if (max < min) 1993 return (EINVAL); 1994 1995 VXLAN_WLOCK(sc); 1996 if (vxlan_can_change_config(sc)) { 1997 sc->vxl_min_port = min; 1998 sc->vxl_max_port = max; 1999 error = 0; 2000 } else 2001 error = EBUSY; 2002 VXLAN_WUNLOCK(sc); 2003 2004 return (error); 2005} 2006 2007static int 2008vxlan_ctrl_set_ftable_timeout(struct vxlan_softc *sc, void *arg) 2009{ 2010 struct ifvxlancmd *cmd; 2011 int error; 2012 2013 cmd = arg; 2014 2015 VXLAN_WLOCK(sc); 2016 if (vxlan_check_ftable_timeout(cmd->vxlcmd_ftable_timeout) == 0) { 2017 sc->vxl_ftable_timeout = cmd->vxlcmd_ftable_timeout; 2018 error = 0; 2019 } else 2020 error = EINVAL; 2021 VXLAN_WUNLOCK(sc); 2022 2023 return (error); 2024} 2025 2026static int 2027vxlan_ctrl_set_ftable_max(struct vxlan_softc *sc, void *arg) 2028{ 2029 struct ifvxlancmd *cmd; 2030 int error; 2031 2032 cmd = arg; 2033 2034 VXLAN_WLOCK(sc); 2035 if (vxlan_check_ftable_max(cmd->vxlcmd_ftable_max) == 0) { 2036 sc->vxl_ftable_max = cmd->vxlcmd_ftable_max; 2037 error = 0; 2038 } else 2039 error = EINVAL; 2040 VXLAN_WUNLOCK(sc); 2041 2042 return (error); 2043} 2044 2045static int 2046vxlan_ctrl_set_multicast_if(struct vxlan_softc * sc, void *arg) 2047{ 2048 struct ifvxlancmd *cmd; 2049 int error; 2050 2051 cmd = arg; 2052 2053 VXLAN_WLOCK(sc); 2054 if (vxlan_can_change_config(sc)) { 2055 strlcpy(sc->vxl_mc_ifname, cmd->vxlcmd_ifname, IFNAMSIZ); 2056 error = 0; 2057 } else 2058 error = EBUSY; 2059 VXLAN_WUNLOCK(sc); 2060 2061 return (error); 2062} 2063 2064static int 2065vxlan_ctrl_set_ttl(struct vxlan_softc *sc, void *arg) 2066{ 2067 struct ifvxlancmd *cmd; 2068 int error; 2069 2070 cmd = arg; 2071 2072 VXLAN_WLOCK(sc); 2073 if (vxlan_check_ttl(cmd->vxlcmd_ttl) == 0) { 2074 sc->vxl_ttl = cmd->vxlcmd_ttl; 2075 if (sc->vxl_im4o != NULL) 2076 sc->vxl_im4o->imo_multicast_ttl = sc->vxl_ttl; 2077 if (sc->vxl_im6o != NULL) 2078 sc->vxl_im6o->im6o_multicast_hlim = sc->vxl_ttl; 2079 error = 0; 2080 } else 2081 error = EINVAL; 2082 VXLAN_WUNLOCK(sc); 2083 2084 return (error); 2085} 2086 2087static int 2088vxlan_ctrl_set_learn(struct vxlan_softc *sc, void *arg) 2089{ 2090 struct ifvxlancmd *cmd; 2091 2092 cmd = arg; 2093 2094 VXLAN_WLOCK(sc); 2095 if (cmd->vxlcmd_flags & VXLAN_CMD_FLAG_LEARN) 2096 sc->vxl_flags |= VXLAN_FLAG_LEARN; 2097 else 2098 sc->vxl_flags &= ~VXLAN_FLAG_LEARN; 2099 VXLAN_WUNLOCK(sc); 2100 2101 return (0); 2102} 2103 2104static int 2105vxlan_ctrl_ftable_entry_add(struct vxlan_softc *sc, void *arg) 2106{ 2107 union vxlan_sockaddr vxlsa; 2108 struct ifvxlancmd *cmd; 2109 struct vxlan_ftable_entry *fe; 2110 int error; 2111 2112 cmd = arg; 2113 vxlsa = cmd->vxlcmd_sa; 2114 2115 if (!VXLAN_SOCKADDR_IS_IPV46(&vxlsa)) 2116 return (EINVAL); 2117 if (vxlan_sockaddr_in_any(&vxlsa) != 0) 2118 return (EINVAL); 2119 if (vxlan_sockaddr_in_multicast(&vxlsa) != 0) 2120 return (EINVAL); 2121 /* BMV: We could support both IPv4 and IPv6 later. */ 2122 if (vxlsa.sa.sa_family != sc->vxl_dst_addr.sa.sa_family) 2123 return (EAFNOSUPPORT); 2124 2125 if (VXLAN_SOCKADDR_IS_IPV6(&vxlsa)) { 2126 error = vxlan_sockaddr_in6_embedscope(&vxlsa); 2127 if (error) 2128 return (error); 2129 } 2130 2131 fe = vxlan_ftable_entry_alloc(); 2132 if (fe == NULL) 2133 return (ENOMEM); 2134 2135 if (vxlsa.in4.sin_port == 0) 2136 vxlsa.in4.sin_port = sc->vxl_dst_addr.in4.sin_port; 2137 2138 vxlan_ftable_entry_init(sc, fe, cmd->vxlcmd_mac, &vxlsa.sa, 2139 VXLAN_FE_FLAG_STATIC); 2140 2141 VXLAN_WLOCK(sc); 2142 error = vxlan_ftable_entry_insert(sc, fe); 2143 VXLAN_WUNLOCK(sc); 2144 2145 if (error) 2146 vxlan_ftable_entry_free(fe); 2147 2148 return (error); 2149} 2150 2151static int 2152vxlan_ctrl_ftable_entry_rem(struct vxlan_softc *sc, void *arg) 2153{ 2154 struct ifvxlancmd *cmd; 2155 struct vxlan_ftable_entry *fe; 2156 int error; 2157 2158 cmd = arg; 2159 2160 VXLAN_WLOCK(sc); 2161 fe = vxlan_ftable_entry_lookup(sc, cmd->vxlcmd_mac); 2162 if (fe != NULL) { 2163 vxlan_ftable_entry_destroy(sc, fe); 2164 error = 0; 2165 } else 2166 error = ENOENT; 2167 VXLAN_WUNLOCK(sc); 2168 2169 return (error); 2170} 2171 2172static int 2173vxlan_ctrl_flush(struct vxlan_softc *sc, void *arg) 2174{ 2175 struct ifvxlancmd *cmd; 2176 int all; 2177 2178 cmd = arg; 2179 all = cmd->vxlcmd_flags & VXLAN_CMD_FLAG_FLUSH_ALL; 2180 2181 VXLAN_WLOCK(sc); 2182 vxlan_ftable_flush(sc, all); 2183 VXLAN_WUNLOCK(sc); 2184 2185 return (0); 2186} 2187 2188static int 2189vxlan_ioctl_drvspec(struct vxlan_softc *sc, struct ifdrv *ifd, int get) 2190{ 2191 const struct vxlan_control *vc; 2192 union { 2193 struct ifvxlancfg cfg; 2194 struct ifvxlancmd cmd; 2195 } args; 2196 int out, error; 2197 2198 if (ifd->ifd_cmd >= vxlan_control_table_size) 2199 return (EINVAL); 2200 2201 bzero(&args, sizeof(args)); 2202 vc = &vxlan_control_table[ifd->ifd_cmd]; 2203 out = (vc->vxlc_flags & VXLAN_CTRL_FLAG_COPYOUT) != 0; 2204 2205 if ((get != 0 && out == 0) || (get == 0 && out != 0)) 2206 return (EINVAL); 2207 2208 if (vc->vxlc_flags & VXLAN_CTRL_FLAG_SUSER) { 2209 error = priv_check(curthread, PRIV_NET_VXLAN); 2210 if (error) 2211 return (error); 2212 } 2213 2214 if (ifd->ifd_len != vc->vxlc_argsize || 2215 ifd->ifd_len > sizeof(args)) 2216 return (EINVAL); 2217 2218 if (vc->vxlc_flags & VXLAN_CTRL_FLAG_COPYIN) { 2219 error = copyin(ifd->ifd_data, &args, ifd->ifd_len); 2220 if (error) 2221 return (error); 2222 } 2223 2224 error = vc->vxlc_func(sc, &args); 2225 if (error) 2226 return (error); 2227 2228 if (vc->vxlc_flags & VXLAN_CTRL_FLAG_COPYOUT) { 2229 error = copyout(&args, ifd->ifd_data, ifd->ifd_len); 2230 if (error) 2231 return (error); 2232 } 2233 2234 return (0); 2235} 2236 2237static int 2238vxlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 2239{ 2240 struct vxlan_softc *sc; 2241 struct ifreq *ifr; 2242 struct ifdrv *ifd; 2243 int error; 2244 2245 sc = ifp->if_softc; 2246 ifr = (struct ifreq *) data; 2247 ifd = (struct ifdrv *) data; 2248 2249 switch (cmd) { 2250 case SIOCADDMULTI: 2251 case SIOCDELMULTI: 2252 error = 0; 2253 break; 2254 2255 case SIOCGDRVSPEC: 2256 case SIOCSDRVSPEC: 2257 error = vxlan_ioctl_drvspec(sc, ifd, cmd == SIOCGDRVSPEC); 2258 break; 2259 2260 case SIOCSIFFLAGS: 2261 error = vxlan_ioctl_ifflags(sc); 2262 break; 2263 2264 case SIOCSIFMEDIA: 2265 case SIOCGIFMEDIA: 2266 error = ifmedia_ioctl(ifp, ifr, &sc->vxl_media, cmd); 2267 break; 2268 2269 default: 2270 error = ether_ioctl(ifp, cmd, data); 2271 break; 2272 } 2273 2274 return (error); 2275} 2276 2277#if defined(INET) || defined(INET6) 2278static uint16_t 2279vxlan_pick_source_port(struct vxlan_softc *sc, struct mbuf *m) 2280{ 2281 int range; 2282 uint32_t hash; 2283 2284 range = sc->vxl_max_port - sc->vxl_min_port + 1; 2285 2286 if (M_HASHTYPE_ISHASH(m)) 2287 hash = m->m_pkthdr.flowid; 2288 else 2289 hash = jenkins_hash(m->m_data, ETHER_HDR_LEN, 2290 sc->vxl_port_hash_key); 2291 2292 return (sc->vxl_min_port + (hash % range)); 2293} 2294 2295static void 2296vxlan_encap_header(struct vxlan_softc *sc, struct mbuf *m, int ipoff, 2297 uint16_t srcport, uint16_t dstport) 2298{ 2299 struct vxlanudphdr *hdr; 2300 struct udphdr *udph; 2301 struct vxlan_header *vxh; 2302 int len; 2303 2304 len = m->m_pkthdr.len - ipoff; 2305 MPASS(len >= sizeof(struct vxlanudphdr)); 2306 hdr = mtodo(m, ipoff); 2307 2308 udph = &hdr->vxlh_udp; 2309 udph->uh_sport = srcport; 2310 udph->uh_dport = dstport; 2311 udph->uh_ulen = htons(len); 2312 udph->uh_sum = 0; 2313 2314 vxh = &hdr->vxlh_hdr; 2315 vxh->vxlh_flags = htonl(VXLAN_HDR_FLAGS_VALID_VNI); 2316 vxh->vxlh_vni = htonl(sc->vxl_vni << VXLAN_HDR_VNI_SHIFT); 2317} 2318#endif 2319 2320static int 2321vxlan_encap4(struct vxlan_softc *sc, const union vxlan_sockaddr *fvxlsa, 2322 struct mbuf *m) 2323{ 2324#ifdef INET 2325 struct ifnet *ifp; 2326 struct ip *ip; 2327 struct in_addr srcaddr, dstaddr; 2328 uint16_t srcport, dstport; 2329 int len, mcast, error; 2330 2331 ifp = sc->vxl_ifp; 2332 srcaddr = sc->vxl_src_addr.in4.sin_addr; 2333 srcport = vxlan_pick_source_port(sc, m); 2334 dstaddr = fvxlsa->in4.sin_addr; 2335 dstport = fvxlsa->in4.sin_port; 2336 2337 M_PREPEND(m, sizeof(struct ip) + sizeof(struct vxlanudphdr), 2338 M_NOWAIT); 2339 if (m == NULL) { 2340 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 2341 return (ENOBUFS); 2342 } 2343 2344 len = m->m_pkthdr.len; 2345 2346 ip = mtod(m, struct ip *); 2347 ip->ip_tos = 0; 2348 ip->ip_len = htons(len); 2349 ip->ip_off = 0; 2350 ip->ip_ttl = sc->vxl_ttl; 2351 ip->ip_p = IPPROTO_UDP; 2352 ip->ip_sum = 0; 2353 ip->ip_src = srcaddr; 2354 ip->ip_dst = dstaddr; 2355 2356 vxlan_encap_header(sc, m, sizeof(struct ip), srcport, dstport); 2357 2358 mcast = (m->m_flags & (M_MCAST | M_BCAST)) ? 1 : 0; 2359 m->m_flags &= ~(M_MCAST | M_BCAST); 2360 2361 error = ip_output(m, NULL, NULL, 0, sc->vxl_im4o, NULL); 2362 if (error == 0) { 2363 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 2364 if_inc_counter(ifp, IFCOUNTER_OBYTES, len); 2365 if (mcast != 0) 2366 if_inc_counter(ifp, IFCOUNTER_OMCASTS, 1); 2367 } else 2368 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 2369 2370 return (error); 2371#else 2372 m_freem(m); 2373 return (ENOTSUP); 2374#endif 2375} 2376 2377static int 2378vxlan_encap6(struct vxlan_softc *sc, const union vxlan_sockaddr *fvxlsa, 2379 struct mbuf *m) 2380{ 2381#ifdef INET6 2382 struct ifnet *ifp; 2383 struct ip6_hdr *ip6; 2384 const struct in6_addr *srcaddr, *dstaddr; 2385 uint16_t srcport, dstport; 2386 int len, mcast, error; 2387 2388 ifp = sc->vxl_ifp; 2389 srcaddr = &sc->vxl_src_addr.in6.sin6_addr; 2390 srcport = vxlan_pick_source_port(sc, m); 2391 dstaddr = &fvxlsa->in6.sin6_addr; 2392 dstport = fvxlsa->in6.sin6_port; 2393 2394 M_PREPEND(m, sizeof(struct ip6_hdr) + sizeof(struct vxlanudphdr), 2395 M_NOWAIT); 2396 if (m == NULL) { 2397 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 2398 return (ENOBUFS); 2399 } 2400 2401 len = m->m_pkthdr.len; 2402 2403 ip6 = mtod(m, struct ip6_hdr *); 2404 ip6->ip6_flow = 0; /* BMV: Keep in forwarding entry? */ 2405 ip6->ip6_vfc = IPV6_VERSION; 2406 ip6->ip6_plen = 0; 2407 ip6->ip6_nxt = IPPROTO_UDP; 2408 ip6->ip6_hlim = sc->vxl_ttl; 2409 ip6->ip6_src = *srcaddr; 2410 ip6->ip6_dst = *dstaddr; 2411 2412 vxlan_encap_header(sc, m, sizeof(struct ip6_hdr), srcport, dstport); 2413 2414 /* 2415 * XXX BMV We need support for RFC6935 before we can send and 2416 * receive IPv6 UDP packets with a zero checksum. 2417 */ 2418 { 2419 struct udphdr *hdr = mtodo(m, sizeof(struct ip6_hdr)); 2420 hdr->uh_sum = in6_cksum_pseudo(ip6, 2421 m->m_pkthdr.len - sizeof(struct ip6_hdr), IPPROTO_UDP, 0); 2422 m->m_pkthdr.csum_flags = CSUM_UDP_IPV6; 2423 m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum); 2424 } 2425 2426 mcast = (m->m_flags & (M_MCAST | M_BCAST)) ? 1 : 0; 2427 m->m_flags &= ~(M_MCAST | M_BCAST); 2428 2429 error = ip6_output(m, NULL, NULL, 0, sc->vxl_im6o, NULL, NULL); 2430 if (error == 0) { 2431 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 2432 if_inc_counter(ifp, IFCOUNTER_OBYTES, len); 2433 if (mcast != 0) 2434 if_inc_counter(ifp, IFCOUNTER_OMCASTS, 1); 2435 } else 2436 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 2437 2438 return (error); 2439#else 2440 m_freem(m); 2441 return (ENOTSUP); 2442#endif 2443} 2444 2445static int 2446vxlan_transmit(struct ifnet *ifp, struct mbuf *m) 2447{ 2448 struct rm_priotracker tracker; 2449 union vxlan_sockaddr vxlsa; 2450 struct vxlan_softc *sc; 2451 struct vxlan_ftable_entry *fe; 2452 struct ifnet *mcifp; 2453 struct ether_header *eh; 2454 int ipv4, error; 2455 2456 sc = ifp->if_softc; 2457 eh = mtod(m, struct ether_header *); 2458 fe = NULL; 2459 mcifp = NULL; 2460 2461 ETHER_BPF_MTAP(ifp, m); 2462 2463 VXLAN_RLOCK(sc, &tracker); 2464 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { 2465 VXLAN_RUNLOCK(sc, &tracker); 2466 m_freem(m); 2467 return (ENETDOWN); 2468 } 2469 2470 if ((m->m_flags & (M_BCAST | M_MCAST)) == 0) 2471 fe = vxlan_ftable_entry_lookup(sc, eh->ether_dhost); 2472 if (fe == NULL) 2473 fe = &sc->vxl_default_fe; 2474 vxlan_sockaddr_copy(&vxlsa, &fe->vxlfe_raddr.sa); 2475 2476 ipv4 = VXLAN_SOCKADDR_IS_IPV4(&vxlsa) != 0; 2477 if (vxlan_sockaddr_in_multicast(&vxlsa) != 0) 2478 mcifp = vxlan_multicast_if_ref(sc, ipv4); 2479 2480 VXLAN_ACQUIRE(sc); 2481 VXLAN_RUNLOCK(sc, &tracker); 2482 2483 if (ipv4 != 0) 2484 error = vxlan_encap4(sc, &vxlsa, m); 2485 else 2486 error = vxlan_encap6(sc, &vxlsa, m); 2487 2488 vxlan_release(sc); 2489 if (mcifp != NULL) 2490 if_rele(mcifp); 2491 2492 return (error); 2493} 2494 2495static void 2496vxlan_qflush(struct ifnet *ifp __unused) 2497{ 2498} 2499 2500static void 2501vxlan_rcv_udp_packet(struct mbuf *m, int offset, struct inpcb *inpcb, 2502 const struct sockaddr *srcsa, void *xvso) 2503{ 2504 struct vxlan_socket *vso; 2505 struct vxlan_header *vxh, vxlanhdr; 2506 uint32_t vni; 2507 int error; 2508 2509 M_ASSERTPKTHDR(m); 2510 vso = xvso; 2511 offset += sizeof(struct udphdr); 2512 2513 if (m->m_pkthdr.len < offset + sizeof(struct vxlan_header)) 2514 goto out; 2515 2516 if (__predict_false(m->m_len < offset + sizeof(struct vxlan_header))) { 2517 m_copydata(m, offset, sizeof(struct vxlan_header), 2518 (caddr_t) &vxlanhdr); 2519 vxh = &vxlanhdr; 2520 } else 2521 vxh = mtodo(m, offset); 2522 2523 /* 2524 * Drop if there is a reserved bit set in either the flags or VNI 2525 * fields of the header. This goes against the specification, but 2526 * a bit set may indicate an unsupported new feature. This matches 2527 * the behavior of the Linux implementation. 2528 */ 2529 if (vxh->vxlh_flags != htonl(VXLAN_HDR_FLAGS_VALID_VNI) || 2530 vxh->vxlh_vni & ~htonl(VXLAN_VNI_MASK)) 2531 goto out; 2532 2533 vni = ntohl(vxh->vxlh_vni) >> VXLAN_HDR_VNI_SHIFT; 2534 /* Adjust to the start of the inner Ethernet frame. */ 2535 m_adj(m, offset + sizeof(struct vxlan_header)); 2536 2537 error = vxlan_input(vso, vni, &m, srcsa); 2538 MPASS(error != 0 || m == NULL); 2539 2540out: 2541 if (m != NULL) 2542 m_freem(m); 2543} 2544 2545static int 2546vxlan_input(struct vxlan_socket *vso, uint32_t vni, struct mbuf **m0, 2547 const struct sockaddr *sa) 2548{ 2549 struct vxlan_softc *sc; 2550 struct ifnet *ifp; 2551 struct mbuf *m; 2552 struct ether_header *eh; 2553 int error; 2554 2555 sc = vxlan_socket_lookup_softc(vso, vni); 2556 if (sc == NULL) 2557 return (ENOENT); 2558 2559 ifp = sc->vxl_ifp; 2560 m = *m0; 2561 eh = mtod(m, struct ether_header *); 2562 2563 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { 2564 error = ENETDOWN; 2565 goto out; 2566 } else if (ifp == m->m_pkthdr.rcvif) { 2567 /* XXX Does not catch more complex loops. */ 2568 error = EDEADLK; 2569 goto out; 2570 } 2571 2572 if (sc->vxl_flags & VXLAN_FLAG_LEARN) 2573 vxlan_ftable_learn(sc, sa, eh->ether_shost); 2574 2575 m_clrprotoflags(m); 2576 m->m_pkthdr.rcvif = ifp; 2577 M_SETFIB(m, ifp->if_fib); 2578 2579 error = netisr_queue_src(NETISR_ETHER, 0, m); 2580 *m0 = NULL; 2581 2582out: 2583 vxlan_release(sc); 2584 return (error); 2585} 2586 2587static void 2588vxlan_set_default_config(struct vxlan_softc *sc) 2589{ 2590 2591 sc->vxl_flags |= VXLAN_FLAG_LEARN; 2592 2593 sc->vxl_vni = VXLAN_VNI_MAX; 2594 sc->vxl_ttl = IPDEFTTL; 2595 2596 if (!vxlan_tunable_int(sc, "legacy_port", vxlan_legacy_port)) { 2597 sc->vxl_src_addr.in4.sin_port = htons(VXLAN_PORT); 2598 sc->vxl_dst_addr.in4.sin_port = htons(VXLAN_PORT); 2599 } else { 2600 sc->vxl_src_addr.in4.sin_port = htons(VXLAN_LEGACY_PORT); 2601 sc->vxl_dst_addr.in4.sin_port = htons(VXLAN_LEGACY_PORT); 2602 } 2603 2604 sc->vxl_min_port = V_ipport_firstauto; 2605 sc->vxl_max_port = V_ipport_lastauto; 2606 2607 sc->vxl_ftable_max = VXLAN_FTABLE_MAX; 2608 sc->vxl_ftable_timeout = VXLAN_FTABLE_TIMEOUT; 2609} 2610 2611static int 2612vxlan_set_user_config(struct vxlan_softc *sc, struct ifvxlanparam *vxlp) 2613{ 2614 2615#ifndef INET 2616 if (vxlp->vxlp_with & (VXLAN_PARAM_WITH_LOCAL_ADDR4 | 2617 VXLAN_PARAM_WITH_REMOTE_ADDR4)) 2618 return (EAFNOSUPPORT); 2619#endif 2620 2621#ifndef INET6 2622 if (vxlp->vxlp_with & (VXLAN_PARAM_WITH_LOCAL_ADDR6 | 2623 VXLAN_PARAM_WITH_REMOTE_ADDR6)) 2624 return (EAFNOSUPPORT); 2625#else 2626 if (vxlp->vxlp_with & VXLAN_PARAM_WITH_LOCAL_ADDR6) { 2627 int error = vxlan_sockaddr_in6_embedscope(&vxlp->vxlp_local_sa); 2628 if (error) 2629 return (error); 2630 } 2631 if (vxlp->vxlp_with & VXLAN_PARAM_WITH_REMOTE_ADDR6) { 2632 int error = vxlan_sockaddr_in6_embedscope( 2633 &vxlp->vxlp_remote_sa); 2634 if (error) 2635 return (error); 2636 } 2637#endif 2638 2639 if (vxlp->vxlp_with & VXLAN_PARAM_WITH_VNI) { 2640 if (vxlan_check_vni(vxlp->vxlp_vni) == 0) 2641 sc->vxl_vni = vxlp->vxlp_vni; 2642 } 2643 2644 if (vxlp->vxlp_with & VXLAN_PARAM_WITH_LOCAL_ADDR4) { 2645 sc->vxl_src_addr.in4.sin_len = sizeof(struct sockaddr_in); 2646 sc->vxl_src_addr.in4.sin_family = AF_INET; 2647 sc->vxl_src_addr.in4.sin_addr = 2648 vxlp->vxlp_local_sa.in4.sin_addr; 2649 } else if (vxlp->vxlp_with & VXLAN_PARAM_WITH_LOCAL_ADDR6) { 2650 sc->vxl_src_addr.in6.sin6_len = sizeof(struct sockaddr_in6); 2651 sc->vxl_src_addr.in6.sin6_family = AF_INET6; 2652 sc->vxl_src_addr.in6.sin6_addr = 2653 vxlp->vxlp_local_sa.in6.sin6_addr; 2654 } 2655 2656 if (vxlp->vxlp_with & VXLAN_PARAM_WITH_REMOTE_ADDR4) { 2657 sc->vxl_dst_addr.in4.sin_len = sizeof(struct sockaddr_in); 2658 sc->vxl_dst_addr.in4.sin_family = AF_INET; 2659 sc->vxl_dst_addr.in4.sin_addr = 2660 vxlp->vxlp_remote_sa.in4.sin_addr; 2661 } else if (vxlp->vxlp_with & VXLAN_PARAM_WITH_REMOTE_ADDR6) { 2662 sc->vxl_dst_addr.in6.sin6_len = sizeof(struct sockaddr_in6); 2663 sc->vxl_dst_addr.in6.sin6_family = AF_INET6; 2664 sc->vxl_dst_addr.in6.sin6_addr = 2665 vxlp->vxlp_remote_sa.in6.sin6_addr; 2666 } 2667 2668 if (vxlp->vxlp_with & VXLAN_PARAM_WITH_LOCAL_PORT) 2669 sc->vxl_src_addr.in4.sin_port = htons(vxlp->vxlp_local_port); 2670 if (vxlp->vxlp_with & VXLAN_PARAM_WITH_REMOTE_PORT) 2671 sc->vxl_dst_addr.in4.sin_port = htons(vxlp->vxlp_remote_port); 2672 2673 if (vxlp->vxlp_with & VXLAN_PARAM_WITH_PORT_RANGE) { 2674 if (vxlp->vxlp_min_port <= vxlp->vxlp_max_port) { 2675 sc->vxl_min_port = vxlp->vxlp_min_port; 2676 sc->vxl_max_port = vxlp->vxlp_max_port; 2677 } 2678 } 2679 2680 if (vxlp->vxlp_with & VXLAN_PARAM_WITH_MULTICAST_IF) 2681 strlcpy(sc->vxl_mc_ifname, vxlp->vxlp_mc_ifname, IFNAMSIZ); 2682 2683 if (vxlp->vxlp_with & VXLAN_PARAM_WITH_FTABLE_TIMEOUT) { 2684 if (vxlan_check_ftable_timeout(vxlp->vxlp_ftable_timeout) == 0) 2685 sc->vxl_ftable_timeout = vxlp->vxlp_ftable_timeout; 2686 } 2687 2688 if (vxlp->vxlp_with & VXLAN_PARAM_WITH_FTABLE_MAX) { 2689 if (vxlan_check_ftable_max(vxlp->vxlp_ftable_max) == 0) 2690 sc->vxl_ftable_max = vxlp->vxlp_ftable_max; 2691 } 2692 2693 if (vxlp->vxlp_with & VXLAN_PARAM_WITH_TTL) { 2694 if (vxlan_check_ttl(vxlp->vxlp_ttl) == 0) 2695 sc->vxl_ttl = vxlp->vxlp_ttl; 2696 } 2697 2698 if (vxlp->vxlp_with & VXLAN_PARAM_WITH_LEARN) { 2699 if (vxlp->vxlp_learn == 0) 2700 sc->vxl_flags &= ~VXLAN_FLAG_LEARN; 2701 } 2702 2703 return (0); 2704} 2705 2706static int 2707vxlan_clone_create(struct if_clone *ifc, int unit, caddr_t params) 2708{ 2709 struct vxlan_softc *sc; 2710 struct ifnet *ifp; 2711 struct ifvxlanparam vxlp; 2712 int error; 2713 2714 sc = malloc(sizeof(struct vxlan_softc), M_VXLAN, M_WAITOK | M_ZERO); 2715 sc->vxl_unit = unit; 2716 vxlan_set_default_config(sc); 2717 2718 if (params != 0) { 2719 error = copyin(params, &vxlp, sizeof(vxlp)); 2720 if (error) 2721 goto fail; 2722 2723 error = vxlan_set_user_config(sc, &vxlp); 2724 if (error) 2725 goto fail; 2726 } 2727 2728 ifp = if_alloc(IFT_ETHER); 2729 if (ifp == NULL) { 2730 error = ENOSPC; 2731 goto fail; 2732 } 2733 2734 sc->vxl_ifp = ifp; 2735 rm_init(&sc->vxl_lock, "vxlanrm"); 2736 callout_init_rw(&sc->vxl_callout, &sc->vxl_lock, 0); 2737 sc->vxl_port_hash_key = arc4random(); 2738 vxlan_ftable_init(sc); 2739 2740 vxlan_sysctl_setup(sc); 2741 2742 ifp->if_softc = sc; 2743 if_initname(ifp, vxlan_name, unit); 2744 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 2745 ifp->if_init = vxlan_init; 2746 ifp->if_ioctl = vxlan_ioctl; 2747 ifp->if_transmit = vxlan_transmit; 2748 ifp->if_qflush = vxlan_qflush; 2749 ifp->if_capabilities |= IFCAP_LINKSTATE; 2750 ifp->if_capenable |= IFCAP_LINKSTATE; 2751 2752 ifmedia_init(&sc->vxl_media, 0, vxlan_media_change, vxlan_media_status); 2753 ifmedia_add(&sc->vxl_media, IFM_ETHER | IFM_AUTO, 0, NULL); 2754 ifmedia_set(&sc->vxl_media, IFM_ETHER | IFM_AUTO); 2755 2756 ether_gen_addr(ifp, &sc->vxl_hwaddr); 2757 ether_ifattach(ifp, sc->vxl_hwaddr.octet); 2758 2759 ifp->if_baudrate = 0; 2760 ifp->if_hdrlen = 0; 2761 2762 return (0); 2763 2764fail: 2765 free(sc, M_VXLAN); 2766 return (error); 2767} 2768 2769static void 2770vxlan_clone_destroy(struct ifnet *ifp) 2771{ 2772 struct vxlan_softc *sc; 2773 2774 sc = ifp->if_softc; 2775 2776 vxlan_teardown(sc); 2777 2778 vxlan_ftable_flush(sc, 1); 2779 2780 ether_ifdetach(ifp); 2781 if_free(ifp); 2782 ifmedia_removeall(&sc->vxl_media); 2783 2784 vxlan_ftable_fini(sc); 2785 2786 vxlan_sysctl_destroy(sc); 2787 rm_destroy(&sc->vxl_lock); 2788 free(sc, M_VXLAN); 2789} 2790 2791/* BMV: Taken from if_bridge. */ 2792static uint32_t 2793vxlan_mac_hash(struct vxlan_softc *sc, const uint8_t *addr) 2794{ 2795 uint32_t a = 0x9e3779b9, b = 0x9e3779b9, c = sc->vxl_ftable_hash_key; 2796 2797 b += addr[5] << 8; 2798 b += addr[4]; 2799 a += addr[3] << 24; 2800 a += addr[2] << 16; 2801 a += addr[1] << 8; 2802 a += addr[0]; 2803 2804/* 2805 * The following hash function is adapted from "Hash Functions" by Bob Jenkins 2806 * ("Algorithm Alley", Dr. Dobbs Journal, September 1997). 2807 */ 2808#define mix(a, b, c) \ 2809do { \ 2810 a -= b; a -= c; a ^= (c >> 13); \ 2811 b -= c; b -= a; b ^= (a << 8); \ 2812 c -= a; c -= b; c ^= (b >> 13); \ 2813 a -= b; a -= c; a ^= (c >> 12); \ 2814 b -= c; b -= a; b ^= (a << 16); \ 2815 c -= a; c -= b; c ^= (b >> 5); \ 2816 a -= b; a -= c; a ^= (c >> 3); \ 2817 b -= c; b -= a; b ^= (a << 10); \ 2818 c -= a; c -= b; c ^= (b >> 15); \ 2819} while (0) 2820 2821 mix(a, b, c); 2822 2823#undef mix 2824 2825 return (c); 2826} 2827 2828static int 2829vxlan_media_change(struct ifnet *ifp) 2830{ 2831 2832 /* Ignore. */ 2833 return (0); 2834} 2835 2836static void 2837vxlan_media_status(struct ifnet *ifp, struct ifmediareq *ifmr) 2838{ 2839 2840 ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID; 2841 ifmr->ifm_active = IFM_ETHER | IFM_FDX; 2842} 2843 2844static int 2845vxlan_sockaddr_cmp(const union vxlan_sockaddr *vxladdr, 2846 const struct sockaddr *sa) 2847{ 2848 2849 return (bcmp(&vxladdr->sa, sa, vxladdr->sa.sa_len)); 2850} 2851 2852static void 2853vxlan_sockaddr_copy(union vxlan_sockaddr *vxladdr, 2854 const struct sockaddr *sa) 2855{ 2856 2857 MPASS(sa->sa_family == AF_INET || sa->sa_family == AF_INET6); 2858 bzero(vxladdr, sizeof(*vxladdr)); 2859 2860 if (sa->sa_family == AF_INET) { 2861 vxladdr->in4 = *satoconstsin(sa); 2862 vxladdr->in4.sin_len = sizeof(struct sockaddr_in); 2863 } else if (sa->sa_family == AF_INET6) { 2864 vxladdr->in6 = *satoconstsin6(sa); 2865 vxladdr->in6.sin6_len = sizeof(struct sockaddr_in6); 2866 } 2867} 2868 2869static int 2870vxlan_sockaddr_in_equal(const union vxlan_sockaddr *vxladdr, 2871 const struct sockaddr *sa) 2872{ 2873 int equal; 2874 2875 if (sa->sa_family == AF_INET) { 2876 const struct in_addr *in4 = &satoconstsin(sa)->sin_addr; 2877 equal = in4->s_addr == vxladdr->in4.sin_addr.s_addr; 2878 } else if (sa->sa_family == AF_INET6) { 2879 const struct in6_addr *in6 = &satoconstsin6(sa)->sin6_addr; 2880 equal = IN6_ARE_ADDR_EQUAL(in6, &vxladdr->in6.sin6_addr); 2881 } else 2882 equal = 0; 2883 2884 return (equal); 2885} 2886 2887static void 2888vxlan_sockaddr_in_copy(union vxlan_sockaddr *vxladdr, 2889 const struct sockaddr *sa) 2890{ 2891 2892 MPASS(sa->sa_family == AF_INET || sa->sa_family == AF_INET6); 2893 2894 if (sa->sa_family == AF_INET) { 2895 const struct in_addr *in4 = &satoconstsin(sa)->sin_addr; 2896 vxladdr->in4.sin_family = AF_INET; 2897 vxladdr->in4.sin_len = sizeof(struct sockaddr_in); 2898 vxladdr->in4.sin_addr = *in4; 2899 } else if (sa->sa_family == AF_INET6) { 2900 const struct in6_addr *in6 = &satoconstsin6(sa)->sin6_addr; 2901 vxladdr->in6.sin6_family = AF_INET6; 2902 vxladdr->in6.sin6_len = sizeof(struct sockaddr_in6); 2903 vxladdr->in6.sin6_addr = *in6; 2904 } 2905} 2906 2907static int 2908vxlan_sockaddr_supported(const union vxlan_sockaddr *vxladdr, int unspec) 2909{ 2910 const struct sockaddr *sa; 2911 int supported; 2912 2913 sa = &vxladdr->sa; 2914 supported = 0; 2915 2916 if (sa->sa_family == AF_UNSPEC && unspec != 0) { 2917 supported = 1; 2918 } else if (sa->sa_family == AF_INET) { 2919#ifdef INET 2920 supported = 1; 2921#endif 2922 } else if (sa->sa_family == AF_INET6) { 2923#ifdef INET6 2924 supported = 1; 2925#endif 2926 } 2927 2928 return (supported); 2929} 2930 2931static int 2932vxlan_sockaddr_in_any(const union vxlan_sockaddr *vxladdr) 2933{ 2934 const struct sockaddr *sa; 2935 int any; 2936 2937 sa = &vxladdr->sa; 2938 2939 if (sa->sa_family == AF_INET) { 2940 const struct in_addr *in4 = &satoconstsin(sa)->sin_addr; 2941 any = in4->s_addr == INADDR_ANY; 2942 } else if (sa->sa_family == AF_INET6) { 2943 const struct in6_addr *in6 = &satoconstsin6(sa)->sin6_addr; 2944 any = IN6_IS_ADDR_UNSPECIFIED(in6); 2945 } else 2946 any = -1; 2947 2948 return (any); 2949} 2950 2951static int 2952vxlan_sockaddr_in_multicast(const union vxlan_sockaddr *vxladdr) 2953{ 2954 const struct sockaddr *sa; 2955 int mc; 2956 2957 sa = &vxladdr->sa; 2958 2959 if (sa->sa_family == AF_INET) { 2960 const struct in_addr *in4 = &satoconstsin(sa)->sin_addr; 2961 mc = IN_MULTICAST(ntohl(in4->s_addr)); 2962 } else if (sa->sa_family == AF_INET6) { 2963 const struct in6_addr *in6 = &satoconstsin6(sa)->sin6_addr; 2964 mc = IN6_IS_ADDR_MULTICAST(in6); 2965 } else 2966 mc = -1; 2967 2968 return (mc); 2969} 2970 2971static int 2972vxlan_sockaddr_in6_embedscope(union vxlan_sockaddr *vxladdr) 2973{ 2974 int error; 2975 2976 MPASS(VXLAN_SOCKADDR_IS_IPV6(vxladdr)); 2977#ifdef INET6 2978 error = sa6_embedscope(&vxladdr->in6, V_ip6_use_defzone); 2979#else 2980 error = EAFNOSUPPORT; 2981#endif 2982 2983 return (error); 2984} 2985 2986static int 2987vxlan_can_change_config(struct vxlan_softc *sc) 2988{ 2989 struct ifnet *ifp; 2990 2991 ifp = sc->vxl_ifp; 2992 VXLAN_LOCK_ASSERT(sc); 2993 2994 if (ifp->if_drv_flags & IFF_DRV_RUNNING) 2995 return (0); 2996 if (sc->vxl_flags & (VXLAN_FLAG_INIT | VXLAN_FLAG_TEARDOWN)) 2997 return (0); 2998 2999 return (1); 3000} 3001 3002static int 3003vxlan_check_vni(uint32_t vni) 3004{ 3005 3006 return (vni >= VXLAN_VNI_MAX); 3007} 3008 3009static int 3010vxlan_check_ttl(int ttl) 3011{ 3012 3013 return (ttl > MAXTTL); 3014} 3015 3016static int 3017vxlan_check_ftable_timeout(uint32_t timeout) 3018{ 3019 3020 return (timeout > VXLAN_FTABLE_MAX_TIMEOUT); 3021} 3022 3023static int 3024vxlan_check_ftable_max(uint32_t max) 3025{ 3026 3027 return (max > VXLAN_FTABLE_MAX); 3028} 3029 3030static void 3031vxlan_sysctl_setup(struct vxlan_softc *sc) 3032{ 3033 struct sysctl_ctx_list *ctx; 3034 struct sysctl_oid *node; 3035 struct vxlan_statistics *stats; 3036 char namebuf[8]; 3037 3038 ctx = &sc->vxl_sysctl_ctx; 3039 stats = &sc->vxl_stats; 3040 snprintf(namebuf, sizeof(namebuf), "%d", sc->vxl_unit); 3041 3042 sysctl_ctx_init(ctx); 3043 sc->vxl_sysctl_node = SYSCTL_ADD_NODE(ctx, 3044 SYSCTL_STATIC_CHILDREN(_net_link_vxlan), OID_AUTO, namebuf, 3045 CTLFLAG_RD, NULL, ""); 3046 3047 node = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(sc->vxl_sysctl_node), 3048 OID_AUTO, "ftable", CTLFLAG_RD, NULL, ""); 3049 SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(node), OID_AUTO, "count", 3050 CTLFLAG_RD, &sc->vxl_ftable_cnt, 0, 3051 "Number of entries in fowarding table"); 3052 SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(node), OID_AUTO, "max", 3053 CTLFLAG_RD, &sc->vxl_ftable_max, 0, 3054 "Maximum number of entries allowed in fowarding table"); 3055 SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(node), OID_AUTO, "timeout", 3056 CTLFLAG_RD, &sc->vxl_ftable_timeout, 0, 3057 "Number of seconds between prunes of the forwarding table"); 3058 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(node), OID_AUTO, "dump", 3059 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE | CTLFLAG_SKIP, 3060 sc, 0, vxlan_ftable_sysctl_dump, "A", 3061 "Dump the forwarding table entries"); 3062 3063 node = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(sc->vxl_sysctl_node), 3064 OID_AUTO, "stats", CTLFLAG_RD, NULL, ""); 3065 SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(node), OID_AUTO, 3066 "ftable_nospace", CTLFLAG_RD, &stats->ftable_nospace, 0, 3067 "Fowarding table reached maximum entries"); 3068 SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(node), OID_AUTO, 3069 "ftable_lock_upgrade_failed", CTLFLAG_RD, 3070 &stats->ftable_lock_upgrade_failed, 0, 3071 "Forwarding table update required lock upgrade"); 3072} 3073 3074static void 3075vxlan_sysctl_destroy(struct vxlan_softc *sc) 3076{ 3077 3078 sysctl_ctx_free(&sc->vxl_sysctl_ctx); 3079 sc->vxl_sysctl_node = NULL; 3080} 3081 3082static int 3083vxlan_tunable_int(struct vxlan_softc *sc, const char *knob, int def) 3084{ 3085 char path[64]; 3086 3087 snprintf(path, sizeof(path), "net.link.vxlan.%d.%s", 3088 sc->vxl_unit, knob); 3089 TUNABLE_INT_FETCH(path, &def); 3090 3091 return (def); 3092} 3093 3094static void 3095vxlan_ifdetach_event(void *arg __unused, struct ifnet *ifp) 3096{ 3097 struct vxlan_softc_head list; 3098 struct vxlan_socket *vso; 3099 struct vxlan_softc *sc, *tsc; 3100 3101 LIST_INIT(&list); 3102 3103 if (ifp->if_flags & IFF_RENAMING) 3104 return; 3105 if ((ifp->if_flags & IFF_MULTICAST) == 0) 3106 return; 3107 3108 VXLAN_LIST_LOCK(); 3109 LIST_FOREACH(vso, &vxlan_socket_list, vxlso_entry) 3110 vxlan_socket_ifdetach(vso, ifp, &list); 3111 VXLAN_LIST_UNLOCK(); 3112 3113 LIST_FOREACH_SAFE(sc, &list, vxl_ifdetach_list, tsc) { 3114 LIST_REMOVE(sc, vxl_ifdetach_list); 3115 3116 VXLAN_WLOCK(sc); 3117 if (sc->vxl_flags & VXLAN_FLAG_INIT) 3118 vxlan_init_wait(sc); 3119 vxlan_teardown_locked(sc); 3120 } 3121} 3122 3123static void 3124vxlan_load(void) 3125{ 3126 3127 mtx_init(&vxlan_list_mtx, "vxlan list", NULL, MTX_DEF); 3128 LIST_INIT(&vxlan_socket_list); 3129 vxlan_ifdetach_event_tag = EVENTHANDLER_REGISTER(ifnet_departure_event, 3130 vxlan_ifdetach_event, NULL, EVENTHANDLER_PRI_ANY); 3131 vxlan_cloner = if_clone_simple(vxlan_name, vxlan_clone_create, 3132 vxlan_clone_destroy, 0); 3133} 3134 3135static void 3136vxlan_unload(void) 3137{ 3138 3139 EVENTHANDLER_DEREGISTER(ifnet_departure_event, 3140 vxlan_ifdetach_event_tag); 3141 if_clone_detach(vxlan_cloner); 3142 mtx_destroy(&vxlan_list_mtx); 3143 MPASS(LIST_EMPTY(&vxlan_socket_list)); 3144} 3145 3146static int 3147vxlan_modevent(module_t mod, int type, void *unused) 3148{ 3149 int error; 3150 3151 error = 0; 3152 3153 switch (type) { 3154 case MOD_LOAD: 3155 vxlan_load(); 3156 break; 3157 case MOD_UNLOAD: 3158 vxlan_unload(); 3159 break; 3160 default: 3161 error = ENOTSUP; 3162 break; 3163 } 3164 3165 return (error); 3166} 3167 3168static moduledata_t vxlan_mod = { 3169 "if_vxlan", 3170 vxlan_modevent, 3171 0 3172}; 3173 3174DECLARE_MODULE(if_vxlan, vxlan_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 3175MODULE_VERSION(if_vxlan, 1); 3176