[ovs-dev] [PATCH 10/13] Upstream VXLAN: Use IP Tunnels rtnl-netlink functions.

Pravin B Shelar pshelar at nicira.com
Thu Nov 22 15:57:19 UTC 2012


From: Pravin Shelar <pshelar at nicira.com>

IP Tunnel modules defines generic rtnl-netlink ops for tunneling
devices VXLAN can directly use them.

Signed-off-by: Pravin B Shelar <pshelar at nicira.com>
---
 drivers/net/vxlan.c |  105 ++++++++++++++++++---------------------------------
 1 files changed, 37 insertions(+), 68 deletions(-)

diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 8b0164a..1977da5 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -45,8 +45,6 @@
 
 #define VXLAN_VERSION	"0.1"
 
-#define VNI_HASH_BITS	10
-#define VNI_HASH_SIZE	(1<<VNI_HASH_BITS)
 #define FDB_HASH_BITS	8
 #define FDB_HASH_SIZE	(1<<FDB_HASH_BITS)
 #define FDB_AGE_DEFAULT 300 /* 5 min */
@@ -64,8 +62,8 @@ MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
 /* per-net private data for this module */
 static int vxlan_net_id;
 struct vxlan_net {
+	struct ip_tunnel_net itn;
 	struct socket	  *sock;	/* UDP encap socket */
-	struct hlist_head vni_list[VNI_HASH_SIZE];
 };
 
 /* Forwarding table entry */
