Add support for IPv6 scoped addresses to vxlan

MFC after:	2 weeks
This commit is contained in:
Bryan Venteicher 2017-12-30 04:03:53 +00:00
parent 8bbeea2b1d
commit 33e0d8f057
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=327375
3 changed files with 121 additions and 67 deletions

View File

@ -236,25 +236,23 @@ DECL_CMD_FUNC(setvxlan_local, addr, d)
switch (ai->ai_family) { switch (ai->ai_family) {
#ifdef INET #ifdef INET
case AF_INET: { case AF_INET: {
struct in_addr addr = ((struct sockaddr_in *) sa)->sin_addr; struct sockaddr_in *sin = (struct sockaddr_in *)sa;
if (IN_MULTICAST(ntohl(addr.s_addr))) if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
errx(1, "local address cannot be multicast"); errx(1, "local address cannot be multicast");
cmd.vxlcmd_sa.in4.sin_family = AF_INET; cmd.vxlcmd_sa.in4 = *sin;
cmd.vxlcmd_sa.in4.sin_addr = addr;
break; break;
} }
#endif #endif
#ifdef INET6 #ifdef INET6
case AF_INET6: { case AF_INET6: {
struct in6_addr *addr = &((struct sockaddr_in6 *)sa)->sin6_addr; struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
if (IN6_IS_ADDR_MULTICAST(addr)) if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
errx(1, "local address cannot be multicast"); errx(1, "local address cannot be multicast");
cmd.vxlcmd_sa.in6.sin6_family = AF_INET6; cmd.vxlcmd_sa.in6 = *sin6;
cmd.vxlcmd_sa.in6.sin6_addr = *addr;
break; break;
} }
#endif #endif
@ -267,10 +265,10 @@ DECL_CMD_FUNC(setvxlan_local, addr, d)
if (!vxlan_exists(s)) { if (!vxlan_exists(s)) {
if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) { if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) {
params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_ADDR4; params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_ADDR4;
params.vxlp_local_in4 = cmd.vxlcmd_sa.in4.sin_addr; params.vxlp_local_sa.in4 = cmd.vxlcmd_sa.in4;
} else { } else {
params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_ADDR6; params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_ADDR6;
params.vxlp_local_in6 = cmd.vxlcmd_sa.in6.sin6_addr; params.vxlp_local_sa.in6 = cmd.vxlcmd_sa.in6;
} }
return; return;
} }
@ -298,25 +296,23 @@ DECL_CMD_FUNC(setvxlan_remote, addr, d)
switch (ai->ai_family) { switch (ai->ai_family) {
#ifdef INET #ifdef INET
case AF_INET: { case AF_INET: {
struct in_addr addr = ((struct sockaddr_in *)sa)->sin_addr; struct sockaddr_in *sin = (struct sockaddr_in *)sa;
if (IN_MULTICAST(ntohl(addr.s_addr))) if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
errx(1, "remote address cannot be multicast"); errx(1, "remote address cannot be multicast");
cmd.vxlcmd_sa.in4.sin_family = AF_INET; cmd.vxlcmd_sa.in4 = *sin;
cmd.vxlcmd_sa.in4.sin_addr = addr;
break; break;
} }
#endif #endif
#ifdef INET6 #ifdef INET6
case AF_INET6: { case AF_INET6: {
struct in6_addr *addr = &((struct sockaddr_in6 *)sa)->sin6_addr; struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
if (IN6_IS_ADDR_MULTICAST(addr)) if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
errx(1, "remote address cannot be multicast"); errx(1, "remote address cannot be multicast");
cmd.vxlcmd_sa.in6.sin6_family = AF_INET6; cmd.vxlcmd_sa.in6 = *sin6;
cmd.vxlcmd_sa.in6.sin6_addr = *addr;
break; break;
} }
#endif #endif
@ -329,10 +325,10 @@ DECL_CMD_FUNC(setvxlan_remote, addr, d)
if (!vxlan_exists(s)) { if (!vxlan_exists(s)) {
if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) { if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) {
params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR4; params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR4;
params.vxlp_remote_in4 = cmd.vxlcmd_sa.in4.sin_addr; params.vxlp_remote_sa.in4 = cmd.vxlcmd_sa.in4;
} else { } else {
params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR6; params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR6;
params.vxlp_remote_in6 = cmd.vxlcmd_sa.in6.sin6_addr; params.vxlp_remote_sa.in6 = cmd.vxlcmd_sa.in6;
} }
return; return;
} }
@ -360,25 +356,23 @@ DECL_CMD_FUNC(setvxlan_group, addr, d)
switch (ai->ai_family) { switch (ai->ai_family) {
#ifdef INET #ifdef INET
case AF_INET: { case AF_INET: {
struct in_addr addr = ((struct sockaddr_in *)sa)->sin_addr; struct sockaddr_in *sin = (struct sockaddr_in *)sa;
if (!IN_MULTICAST(ntohl(addr.s_addr))) if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
errx(1, "group address must be multicast"); errx(1, "group address must be multicast");
cmd.vxlcmd_sa.in4.sin_family = AF_INET; cmd.vxlcmd_sa.in4 = *sin;
cmd.vxlcmd_sa.in4.sin_addr = addr;
break; break;
} }
#endif #endif
#ifdef INET6 #ifdef INET6
case AF_INET6: { case AF_INET6: {
struct in6_addr *addr = &((struct sockaddr_in6 *)sa)->sin6_addr; struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
if (!IN6_IS_ADDR_MULTICAST(addr)) if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
errx(1, "group address must be multicast"); errx(1, "group address must be multicast");
cmd.vxlcmd_sa.in6.sin6_family = AF_INET6; cmd.vxlcmd_sa.in6 = *sin6;
cmd.vxlcmd_sa.in6.sin6_addr = *addr;
break; break;
} }
#endif #endif
@ -391,10 +385,10 @@ DECL_CMD_FUNC(setvxlan_group, addr, d)
if (!vxlan_exists(s)) { if (!vxlan_exists(s)) {
if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) { if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) {
params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR4; params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR4;
params.vxlp_remote_in4 = cmd.vxlcmd_sa.in4.sin_addr; params.vxlp_remote_sa.in4 = cmd.vxlcmd_sa.in4;
} else { } else {
params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR6; params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR6;
params.vxlp_remote_in6 = cmd.vxlcmd_sa.in6.sin6_addr; params.vxlp_remote_sa.in6 = cmd.vxlcmd_sa.in6;
} }
return; return;
} }

