[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <87hajcm7ym.wl%atzm@stratosphere.co.jp>
Date: Fri, 12 Apr 2013 18:09:05 +0900
From: Atzm Watanabe <atzm@...atosphere.co.jp>
To: netdev@...r.kernel.org
Cc: "David S. Miller" <davem@...emloft.net>,
Stephen Hemminger <stephen@...workplumber.org>,
Cong Wang <xiyou.wangcong@...il.com>
Subject: [PATCH v3] vxlan: Allow setting destination to unicast address.
This patch allows setting VXLAN destination to unicast address.
It allows that VXLAN can be used as peer-to-peer tunnel without
multicast.
v3: move a new attribute REMOTE into the last of an enum list
based by Stephen Hemminger's comments.
v2: use a new attribute REMOTE instead of GROUP based by
Cong Wang's comments.
Signed-off-by: Atzm Watanabe <atzm@...atosphere.co.jp>
---
drivers/net/vxlan.c | 45 ++++++++++++++++++++++++++++++++++----------
include/uapi/linux/if_link.h | 1 +
2 files changed, 36 insertions(+), 10 deletions(-)
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 9a64715..e468d5a 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -106,7 +106,7 @@ struct vxlan_dev {
struct hlist_node hlist;
struct net_device *dev;
__u32 vni; /* virtual network id */
- __be32 gaddr; /* multicast group */
+ __be32 daddr; /* destination address */
__be32 saddr; /* source address */
unsigned int link; /* link to multicast over */
__u16 port_min; /* source port range */
@@ -591,7 +591,7 @@ static bool vxlan_group_used(struct vxlan_net *vn,
if (!netif_running(vxlan->dev))
continue;
- if (vxlan->gaddr == this->gaddr)
+ if (vxlan->daddr == this->daddr)
return true;
}
@@ -605,7 +605,7 @@ static int vxlan_join_group(struct net_device *dev)
struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id);
struct sock *sk = vn->sock->sk;
struct ip_mreqn mreq = {
- .imr_multiaddr.s_addr = vxlan->gaddr,
+ .imr_multiaddr.s_addr = vxlan->daddr,
.imr_ifindex = vxlan->link,
};
int err;
@@ -633,7 +633,7 @@ static int vxlan_leave_group(struct net_device *dev)
int err = 0;
struct sock *sk = vn->sock->sk;
struct ip_mreqn mreq = {
- .imr_multiaddr.s_addr = vxlan->gaddr,
+ .imr_multiaddr.s_addr = vxlan->daddr,
.imr_ifindex = vxlan->link,
};
@@ -1106,7 +1106,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
did_rsc = false;
group.remote_port = vxlan_port;
group.remote_vni = vxlan->vni;
- group.remote_ip = vxlan->gaddr;
+ group.remote_ip = vxlan->daddr;
group.remote_ifindex = vxlan->link;
group.remote_next = 0;
rdst0 = &group;
@@ -1189,7 +1189,7 @@ static int vxlan_open(struct net_device *dev)
struct vxlan_dev *vxlan = netdev_priv(dev);
int err;
- if (vxlan->gaddr) {
+ if (IN_MULTICAST(ntohl(vxlan->daddr))) {
err = vxlan_join_group(dev);
if (err)
return err;
@@ -1223,7 +1223,7 @@ static int vxlan_stop(struct net_device *dev)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
- if (vxlan->gaddr)
+ if (IN_MULTICAST(ntohl(vxlan->daddr)))
vxlan_leave_group(dev);
del_timer_sync(&vxlan->age_timer);
@@ -1322,6 +1322,7 @@ static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = {
[IFLA_VXLAN_RSC] = { .type = NLA_U8 },
[IFLA_VXLAN_L2MISS] = { .type = NLA_U8 },
[IFLA_VXLAN_L3MISS] = { .type = NLA_U8 },
+ [IFLA_VXLAN_REMOTE] = { .len = FIELD_SIZEOF(struct iphdr, daddr) },
};
static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[])
@@ -1347,6 +1348,9 @@ static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[])
return -ERANGE;
}
+ if (data[IFLA_VXLAN_GROUP] && data[IFLA_VXLAN_REMOTE])
+ return -EINVAL;
+
if (data[IFLA_VXLAN_GROUP]) {
__be32 gaddr = nla_get_be32(data[IFLA_VXLAN_GROUP]);
if (!IN_MULTICAST(ntohl(gaddr))) {
@@ -1355,6 +1359,14 @@ static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[])
}
}
+ if (data[IFLA_VXLAN_REMOTE]) {
+ __be32 daddr = nla_get_be32(data[IFLA_VXLAN_REMOTE]);
+ if (IN_MULTICAST(ntohl(daddr))) {
+ pr_debug("remote address is not IPv4 unicast\n");
+ return -EADDRNOTAVAIL;
+ }
+ }
+
if (data[IFLA_VXLAN_PORT_RANGE]) {
const struct ifla_vxlan_port_range *p
= nla_data(data[IFLA_VXLAN_PORT_RANGE]);
@@ -1399,7 +1411,10 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
vxlan->vni = vni;
if (data[IFLA_VXLAN_GROUP])
- vxlan->gaddr = nla_get_be32(data[IFLA_VXLAN_GROUP]);
+ vxlan->daddr = nla_get_be32(data[IFLA_VXLAN_GROUP]);
+
+ if (data[IFLA_VXLAN_REMOTE])
+ vxlan->daddr = nla_get_be32(data[IFLA_VXLAN_REMOTE]);
if (data[IFLA_VXLAN_LOCAL])
vxlan->saddr = nla_get_be32(data[IFLA_VXLAN_LOCAL]);
@@ -1492,6 +1507,7 @@ static size_t vxlan_get_size(const struct net_device *dev)
nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_L3MISS */
nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_AGEING */
nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_LIMIT */
+ nla_total_size(sizeof(__be32))+ /* IFLA_VXLAN_REMOTE */
nla_total_size(sizeof(struct ifla_vxlan_port_range)) +
0;
}
@@ -1507,8 +1523,17 @@ static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev)
if (nla_put_u32(skb, IFLA_VXLAN_ID, vxlan->vni))
goto nla_put_failure;
- if (vxlan->gaddr && nla_put_be32(skb, IFLA_VXLAN_GROUP, vxlan->gaddr))
- goto nla_put_failure;
+ if (vxlan->daddr) {
+ int err;
+
+ if (IN_MULTICAST(ntohl(vxlan->daddr)))
+ err = nla_put_be32(skb, IFLA_VXLAN_GROUP, vxlan->daddr);
+ else
+ err = nla_put_be32(skb, IFLA_VXLAN_REMOTE, vxlan->daddr);
+
+ if (err)
+ goto nla_put_failure;
+ }
if (vxlan->link && nla_put_u32(skb, IFLA_VXLAN_LINK, vxlan->link))
goto nla_put_failure;
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 6b35c42..afc8027 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -309,6 +309,7 @@ enum {
IFLA_VXLAN_RSC,
IFLA_VXLAN_L2MISS,
IFLA_VXLAN_L3MISS,
+ IFLA_VXLAN_REMOTE,
__IFLA_VXLAN_MAX
};
#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
--
1.8.1.5
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists