netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next 0/2] vxlan: allow specifying multiple default destinations
@ 2013-04-25 11:03 Mike Rapoport
  2013-04-25 11:03 ` [PATCH net-next 1/2] vxlan: introduce vxlan_rdst_append Mike Rapoport
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Mike Rapoport @ 2013-04-25 11:03 UTC (permalink / raw)
  To: netdev; +Cc: Mike Rapoport

Hi,

These patches add ability to specify multiple default destinations to
vxlan. This ability is usefull in cases when multicast are disabled on
infrastructure level, for instance in public clouds.

The patches are based on top of Cong's changes for IPv6 support.

Mike Rapoport (2):
  vxlan: introduce vxlan_rdst_append
  vxlan: allow specifying multiple default destinations

 drivers/net/vxlan.c          | 190 ++++++++++++++++++++++++++++++++++++++++++-
 include/uapi/linux/if_link.h |  14 ++++
 2 files changed, 200 insertions(+), 4 deletions(-)

-- 
1.8.1.5

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH net-next 1/2] vxlan: introduce vxlan_rdst_append
  2013-04-25 11:03 [PATCH net-next 0/2] vxlan: allow specifying multiple default destinations Mike Rapoport
@ 2013-04-25 11:03 ` Mike Rapoport
  2013-04-25 11:03 ` [PATCH net-next 2/2] vxlan: allow specifying multiple default destinations Mike Rapoport
  2013-04-25 11:04 ` [PATCH iproute2] " Mike Rapoport
  2 siblings, 0 replies; 6+ messages in thread
From: Mike Rapoport @ 2013-04-25 11:03 UTC (permalink / raw)
  To: netdev; +Cc: Mike Rapoport

to allow remotes list management for both FDB entries and default
destinations

Signed-off-by: Mike Rapoport <mike.rapoport@ravellosystems.com>
---
 drivers/net/vxlan.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index be42e00..8963a83 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -387,14 +387,13 @@ static struct vxlan_fdb *vxlan_find_mac(struct vxlan_dev *vxlan,
 	return NULL;
 }
 