View File

@ -68,10 +68,12 @@ __FBSDID("$FreeBSD$");
#include <netinet/ip.h> #include <netinet/ip.h>
#include <netinet/ip6.h> #include <netinet/ip6.h>
#include <netinet/ip_var.h> #include <netinet/ip_var.h>
#include <netinet6/ip6_var.h>
#include <netinet/udp.h> #include <netinet/udp.h>
#include <netinet/udp_var.h> #include <netinet/udp_var.h>
#include <netinet6/ip6_var.h>
#include <netinet6/scope6_var.h>
struct vxlan_softc; struct vxlan_softc;
LIST_HEAD(vxlan_softc_head, vxlan_softc); LIST_HEAD(vxlan_softc_head, vxlan_softc);
@ -215,9 +217,9 @@ static void vxlan_ftable_fini(struct vxlan_softc *);
static void vxlan_ftable_flush(struct vxlan_softc *, int); static void vxlan_ftable_flush(struct vxlan_softc *, int);
static void vxlan_ftable_expire(struct vxlan_softc *); static void vxlan_ftable_expire(struct vxlan_softc *);
static int vxlan_ftable_update_locked(struct vxlan_softc *, static int vxlan_ftable_update_locked(struct vxlan_softc *,
const struct sockaddr *, const uint8_t *, const union vxlan_sockaddr *, const uint8_t *,
struct rm_priotracker *); struct rm_priotracker *);
static int vxlan_ftable_update(struct vxlan_softc *, static int vxlan_ftable_learn(struct vxlan_softc *,
const struct sockaddr *, const uint8_t *); const struct sockaddr *, const uint8_t *);
static int vxlan_ftable_sysctl_dump(SYSCTL_HANDLER_ARGS); static int vxlan_ftable_sysctl_dump(SYSCTL_HANDLER_ARGS);
@ -358,6 +360,7 @@ static void vxlan_sockaddr_in_copy(union vxlan_sockaddr *,
static int vxlan_sockaddr_supported(const union vxlan_sockaddr *, int); static int vxlan_sockaddr_supported(const union vxlan_sockaddr *, int);
static int vxlan_sockaddr_in_any(const union vxlan_sockaddr *); static int vxlan_sockaddr_in_any(const union vxlan_sockaddr *);
static int vxlan_sockaddr_in_multicast(const union vxlan_sockaddr *); static int vxlan_sockaddr_in_multicast(const union vxlan_sockaddr *);
static int vxlan_sockaddr_in6_embedscope(union vxlan_sockaddr *);
static int vxlan_can_change_config(struct vxlan_softc *); static int vxlan_can_change_config(struct vxlan_softc *);
static int vxlan_check_vni(uint32_t); static int vxlan_check_vni(uint32_t);
@ -576,10 +579,10 @@ vxlan_ftable_expire(struct vxlan_softc *sc)
} }
static int static int
vxlan_ftable_update_locked(struct vxlan_softc *sc, const struct sockaddr *sa, vxlan_ftable_update_locked(struct vxlan_softc *sc,
const uint8_t *mac, struct rm_priotracker *tracker) const union vxlan_sockaddr *vxlsa, const uint8_t *mac,
struct rm_priotracker *tracker)
{ {
union vxlan_sockaddr vxlsa;
struct vxlan_ftable_entry *fe; struct vxlan_ftable_entry *fe;
int error; int error;
@ -596,7 +599,7 @@ vxlan_ftable_update_locked(struct vxlan_softc *sc, const struct sockaddr *sa,
fe->vxlfe_expire = time_uptime + sc->vxl_ftable_timeout; fe->vxlfe_expire = time_uptime + sc->vxl_ftable_timeout;
if (!VXLAN_FE_IS_DYNAMIC(fe) || if (!VXLAN_FE_IS_DYNAMIC(fe) ||
vxlan_sockaddr_in_equal(&fe->vxlfe_raddr, sa)) vxlan_sockaddr_in_equal(&fe->vxlfe_raddr, &vxlsa->sa))
return (0); return (0);
if (!VXLAN_LOCK_WOWNED(sc)) { if (!VXLAN_LOCK_WOWNED(sc)) {
VXLAN_RUNLOCK(sc, tracker); VXLAN_RUNLOCK(sc, tracker);
@ -604,7 +607,7 @@ vxlan_ftable_update_locked(struct vxlan_softc *sc, const struct sockaddr *sa,
sc->vxl_stats.ftable_lock_upgrade_failed++; sc->vxl_stats.ftable_lock_upgrade_failed++;
goto again; goto again;
} }
vxlan_sockaddr_in_copy(&fe->vxlfe_raddr, sa); vxlan_sockaddr_in_copy(&fe->vxlfe_raddr, &vxlsa->sa);
return (0); return (0);
} }
@ -624,15 +627,7 @@ vxlan_ftable_update_locked(struct vxlan_softc *sc, const struct sockaddr *sa,
if (fe == NULL) if (fe == NULL)
return (ENOMEM); return (ENOMEM);
/* vxlan_ftable_entry_init(sc, fe, mac, &vxlsa->sa, VXLAN_FE_FLAG_DYNAMIC);
* The source port may be randomly select by the remove host, so
* use the port of the default destination address.
*/
vxlan_sockaddr_copy(&vxlsa, sa);
vxlsa.in4.sin_port = sc->vxl_dst_addr.in4.sin_port;
vxlan_ftable_entry_init(sc, fe, mac, &vxlsa.sa,
VXLAN_FE_FLAG_DYNAMIC);
/* The prior lookup failed, so the insert should not. */ /* The prior lookup failed, so the insert should not. */
error = vxlan_ftable_entry_insert(sc, fe); error = vxlan_ftable_entry_insert(sc, fe);
@ -642,14 +637,28 @@ vxlan_ftable_update_locked(struct vxlan_softc *sc, const struct sockaddr *sa,
} }
static int static int
vxlan_ftable_update(struct vxlan_softc *sc, const struct sockaddr *sa, vxlan_ftable_learn(struct vxlan_softc *sc, const struct sockaddr *sa,
const uint8_t *mac) const uint8_t *mac)
{ {
struct rm_priotracker tracker; struct rm_priotracker tracker;
union vxlan_sockaddr vxlsa;
int error; int error;
/*
* The source port may be randomly selected by the remote host, so
* use the port of the default destination address.
*/
vxlan_sockaddr_copy(&vxlsa, sa);
vxlsa.in4.sin_port = sc->vxl_dst_addr.in4.sin_port;
if (VXLAN_SOCKADDR_IS_IPV6(&vxlsa)) {
error = vxlan_sockaddr_in6_embedscope(&vxlsa);
if (error)
return (error);
}
VXLAN_RLOCK(sc, &tracker); VXLAN_RLOCK(sc, &tracker);
error = vxlan_ftable_update_locked(sc, sa, mac, &tracker); error = vxlan_ftable_update_locked(sc, &vxlsa, mac, &tracker);
VXLAN_UNLOCK(sc, &tracker); VXLAN_UNLOCK(sc, &tracker);
return (error); return (error);
@ -1051,8 +1060,8 @@ vxlan_socket_ifdetach(struct vxlan_socket *vso, struct ifnet *ifp,
static struct vxlan_socket * static struct vxlan_socket *
vxlan_socket_mc_lookup(const union vxlan_sockaddr *vxlsa) vxlan_socket_mc_lookup(const union vxlan_sockaddr *vxlsa)
{ {
struct vxlan_socket *vso;
union vxlan_sockaddr laddr; union vxlan_sockaddr laddr;
struct vxlan_socket *vso;
laddr = *vxlsa; laddr = *vxlsa;
@ -1406,7 +1415,7 @@ vxlan_setup_multicast_interface(struct vxlan_softc *sc)
ifp = ifunit_ref(sc->vxl_mc_ifname); ifp = ifunit_ref(sc->vxl_mc_ifname);
if (ifp == NULL) { if (ifp == NULL) {
if_printf(sc->vxl_ifp, "multicast interfaces %s does " if_printf(sc->vxl_ifp, "multicast interface %s does "
"not exist\n", sc->vxl_mc_ifname); "not exist\n", sc->vxl_mc_ifname);
return (ENOENT); return (ENOENT);
} }
@ -1830,6 +1839,13 @@ vxlan_ctrl_get_config(struct vxlan_softc *sc, void *arg)
cfg->vxlc_ttl = sc->vxl_ttl; cfg->vxlc_ttl = sc->vxl_ttl;
VXLAN_RUNLOCK(sc, &tracker); VXLAN_RUNLOCK(sc, &tracker);
#ifdef INET6
if (VXLAN_SOCKADDR_IS_IPV6(&cfg->vxlc_local_sa))
sa6_recoverscope(&cfg->vxlc_local_sa.in6);
if (VXLAN_SOCKADDR_IS_IPV6(&cfg->vxlc_remote_sa))
sa6_recoverscope(&cfg->vxlc_remote_sa.in6);
#endif
return (0); return (0);
} }
@ -1869,6 +1885,11 @@ vxlan_ctrl_set_local_addr(struct vxlan_softc *sc, void *arg)
return (EINVAL); return (EINVAL);
if (vxlan_sockaddr_in_multicast(vxlsa) != 0) if (vxlan_sockaddr_in_multicast(vxlsa) != 0)
return (EINVAL); return (EINVAL);
if (VXLAN_SOCKADDR_IS_IPV6(vxlsa)) {
error = vxlan_sockaddr_in6_embedscope(vxlsa);
if (error)
return (error);
}
VXLAN_WLOCK(sc); VXLAN_WLOCK(sc);
if (vxlan_can_change_config(sc)) { if (vxlan_can_change_config(sc)) {
@ -1893,6 +1914,11 @@ vxlan_ctrl_set_remote_addr(struct vxlan_softc *sc, void *arg)
if (!VXLAN_SOCKADDR_IS_IPV46(vxlsa)) if (!VXLAN_SOCKADDR_IS_IPV46(vxlsa))
return (EINVAL); return (EINVAL);
if (VXLAN_SOCKADDR_IS_IPV6(vxlsa)) {
error = vxlan_sockaddr_in6_embedscope(vxlsa);
if (error)
return (error);
}
VXLAN_WLOCK(sc); VXLAN_WLOCK(sc);
if (vxlan_can_change_config(sc)) { if (vxlan_can_change_config(sc)) {
@ -2093,6 +2119,12 @@ vxlan_ctrl_ftable_entry_add(struct vxlan_softc *sc, void *arg)
if (vxlsa.sa.sa_family != sc->vxl_dst_addr.sa.sa_family) if (vxlsa.sa.sa_family != sc->vxl_dst_addr.sa.sa_family)
return (EAFNOSUPPORT); return (EAFNOSUPPORT);
if (VXLAN_SOCKADDR_IS_IPV6(&vxlsa)) {
error = vxlan_sockaddr_in6_embedscope(&vxlsa);
if (error)
return (error);
}
fe = vxlan_ftable_entry_alloc(); fe = vxlan_ftable_entry_alloc();
if (fe == NULL) if (fe == NULL)
return (ENOMEM); return (ENOMEM);
@ -2248,7 +2280,6 @@ vxlan_pick_source_port(struct vxlan_softc *sc, struct mbuf *m)
range = sc->vxl_max_port - sc->vxl_min_port + 1; range = sc->vxl_max_port - sc->vxl_min_port + 1;
/* check if flowid is set and not opaque */
if (M_HASHTYPE_ISHASH(m)) if (M_HASHTYPE_ISHASH(m))
hash = m->m_pkthdr.flowid; hash = m->m_pkthdr.flowid;
else else
@ -2536,7 +2567,7 @@ vxlan_input(struct vxlan_socket *vso, uint32_t vni, struct mbuf **m0,
} }
if (sc->vxl_flags & VXLAN_FLAG_LEARN) if (sc->vxl_flags & VXLAN_FLAG_LEARN)
vxlan_ftable_update(sc, sa, eh->ether_shost); vxlan_ftable_learn(sc, sa, eh->ether_shost);
m_clrprotoflags(m); m_clrprotoflags(m);
m->m_pkthdr.rcvif = ifp; m->m_pkthdr.rcvif = ifp;
@ -2588,6 +2619,18 @@ vxlan_set_user_config(struct vxlan_softc *sc, struct ifvxlanparam *vxlp)
if (vxlp->vxlp_with & (VXLAN_PARAM_WITH_LOCAL_ADDR6 | if (vxlp->vxlp_with & (VXLAN_PARAM_WITH_LOCAL_ADDR6 |
VXLAN_PARAM_WITH_REMOTE_ADDR6)) VXLAN_PARAM_WITH_REMOTE_ADDR6))
return (EAFNOSUPPORT); return (EAFNOSUPPORT);
#else
if (vxlp->vxlp_with & VXLAN_PARAM_WITH_LOCAL_ADDR6) {
int error = vxlan_sockaddr_in6_embedscope(&vxlp->vxlp_local_sa);
if (error)
return (error);
}
if (vxlp->vxlp_with & VXLAN_PARAM_WITH_REMOTE_ADDR6) {
int error = vxlan_sockaddr_in6_embedscope(
&vxlp->vxlp_remote_sa);
if (error)
return (error);
}
#endif #endif
if (vxlp->vxlp_with & VXLAN_PARAM_WITH_VNI) { if (vxlp->vxlp_with & VXLAN_PARAM_WITH_VNI) {
@ -2598,21 +2641,25 @@ vxlan_set_user_config(struct vxlan_softc *sc, struct ifvxlanparam *vxlp)
if (vxlp->vxlp_with & VXLAN_PARAM_WITH_LOCAL_ADDR4) { if (vxlp->vxlp_with & VXLAN_PARAM_WITH_LOCAL_ADDR4) {
sc->vxl_src_addr.in4.sin_len = sizeof(struct sockaddr_in); sc->vxl_src_addr.in4.sin_len = sizeof(struct sockaddr_in);
sc->vxl_src_addr.in4.sin_family = AF_INET; sc->vxl_src_addr.in4.sin_family = AF_INET;
sc->vxl_src_addr.in4.sin_addr = vxlp->vxlp_local_in4; sc->vxl_src_addr.in4.sin_addr =
vxlp->vxlp_local_sa.in4.sin_addr;
} else if (vxlp->vxlp_with & VXLAN_PARAM_WITH_LOCAL_ADDR6) { } else if (vxlp->vxlp_with & VXLAN_PARAM_WITH_LOCAL_ADDR6) {
sc->vxl_src_addr.in6.sin6_len = sizeof(struct sockaddr_in6); sc->vxl_src_addr.in6.sin6_len = sizeof(struct sockaddr_in6);
sc->vxl_src_addr.in6.sin6_family = AF_INET6; sc->vxl_src_addr.in6.sin6_family = AF_INET6;
sc->vxl_src_addr.in6.sin6_addr = vxlp->vxlp_local_in6; sc->vxl_src_addr.in6.sin6_addr =
vxlp->vxlp_local_sa.in6.sin6_addr;
} }
if (vxlp->vxlp_with & VXLAN_PARAM_WITH_REMOTE_ADDR4) { if (vxlp->vxlp_with & VXLAN_PARAM_WITH_REMOTE_ADDR4) {
sc->vxl_dst_addr.in4.sin_len = sizeof(struct sockaddr_in); sc->vxl_dst_addr.in4.sin_len = sizeof(struct sockaddr_in);
sc->vxl_dst_addr.in4.sin_family = AF_INET; sc->vxl_dst_addr.in4.sin_family = AF_INET;
sc->vxl_dst_addr.in4.sin_addr = vxlp->vxlp_remote_in4; sc->vxl_dst_addr.in4.sin_addr =
vxlp->vxlp_remote_sa.in4.sin_addr;
} else if (vxlp->vxlp_with & VXLAN_PARAM_WITH_REMOTE_ADDR6) { } else if (vxlp->vxlp_with & VXLAN_PARAM_WITH_REMOTE_ADDR6) {
sc->vxl_dst_addr.in6.sin6_len = sizeof(struct sockaddr_in6); sc->vxl_dst_addr.in6.sin6_len = sizeof(struct sockaddr_in6);
sc->vxl_dst_addr.in6.sin6_family = AF_INET6; sc->vxl_dst_addr.in6.sin6_family = AF_INET6;
sc->vxl_dst_addr.in6.sin6_addr = vxlp->vxlp_remote_in6; sc->vxl_dst_addr.in6.sin6_addr =
vxlp->vxlp_remote_sa.in6.sin6_addr;
} }
if (vxlp->vxlp_with & VXLAN_PARAM_WITH_LOCAL_PORT) if (vxlp->vxlp_with & VXLAN_PARAM_WITH_LOCAL_PORT)
@ -2930,6 +2977,21 @@ vxlan_sockaddr_in_multicast(const union vxlan_sockaddr *vxladdr)
return (mc); return (mc);
} }
static int
vxlan_sockaddr_in6_embedscope(union vxlan_sockaddr *vxladdr)
{
int error;
MPASS(VXLAN_SOCKADDR_IS_IPV6(vxladdr));
#ifdef INET6
error = sa6_embedscope(&vxladdr->in6, V_ip6_use_defzone);
#else
error = EAFNOSUPPORT;
#endif
return (error);
}
static int static int
vxlan_can_change_config(struct vxlan_softc *sc) vxlan_can_change_config(struct vxlan_softc *sc)
{ {

View File

@ -54,6 +54,12 @@ struct vxlan_header {
#define VXLAN_PORT 4789 #define VXLAN_PORT 4789
#define VXLAN_LEGACY_PORT 8472 #define VXLAN_LEGACY_PORT 8472
union vxlan_sockaddr {
struct sockaddr sa;
struct sockaddr_in in4;
struct sockaddr_in6 in6;
};
struct ifvxlanparam { struct ifvxlanparam {
uint64_t vxlp_with; uint64_t vxlp_with;
@ -72,10 +78,8 @@ struct ifvxlanparam {
#define VXLAN_PARAM_WITH_LEARN 0x1000 #define VXLAN_PARAM_WITH_LEARN 0x1000
uint32_t vxlp_vni; uint32_t vxlp_vni;
struct in_addr vxlp_local_in4; union vxlan_sockaddr vxlp_local_sa;
struct in6_addr vxlp_local_in6; union vxlan_sockaddr vxlp_remote_sa;
struct in_addr vxlp_remote_in4;
struct in6_addr vxlp_remote_in6;
uint16_t vxlp_local_port; uint16_t vxlp_local_port;
uint16_t vxlp_remote_port; uint16_t vxlp_remote_port;
uint16_t vxlp_min_port; uint16_t vxlp_min_port;
@ -87,12 +91,6 @@ struct ifvxlanparam {
uint8_t vxlp_learn; uint8_t vxlp_learn;
}; };
union vxlan_sockaddr {
struct sockaddr sa;
struct sockaddr_in in4;
struct sockaddr_in6 in6;
};
#define VXLAN_SOCKADDR_IS_IPV4(_vxsin) ((_vxsin)->sa.sa_family == AF_INET) #define VXLAN_SOCKADDR_IS_IPV4(_vxsin) ((_vxsin)->sa.sa_family == AF_INET)
#define VXLAN_SOCKADDR_IS_IPV6(_vxsin) ((_vxsin)->sa.sa_family == AF_INET6) #define VXLAN_SOCKADDR_IS_IPV6(_vxsin) ((_vxsin)->sa.sa_family == AF_INET6)
#define VXLAN_SOCKADDR_IS_IPV46(_vxsin) \ #define VXLAN_SOCKADDR_IS_IPV46(_vxsin) \