@@ -82,7 +80,6 @@ struct vxlan_fdb {
 /* Pseudo network device */
 struct vxlan_dev {
 	struct ip_tunnel tunnel;
-	struct hlist_node hlist;
 	unsigned int      link;		/* link to multicast over */
 	__u16		  port_min;	/* source port range */
 	__u16		  port_max;
@@ -103,30 +100,6 @@ struct vxlan_dev {
 #define VXLAN_F_L2MISS	0x08
 #define VXLAN_F_L3MISS	0x10
 
-/* salt for hash table */
-static u32 vxlan_salt __read_mostly;
-
-static inline struct hlist_head *vni_head(struct net *net, __be32 id)
-{
-	struct vxlan_net *vn = net_generic(net, vxlan_net_id);
-
-	return &vn->vni_list[hash_32((__force u32)id, VNI_HASH_BITS)];
-}
-
-/* Look up VNI in a per net namespace table */
-static struct vxlan_dev *vxlan_find_vni(struct net *net, __be32 vni)
-{
-	struct vxlan_dev *vxlan;
-	struct hlist_node *node;
-
-	hlist_for_each_entry_rcu(vxlan, node, vni_head(net, vni), hlist) {
-		if (vxlan->tunnel.parms.i_key == vni)
-			return vxlan;
-	}
-
-	return NULL;
-}
-
 /* Fill in neighbour message in skbuff. */
 static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan,
 			   const struct vxlan_fdb *fdb,
@@ -453,19 +426,18 @@ static void vxlan_snoop(struct net_device *dev,
 static bool vxlan_group_used(struct vxlan_net *vn,
 			     const struct vxlan_dev *this)
 {
-	const struct vxlan_dev *vxlan;
-	struct hlist_node *node;
+	const struct ip_tunnel *t;
 	unsigned h;
 
-	for (h = 0; h < VNI_HASH_SIZE; ++h)
-		hlist_for_each_entry(vxlan, node, &vn->vni_list[h], hlist) {
-			if (vxlan == this)
+	for (h = 0; h < IPT_HASH_SIZE; ++h)
+		for_each_ip_tunnel_rcu(t, vn->itn.tunnels[h]) {
+			if (t == (const struct ip_tunnel *) this)
 				continue;
 
-			if (!netif_running(vxlan->tunnel.dev))
+			if (!netif_running(t->dev))
 				continue;
 
-			if (vxlan->tunnel.parms.iph.daddr == this->tunnel.parms.iph.daddr)
+			if (t->parms.iph.daddr == this->tunnel.parms.iph.daddr)
 				return true;
 		}
 
@@ -575,12 +547,13 @@ static int vxlan_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)
 {
 	struct vxlan_dev *vxlan;
 	struct net *net = dev_net(skb->dev);
+	struct vxlan_net *vn = net_generic(net, vxlan_net_id);
 	struct iphdr *oip;
 	struct pcpu_tstats *stats;
 	int err;
 
 	/* Is this VNI defined? */
-	vxlan = vxlan_find_vni(net, tpi->key);
+	vxlan = (struct vxlan_dev *) ip_tunnel_lookup_key(&vn->itn, tpi->key);
 	if (!vxlan)
 		return 1;
 
@@ -1108,6 +1081,8 @@ static void vxlan_setup(struct net_device *dev)
 
 	for (h = 0; h < FDB_HASH_SIZE; ++h)
 		INIT_HLIST_HEAD(&vxlan->fdb_head[h]);
+
+	ip_tunnel_setup(dev, vxlan_net_id);
 }
 
 static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = {
@@ -1172,22 +1147,19 @@ static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[])
 	return 0;
 }
 
-static int vxlan_newlink(struct net *net, struct net_device *dev,
-			 struct nlattr *tb[], struct nlattr *data[])
+static int vxlan_netlink_parms(struct ip_tunnel *t, struct nlattr *data[],
+			struct nlattr *tb[], struct ip_tunnel_parm *parms)
 {
-	struct vxlan_dev *vxlan = netdev_priv(dev);
+	struct vxlan_dev *vxlan = (struct vxlan_dev *)t;
+	struct net_device *dev = vxlan->tunnel.dev;
+	struct net *net = dev_net(dev);
 	__u32 vni;
-	int err;
 
 	if (!data[IFLA_VXLAN_ID])
 		return -EINVAL;
 
 	vni = nla_get_u32(data[IFLA_VXLAN_ID]);
 	vxlan->tunnel.parms.i_key = htonl(vni << 8);
-	if (vxlan_find_vni(net, vxlan->tunnel.parms.i_key)) {
-		pr_info("duplicate VNI %u\n", vni);
-		return -EEXIST;
-	}
 
 	if (data[IFLA_VXLAN_GROUP])
 		vxlan->tunnel.parms.iph.daddr = nla_get_be32(data[IFLA_VXLAN_GROUP]);
@@ -1249,20 +1221,7 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
 		vxlan->port_max = ntohs(p->high);
 	}
 
-	err = register_netdevice(dev);
-	if (!err)
-		hlist_add_head_rcu(&vxlan->hlist, vni_head(net, vxlan->tunnel.parms.i_key));
-
-	return err;
-}
-
-static void vxlan_dellink(struct net_device *dev, struct list_head *head)
-{
-	struct vxlan_dev *vxlan = netdev_priv(dev);
-
-	hlist_del_rcu(&vxlan->hlist);
-
-	unregister_netdevice_queue(dev, head);
+	return 0;
 }
 
 static size_t vxlan_get_size(const struct net_device *dev)
@@ -1339,8 +1298,8 @@ static struct rtnl_link_ops vxlan_link_ops __read_mostly = {
 	.priv_size	= sizeof(struct vxlan_dev),
 	.setup		= vxlan_setup,
 	.validate	= vxlan_validate,
-	.newlink	= vxlan_newlink,
-	.dellink	= vxlan_dellink,
+	.newlink        = ip_tunnel_newlink,
+	.dellink	= ip_tunnel_dellink,
 	.get_size	= vxlan_get_size,
 	.fill_info	= vxlan_fill_info,
 };
@@ -1388,18 +1347,28 @@ struct socket *vxlan_create_socket(struct net *net, int portno)
 }
 EXPORT_SYMBOL(vxlan_create_socket);
 
+static const struct ip_tunnel_ops vxlan_tunnel_ops = {
+	.flags = HASH_ON_KEY,
+	.parse_netlink_parms = vxlan_netlink_parms,
+};
+
 static __net_init int vxlan_init_net(struct net *net)
 {
 	struct vxlan_net *vn = net_generic(net, vxlan_net_id);
-	unsigned h;
+	struct ip_tunnel_net *itn = &vn->itn;
+	int rc;
+
+	itn->ops = &vxlan_tunnel_ops;
+	rc =  ip_tunnel_init_net(net, vxlan_net_id, NULL);
+	if (rc)
+		return rc;
 
 	vn->sock = vxlan_create_socket(net, vxlan_port);
 	if (IS_ERR(vn->sock)) {
+		ip_tunnel_delete_net(itn);
 		vn->sock = NULL;
 		return PTR_ERR(vn->sock);
 	}
-	for (h = 0; h < VNI_HASH_SIZE; ++h)
-		INIT_HLIST_HEAD(&vn->vni_list[h]);
 
 	return 0;
 }
@@ -1407,11 +1376,13 @@ static __net_init int vxlan_init_net(struct net *net)
 static __net_exit void vxlan_exit_net(struct net *net)
 {
 	struct vxlan_net *vn = net_generic(net, vxlan_net_id);
+	struct ip_tunnel_net *itn = &vn->itn;
 
 	if (vn->sock) {
 		sk_release_kernel(vn->sock->sk);
 		vn->sock = NULL;
 	}
+	ip_tunnel_delete_net(itn);
 }
 
 static struct pernet_operations vxlan_net_ops = {
@@ -1422,17 +1393,15 @@ static struct pernet_operations vxlan_net_ops = {
 };
 
 static struct ipt_protocol vxlan_protocol = {
-	.handler        = vxlan_rcv,
-	.priority       = 0,
-	.type           = IPT_VXLAN,
+	.handler	= vxlan_rcv,
+	.priority	= 0,
+	.type		= IPT_VXLAN,
 };
 
 static int __init vxlan_init_module(void)
 {
 	int rc;
 
-	get_random_bytes(&vxlan_salt, sizeof(vxlan_salt));
-
 	rc = register_pernet_device(&vxlan_net_ops);
 	if (rc)
 		goto out1;
-- 
1.7.1




More information about the dev mailing list