svn commit: r266469 - in projects/vxlan: sbin/ifconfig sys/net
Bryan Venteicher
bryanv at FreeBSD.org
Tue May 20 14:52:57 UTC 2014
Author: bryanv
Date: Tue May 20 14:52:56 2014
New Revision: 266469
URL: http://svnweb.freebsd.org/changeset/base/266469
Log:
Add partially baked IPv4 multicast support and lots of cleanup
Modified:
projects/vxlan/sbin/ifconfig/ifvxlan.c
projects/vxlan/sys/net/if_vxlan.c
projects/vxlan/sys/net/if_vxlan.h
Modified: projects/vxlan/sbin/ifconfig/ifvxlan.c
==============================================================================
--- projects/vxlan/sbin/ifconfig/ifvxlan.c Tue May 20 14:39:22 2014 (r266468)
+++ projects/vxlan/sbin/ifconfig/ifvxlan.c Tue May 20 14:52:56 2014 (r266469)
@@ -39,6 +39,7 @@
#include <net/if_var.h>
#include <net/if_vxlan.h>
#include <net/route.h>
+#include <netinet/in.h>
#include <ctype.h>
#include <stdio.h>
@@ -94,7 +95,7 @@ vxlan_exists(int sock)
bzero(&cfg, sizeof(cfg));
- return (do_cmd(s, VXLAN_CMD_GET_CONFIG, &cfg, sizeof(cfg)) != -1);
+ return (do_cmd(sock, VXLAN_CMD_GET_CONFIG, &cfg, sizeof(cfg), 0) != -1);
}
static void
@@ -111,6 +112,10 @@ vxlan_status(int s)
vni = cfg.vxlc_vni;
+ /* Just report nothing if the network identity isn't set yet. */
+ if (vni >= VXLAN_VNI_MAX)
+ return;
+
sin = sstosin(&cfg.vxlc_local_sa);
if (getnameinfo(sintosa(sin), sin->sin_len, src, sizeof(src),
NULL, 0, NI_NUMERICHOST) != 0)
@@ -122,7 +127,7 @@ vxlan_status(int s)
NULL, 0, NI_NUMERICHOST) != 0)
dst[0] = '\0';
dport = ntohs(sin->sin_port);
- group = IN_MULTICAST(sin->sin_addr.s_addr);
+ group = IN_MULTICAST(ntohl(sin->sin_addr.s_addr));
printf("\tvxlan %d local %s:%u %s %s:%u\n",
vni, src, sport, group ? "group" : "remote", dst, dport);
@@ -134,13 +139,9 @@ vxlan_status(int s)
(VXLAN_PARAM_WITH_REMOTE_ADDR4 | VXLAN_PARAM_WITH_REMOTE_ADDR6)
static void
-vxlan_verify_params(void)
+vxlan_check_params(void)
{
- if (params.vxlp_vni == VXLAN_VNI_MAX)
- errx(1, "must specify a network identifier for vxlan create");
- if ((params.vxlp_with & _REMOTE_ADDR46) == 0)
- errx(1, "must specify a remote or multicast group address");
if ((params.vxlp_with & _LOCAL_ADDR46) == _LOCAL_ADDR46)
errx(1, "cannot specify both local IPv4 and IPv6 addresses");
if ((params.vxlp_with & _REMOTE_ADDR46) == _REMOTE_ADDR46)
@@ -149,7 +150,7 @@ vxlan_verify_params(void)
params.vxlp_with & VXLAN_PARAM_WITH_REMOTE_ADDR6) ||
(params.vxlp_with & VXLAN_PARAM_WITH_LOCAL_ADDR6 &&
params.vxlp_with & VXLAN_PARAM_WITH_REMOTE_ADDR4))
- errx(1, "cannot mix IPv4/IPv6 addresses");
+ errx(1, "cannot mix IPv4 and IPv6 addresses");
}
#undef _LOCAL_ADDR46
@@ -159,14 +160,14 @@ static void
vxlan_cb(int s, void *arg)
{
- //vxlan_verify_params();
+ /* BMV: Anything? */
}
static void
vxlan_create(int s, struct ifreq *ifr)
{
- vxlan_verify_params();
+ vxlan_check_params();
ifr->ifr_data = (caddr_t) ¶ms;
if (ioctl(s, SIOCIFCREATE2, ifr) < 0)
@@ -176,22 +177,35 @@ vxlan_create(int s, struct ifreq *ifr)
static
DECL_CMD_FUNC(setvxlan_vni, arg, d)
{
+ struct ifvxlancmd cmd;
u_long val;
if (get_val(arg, &val) < 0 || val >= VXLAN_VNI_MAX)
errx(1, "invalid network identifier: %s", arg);
- params.vxlp_with |= VXLAN_PARAM_WITH_VNI;
- params.vxlp_vni = val;
+ if (!vxlan_exists(s)) {
+ params.vxlp_with |= VXLAN_PARAM_WITH_VNI;
+ params.vxlp_vni = val;
+ return;
+ }
+
+ bzero(&cmd, sizeof(cmd));
+ cmd.vxlcmd_vni = val;
+
+ if (do_cmd(s, VXLAN_CMD_SET_VNI, &cmd, sizeof(cmd), 1) < 0)
+ err(1, "VXLAN_CMD_SET_VNI");
}
static
DECL_CMD_FUNC(setvxlan_local, addr, d)
{
+ struct ifvxlancmd cmd;
struct addrinfo *ai;
struct sockaddr *sa;
int error;
+ bzero(&cmd, sizeof(cmd));
+
if ((error = getaddrinfo(addr, NULL, NULL, &ai)) != 0)
errx(1, "error in parsing local address string: %s",
gai_strerror(error));
@@ -203,11 +217,11 @@ DECL_CMD_FUNC(setvxlan_local, addr, d)
case AF_INET: {
struct in_addr addr = ((struct sockaddr_in *) sa)->sin_addr;
- if (IN_MULTICAST(addr.s_addr))
+ if (IN_MULTICAST(ntohl(addr.s_addr)))
errx(1, "local address cannot be multicast");
- params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_ADDR4;
- params.vxlp_local_in4 = addr;
+ cmd.vxlcmd_sa.in4.sin_family = AF_INET;
+ cmd.vxlcmd_sa.in4.sin_addr = addr;
break;
}
#endif
@@ -218,8 +232,8 @@ DECL_CMD_FUNC(setvxlan_local, addr, d)
if (IN6_IS_ADDR_MULTICAST(addr))
errx(1, "local address cannot be multicast");
- params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_ADDR6;
- params.vxlp_local_in6 = *addr;
+ cmd.vxlcmd_sa.in6.sin6_family = AF_INET6;
+ cmd.vxlcmd_sa.in6.sin6_addr = *addr;
break;
}
#endif
@@ -228,15 +242,32 @@ DECL_CMD_FUNC(setvxlan_local, addr, d)
}
freeaddrinfo(ai);
+
+ if (!vxlan_exists(s)) {
+ if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) {
+ params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_ADDR4;
+ params.vxlp_local_in4 = cmd.vxlcmd_sa.in4.sin_addr;
+ } else {
+ params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_ADDR6;
+ params.vxlp_local_in6 = cmd.vxlcmd_sa.in6.sin6_addr;
+ }
+ return;
+ }
+
+ if (do_cmd(s, VXLAN_CMD_SET_LOCAL_ADDR, &cmd, sizeof(cmd), 1) < 0)
+ err(1, "VXLAN_CMD_SET_LOCAL_ADDR");
}
static
DECL_CMD_FUNC(setvxlan_remote, addr, d)
{
+ struct ifvxlancmd cmd;
struct addrinfo *ai;
struct sockaddr *sa;
int error;
+ bzero(&cmd, sizeof(cmd));
+
if ((error = getaddrinfo(addr, NULL, NULL, &ai)) != 0)
errx(1, "error in parsing remote address string: %s",
gai_strerror(error));
@@ -248,11 +279,11 @@ DECL_CMD_FUNC(setvxlan_remote, addr, d)
case AF_INET: {
struct in_addr addr = ((struct sockaddr_in *)sa)->sin_addr;
- if (IN_MULTICAST(addr.s_addr))
+ if (IN_MULTICAST(ntohl(addr.s_addr)))
errx(1, "remote address cannot be multicast");
- params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR4;
- params.vxlp_remote_in4 = addr;
+ cmd.vxlcmd_sa.in4.sin_family = AF_INET;
+ cmd.vxlcmd_sa.in4.sin_addr = addr;
break;
}
#endif
@@ -263,8 +294,8 @@ DECL_CMD_FUNC(setvxlan_remote, addr, d)
if (IN6_IS_ADDR_MULTICAST(addr))
errx(1, "remote address cannot be multicast");
- params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR6;
- params.vxlp_remote_in6 = *addr;
+ cmd.vxlcmd_sa.in6.sin6_family = AF_INET6;
+ cmd.vxlcmd_sa.in6.sin6_addr = *addr;
break;
}
#endif
@@ -273,15 +304,32 @@ DECL_CMD_FUNC(setvxlan_remote, addr, d)
}
freeaddrinfo(ai);
+
+ if (!vxlan_exists(s)) {
+ if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) {
+ params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR4;
+ params.vxlp_remote_in4 = cmd.vxlcmd_sa.in4.sin_addr;
+ } else {
+ params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR6;
+ params.vxlp_remote_in6 = cmd.vxlcmd_sa.in6.sin6_addr;
+ }
+ return;
+ }
+
+ if (do_cmd(s, VXLAN_CMD_SET_REMOTE_ADDR, &cmd, sizeof(cmd), 1) < 0)
+ err(1, "VXLAN_CMD_SET_REMOTE_ADDR");
}
static
DECL_CMD_FUNC(setvxlan_group, addr, d)
{
+ struct ifvxlancmd cmd;
struct addrinfo *ai;
struct sockaddr *sa;
int error;
+ bzero(&cmd, sizeof(cmd));
+
if ((error = getaddrinfo(addr, NULL, NULL, &ai)) != 0)
errx(1, "error in parsing group address string: %s",
gai_strerror(error));
@@ -293,11 +341,11 @@ DECL_CMD_FUNC(setvxlan_group, addr, d)
case AF_INET: {
struct in_addr addr = ((struct sockaddr_in *)sa)->sin_addr;
- if (!IN_MULTICAST(addr.s_addr))
+ if (!IN_MULTICAST(ntohl(addr.s_addr)))
errx(1, "group address must be multicast");
- params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR4;
- params.vxlp_remote_in4 = addr;
+ cmd.vxlcmd_sa.in4.sin_family = AF_INET;
+ cmd.vxlcmd_sa.in4.sin_addr = addr;
break;
}
#endif
@@ -305,11 +353,11 @@ DECL_CMD_FUNC(setvxlan_group, addr, d)
case AF_INET6: {
struct in6_addr *addr = &((struct sockaddr_in6 *)sa)->sin6_addr;
- if (IN6_IS_ADDR_MULTICAST(addr))
+ if (!IN6_IS_ADDR_MULTICAST(addr))
errx(1, "group address must be multicast");
- params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR6;
- params.vxlp_remote_in6 = *addr;
+ cmd.vxlcmd_sa.in6.sin6_family = AF_INET6;
+ cmd.vxlcmd_sa.in6.sin6_addr = *addr;
break;
}
#endif
@@ -318,35 +366,70 @@ DECL_CMD_FUNC(setvxlan_group, addr, d)
}
freeaddrinfo(ai);
+
+ if (!vxlan_exists(s)) {
+ if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) {
+ params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR4;
+ params.vxlp_remote_in4 = cmd.vxlcmd_sa.in4.sin_addr;
+ } else {
+ params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR6;
+ params.vxlp_remote_in6 = cmd.vxlcmd_sa.in6.sin6_addr;
+ }
+ return;
+ }
+
+ if (do_cmd(s, VXLAN_CMD_SET_REMOTE_ADDR, &cmd, sizeof(cmd), 1) < 0)
+ err(1, "VXLAN_CMD_SET_REMOTE_ADDR");
}
static
DECL_CMD_FUNC(setvxlan_local_port, arg, d)
{
+ struct ifvxlancmd cmd;
u_long val;
if (get_val(arg, &val) < 0 || val >= UINT16_MAX)
errx(1, "invalid local port: %s", arg);
- params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_PORT;
- params.vxlp_local_port = val;
+ if (!vxlan_exists(s)) {
+ params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_PORT;
+ params.vxlp_local_port = val;
+ return;
+ }
+
+ bzero(&cmd, sizeof(cmd));
+ cmd.vxlcmd_port = val;
+
+ if (do_cmd(s, VXLAN_CMD_SET_LOCAL_PORT, &cmd, sizeof(cmd), 1) < 0)
+ err(1, "VXLAN_CMD_SET_LOCAL_PORT");
}
static
DECL_CMD_FUNC(setvxlan_remote_port, arg, d)
{
+ struct ifvxlancmd cmd;
u_long val;
if (get_val(arg, &val) < 0 || val >= UINT16_MAX)
errx(1, "invalid remote port: %s", arg);
- params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_PORT;
- params.vxlp_remote_port = val;
+ if (!vxlan_exists(s)) {
+ params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_PORT;
+ params.vxlp_remote_port = val;
+ return;
+ }
+
+ bzero(&cmd, sizeof(cmd));
+ cmd.vxlcmd_port = val;
+
+ if (do_cmd(s, VXLAN_CMD_SET_REMOTE_PORT, &cmd, sizeof(cmd), 1) < 0)
+ err(1, "VXLAN_CMD_SET_REMOTE_PORT");
}
static
DECL_CMD_FUNC2(setvxlan_port_range, arg1, arg2)
{
+ struct ifvxlancmd cmd;
u_long min, max;
if (get_val(arg1, &min) < 0 || min >= UINT16_MAX)
@@ -356,53 +439,104 @@ DECL_CMD_FUNC2(setvxlan_port_range, arg1
if (max < min)
errx(1, "invalid port range");
- params.vxlp_with |= VXLAN_PARAM_WITH_PORT_RANGE;
- params.vxlp_min_port = min;
- params.vxlp_max_port = max;
+ if (!vxlan_exists(s)) {
+ params.vxlp_with |= VXLAN_PARAM_WITH_PORT_RANGE;
+ params.vxlp_min_port = min;
+ params.vxlp_max_port = max;
+ return;
+ }
+
+ bzero(&cmd, sizeof(cmd));
+ cmd.vxlcmd_port_min = min;
+ cmd.vxlcmd_port_max = max;
+
+ if (do_cmd(s, VXLAN_CMD_SET_PORT_RANGE, &cmd, sizeof(cmd), 1) < 0)
+ err(1, "VXLAN_CMD_SET_PORT_RANGE");
}
static
DECL_CMD_FUNC(setvxlan_timeout, arg, d)
{
+ struct ifvxlancmd cmd;
u_long val;
if (get_val(arg, &val) < 0 || (val & ~0xFFFFFFFF) != 0)
errx(1, "invalid timeout value: %s", arg);
- params.vxlp_with |= VXLAN_PARAM_WITH_FTABLE_TIMEOUT;
- params.vxlp_ftable_timeout = val & 0xFFFFFFFF;
+ if (!vxlan_exists(s)) {
+ params.vxlp_with |= VXLAN_PARAM_WITH_FTABLE_TIMEOUT;
+ params.vxlp_ftable_timeout = val & 0xFFFFFFFF;
+ return;
+ }
+
+ bzero(&cmd, sizeof(cmd));
+ cmd.vxlcmd_ftable_timeout = val & 0xFFFFFFFF;
+
+ if (do_cmd(s, VXLAN_CMD_SET_FTABLE_TIMEOUT, &cmd, sizeof(cmd), 1) < 0)
+ err(1, "VXLAN_CMD_SET_FTABLE_TIMEOUT");
}
static
DECL_CMD_FUNC(setvxlan_maxaddr, arg, d)
{
+ struct ifvxlancmd cmd;
u_long val;
if (get_val(arg, &val) < 0 || (val & ~0xFFFFFFFF) != 0)
errx(1, "invalid maxaddr value: %s", arg);
- params.vxlp_with |= VXLAN_PARAM_WITH_FTABLE_MAX;
- params.vxlp_ftable_max = val & 0xFFFFFFFF;
+ if (!vxlan_exists(s)) {
+ params.vxlp_with |= VXLAN_PARAM_WITH_FTABLE_MAX;
+ params.vxlp_ftable_max = val & 0xFFFFFFFF;
+ return;
+ }
+
+ bzero(&cmd, sizeof(cmd));
+ cmd.vxlcmd_ftable_max = val & 0xFFFFFFFF;
+
+ if (do_cmd(s, VXLAN_CMD_SET_FTABLE_MAX, &cmd, sizeof(cmd), 1) < 0)
+ err(1, "VXLAN_CMD_SET_FTABLE_MAX");
}
static
DECL_CMD_FUNC(setvxlan_ttl, arg, d)
{
+ struct ifvxlancmd cmd;
u_long val;
if (get_val(arg, &val) < 0 || val > 256)
errx(1, "invalid TTL value: %s", arg);
- params.vxlp_with |= VXLAN_PARAM_WITH_TTL;
- params.vxlp_ttl = val;
+ if (!vxlan_exists(s)) {
+ params.vxlp_with |= VXLAN_PARAM_WITH_TTL;
+ params.vxlp_ttl = val;
+ return;
+ }
+
+ bzero(&cmd, sizeof(cmd));
+ cmd.vxlcmd_ttl = val;
+
+ if (do_cmd(s, VXLAN_CMD_SET_TTL, &cmd, sizeof(cmd), 1) < 0)
+ err(1, "VXLAN_CMD_SET_TTL");
}
static
DECL_CMD_FUNC(setvxlan_learn, arg, d)
{
+ struct ifvxlancmd cmd;
+
+ if (!vxlan_exists(s)) {
+ params.vxlp_with |= VXLAN_PARAM_WITH_LEARN;
+ params.vxlp_learn = d;
+ return;
+ }
- params.vxlp_with |= VXLAN_PARAM_WITH_NOLEARN;
- params.vxlp_nolearn = !!d;
+ bzero(&cmd, sizeof(cmd));
+ if (d != 0)
+ cmd.vxlcmd_flags |= VXLAN_CMD_FLAG_LEARN;
+
+ if (do_cmd(s, VXLAN_CMD_SET_LEARN, &cmd, sizeof(cmd), 1) < 0)
+ err(1, "VXLAN_CMD_SET_LEARN");
}
static void
@@ -433,6 +567,19 @@ static struct cmd vxlan_cmds[] = {
DEF_CLONE_CMD("learn", 1, setvxlan_learn),
DEF_CLONE_CMD("-learn", 0, setvxlan_learn),
+ DEF_CMD_ARG("vni", setvxlan_vni),
+ DEF_CMD_ARG("local", setvxlan_local),
+ DEF_CMD_ARG("remote", setvxlan_remote),
+ DEF_CMD_ARG("group", setvxlan_group),
+ DEF_CMD_ARG("localport", setvxlan_local_port),
+ DEF_CMD_ARG("remoteport", setvxlan_remote_port),
+ DEF_CMD_ARG2("portrange", setvxlan_port_range),
+ DEF_CMD_ARG("timeout", setvxlan_timeout),
+ DEF_CMD_ARG("maxaddr", setvxlan_maxaddr),
+ DEF_CMD_ARG("ttl", setvxlan_ttl),
+ DEF_CMD("learn", 1, setvxlan_learn),
+ DEF_CMD("-learn", 0, setvxlan_learn),
+
DEF_CMD("flush", 0, setvxlan_flush),
DEF_CMD("flushall", 1, setvxlan_flush),
};
Modified: projects/vxlan/sys/net/if_vxlan.c
==============================================================================
--- projects/vxlan/sys/net/if_vxlan.c Tue May 20 14:39:22 2014 (r266468)
+++ projects/vxlan/sys/net/if_vxlan.c Tue May 20 14:52:56 2014 (r266469)
@@ -63,7 +63,9 @@ __FBSDID("$FreeBSD$");
#include <netinet/in_var.h>
#include <netinet/in_pcb.h>
#include <netinet/ip.h>
+#include <netinet/ip6.h>
#include <netinet/ip_var.h>
+#include <netinet6/ip6_var.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
@@ -73,6 +75,15 @@ struct vxlan_ftable_entry;
LIST_HEAD(vxlan_ftable_head, vxlan_ftable_entry);
LIST_HEAD(vxlan_softc_head, vxlan_softc);
+#define VXLAN_SO_MC_MAX_GROUPS 32
+
+struct vxlan_socket_mc_info {
+ union vxlan_sockaddr vxlsomc_saddr;
+ union vxlan_sockaddr vxlsomc_gaddr;
+ int vxlsomc_ifidx;
+ int vxlsomc_users;
+};
+
#define VXLAN_SO_VNI_HASH_SHIFT 5
#define VXLAN_SO_VNI_HASH_SIZE (1 << VXLAN_SO_VNI_HASH_SHIFT)
#define VXLAN_SO_VNI_HASH(_vni) ((_vni) % VXLAN_SO_VNI_HASH_SIZE)
@@ -83,8 +94,8 @@ struct vxlan_socket {
u_int vxlso_refcnt;
union vxlan_sockaddr vxlso_laddr;
LIST_ENTRY(vxlan_socket) vxlso_entry;
- /* Lookup hash from VNI to vxlan softc. */
struct vxlan_softc_head vxlso_vni_hash[VXLAN_SO_VNI_HASH_SIZE];
+ struct vxlan_socket_mc_info vxlso_mc[VXLAN_SO_MC_MAX_GROUPS];
};
#define VXLAN_SO_RLOCK(_vso) rw_rlock(&(_vso)->vxlso_lock)
@@ -121,8 +132,8 @@ struct vxlan_ftable_entry {
(vxlan_mac_hash(_sc, _mac) % VXLAN_SC_FTABLE_SIZE)
struct vxlan_statistics {
+ uint32_t ftable_nospace;
uint32_t ftable_lock_upgrade;
-
};
struct vxlan_softc {
@@ -130,13 +141,13 @@ struct vxlan_softc {
struct vxlan_socket *vxl_sock;
struct rwlock vxl_lock;
volatile u_int vxl_refcnt;
+ uint32_t vxl_vni;
union vxlan_sockaddr vxl_src_addr;
union vxlan_sockaddr vxl_dst_addr;
- uint32_t vxl_vni;
uint32_t vxl_flags;
-#define VXLAN_FLAG_INITING 0x0001
-#define VXLAN_FLAG_RELEASED 0x0002
-#define VXLAN_FLAG_NOLEARN 0x0004
+#define VXLAN_FLAG_INIT 0x0001
+#define VXLAN_FLAG_TEARDOWN 0x0002
+#define VXLAN_FLAG_LEARN 0x0004
uint32_t vxl_last_port_hash;
uint16_t vxl_min_port;
@@ -146,7 +157,6 @@ struct vxlan_softc {
/* Lookup table from MAC address to forwarding entry. */
uint32_t vxl_ftable_cnt;
uint32_t vxl_ftable_max;
- uint32_t vxl_ftable_nospace;
uint32_t vxl_ftable_timeout;
uint32_t vxl_ftable_hash_key;
struct vxlan_ftable_head *vxl_ftable;
@@ -154,8 +164,19 @@ struct vxlan_softc {
/* Derived from vxl_dst_addr. */
struct vxlan_ftable_entry vxl_default_fe;
- struct vxlan_statistics vxl_stats;
+#ifdef INET
+ struct ip_moptions *vxl_im4o;
+#endif
+#ifdef INET6
+ struct ip6_moptions *vxl_im6o;
+#endif
+
int vxl_unit;
+ int vxl_ifindex;
+ int vxl_vso_mc_index;
+ struct vxlan_statistics vxl_stats;
+ struct sysctl_oid *vxl_sysctl_node;
+ struct sysctl_ctx_list vxl_sysctl_ctx;
struct callout vxl_callout;
uint8_t vxl_hwaddr[ETHER_ADDR_LEN];
LIST_ENTRY(vxlan_softc) vxl_entry;
@@ -195,7 +216,7 @@ static struct vxlan_ftable_entry *
static int vxlan_ftable_entry_insert(struct vxlan_softc *,
struct vxlan_ftable_entry *);
static void vxlan_ftable_entry_destroy(struct vxlan_softc *,
- struct vxlan_ftable_entry *fe);
+ struct vxlan_ftable_entry *);
static int vxlan_ftable_update(struct vxlan_softc *,
const struct sockaddr *, const uint8_t *);
static void vxlan_ftable_expire(struct vxlan_softc *);
@@ -203,7 +224,7 @@ static void vxlan_ftable_expire(struct v
static struct vxlan_socket *
vxlan_socket_alloc(const union vxlan_sockaddr *);
static void vxlan_socket_destroy(struct vxlan_socket *);
-static int vxlan_socket_create(struct ifnet *,
+static int vxlan_socket_create(struct ifnet *, int,
const union vxlan_sockaddr *, struct vxlan_socket **);
static int vxlan_socket_insert_softc(struct vxlan_socket *,
struct vxlan_softc *);
@@ -213,11 +234,27 @@ static struct vxlan_softc *
static struct vxlan_softc *
vxlan_socket_lookup_softc(struct vxlan_socket *, uint32_t);
+static struct vxlan_socket *
+ vxlan_socket_mc_lookup(const union vxlan_sockaddr *);
+static int vxlan_socket_mc_join_group(struct vxlan_socket *,
+ const union vxlan_sockaddr *, const union vxlan_sockaddr *,
+ int *, union vxlan_sockaddr *);
+static int vxlan_socket_mc_leave_group(struct vxlan_socket *,
+ const union vxlan_sockaddr *,
+ const union vxlan_sockaddr *, int);
+static int vxlan_socket_mc_add_group(struct vxlan_socket *,
+ const union vxlan_sockaddr *, const union vxlan_sockaddr *,
+ int, int *);
+static void vxlan_socket_mc_release_group_by_idx(struct vxlan_socket *,
+ int);
+
+static struct vxlan_socket *
+ vxlan_socket_lookup(union vxlan_sockaddr *vxlsa);
+
static int vxlan_valid_init_config(struct vxlan_softc *);
static void vxlan_init(void *);
-static void vxlan_stop(struct vxlan_softc *);
-static void vxlan_release_socket(struct vxlan_softc *);
static void vxlan_release(struct vxlan_softc *);
+static void vxlan_teardown(struct vxlan_softc *);
static void vxlan_timer(void *);
static uint16_t vxlan_pick_source_port(struct vxlan_softc *,
const struct ether_header *);
@@ -225,6 +262,8 @@ static void vxlan_encap_header(struct vx
int, uint16_t, uint16_t);
static int vxlan_encap4(struct vxlan_softc *,
const union vxlan_sockaddr *, struct mbuf *);
+static int vxlan_encap6(struct vxlan_softc *,
+ const union vxlan_sockaddr *, struct mbuf *);
static int vxlan_transmit(struct ifnet *, struct mbuf *);
static void vxlan_qflush(struct ifnet *);
@@ -239,13 +278,14 @@ static int vxlan_ctrl_set_local_addr(str
static int vxlan_ctrl_set_remote_addr(struct vxlan_softc *, void *);
static int vxlan_ctrl_set_local_port(struct vxlan_softc *, void *);
static int vxlan_ctrl_set_remote_port(struct vxlan_softc *, void *);
-static int vxlan_ctrl_flush(struct vxlan_softc *, void *);
-static int vxlan_ctrl_ftable_timeout(struct vxlan_softc *, void *);
-static int vxlan_ctrl_ftable_max(struct vxlan_softc *, void *);
+static int vxlan_ctrl_set_port_range(struct vxlan_softc *, void *);
+static int vxlan_ctrl_set_ftable_timeout(struct vxlan_softc *, void *);
+static int vxlan_ctrl_set_ftable_max(struct vxlan_softc *, void *);
+static int vxlan_ctrl_set_ttl(struct vxlan_softc *, void *);
+static int vxlan_ctrl_set_learn(struct vxlan_softc *, void *);
static int vxlan_ctrl_ftable_entry_add(struct vxlan_softc *, void *);
static int vxlan_ctrl_ftable_entry_rem(struct vxlan_softc *, void *);
-static int vxlan_ctrl_ttl(struct vxlan_softc *, void *);
-static int vxlan_ctrl_learn(struct vxlan_softc *, void *);
+static int vxlan_ctrl_flush(struct vxlan_softc *, void *);
static int vxlan_ioctl_drvspec(struct vxlan_softc *,
struct ifdrv *, int);
static int vxlan_ioctl_ifflags(struct vxlan_softc *);
@@ -270,21 +310,16 @@ static void vxlan_sockaddr_in_copy(union
static int vxlan_sockaddr_in_any(const union vxlan_sockaddr *);
static int vxlan_sockaddr_in_multicast(const union vxlan_sockaddr *);
-static int vxlan_initing_or_running(struct vxlan_softc *);
+static int vxlan_can_change_config(struct vxlan_softc *);
static int vxlan_check_vni(uint32_t);
static int vxlan_check_ttl(int);
static int vxlan_check_ftable_timeout(uint32_t);
static int vxlan_check_ftable_max(uint32_t);
+static void vxlan_sysctl_setup(struct vxlan_softc *);
+static void vxlan_sysctl_destroy(struct vxlan_softc *);
static int vxlan_tunable_int(struct vxlan_softc *, const char *, int);
-SYSCTL_DECL(_net_link);
-SYSCTL_NODE(_net_link, OID_AUTO, vxlan, CTLFLAG_RW, 0,
- "Virtual eXtensible Local Area Network");
-
-static int vxlan_legacy_port = 0;
-TUNABLE_INT("net.link.vxlan.legacy_port", &vxlan_legacy_port);
-
static const char vxlan_name[] = "vxlan";
static MALLOC_DEFINE(M_VXLAN, vxlan_name,
"Virtual eXtensible LAN Interface");
@@ -292,6 +327,15 @@ static struct if_clone *vxlan_cloner;
static struct mtx vxlan_list_mtx;
static LIST_HEAD(, vxlan_socket) vxlan_socket_list;
+SYSCTL_DECL(_net_link);
+SYSCTL_NODE(_net_link, OID_AUTO, vxlan, CTLFLAG_RW, 0,
+ "Virtual eXtensible Local Area Network");
+
+static int vxlan_legacy_port = 0;
+TUNABLE_INT("net.link.vxlan.legacy_port", &vxlan_legacy_port);
+static int vxlan_reuse_port = 0;
+TUNABLE_INT("net.link.vxlan.reuse_port", &vxlan_reuse_port);
+
/* Default maximum number of addresses in the forwarding table. */
#ifndef VXLAN_FTABLE_MAX
#define VXLAN_FTABLE_MAX 2000
@@ -302,6 +346,14 @@ static LIST_HEAD(, vxlan_socket) vxlan_s
#define VXLAN_FTABLE_TIMEOUT (20 * 60)
#endif
+/*
+ * Maximum timeout (in seconds) of addresses learned in the forwarding
+ * table.
+ */
+#ifndef VXLAN_FTABLE_MAX_TIMEOUT
+#define VXLAN_FTABLE_MAX_TIMEOUT (60 * 60 * 24)
+#endif
+
/* Number of seconds between pruning attempts of the forwarding table. */
#ifndef VXLAN_FTABLE_PRUNE
#define VXLAN_FTABLE_PRUNE (5 * 60)
@@ -327,72 +379,78 @@ static const struct vxlan_control vxlan_
[VXLAN_CMD_SET_VNI] =
{ vxlan_ctrl_set_vni,
- sizeof(struct ifvxlancfg),
+ sizeof(struct ifvxlancmd),
VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER,
},
[VXLAN_CMD_SET_LOCAL_ADDR] =
{ vxlan_ctrl_set_local_addr,
- sizeof(struct ifvxlancfg),
+ sizeof(struct ifvxlancmd),
VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER,
},
[VXLAN_CMD_SET_REMOTE_ADDR] =
{ vxlan_ctrl_set_remote_addr,
- sizeof(struct ifvxlancfg),
+ sizeof(struct ifvxlancmd),
VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER,
},
[VXLAN_CMD_SET_LOCAL_PORT] =
{ vxlan_ctrl_set_local_port,
- sizeof(struct ifvxlancfg),
+ sizeof(struct ifvxlancmd),
VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER,
},
[VXLAN_CMD_SET_REMOTE_PORT] =
{ vxlan_ctrl_set_remote_port,
- sizeof(struct ifvxlancfg),
+ sizeof(struct ifvxlancmd),
VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER,
},
- [VXLAN_CMD_FLUSH] =
- { vxlan_ctrl_flush,
+ [VXLAN_CMD_SET_PORT_RANGE] =
+ { vxlan_ctrl_set_port_range,
sizeof(struct ifvxlancmd),
VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER,
},
- [VXLAN_CMD_FTABLE_TIMEOUT] =
- { vxlan_ctrl_ftable_timeout,
+ [VXLAN_CMD_SET_FTABLE_TIMEOUT] =
+ { vxlan_ctrl_set_ftable_timeout,
sizeof(struct ifvxlancmd),
VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER,
},
- [VXLAN_CMD_FTABLE_MAX] =
- { vxlan_ctrl_ftable_max,
+ [VXLAN_CMD_SET_FTABLE_MAX] =
+ { vxlan_ctrl_set_ftable_max,
sizeof(struct ifvxlancmd),
VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER,
},
- [VXLAN_CMD_FTABLE_ENTRY_ADD] =
- { vxlan_ctrl_ftable_entry_add,
+ [VXLAN_CMD_SET_TTL] =
+ { vxlan_ctrl_set_ttl,
sizeof(struct ifvxlancmd),
VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER,
},
- [VXLAN_CMD_FTABLE_ENTRY_REM] =
- { vxlan_ctrl_ftable_entry_rem,
+ [VXLAN_CMD_SET_LEARN] =
+ { vxlan_ctrl_set_learn,
sizeof(struct ifvxlancmd),
VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER,
},
- [VXLAN_CMD_TTL] =
- { vxlan_ctrl_ttl,
+ [VXLAN_CMD_FTABLE_ENTRY_ADD] =
+ { vxlan_ctrl_ftable_entry_add,
+ sizeof(struct ifvxlancmd),
+ VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER,
+ },
+
+ [VXLAN_CMD_FTABLE_ENTRY_REM] =
+ { vxlan_ctrl_ftable_entry_rem,
sizeof(struct ifvxlancmd),
VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER,
},
- [VXLAN_CMD_LEARN] =
- { vxlan_ctrl_learn,
+ [VXLAN_CMD_FLUSH] =
+ { vxlan_ctrl_flush,
sizeof(struct ifvxlancmd),
VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER,
},
@@ -415,7 +473,6 @@ vxlan_ftable_addr_cmp(const uint8_t *a,
static void
vxlan_ftable_init(struct vxlan_softc *sc)
{
- static const uint8_t mac[ETHER_ADDR_LEN];
int i;
sc->vxl_ftable = malloc(sizeof(struct vxlan_ftable_head) *
@@ -424,9 +481,6 @@ vxlan_ftable_init(struct vxlan_softc *sc
for (i = 0; i < VXLAN_SC_FTABLE_SIZE; i++)
LIST_INIT(&sc->vxl_ftable[i]);
sc->vxl_ftable_hash_key = arc4random();
-
- vxlan_ftable_entry_init(sc, &sc->vxl_default_fe, mac,
- &sc->vxl_dst_addr.sa, VXLAN_FE_FLAG_STATIC);
}
static void
@@ -517,7 +571,7 @@ again:
}
if (sc->vxl_ftable_cnt >= sc->vxl_ftable_max) {
- sc->vxl_ftable_nospace++;
+ sc->vxl_stats.ftable_nospace++;
return (ENOSPC);
}
@@ -651,7 +705,7 @@ out:
}
static struct vxlan_socket *
-vxlan_socket_alloc(const union vxlan_sockaddr *vxlsa)
+vxlan_socket_alloc(const union vxlan_sockaddr *sa)
{
struct vxlan_socket *vso;
int i;
@@ -661,7 +715,7 @@ vxlan_socket_alloc(const union vxlan_soc
refcount_init(&vso->vxlso_refcnt, 0);
for (i = 0; i < VXLAN_SO_VNI_HASH_SIZE; i++)
LIST_INIT(&vso->vxlso_vni_hash[i]);
- vso->vxlso_laddr = *vxlsa;
+ vso->vxlso_laddr = *sa;
return (vso);
}
@@ -671,11 +725,20 @@ vxlan_socket_destroy(struct vxlan_socket
{
struct socket *so;
struct inpcb *inp;
+ struct vxlan_socket_mc_info *mc;
int i;
+ for (i = 0; i < VXLAN_SO_MC_MAX_GROUPS; i++) {
+ mc = &vso->vxlso_mc[i];
+ KASSERT(mc->vxlsomc_gaddr.sa.sa_family == AF_UNSPEC,
+ ("%s: socket %p mc[%d] still has address",
+ __func__, vso, i));
+ }
+
for (i = 0; i < VXLAN_SO_VNI_HASH_SIZE; i++) {
KASSERT(LIST_EMPTY(&vso->vxlso_vni_hash[i]),
- ("%s: socket %p vni_hash[%d] not empty", __func__, vso, i));
+ ("%s: socket %p vni_hash[%d] not empty",
+ __func__, vso, i));
}
so = vso->vxlso_sock;
@@ -734,57 +797,114 @@ vxlan_socket_insert(struct vxlan_socket
}
static int
-vxlan_socket_create(struct ifnet *ifp, const union vxlan_sockaddr *vxlsa,
- struct vxlan_socket **vsop)
+vxlan_socket_init(struct vxlan_socket *vso, struct ifnet *ifp)
{
- union vxlan_sockaddr baddr;
- struct vxlan_socket *vso;
- struct thread *td;
struct inpcb *inp;
+ struct thread *td;
int error;
td = curthread;
- *vsop = NULL;
-
- vso = vxlan_socket_alloc(vxlsa);
- if (vso == NULL)
- return (ENOMEM);
error = socreate(vso->vxlso_laddr.sa.sa_family, &vso->vxlso_sock,
SOCK_DGRAM, IPPROTO_UDP, td->td_ucred, td);
if (error) {
if_printf(ifp, "cannot create socket: %d\n", error);
- goto fail;
+ return (error);
}
inp = sotoinpcb(vso->vxlso_sock);
-
/*
* XXX: Use a spare field in the inpcb to obtain the vxlan socket
* in the tunneling callback. We instead should be able to pass a
* context to the tunneling callback.
*/
- INP_WLOCK(inp);
MPASS(inp->inp_pspare[0] == NULL);
inp->inp_pspare[0] = vso;
- INP_WUNLOCK(inp);
error = udp_set_kernel_tunneling(vso->vxlso_sock, vxlan_rcv_udp_packet);
if (error) {
if_printf(ifp, "cannot set tunneling function: %d\n", error);
- goto fail;
+ return (error);
}
- baddr = vso->vxlso_laddr;
- MPASS(baddr.in4.sin_port != 0);
+ if (vxlan_reuse_port != 0) {
+ struct sockopt sopt;
+ int val = 1;
+
+ bzero(&sopt, sizeof(sopt));
+ sopt.sopt_dir = SOPT_SET;
+ sopt.sopt_level = IPPROTO_IP;
+ sopt.sopt_name = SO_REUSEPORT;
+ sopt.sopt_val = &val;
+ sopt.sopt_valsize = sizeof(val);
+ error = sosetopt(vso->vxlso_sock, &sopt);
+ if (error) {
+ if_printf(ifp,
+ "cannot set REUSEADDR socket opt: %d\n", error);
+ return (error);
+ }
+ }
- error = sobind(vso->vxlso_sock, &baddr.sa, td);
+ return (0);
+}
+
+static int
+vxlan_socket_bind(struct vxlan_socket *vso, struct ifnet *ifp)
+{
+ union vxlan_sockaddr laddr;
+ struct thread *td;
+ int error;
+
+ td = curthread;
+ laddr = vso->vxlso_laddr;
+
+ error = sobind(vso->vxlso_sock, &laddr.sa, td);
if (error) {
if (error != EADDRINUSE)
if_printf(ifp, "cannot bind socket: %d\n", error);
- goto fail;
+ return (error);
+ }
+
+ return (0);
+}
+
+static int
+vxlan_socket_create(struct ifnet *ifp, int multicast,
+ const union vxlan_sockaddr *saddr, struct vxlan_socket **vsop)
+{
+ union vxlan_sockaddr laddr;
+ struct vxlan_socket *vso;
+ int error;
+
+ laddr = *saddr;
+
+ /*
+ * If this socket will be multicast, then only the local port
+ * must be specified when binding.
+ */
+ if (multicast != 0) {
+ if (VXLAN_SOCKADDR_IS_IPV4(&laddr))
+ laddr.in4.sin_addr.s_addr = INADDR_ANY;
+ else
+ laddr.in6.sin6_addr = in6addr_any;
}
+ vso = vxlan_socket_alloc(&laddr);
+ if (vso == NULL)
+ return (ENOMEM);
+
+ error = vxlan_socket_init(vso, ifp);
+ if (error)
+ goto fail;
+
+ error = vxlan_socket_bind(vso, ifp);
+ if (error)
+ goto fail;
+
+ /*
+ * There is a small window between the bind and the insert, but
+ * let's not worry about that for now.
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-projects
mailing list