Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F149285440
D14222.1789818788.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
29 KB
Referenced Files
None
Subscribers
None
D14222.1789818788.diff
View Options
Index: sbin/ifconfig/ifconfig.8
===================================================================
--- sbin/ifconfig/ifconfig.8
+++ sbin/ifconfig/ifconfig.8
@@ -2734,13 +2734,18 @@
When the interface is configured in unicast mode, the listening socket
is bound to this address.
.It Cm vxlanremote Ar address
-The interface can be configured in a unicast, or point-to-point, mode
-to create a tunnel between two hosts.
-This is the IP address of the remote end of the tunnel.
+The interface can be configured in a unicast mode, where frames without a
+learned address are flooded to specific remote hosts. This adds the specified
+address to the list of destination hosts.
+.It Cm -vxlanremote Ar address
+Remove the specified address from the list of destination unicast hosts.
.It Cm vxlangroup Ar address
The interface can be configured in a multicast mode
to create a virtual network of hosts.
This is the IP multicast group address the interface will join.
+The multicast destination will not be used if any unicast destinations are
+specified by
+.Cm vxlanremote .
.It Cm vxlanlocalport Ar port
The port number the interface will listen on.
The default port number is 4789.
Index: sbin/ifconfig/ifvxlan.c
===================================================================
--- sbin/ifconfig/ifvxlan.c
+++ sbin/ifconfig/ifvxlan.c
@@ -98,13 +98,52 @@
}
static void
+vxlan_status_remotes(int s)
+{
+ struct ifvxlanreqremotes rmts;
+ struct ifvxlanreqremote *rmt;
+ struct sockaddr *rsa;
+ char dst[NI_MAXHOST], dstport[NI_MAXSERV];
+ char *inbuf = NULL, *ninbuf;
+ int i, len = 2048, ipv6;
+
+ for (;;) {
+ ninbuf = realloc(inbuf, len);
+ if (ninbuf == NULL)
+ err(1, "unable to allocate remotes buffer");
+ rmts.vxlr_len = len;
+ rmts.vxlr_buf = inbuf = ninbuf;
+ if (do_cmd(s, VXLAN_CMD_GET_REMOTES, &rmts, sizeof(rmts), 0) < 0)
+ err(1, "unable to get list of remotes");
+ if ((rmts.vxlr_len + sizeof(*rmt)) < len)
+ break;
+ len *= 2;
+ }
+
+ for (i = 0; i < (rmts.vxlr_len / sizeof(*rmt)); i++) {
+ rmt = rmts.vxlr_rmt + i;
+ rsa = &rmt->vxlr_sa.sa;
+ ipv6 = rsa->sa_family == AF_INET6;
+
+ if (getnameinfo(rsa, rsa->sa_len, dst, sizeof(dst),
+ dstport, sizeof(dstport), NI_NUMERICHOST | NI_NUMERICSERV) != 0)
+ dst[0] = dstport[0] = '\0';
+
+ printf("\n\t\t\t%s%s%s",
+ ipv6 ? "[" : "", dst, ipv6 ? "]" : "");
+ }
+
+ free(inbuf);
+}
+
+static void
vxlan_status(int s)
{
struct ifvxlancfg cfg;
- char src[NI_MAXHOST], dst[NI_MAXHOST];
+ char src[NI_MAXHOST], group[NI_MAXHOST];
char srcport[NI_MAXSERV], dstport[NI_MAXSERV];
- struct sockaddr *lsa, *rsa;
- int vni, mc, ipv6;
+ struct sockaddr *lsa, *msa;
+ int vni, ipv6;
bzero(&cfg, sizeof(cfg));
@@ -113,8 +152,8 @@
vni = cfg.vxlc_vni;
lsa = &cfg.vxlc_local_sa.sa;
- rsa = &cfg.vxlc_remote_sa.sa;
- ipv6 = rsa->sa_family == AF_INET6;
+ msa = &cfg.vxlc_mcast_sa.sa;
+ ipv6 = lsa->sa_family == AF_INET6;
/* Just report nothing if the network identity isn't set yet. */
if (vni >= VXLAN_VNI_MAX)
@@ -123,33 +162,30 @@
if (getnameinfo(lsa, lsa->sa_len, src, sizeof(src),
srcport, sizeof(srcport), NI_NUMERICHOST | NI_NUMERICSERV) != 0)
src[0] = srcport[0] = '\0';
- if (getnameinfo(rsa, rsa->sa_len, dst, sizeof(dst),
+ if (getnameinfo(msa, msa->sa_len, group, sizeof(group),
dstport, sizeof(dstport), NI_NUMERICHOST | NI_NUMERICSERV) != 0)
- dst[0] = dstport[0] = '\0';
+ group[0] = dstport[0] = '\0';
- if (!ipv6) {
- struct sockaddr_in *sin = (struct sockaddr_in *)rsa;
- mc = IN_MULTICAST(ntohl(sin->sin_addr.s_addr));
- } else {
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)rsa;
- mc = IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr);
- }
-
printf("\tvxlan vni %d", vni);
printf(" local %s%s%s:%s", ipv6 ? "[" : "", src, ipv6 ? "]" : "",
srcport);
- printf(" %s %s%s%s:%s", mc ? "group" : "remote", ipv6 ? "[" : "",
- dst, ipv6 ? "]" : "", dstport);
+ if (cfg.vxlc_remote_cnt == 0)
+ printf(" group %s%s%s",
+ ipv6 ? "[" : "",
+ group, ipv6 ? "]" : "");
+
if (verbose) {
printf("\n\t\tconfig: ");
- printf("%slearning portrange %d-%d ttl %d",
+ printf("%slearning portrange %d-%d ttl %d rport %d",
cfg.vxlc_learn ? "" : "no", cfg.vxlc_port_min,
- cfg.vxlc_port_max, cfg.vxlc_ttl);
+ cfg.vxlc_port_max, cfg.vxlc_ttl, cfg.vxlc_remote_port);
printf("\n\t\tftable: ");
printf("cnt %d max %d timeout %d",
cfg.vxlc_ftable_cnt, cfg.vxlc_ftable_max,
cfg.vxlc_ftable_timeout);
+ printf("\n\t\tflooding: %d hosts", cfg.vxlc_remote_cnt);
+ vxlan_status_remotes(s);
}
putchar('\n');
@@ -338,6 +374,55 @@
}
static
+DECL_CMD_FUNC(unsetvxlan_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));
+
+ sa = ai->ai_addr;
+
+ switch (ai->ai_family) {
+#ifdef INET
+ case AF_INET: {
+ struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+
+ if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
+ errx(1, "remote address cannot be multicast");
+
+ cmd.vxlcmd_sa.in4 = *sin;
+ break;
+ }
+#endif
+#ifdef INET6
+ case AF_INET6: {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+
+ if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
+ errx(1, "remote address cannot be multicast");
+
+ cmd.vxlcmd_sa.in6 = *sin6;
+ break;
+ }
+#endif
+ default:
+ errx(1, "remote address %s not supported", addr);
+ }
+
+ freeaddrinfo(ai);
+
+ if (do_cmd(s, VXLAN_CMD_UNSET_REMOTE_ADDR, &cmd, sizeof(cmd), 1) < 0)
+ err(1, "VXLAN_CMD_UNSET_REMOTE_ADDR");
+}
+
+static
DECL_CMD_FUNC(setvxlan_group, addr, d)
{
struct ifvxlancmd cmd;
@@ -384,17 +469,17 @@
if (!vxlan_exists(s)) {
if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) {
- params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR4;
- params.vxlp_remote_sa.in4 = cmd.vxlcmd_sa.in4;
+ params.vxlp_with |= VXLAN_PARAM_WITH_MCAST_GROUP4;
+ params.vxlp_mcast_group4 = cmd.vxlcmd_sa.in4.sin_addr;
} else {
- params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR6;
- params.vxlp_remote_sa.in6 = cmd.vxlcmd_sa.in6;
+ params.vxlp_with |= VXLAN_PARAM_WITH_MCAST_GROUP6;
+ params.vxlp_mcast_group6 = 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");
+ if (do_cmd(s, VXLAN_CMD_SET_MULTICAST_GROUP, &cmd, sizeof(cmd), 1) < 0)
+ err(1, "VXLAN_CMD_SET_MULTICAST_GROUP");
}
static
@@ -607,6 +692,7 @@
DEF_CMD_ARG("vxlanid", setvxlan_vni),
DEF_CMD_ARG("vxlanlocal", setvxlan_local),
DEF_CMD_ARG("vxlanremote", setvxlan_remote),
+ DEF_CMD_ARG("-vxlanremote", unsetvxlan_remote),
DEF_CMD_ARG("vxlangroup", setvxlan_group),
DEF_CMD_ARG("vxlanlocalport", setvxlan_local_port),
DEF_CMD_ARG("vxlanremoteport", setvxlan_remote_port),
Index: sys/net/if_vxlan.h
===================================================================
--- sys/net/if_vxlan.h
+++ sys/net/if_vxlan.h
@@ -73,9 +73,11 @@
#define VXLAN_PARAM_WITH_PORT_RANGE 0x0080
#define VXLAN_PARAM_WITH_FTABLE_TIMEOUT 0x0100
#define VXLAN_PARAM_WITH_FTABLE_MAX 0x0200
-#define VXLAN_PARAM_WITH_MULTICAST_IF 0x0400
-#define VXLAN_PARAM_WITH_TTL 0x0800
-#define VXLAN_PARAM_WITH_LEARN 0x1000
+#define VXLAN_PARAM_WITH_MCAST_GROUP4 0x0400
+#define VXLAN_PARAM_WITH_MCAST_GROUP6 0x0800
+#define VXLAN_PARAM_WITH_MULTICAST_IF 0x1000
+#define VXLAN_PARAM_WITH_TTL 0x2000
+#define VXLAN_PARAM_WITH_LEARN 0x4000
uint32_t vxlp_vni;
union vxlan_sockaddr vxlp_local_sa;
@@ -85,6 +87,8 @@
uint16_t vxlp_min_port;
uint16_t vxlp_max_port;
char vxlp_mc_ifname[IFNAMSIZ];
+ struct in_addr vxlp_mcast_group4;
+ struct in6_addr vxlp_mcast_group6;
uint32_t vxlp_ftable_timeout;
uint32_t vxlp_ftable_max;
uint8_t vxlp_ttl;
@@ -99,31 +103,50 @@
#define VXLAN_CMD_GET_CONFIG 0
#define VXLAN_CMD_SET_VNI 1
#define VXLAN_CMD_SET_LOCAL_ADDR 2
-#define VXLAN_CMD_SET_REMOTE_ADDR 4
-#define VXLAN_CMD_SET_LOCAL_PORT 5
-#define VXLAN_CMD_SET_REMOTE_PORT 6
-#define VXLAN_CMD_SET_PORT_RANGE 7
-#define VXLAN_CMD_SET_FTABLE_TIMEOUT 8
-#define VXLAN_CMD_SET_FTABLE_MAX 9
-#define VXLAN_CMD_SET_MULTICAST_IF 10
-#define VXLAN_CMD_SET_TTL 11
-#define VXLAN_CMD_SET_LEARN 12
-#define VXLAN_CMD_FTABLE_ENTRY_ADD 13
-#define VXLAN_CMD_FTABLE_ENTRY_REM 14
-#define VXLAN_CMD_FLUSH 15
+#define VXLAN_CMD_SET_REMOTE_ADDR 3
+#define VXLAN_CMD_UNSET_REMOTE_ADDR 4
+#define VXLAN_CMD_GET_REMOTES 5
+#define VXLAN_CMD_SET_LOCAL_PORT 6
+#define VXLAN_CMD_SET_REMOTE_PORT 7
+#define VXLAN_CMD_SET_PORT_RANGE 8
+#define VXLAN_CMD_SET_FTABLE_TIMEOUT 9
+#define VXLAN_CMD_SET_FTABLE_MAX 10
+#define VXLAN_CMD_SET_MULTICAST_GROUP 11
+#define VXLAN_CMD_SET_MULTICAST_IF 12
+#define VXLAN_CMD_SET_TTL 13
+#define VXLAN_CMD_SET_LEARN 14
+#define VXLAN_CMD_FTABLE_ENTRY_ADD 15
+#define VXLAN_CMD_FTABLE_ENTRY_REM 16
+#define VXLAN_CMD_FLUSH 17
struct ifvxlancfg {
uint32_t vxlc_vni;
union vxlan_sockaddr vxlc_local_sa;
- union vxlan_sockaddr vxlc_remote_sa;
+ union vxlan_sockaddr vxlc_mcast_sa;
uint32_t vxlc_mc_ifindex;
uint32_t vxlc_ftable_cnt;
uint32_t vxlc_ftable_max;
uint32_t vxlc_ftable_timeout;
+ uint32_t vxlc_remote_cnt;
+ uint16_t vxlc_remote_port;
uint16_t vxlc_port_min;
uint16_t vxlc_port_max;
uint8_t vxlc_learn;
uint8_t vxlc_ttl;
+};
+
+struct ifvxlanreqremote {
+ union vxlan_sockaddr vxlr_sa;
+};
+
+struct ifvxlanreqremotes {
+ uint32_t vxlr_len;
+ union {
+ caddr_t vxlru_buf;
+ struct ifvxlanreqremote *vxlru_rmt;
+ } vxlr_u;
+#define vxlr_buf vxlr_u.vxlru_buf
+#define vxlr_rmt vxlr_u.vxlru_rmt
};
struct ifvxlancmd {
Index: sys/net/if_vxlan.c
===================================================================
--- sys/net/if_vxlan.c
+++ sys/net/if_vxlan.c
@@ -139,18 +139,27 @@
uint32_t ftable_lock_upgrade_failed;
};
+struct vxlan_rmtlist_entry {
+ LIST_ENTRY(vxlan_rmtlist_entry) vxlre_next;
+ union vxlan_sockaddr vxlre_raddr;
+};
+
+#define VXLAN_REMOTES_MAX 64
+
struct vxlan_softc {
struct ifnet *vxl_ifp;
struct vxlan_socket *vxl_sock;
uint32_t vxl_vni;
union vxlan_sockaddr vxl_src_addr;
- union vxlan_sockaddr vxl_dst_addr;
+ LIST_HEAD(, vxlan_rmtlist_entry) vxl_rmtlist;
+ uint32_t vxl_rmtlist_cnt;
uint32_t vxl_flags;
#define VXLAN_FLAG_INIT 0x0001
#define VXLAN_FLAG_TEARDOWN 0x0002
#define VXLAN_FLAG_LEARN 0x0004
uint32_t vxl_port_hash_key;
+ uint16_t vxl_dst_port;
uint16_t vxl_min_port;
uint16_t vxl_max_port;
uint8_t vxl_ttl;
@@ -162,9 +171,7 @@
uint32_t vxl_ftable_hash_key;
struct vxlan_ftable_head *vxl_ftable;
- /* Derived from vxl_dst_addr. */
- struct vxlan_ftable_entry vxl_default_fe;
-
+ union vxlan_sockaddr vxl_mcast_addr;
struct ip_moptions *vxl_im4o;
struct ip6_moptions *vxl_im6o;
@@ -239,6 +246,12 @@
static void vxlan_ftable_entry_dump(struct vxlan_ftable_entry *,
struct sbuf *);
+static int vxlan_rmtlist_entry_add(struct vxlan_softc *,
+ struct vxlan_rmtlist_entry *);
+static int vxlan_rmtlist_entry_remove(struct vxlan_softc *,
+ union vxlan_sockaddr *);
+static void vxlan_rmtlist_flush(struct vxlan_softc *);
+
static struct vxlan_socket *
vxlan_socket_alloc(const union vxlan_sockaddr *);
static void vxlan_socket_destroy(struct vxlan_socket *);
@@ -306,11 +319,14 @@
static int vxlan_ctrl_set_vni(struct vxlan_softc *, void *);
static int vxlan_ctrl_set_local_addr(struct vxlan_softc *, void *);
static int vxlan_ctrl_set_remote_addr(struct vxlan_softc *, void *);
+static int vxlan_ctrl_unset_remote_addr(struct vxlan_softc *, void *);
+static int vxlan_ctrl_get_remotes(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_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_multicast_group(struct vxlan_softc * , void *);
static int vxlan_ctrl_set_multicast_if(struct vxlan_softc * , void *);
static int vxlan_ctrl_set_ttl(struct vxlan_softc *, void *);
static int vxlan_ctrl_set_learn(struct vxlan_softc *, void *);
@@ -454,6 +470,16 @@
VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER,
},
+ [VXLAN_CMD_UNSET_REMOTE_ADDR] =
+ { vxlan_ctrl_unset_remote_addr, sizeof(struct ifvxlancmd),
+ VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER,
+ },
+
+ [VXLAN_CMD_GET_REMOTES] =
+ { vxlan_ctrl_get_remotes, sizeof(struct ifvxlanreqremotes),
+ VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_COPYOUT,
+ },
+
[VXLAN_CMD_SET_LOCAL_PORT] =
{ vxlan_ctrl_set_local_port, sizeof(struct ifvxlancmd),
VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER,
@@ -479,6 +505,11 @@
VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER,
},
+ [VXLAN_CMD_SET_MULTICAST_GROUP] =
+ { vxlan_ctrl_set_multicast_group, sizeof(struct ifvxlancmd),
+ VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER,
+ },
+
[VXLAN_CMD_SET_MULTICAST_IF] =
{ vxlan_ctrl_set_multicast_if, sizeof(struct ifvxlancmd),
VXLAN_CTRL_FLAG_COPYIN | VXLAN_CTRL_FLAG_SUSER,
@@ -648,12 +679,8 @@
union vxlan_sockaddr vxlsa;
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;
+ vxlsa.in4.sin_port = sc->vxl_dst_port;
if (VXLAN_SOCKADDR_IS_IPV6(&vxlsa)) {
error = vxlan_sockaddr_in6_embedscope(&vxlsa);
@@ -843,6 +870,80 @@
sbuf_setpos(sb, len);
}
+static int
+vxlan_rmtlist_entry_add(struct vxlan_softc *sc,
+ struct vxlan_rmtlist_entry *re)
+{
+ struct vxlan_rmtlist_entry *lre;
+ int found;
+
+ VXLAN_LOCK_WASSERT(sc);
+
+ if (sc->vxl_rmtlist_cnt == VXLAN_REMOTES_MAX)
+ return (ENOSPC);
+
+ found = 0;
+ LIST_FOREACH(lre, &sc->vxl_rmtlist, vxlre_next) {
+ if (bcmp(&re->vxlre_raddr.sa, &lre->vxlre_raddr.sa,
+ re->vxlre_raddr.sa.sa_len) == 0) {
+ found++;
+ break;
+ }
+ }
+
+ if (found)
+ return (EEXIST);
+
+ LIST_INSERT_HEAD(&sc->vxl_rmtlist, re, vxlre_next);
+ sc->vxl_rmtlist_cnt++;
+
+ return (0);
+}
+
+static int
+vxlan_rmtlist_entry_remove(struct vxlan_softc *sc,
+ union vxlan_sockaddr *vxlsa)
+{
+ struct vxlan_rmtlist_entry *lre, *tre;
+ int found;
+
+ VXLAN_LOCK_WASSERT(sc);
+
+ if (LIST_EMPTY(&sc->vxl_rmtlist))
+ return (ENOENT);
+
+ found = 0;
+ LIST_FOREACH_SAFE(lre, &sc->vxl_rmtlist, vxlre_next, tre) {
+ if (bcmp(&vxlsa->sa, &lre->vxlre_raddr.sa,
+ vxlsa->sa.sa_len) == 0) {
+ LIST_REMOVE(lre, vxlre_next);
+ free(lre, M_VXLAN);
+ sc->vxl_rmtlist_cnt--;
+ found++;
+ break;
+ }
+ }
+
+ if (!found)
+ return (ENOENT);
+
+ return (0);
+}
+
+static void
+vxlan_rmtlist_flush(struct vxlan_softc *sc)
+{
+ struct vxlan_rmtlist_entry *lre, *tre;
+
+ VXLAN_LOCK_WASSERT(sc);
+
+ LIST_FOREACH_SAFE(lre, &sc->vxl_rmtlist, vxlre_next, tre) {
+ LIST_REMOVE(lre, vxlre_next);
+ free(lre, M_VXLAN);
+ sc->vxl_rmtlist_cnt--;
+ }
+}
+
static struct vxlan_socket *
vxlan_socket_alloc(const union vxlan_sockaddr *sa)
{
@@ -1443,7 +1544,7 @@
const union vxlan_sockaddr *group;
int error;
- group = &sc->vxl_dst_addr;
+ group = &sc->vxl_mcast_addr;
error = 0;
if (sc->vxl_mc_ifname[0] != '\0') {
@@ -1479,16 +1580,16 @@
{
struct vxlan_socket *vso;
struct ifnet *ifp;
- union vxlan_sockaddr *saddr, *daddr;
- int multicast, error;
+ union vxlan_sockaddr *saddr, *gaddr;
+ int multicast = 0, error;
vso = NULL;
ifp = sc->vxl_ifp;
saddr = &sc->vxl_src_addr;
- daddr = &sc->vxl_dst_addr;
+ gaddr = &sc->vxl_mcast_addr;
- multicast = vxlan_sockaddr_in_multicast(daddr);
- MPASS(multicast != -1);
+ if (gaddr->sa.sa_len != 0)
+ multicast = 1;
sc->vxl_vso_mc_index = -1;
/*
@@ -1514,7 +1615,7 @@
if (error)
goto out;
- error = vxlan_socket_mc_add_group(vso, daddr, saddr,
+ error = vxlan_socket_mc_add_group(vso, gaddr, saddr,
sc->vxl_mc_ifindex, &sc->vxl_vso_mc_index);
if (error)
goto out;
@@ -1554,9 +1655,9 @@
ifp = sc->vxl_ifp;
ifp->if_hdrlen = ETHER_HDR_LEN + sizeof(struct vxlanudphdr);
- if (VXLAN_SOCKADDR_IS_IPV4(&sc->vxl_dst_addr) != 0)
+ if (VXLAN_SOCKADDR_IS_IPV4(&sc->vxl_src_addr) != 0)
ifp->if_hdrlen += sizeof(struct ip);
- else if (VXLAN_SOCKADDR_IS_IPV6(&sc->vxl_dst_addr) != 0)
+ else if (VXLAN_SOCKADDR_IS_IPV6(&sc->vxl_src_addr) != 0)
ifp->if_hdrlen += sizeof(struct ip6_hdr);
}
@@ -1575,37 +1676,18 @@
goto fail;
}
- if (vxlan_sockaddr_supported(&sc->vxl_dst_addr, 0) == 0) {
- reason = "destination address type is not supported";
- goto fail;
- }
-
- if (vxlan_sockaddr_in_any(&sc->vxl_dst_addr) != 0) {
- reason = "no valid destination address specified";
- goto fail;
- }
-
- if (vxlan_sockaddr_in_multicast(&sc->vxl_dst_addr) == 0 &&
+ if (vxlan_sockaddr_in_any(&sc->vxl_mcast_addr) != 0 &&
sc->vxl_mc_ifname[0] != '\0') {
reason = "can only specify interface with a group address";
goto fail;
}
- if (vxlan_sockaddr_in_any(&sc->vxl_src_addr) == 0) {
- if (VXLAN_SOCKADDR_IS_IPV4(&sc->vxl_src_addr) ^
- VXLAN_SOCKADDR_IS_IPV4(&sc->vxl_dst_addr)) {
- reason = "source and destination address must both "
- "be either IPv4 or IPv6";
- goto fail;
- }
- }
-
if (sc->vxl_src_addr.in4.sin_port == 0) {
reason = "local port not specified";
goto fail;
}
- if (sc->vxl_dst_addr.in4.sin_port == 0) {
+ if (sc->vxl_dst_port == 0) {
reason = "remote port not specified";
goto fail;
}
@@ -1639,7 +1721,6 @@
static void
vxlan_init(void *xsc)
{
- static const uint8_t empty_mac[ETHER_ADDR_LEN];
struct vxlan_softc *sc;
struct ifnet *ifp;
@@ -1662,10 +1743,6 @@
if (vxlan_setup_socket(sc) != 0)
goto out;
- /* Initialize the default forwarding entry. */
- vxlan_ftable_entry_init(sc, &sc->vxl_default_fe, empty_mac,
- &sc->vxl_dst_addr.sa, VXLAN_FE_FLAG_STATIC);
-
VXLAN_WLOCK(sc);
ifp->if_drv_flags |= IFF_DRV_RUNNING;
callout_reset(&sc->vxl_callout, vxlan_ftable_prune_period * hz,
@@ -1831,12 +1908,14 @@
cfg->vxlc_vni = sc->vxl_vni;
memcpy(&cfg->vxlc_local_sa, &sc->vxl_src_addr,
sizeof(union vxlan_sockaddr));
- memcpy(&cfg->vxlc_remote_sa, &sc->vxl_dst_addr,
+ memcpy(&cfg->vxlc_mcast_sa, &sc->vxl_mcast_addr,
sizeof(union vxlan_sockaddr));
cfg->vxlc_mc_ifindex = sc->vxl_mc_ifindex;
cfg->vxlc_ftable_cnt = sc->vxl_ftable_cnt;
cfg->vxlc_ftable_max = sc->vxl_ftable_max;
cfg->vxlc_ftable_timeout = sc->vxl_ftable_timeout;
+ cfg->vxlc_remote_cnt = sc->vxl_rmtlist_cnt;
+ cfg->vxlc_remote_port = sc->vxl_dst_port;
cfg->vxlc_port_min = sc->vxl_min_port;
cfg->vxlc_port_max = sc->vxl_max_port;
cfg->vxlc_learn = (sc->vxl_flags & VXLAN_FLAG_LEARN) != 0;
@@ -1846,8 +1925,6 @@
#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);
@@ -1895,6 +1972,12 @@
return (error);
}
+ if (sc->vxl_rmtlist_cnt != 0 &&
+ vxlsa->sa.sa_family != sc->vxl_src_addr.sa.sa_family) {
+ if_printf(sc->vxl_ifp, "removed all remote hosts because source address family changed\n");
+ vxlan_rmtlist_flush(sc);
+ }
+
VXLAN_WLOCK(sc);
if (vxlan_can_change_config(sc)) {
vxlan_sockaddr_in_copy(&sc->vxl_src_addr, &vxlsa->sa);
@@ -1911,11 +1994,56 @@
{
struct ifvxlancmd *cmd;
union vxlan_sockaddr *vxlsa;
+ struct vxlan_rmtlist_entry *re;
int error;
+ const char *reason;
cmd = arg;
vxlsa = &cmd->vxlcmd_sa;
+ if (vxlan_sockaddr_supported(vxlsa, 0) == 0) {
+ reason = "destination address type is not supported";
+ goto fail;
+ }
+
+ if (vxlan_sockaddr_in_any(vxlsa) != 0) {
+ reason = "no valid destination address specified";
+ goto fail;
+ }
+
+ if (vxlan_sockaddr_in_any(&sc->vxl_src_addr) == 0) {
+ if (VXLAN_SOCKADDR_IS_IPV4(&sc->vxl_src_addr) ^
+ VXLAN_SOCKADDR_IS_IPV4(vxlsa)) {
+ reason = "source and destination address must both "
+ "be either IPv4 or IPv6";
+ goto fail;
+ }
+ }
+
+ re = malloc(sizeof(struct vxlan_rmtlist_entry), M_VXLAN, M_WAITOK | M_ZERO);
+
+ VXLAN_WLOCK(sc);
+ vxlan_sockaddr_in_copy(&re->vxlre_raddr, &vxlsa->sa);
+ error = vxlan_rmtlist_entry_add(sc, re);
+ VXLAN_WUNLOCK(sc);
+
+ return (error);
+
+fail:
+ if_printf(sc->vxl_ifp, "cannot add remote: %s\n", reason);
+ return (EINVAL);
+}
+
+static int
+vxlan_ctrl_unset_remote_addr(struct vxlan_softc *sc, void *arg)
+{
+ struct ifvxlancmd *cmd;
+ union vxlan_sockaddr *vxlsa;
+ int error;
+
+ cmd = arg;
+ vxlsa = &cmd->vxlcmd_sa;
+
if (!VXLAN_SOCKADDR_IS_IPV46(vxlsa))
return (EINVAL);
if (VXLAN_SOCKADDR_IS_IPV6(vxlsa)) {
@@ -1925,17 +2053,70 @@
}
VXLAN_WLOCK(sc);
- if (vxlan_can_change_config(sc)) {
- vxlan_sockaddr_in_copy(&sc->vxl_dst_addr, &vxlsa->sa);
- error = 0;
- } else
- error = EBUSY;
+ error = vxlan_rmtlist_entry_remove(sc, vxlsa);
VXLAN_WUNLOCK(sc);
return (error);
}
static int
+vxlan_ctrl_get_remotes(struct vxlan_softc *sc, void *arg)
+{
+ struct rm_priotracker tracker;
+ struct vxlan_rmtlist_entry *re;
+ struct ifvxlanreqremotes *rmts;
+ struct ifvxlanreqremote rmt;
+ int count, buflen, len, error;
+ char *buf, *outbuf;
+
+ rmts = arg;
+
+ VXLAN_RLOCK(sc, &tracker);
+ count = 0;
+ LIST_FOREACH(re, &sc->vxl_rmtlist, vxlre_next)
+ count++;
+ VXLAN_RUNLOCK(sc, &tracker);
+
+ buflen = sizeof(rmt) * count;
+ if (rmts->vxlr_len == 0) {
+ rmts->vxlr_len = buflen;
+ return (0);
+ }
+
+ outbuf = malloc(buflen, M_TEMP, M_WAITOK | M_ZERO);
+
+ count = 0;
+ buf = outbuf;
+ len = min(rmts->vxlr_len, buflen);
+
+ VXLAN_RLOCK(sc, &tracker);
+ LIST_FOREACH(re, &sc->vxl_rmtlist, vxlre_next) {
+ bzero(&rmt, sizeof(rmt));
+ if (len < sizeof(rmt))
+ break;
+
+ memcpy(&rmt.vxlr_sa, &re->vxlre_raddr.sa,
+ sizeof(union vxlan_sockaddr));
+
+#ifdef INET6
+ if (VXLAN_SOCKADDR_IS_IPV6(&rmt.vxlr_sa))
+ sa6_recoverscope(&rmt.vxlr_sa.in6);
+#endif
+
+ memcpy(buf, &rmt, sizeof(rmt));
+ count++;
+ buf += sizeof(rmt);
+ len -= sizeof(rmt);
+ }
+ VXLAN_RUNLOCK(sc, &tracker);
+
+ rmts->vxlr_len = sizeof(rmt) * count;
+ error = copyout(outbuf, rmts->vxlr_buf, rmts->vxlr_len);
+ free(outbuf, M_TEMP);
+ return (error);
+}
+
+static int
vxlan_ctrl_set_local_port(struct vxlan_softc *sc, void *arg)
{
struct ifvxlancmd *cmd;
@@ -1970,7 +2151,7 @@
VXLAN_WLOCK(sc);
if (vxlan_can_change_config(sc)) {
- sc->vxl_dst_addr.in4.sin_port = htons(cmd->vxlcmd_port);
+ sc->vxl_dst_port = cmd->vxlcmd_port;
error = 0;
} else
error = EBUSY;
@@ -2044,6 +2225,34 @@
}
static int
+vxlan_ctrl_set_multicast_group(struct vxlan_softc *sc, void *arg)
+{
+ struct ifvxlancmd *cmd;
+ union vxlan_sockaddr *vxlsa;
+ int error;
+
+ cmd = arg;
+ vxlsa = &cmd->vxlcmd_sa;
+
+ if (!VXLAN_SOCKADDR_IS_IPV46(vxlsa))
+ return (EINVAL);
+ if (vxlan_sockaddr_in_any(vxlsa) != 0)
+ return (EINVAL);
+ if (vxlan_sockaddr_in_multicast(vxlsa) == 0)
+ return (EINVAL);
+
+ VXLAN_WLOCK(sc);
+ if (vxlan_can_change_config(sc)) {
+ vxlan_sockaddr_in_copy(&sc->vxl_mcast_addr, &vxlsa->sa);
+ error = 0;
+ } else
+ error = EBUSY;
+ VXLAN_WUNLOCK(sc);
+
+ return (error);
+}
+
+static int
vxlan_ctrl_set_multicast_if(struct vxlan_softc * sc, void *arg)
{
struct ifvxlancmd *cmd;
@@ -2120,7 +2329,7 @@
if (vxlan_sockaddr_in_multicast(&vxlsa) != 0)
return (EINVAL);
/* BMV: We could support both IPv4 and IPv6 later. */
- if (vxlsa.sa.sa_family != sc->vxl_dst_addr.sa.sa_family)
+ if (vxlsa.sa.sa_family != sc->vxl_src_addr.sa.sa_family)
return (EAFNOSUPPORT);
if (VXLAN_SOCKADDR_IS_IPV6(&vxlsa)) {
@@ -2133,9 +2342,6 @@
if (fe == NULL)
return (ENOMEM);
- if (vxlsa.in4.sin_port == 0)
- vxlsa.in4.sin_port = sc->vxl_dst_addr.in4.sin_port;
-
vxlan_ftable_entry_init(sc, fe, cmd->vxlcmd_mac, &vxlsa.sa,
VXLAN_FE_FLAG_STATIC);
@@ -2333,7 +2539,7 @@
srcaddr = sc->vxl_src_addr.in4.sin_addr;
srcport = vxlan_pick_source_port(sc, m);
dstaddr = fvxlsa->in4.sin_addr;
- dstport = fvxlsa->in4.sin_port;
+ dstport = htons(sc->vxl_dst_port);
M_PREPEND(m, sizeof(struct ip) + sizeof(struct vxlanudphdr),
M_NOWAIT);
@@ -2390,7 +2596,7 @@
srcaddr = &sc->vxl_src_addr.in6.sin6_addr;
srcport = vxlan_pick_source_port(sc, m);
dstaddr = &fvxlsa->in6.sin6_addr;
- dstport = fvxlsa->in6.sin6_port;
+ dstport = htons(sc->vxl_dst_port);
M_PREPEND(m, sizeof(struct ip6_hdr) + sizeof(struct vxlanudphdr),
M_NOWAIT);
@@ -2450,9 +2656,11 @@
union vxlan_sockaddr vxlsa;
struct vxlan_softc *sc;
struct vxlan_ftable_entry *fe;
+ struct vxlan_rmtlist_entry *re;
struct ifnet *mcifp;
struct ether_header *eh;
int ipv4, error;
+ struct mbuf *nm;
sc = ifp->if_softc;
eh = mtod(m, struct ether_header *);
@@ -2470,22 +2678,52 @@
if ((m->m_flags & (M_BCAST | M_MCAST)) == 0)
fe = vxlan_ftable_entry_lookup(sc, eh->ether_dhost);
- if (fe == NULL)
- fe = &sc->vxl_default_fe;
- vxlan_sockaddr_copy(&vxlsa, &fe->vxlfe_raddr.sa);
- ipv4 = VXLAN_SOCKADDR_IS_IPV4(&vxlsa) != 0;
- if (vxlan_sockaddr_in_multicast(&vxlsa) != 0)
- mcifp = vxlan_multicast_if_ref(sc, ipv4);
-
VXLAN_ACQUIRE(sc);
VXLAN_RUNLOCK(sc, &tracker);
- if (ipv4 != 0)
- error = vxlan_encap4(sc, &vxlsa, m);
- else
- error = vxlan_encap6(sc, &vxlsa, m);
+ if (fe != NULL) {
+ vxlan_sockaddr_copy(&vxlsa, &fe->vxlfe_raddr.sa);
+ ipv4 = VXLAN_SOCKADDR_IS_IPV4(&vxlsa) != 0;
+
+ if (ipv4 != 0)
+ error = vxlan_encap4(sc, &vxlsa, m);
+ else
+ error = vxlan_encap6(sc, &vxlsa, m);
+ } else if (sc->vxl_rmtlist_cnt != 0) {
+ LIST_FOREACH(re, &sc->vxl_rmtlist, vxlre_next) {
+ nm = m_dup(m, M_NOWAIT);
+ if (nm == NULL) {
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ continue;
+ }
+
+ vxlan_sockaddr_copy(&vxlsa, &re->vxlre_raddr.sa);
+
+ ipv4 = VXLAN_SOCKADDR_IS_IPV4(&vxlsa) != 0;
+
+ if (ipv4 != 0)
+ error = vxlan_encap4(sc, &vxlsa, nm);
+ else
+ error = vxlan_encap6(sc, &vxlsa, nm);
+ }
+
+ m_freem(m);
+ } else if (vxlan_sockaddr_in_multicast(&sc->vxl_mcast_addr) != 0) {
+ vxlan_sockaddr_copy(&vxlsa, &sc->vxl_mcast_addr.sa);
+
+ ipv4 = VXLAN_SOCKADDR_IS_IPV4(&vxlsa) != 0;
+ mcifp = vxlan_multicast_if_ref(sc, ipv4);
+
+ if (ipv4 != 0)
+ error = vxlan_encap4(sc, &vxlsa, m);
+ else
+ error = vxlan_encap6(sc, &vxlsa, m);
+ } else {
+ error = ENETDOWN;
+ }
+
vxlan_release(sc);
if (mcifp != NULL)
if_rele(mcifp);
@@ -2596,10 +2834,10 @@
if (!vxlan_tunable_int(sc, "legacy_port", vxlan_legacy_port)) {
sc->vxl_src_addr.in4.sin_port = htons(VXLAN_PORT);
- sc->vxl_dst_addr.in4.sin_port = htons(VXLAN_PORT);
+ sc->vxl_dst_port = VXLAN_PORT;
} else {
sc->vxl_src_addr.in4.sin_port = htons(VXLAN_LEGACY_PORT);
- sc->vxl_dst_addr.in4.sin_port = htons(VXLAN_LEGACY_PORT);
+ sc->vxl_dst_port = VXLAN_LEGACY_PORT;
}
sc->vxl_min_port = V_ipport_firstauto;
@@ -2612,6 +2850,7 @@
static int
vxlan_set_user_config(struct vxlan_softc *sc, struct ifvxlanparam *vxlp)
{
+ struct vxlan_rmtlist_entry *re;
#ifndef INET
if (vxlp->vxlp_with & (VXLAN_PARAM_WITH_LOCAL_ADDR4 |
@@ -2655,21 +2894,25 @@
}
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_family = AF_INET;
- sc->vxl_dst_addr.in4.sin_addr =
+ re = malloc(sizeof(struct vxlan_rmtlist_entry), M_VXLAN, M_WAITOK | M_ZERO);
+ re->vxlre_raddr.in4.sin_len = sizeof(struct sockaddr_in);
+ re->vxlre_raddr.in4.sin_family = AF_INET;
+ re->vxlre_raddr.in4.sin_addr =
vxlp->vxlp_remote_sa.in4.sin_addr;
+ vxlan_rmtlist_entry_add(sc, re);
} 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_family = AF_INET6;
- sc->vxl_dst_addr.in6.sin6_addr =
+ re = malloc(sizeof(struct vxlan_rmtlist_entry), M_VXLAN, M_WAITOK | M_ZERO);
+ re->vxlre_raddr.in6.sin6_len = sizeof(struct sockaddr_in6);
+ re->vxlre_raddr.in6.sin6_family = AF_INET6;
+ re->vxlre_raddr.in6.sin6_addr =
vxlp->vxlp_remote_sa.in6.sin6_addr;
+ vxlan_rmtlist_entry_add(sc, re);
}
if (vxlp->vxlp_with & VXLAN_PARAM_WITH_LOCAL_PORT)
sc->vxl_src_addr.in4.sin_port = htons(vxlp->vxlp_local_port);
if (vxlp->vxlp_with & VXLAN_PARAM_WITH_REMOTE_PORT)
- sc->vxl_dst_addr.in4.sin_port = htons(vxlp->vxlp_remote_port);
+ sc->vxl_dst_port = vxlp->vxlp_remote_port;
if (vxlp->vxlp_with & VXLAN_PARAM_WITH_PORT_RANGE) {
if (vxlp->vxlp_min_port <= vxlp->vxlp_max_port) {
@@ -2678,6 +2921,16 @@
}
}
+ if (vxlp->vxlp_with & VXLAN_PARAM_WITH_MCAST_GROUP4) {
+ sc->vxl_mcast_addr.in4.sin_len = sizeof(struct sockaddr_in);
+ sc->vxl_mcast_addr.in4.sin_family = AF_INET;
+ sc->vxl_mcast_addr.in4.sin_addr = vxlp->vxlp_mcast_group4;
+ } else if (vxlp->vxlp_with & VXLAN_PARAM_WITH_MCAST_GROUP6) {
+ sc->vxl_mcast_addr.in6.sin6_len = sizeof(struct sockaddr_in6);
+ sc->vxl_mcast_addr.in6.sin6_family = AF_INET6;
+ sc->vxl_mcast_addr.in6.sin6_addr = vxlp->vxlp_mcast_group6;
+ }
+
if (vxlp->vxlp_with & VXLAN_PARAM_WITH_MULTICAST_IF)
strlcpy(sc->vxl_mc_ifname, vxlp->vxlp_mc_ifname, IFNAMSIZ);
@@ -2715,6 +2968,7 @@
sc = malloc(sizeof(struct vxlan_softc), M_VXLAN, M_WAITOK | M_ZERO);
sc->vxl_unit = unit;
vxlan_set_default_config(sc);
+ LIST_INIT(&sc->vxl_rmtlist);
if (params != 0) {
error = copyin(params, &vxlp, sizeof(vxlp));
@@ -2777,6 +3031,8 @@
vxlan_teardown(sc);
vxlan_ftable_flush(sc, 1);
+
+ vxlan_rmtlist_flush(sc);
ether_ifdetach(ifp);
if_free(ifp);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Sep 19, 11:53 AM (19 h, 10 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29779560
Default Alt Text
D14222.1789818788.diff (29 KB)
Attached To
Mode
D14222: Add multiple unicast destinations to vxlan
Attached
Detach File
Event Timeline
Log In to Comment