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