-/* Add/update destinations for multicast */
-static int vxlan_fdb_append(struct vxlan_fdb *f, union vxlan_addr *ip,
-			    __u32 port, __u32 vni, __u32 ifindex)
+static int vxlan_rdst_append(struct vxlan_rdst *rdst, union vxlan_addr *ip,
+			     __u32 port, __u32 vni, __u32 ifindex)
 {
 	struct vxlan_rdst *rd_prev, *rd;
 
 	rd_prev = NULL;
-	for (rd = &f->remote; rd; rd = rd->remote_next) {
+	for (rd = rdst; rd; rd = rd->remote_next) {
 		if (vxlan_addr_equal(&rd->remote_ip, ip) &&
 		    rd->remote_port == port &&
 		    rd->remote_vni == vni &&
@@ -414,6 +413,13 @@ static int vxlan_fdb_append(struct vxlan_fdb *f, union vxlan_addr *ip,
 	return 1;
 }
 
+/* Add/update destinations for multicast */
+static int vxlan_fdb_append(struct vxlan_fdb *f, union vxlan_addr *ip,
+			    __u32 port, __u32 vni, __u32 ifindex)
+{
+	return vxlan_rdst_append(&f->remote, ip, port, vni, ifindex);
+}
+
 /* Add new entry to forwarding table -- assumes lock held */
 static int vxlan_fdb_create(struct vxlan_dev *vxlan,
 			    const u8 *mac, union vxlan_addr *ip,
-- 
1.8.1.5

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH net-next 2/2] vxlan: allow specifying multiple default destinations
  2013-04-25 11:03 [PATCH net-next 0/2] vxlan: allow specifying multiple default destinations Mike Rapoport
  2013-04-25 11:03 ` [PATCH net-next 1/2] vxlan: introduce vxlan_rdst_append Mike Rapoport
@ 2013-04-25 11:03 ` Mike Rapoport
  2013-04-26  6:59   ` Atzm Watanabe
  2013-04-25 11:04 ` [PATCH iproute2] " Mike Rapoport
  2 siblings, 1 reply; 6+ messages in thread
From: Mike Rapoport @ 2013-04-25 11:03 UTC (permalink / raw)
  To: netdev; +Cc: Mike Rapoport

A list of multiple default destinations can be used in environments that
disable multicast on the infrastructure level, e.g. public clouds.

Signed-off-by: Mike Rapoport <mike.rapoport@ravellosystems.com>
---
 drivers/net/vxlan.c          | 176 +++++++++++++++++++++++++++++++++++++++++++
 include/uapi/linux/if_link.h |  14 ++++
 2 files changed, 190 insertions(+)

diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 8963a83..eb4bbec 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -131,6 +131,8 @@ struct vxlan_dev {
 	unsigned int	  addrcnt;
 	unsigned int	  addrmax;
 
+	unsigned int	  remote_cnt;  /* for additional default destinations */
+
 	struct hlist_head fdb_head[FDB_HASH_SIZE];
 };
 
@@ -679,6 +681,104 @@ static void vxlan_snoop(struct net_device *dev,
 	}
 }
 
+/* Add remote to default destinations list */
+static int vxlan_remote_add(struct vxlan_dev *vxlan, struct nlattr *attr)
+{
+	struct vxlan_addr ip;
+	struct nlattr *i;
+	u32 port, ifindex, vni;
+	int rem, err = 0;
+	bool addr_set = false;
+
+	port = vxlan_port;
+	vni = vxlan->default_dst.remote_vni;
+	ifindex = vxlan->default_dst.remote_ifindex;
+
+	nla_for_each_nested(i, attr, rem) {
+		switch (nla_type(i)) {
+		case IFLA_VXLAN_REMOTE_ADDR:
+			err = vxlan_nla_get_addr(&ip, i);
+			addr_set = true;
+			break;
+		case IFLA_VXLAN_REMOTE_PORT:
+			port = nla_get_u32(attr);
+			break;
+		case IFLA_VXLAN_REMOTE_VNI:
+			vni = nla_get_u32(attr);
+			break;
+		case IFLA_VXLAN_REMOTE_IFINDEX:
+			ifindex = nla_get_u32(attr);
+			break;
+		default:
+			err = -EINVAL;
+			break;
+		};
+
+		if (err)
+			return err;
+	}
+
+	if (!addr_set)
+		return -EINVAL;
+
+	err = vxlan_rdst_append(&vxlan->default_dst, &ip,
+				port, vni, ifindex);
+	if (err < 0)
+		return err;
+
+	if (err == 0)
+		return -EEXIST;
+
+	vxlan->remote_cnt++;
+
+#if IS_ENABLED(CONFIG_IPV6)
+	if (ip.va_sa == AF_INET6)
+		netdev_dbg(vxlan->dev, "dstadd %pI6\n", &ip.va_sin6);
+	else
+#endif
+		netdev_dbg(vxlan->dev, "dstadd %pI4\n", &ip.va_sin);
+
+	return 0;
+}
+
+static void vxlan_remote_destroy(struct vxlan_dev *vxlan,
+				 struct vxlan_rdst *rd)
+{
+#if IS_ENABLED(CONFIG_IPV6)
+	if (rd->remote_ip.va_sa == AF_INET6)
+		netdev_dbg(vxlan->dev, "dstdel %pI6\n", &rd->remote_ip.va_sin6);
+	else
+#endif
+		netdev_dbg(vxlan->dev, "dstdel %pI4\n", &rd->remote_ip.va_sin);
+
+	--vxlan->remote_cnt;
+	kfree(rd);
+}
+
+/* Delete remote from default destinations list */
+static int vxlan_remote_delete(struct vxlan_dev *vxlan, struct nlattr *attr)
+{
+	struct vxlan_rdst *rd, *rd_prev = NULL;
+	struct vxlan_addr ip;
+	int err;
+
+	err = vxlan_nla_get_addr(&ip, attr);
+	if (err)
+		return err;
+
+	rd_prev = &vxlan->default_dst;
+
+	for (rd = vxlan->default_dst.remote_next; rd; rd = rd->remote_next) {
+		if (vxlan_addr_equal(&rd->remote_ip, &ip)) {
+			rd_prev->remote_next = rd->remote_next;
+			vxlan_remote_destroy(vxlan, rd);
+			return 0;
+		}
+		rd_prev = rd;
+	}
+
+	return -ENOENT;
+}
 
 /* See if multicast group is already in use by other ID */
 static bool vxlan_group_used(struct vxlan_net *vn,
@@ -1500,6 +1600,14 @@ static void vxlan_flush(struct vxlan_dev *vxlan)
 	spin_unlock_bh(&vxlan->hash_lock);
 }
 
+static void vxlan_remotes_flush(struct vxlan_dev *vxlan)
+{
+	struct vxlan_rdst *rd;
+
+	for (rd = vxlan->default_dst.remote_next; rd; rd = rd->remote_next)
+		vxlan_remote_destroy(vxlan, rd);
+}
+
 /* Cleanup timer and forwarding table on shutdown */
 static int vxlan_stop(struct net_device *dev)
 {
@@ -1511,6 +1619,7 @@ static int vxlan_stop(struct net_device *dev)
 	del_timer_sync(&vxlan->age_timer);
 
 	vxlan_flush(vxlan);
+	vxlan_remotes_flush(vxlan);
 
 	return 0;
 }
@@ -1662,6 +1771,27 @@ static const struct ethtool_ops vxlan_ethtool_ops = {
 	.get_link	= ethtool_op_get_link,
 };
 
+static int vxlan_changelink(struct net_device *dev,
+			    struct nlattr *tb[], struct nlattr *data[])
+{
+	struct vxlan_dev *vxlan = netdev_priv(dev);
+	int err;
+
+	if (data[IFLA_VXLAN_REMOTE_ADD]) {
+		err = vxlan_remote_add(vxlan, data[IFLA_VXLAN_REMOTE_ADD]);
+		if (err)
+			return err;
+	}
+
+	if (data[IFLA_VXLAN_REMOTE_DEL]) {
+		err = vxlan_remote_delete(vxlan, data[IFLA_VXLAN_REMOTE_DEL]);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
 static int vxlan_newlink(struct net *net, struct net_device *dev,
 			 struct nlattr *tb[], struct nlattr *data[])
 {
@@ -1778,6 +1908,23 @@ static void vxlan_dellink(struct net_device *dev, struct list_head *head)
 	unregister_netdevice_queue(dev, head);
 }
 
+static size_t vxlan_remote_list_size(const struct net_device *dev)
+{
+	struct vxlan_dev *vxlan = netdev_priv(dev);
+	ssize_t size = nla_total_size(sizeof(struct nlattr));
+	struct vxlan_rdst *rd;
+
+	for (rd = vxlan->default_dst.remote_next; rd; rd = rd->remote_next)
+#if IS_ENABLED(CONFIG_IPV6)
+		if (rd->remote_ip.va_sa == AF_INET6)
+			size += nla_total_size(sizeof(struct in6_addr));
+		else
+#endif
+			size += nla_total_size(sizeof(__be32));
+
+	return size;
+}
+
 static size_t vxlan_get_size(const struct net_device *dev)
 {
 
@@ -1795,6 +1942,7 @@ static size_t vxlan_get_size(const struct net_device *dev)
 		nla_total_size(sizeof(__u32)) +	/* IFLA_VXLAN_AGEING */
 		nla_total_size(sizeof(__u32)) +	/* IFLA_VXLAN_LIMIT */
 		nla_total_size(sizeof(struct ifla_vxlan_port_range)) +
+		vxlan_remote_list_size(dev) +
 		0;
 }
 
@@ -1857,6 +2005,33 @@ static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev)
 	if (nla_put(skb, IFLA_VXLAN_PORT_RANGE, sizeof(ports), &ports))
 		goto nla_put_failure;
 
+	if (vxlan->remote_cnt) {
+		struct vxlan_rdst *rdst;
+		struct nlattr *nest;
+
+		nest = nla_nest_start(skb, IFLA_VXLAN_REMOTE_LST);
+		if (nest == NULL)
+			goto nla_put_failure;
+
+		for (rdst = vxlan->default_dst.remote_next; rdst;
+		     rdst = rdst->remote_next) {
+			if (rdst->remote_ip.va_sa == AF_INET) {
+				if (nla_put_be32(skb, IFLA_VXLAN_REMOTE_ADDR,
+						 rdst->remote_ip.va_sin))
+					goto nla_put_failure;
+			} else {
+#if IS_ENABLED(CONFIG_IPV6)
+				if (nla_put(skb, IFLA_VXLAN_REMOTE_ADDR,
+					    sizeof(struct in6_addr),
+					    &rdst->remote_ip.va_sin6))
+					goto nla_put_failure;
+#endif
+			}
+		}
+
+		nla_nest_end(skb, nest);
+	}
+
 	return 0;
 
 nla_put_failure:
@@ -1871,6 +2046,7 @@ static struct rtnl_link_ops vxlan_link_ops __read_mostly = {
 	.setup		= vxlan_setup,
 	.validate	= vxlan_validate,
 	.newlink	= vxlan_newlink,
+	.changelink	= vxlan_changelink,
 	.dellink	= vxlan_dellink,
 	.get_size	= vxlan_get_size,
 	.fill_info	= vxlan_fill_info,
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 92ae9bd..74f1bb8 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -312,10 +312,24 @@ enum {
 	IFLA_VXLAN_L3MISS,
 	IFLA_VXLAN_REMOTE6,
 	IFLA_VXLAN_LOCAL6,
+	IFLA_VXLAN_REMOTE_ADD,
+	IFLA_VXLAN_REMOTE_DEL,
+	IFLA_VXLAN_REMOTE_LST,
 	__IFLA_VXLAN_MAX
 };
 #define IFLA_VXLAN_MAX	(__IFLA_VXLAN_MAX - 1)
 
+enum {
+	IFLA_VXLAN_REMOTE_UNSPEC,
+	IFLA_VXLAN_REMOTE_ADDR,
+	IFLA_VXLAN_REMOTE_IFINDEX,
+	IFLA_VXLAN_REMOTE_PORT,
+	IFLA_VXLAN_REMOTE_VNI,
+	__IFLA_VXLAN_REMOTE_MAX
+};
+
+#define IFLA_VXLAN_REMOTE_MAX	(__IFLA_VXLAN_GRP_MAX - 1)
+
 struct ifla_vxlan_port_range {
 	__be16	low;
 	__be16	high;
-- 
1.8.1.5

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH iproute2] vxlan: allow specifying multiple default destinations
  2013-04-25 11:03 [PATCH net-next 0/2] vxlan: allow specifying multiple default destinations Mike Rapoport
  2013-04-25 11:03 ` [PATCH net-next 1/2] vxlan: introduce vxlan_rdst_append Mike Rapoport
  2013-04-25 11:03 ` [PATCH net-next 2/2] vxlan: allow specifying multiple default destinations Mike Rapoport
@ 2013-04-25 11:04 ` Mike Rapoport
  2 siblings, 0 replies; 6+ messages in thread
From: Mike Rapoport @ 2013-04-25 11:04 UTC (permalink / raw)
  To: netdev; +Cc: Mike Rapoport

Signed-off-by: Mike Rapoport <mike.rapoport@ravellosystems.com>
---
This patch depends on the pending changes to ip/iplink_vxlan.c as as
well as on IPv6 support in vxlan. I'll rebase and resend it once all
the changes to vxlan are merged.

 ip/iplink_vxlan.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 84 insertions(+)

diff --git a/ip/iplink_vxlan.c b/ip/iplink_vxlan.c
index 661ab9e..9ba5a1d 100644
--- a/ip/iplink_vxlan.c
+++ b/ip/iplink_vxlan.c
@@ -28,11 +28,56 @@ static void explain(void)
 	fprintf(stderr, "                 [ port MIN MAX ] [ [no]learning ]\n");
 	fprintf(stderr, "                 [ [no]proxy ] [ [no]rsc ]\n");
 	fprintf(stderr, "                 [ [no]l2miss ] [ [no]l3miss ]\n");
+	fprintf(stderr, "                 [ dstadd DST ]\n");
+	fprintf(stderr, "                 [ dstdel ADDR ]\n");
 	fprintf(stderr, "\n");
 	fprintf(stderr, "Where: VNI := 0-16777215\n");
 	fprintf(stderr, "       ADDR := { IP_ADDRESS | any }\n");
 	fprintf(stderr, "       TOS  := { NUMBER | inherit }\n");
 	fprintf(stderr, "       TTL  := { 1..255 | inherit }\n");
+	fprintf(stderr, "       DST  := [ ADDR [port PORT] [vni VNI] [via DEV]]\n");
+}
+
+static int vxlan_parse_dst(int *argcp, char ***argvp, struct nlmsghdr *n)
+{
+	int argc = *argcp;
+	char **argv = *argvp;
+	__u32 vni, port, ifindex;
+	struct rtattr *tail;
+
+	tail = NLMSG_TAIL(n);
+	addattr_l(n, 1024, IFLA_VXLAN_REMOTE_ADD, NULL, 0);
+
+	while (argc > 0) {
+		if (!matches(*argv, "vni")) {
+			NEXT_ARG();
+			if (get_u32(&vni, *argv, 0) ||
+			    vni >= 1u << 24)
+				invarg("invalid id", *argv);
+			addattr32(n, 1024, IFLA_VXLAN_REMOTE_VNI, vni);
+		} else if (!matches(*argv, "port")) {
+			NEXT_ARG();
+			if (get_u32(&port, *argv, 0))
+				invarg("port", *argv);
+			addattr32(n, 1024, IFLA_VXLAN_REMOTE_PORT, port);
+		} else if (!matches(*argv, "via")) {
+			NEXT_ARG();
+			ifindex = if_nametoindex(*argv);
+			addattr32(n, 1024, IFLA_VXLAN_REMOTE_IFINDEX, ifindex);
+		} else {
+			inet_prefix addr;
+			get_prefix(&addr, *argv, AF_UNSPEC);
+			addattr_l(n, 1024, IFLA_VXLAN_REMOTE_ADDR,
+				  &addr.data, addr.bytelen);
+		}
+		argc--, argv++;
+	}
+
+	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *)tail;
+
+	*argcp = argc;
+	*argvp = argv;
+	return 0;
 }
 
 static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
@@ -56,6 +101,7 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
 	__u32 age = 0;
 	__u32 maxaddr = 0;
 	struct ifla_vxlan_port_range range = { 0, 0 };
+	inet_prefix *remote_del = NULL;
 
 	while (argc > 0) {
 		if (!matches(*argv, "id") ||
@@ -138,6 +184,14 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
 				invarg("max port", *argv);
 			range.low = htons(minport);
 			range.high = htons(maxport);
+		} else if (!matches(*argv, "dstadd")) {
+			NEXT_ARG();
+			vxlan_parse_dst(&argc, &argv, n);
+		} else if (!matches(*argv, "dstdel")) {
+			inet_prefix addr;
+			NEXT_ARG();
+			get_prefix(&addr, *argv, AF_UNSPEC);
+			remote_del = &addr;
 		} else if (!matches(*argv, "nolearning")) {
 			learning = 0;
 		} else if (!matches(*argv, "learning")) {
@@ -202,10 +256,37 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
 	if (range.low || range.high)
 		addattr_l(n, 1024, IFLA_VXLAN_PORT_RANGE,
 			  &range, sizeof(range));
+	if (remote_del)
+		addattr_l(n, 1024, IFLA_VXLAN_REMOTE_DEL, remote_del->data,
+			  remote_del->bytelen);
 
 	return 0;
 }
 
+static void vxlan_print_remotes(FILE *f, struct rtattr *attr)
+{
+	struct rtattr *i;
+	char s1[1024];
+	int rem, n = 0;
+
+	fprintf(f, "\n      default destinations :\n");
+
+	rem = RTA_PAYLOAD(attr);
+	for (i = RTA_DATA(attr); RTA_OK(i, rem); i = RTA_NEXT(i, rem), n++) {
+		if (RTA_PAYLOAD(i) >= sizeof(struct in6_addr)) {
+			struct in6_addr addr;
+			memcpy(&addr, RTA_DATA(i), sizeof(struct in6_addr));
+			fprintf(f, "        %s\n",
+				format_host(AF_INET6, sizeof(struct in6_addr),
+					    &addr, s1, sizeof(s1)));
+		} else if (RTA_PAYLOAD(i) >= sizeof(__be32)) {
+			__be32 addr = rta_getattr_u32(i);
+			fprintf(f, "        %s\n",
+				format_host(AF_INET, 4, &addr, s1, sizeof(s1)));
+		}
+	}
+}
+
 static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
 {
 	__u32 vni;
@@ -308,6 +389,9 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
 	if (tb[IFLA_VXLAN_LIMIT] &&
 	    (maxaddr = rta_getattr_u32(tb[IFLA_VXLAN_LIMIT]) != 0))
 		    fprintf(f, "maxaddr %u ", maxaddr);
+
+	if (tb[IFLA_VXLAN_REMOTE_LST])
+		vxlan_print_remotes(f, tb[IFLA_VXLAN_REMOTE_LST]);
 }
 
 struct link_util vxlan_link_util = {
-- 
1.8.1.5

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH net-next 2/2] vxlan: allow specifying multiple default destinations
  2013-04-25 11:03 ` [PATCH net-next 2/2] vxlan: allow specifying multiple default destinations Mike Rapoport
@ 2013-04-26  6:59   ` Atzm Watanabe
  2013-04-27 22:57     ` Mike Rapoport
  0 siblings, 1 reply; 6+ messages in thread
From: Atzm Watanabe @ 2013-04-26  6:59 UTC (permalink / raw)
  To: Mike Rapoport; +Cc: netdev

At Thu, 25 Apr 2013 14:03:49 +0300,
Mike Rapoport wrote:
> +/* Add remote to default destinations list */
> +static int vxlan_remote_add(struct vxlan_dev *vxlan, struct nlattr *attr)
> +{
> +	struct vxlan_addr ip;
> +	struct nlattr *i;
> +	u32 port, ifindex, vni;
> +	int rem, err = 0;
> +	bool addr_set = false;
> +
> +	port = vxlan_port;
> +	vni = vxlan->default_dst.remote_vni;
> +	ifindex = vxlan->default_dst.remote_ifindex;
> +
> +	nla_for_each_nested(i, attr, rem) {
> +		switch (nla_type(i)) {
> +		case IFLA_VXLAN_REMOTE_ADDR:
> +			err = vxlan_nla_get_addr(&ip, i);
> +			addr_set = true;
> +			break;
> +		case IFLA_VXLAN_REMOTE_PORT:
> +			port = nla_get_u32(attr);
> +			break;
> +		case IFLA_VXLAN_REMOTE_VNI:
> +			vni = nla_get_u32(attr);
> +			break;
> +		case IFLA_VXLAN_REMOTE_IFINDEX:
> +			ifindex = nla_get_u32(attr);
> +			break;
> +		default:
> +			err = -EINVAL;
> +			break;
> +		};
> +
> +		if (err)
> +			return err;
> +	}
> +
> +	if (!addr_set)
> +		return -EINVAL;
> +
> +	err = vxlan_rdst_append(&vxlan->default_dst, &ip,
> +				port, vni, ifindex);
> +	if (err < 0)
> +		return err;
> +
> +	if (err == 0)
> +		return -EEXIST;
> +
> +	vxlan->remote_cnt++;
> +
> +#if IS_ENABLED(CONFIG_IPV6)
> +	if (ip.va_sa == AF_INET6)
> +		netdev_dbg(vxlan->dev, "dstadd %pI6\n", &ip.va_sin6);
> +	else
> +#endif
> +		netdev_dbg(vxlan->dev, "dstadd %pI4\n", &ip.va_sin);
> +
> +	return 0;
> +}
> +
> +static void vxlan_remote_destroy(struct vxlan_dev *vxlan,
> +				 struct vxlan_rdst *rd)
> +{
> +#if IS_ENABLED(CONFIG_IPV6)
> +	if (rd->remote_ip.va_sa == AF_INET6)
> +		netdev_dbg(vxlan->dev, "dstdel %pI6\n", &rd->remote_ip.va_sin6);
> +	else
> +#endif
> +		netdev_dbg(vxlan->dev, "dstdel %pI4\n", &rd->remote_ip.va_sin);
> +
> +	--vxlan->remote_cnt;
> +	kfree(rd);
> +}
> +
> +/* Delete remote from default destinations list */
> +static int vxlan_remote_delete(struct vxlan_dev *vxlan, struct nlattr *attr)
> +{
> +	struct vxlan_rdst *rd, *rd_prev = NULL;
> +	struct vxlan_addr ip;
> +	int err;
> +
> +	err = vxlan_nla_get_addr(&ip, attr);
> +	if (err)
> +		return err;
> +
> +	rd_prev = &vxlan->default_dst;
> +
> +	for (rd = vxlan->default_dst.remote_next; rd; rd = rd->remote_next) {
> +		if (vxlan_addr_equal(&rd->remote_ip, &ip)) {
> +			rd_prev->remote_next = rd->remote_next;
> +			vxlan_remote_destroy(vxlan, rd);
> +			return 0;
> +		}
> +		rd_prev = rd;
> +	}
> +
> +	return -ENOENT;
> +}

I think the default destinations should be used for not only sending
but receiving, so when multicast address was added, it should be
joined to the group, if the interface state is up.
(Forbidding the change on the running interface may make it easy.)

Also vxlan_open() and vxlan_stop() will need to control the
membership of groups in the default destination list.


>  /* See if multicast group is already in use by other ID */
>  static bool vxlan_group_used(struct vxlan_net *vn,
> @@ -1500,6 +1600,14 @@ static void vxlan_flush(struct vxlan_dev *vxlan)
>  	spin_unlock_bh(&vxlan->hash_lock);
>  }
>  
> +static void vxlan_remotes_flush(struct vxlan_dev *vxlan)
> +{
> +	struct vxlan_rdst *rd;
> +
> +	for (rd = vxlan->default_dst.remote_next; rd; rd = rd->remote_next)
> +		vxlan_remote_destroy(vxlan, rd);
> +}
> +
>  /* Cleanup timer and forwarding table on shutdown */
>  static int vxlan_stop(struct net_device *dev)
>  {
> @@ -1511,6 +1619,7 @@ static int vxlan_stop(struct net_device *dev)
>  	del_timer_sync(&vxlan->age_timer);
>  
>  	vxlan_flush(vxlan);
> +	vxlan_remotes_flush(vxlan);
>  
>  	return 0;
>  }

vxlan_stop() is called when interface state changes to down.
I think the default destinations should not be flushed at this timing,
and this should be done at dellink instead.


Thanks.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net-next 2/2] vxlan: allow specifying multiple default destinations
  2013-04-26  6:59   ` Atzm Watanabe
@ 2013-04-27 22:57     ` Mike Rapoport
  0 siblings, 0 replies; 6+ messages in thread
From: Mike Rapoport @ 2013-04-27 22:57 UTC (permalink / raw)
  To: Atzm Watanabe; +Cc: netdev

On Fri, Apr 26, 2013 at 03:59:49PM +0900, Atzm Watanabe wrote:
> At Thu, 25 Apr 2013 14:03:49 +0300,
> Mike Rapoport wrote:
> > +/* Add remote to default destinations list */
> > +static int vxlan_remote_add(struct vxlan_dev *vxlan, struct nlattr *attr)
> > +{

...

> > +}
> 
> I think the default destinations should be used for not only sending
> but receiving, so when multicast address was added, it should be
> joined to the group, if the interface state is up.
> (Forbidding the change on the running interface may make it easy.)
> 
> Also vxlan_open() and vxlan_stop() will need to control the
> membership of groups in the default destination list.

My original idea was to simulate multicast group with a list of unicast
destinations for cases when multicast is impossible. I'd prefer to limit
the additional destinations for unicast addresses for now. The support
for several multicast groups with the same VNI can be added later on,
IMHO. 
 
> 
> >  /* See if multicast group is already in use by other ID */
> >  static bool vxlan_group_used(struct vxlan_net *vn,
> > @@ -1500,6 +1600,14 @@ static void vxlan_flush(struct vxlan_dev *vxlan)
> >  	spin_unlock_bh(&vxlan->hash_lock);
> >  }
> >  
> > +static void vxlan_remotes_flush(struct vxlan_dev *vxlan)
> > +{
> > +	struct vxlan_rdst *rd;
> > +
> > +	for (rd = vxlan->default_dst.remote_next; rd; rd = rd->remote_next)
> > +		vxlan_remote_destroy(vxlan, rd);
> > +}
> > +
> >  /* Cleanup timer and forwarding table on shutdown */
> >  static int vxlan_stop(struct net_device *dev)
> >  {
> > @@ -1511,6 +1619,7 @@ static int vxlan_stop(struct net_device *dev)
> >  	del_timer_sync(&vxlan->age_timer);
> >  
> >  	vxlan_flush(vxlan);
> > +	vxlan_remotes_flush(vxlan);
> >  
> >  	return 0;
> >  }
> 
> vxlan_stop() is called when interface state changes to down.
> I think the default destinations should not be flushed at this timing,
> and this should be done at dellink instead.

Agree, will fix.

> 
> Thanks.

--
Sincerely yours,
Mike.

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2013-04-27 22:57 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-04-25 11:03 [PATCH net-next 0/2] vxlan: allow specifying multiple default destinations Mike Rapoport
2013-04-25 11:03 ` [PATCH net-next 1/2] vxlan: introduce vxlan_rdst_append Mike Rapoport
2013-04-25 11:03 ` [PATCH net-next 2/2] vxlan: allow specifying multiple default destinations Mike Rapoport
2013-04-26  6:59   ` Atzm Watanabe
2013-04-27 22:57     ` Mike Rapoport
2013-04-25 11:04 ` [PATCH iproute2] " Mike Rapoport

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).