[ovs-dev] [PATCH 07/13] Upstream VXLAN: use IP Tunnel protocol handler.

Pravin B Shelar pshelar at nicira.com
Wed Nov 7 01:00:08 UTC 2012


IP Tunnel protocol handler allows multiple modules register for
same protocol, e.g. linux vxlan devices and Open vSwitch both
can register for VXLAN device.

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

diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index d2449f3..be2064b 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -497,11 +497,12 @@ static int vxlan_leave_group(struct net_device *dev)
 /* Callback from net/ipv4/udp.c to receive packets */
 static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
 {
-	struct iphdr *oip;
 	struct vxlanhdr *vxh;
-	struct vxlan_dev *vxlan;
-	struct pcpu_tstats *stats;
-	int err;
+	struct inet_sock *inet = inet_sk(sk);
+	struct tnl_ptk_info tpi;
+	struct ipt_protocol *proto;
+	struct hlist_node *n;
+	struct hlist_head *head;
 
 	/* pop off outer UDP header */
 	__skb_pull(skb, sizeof(struct udphdr));
@@ -520,14 +521,40 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
 	}
 
 	__skb_pull(skb, sizeof(struct vxlanhdr));
+	tpi.key = vxh->vx_vni;
+
+	head = ipt_hash_bucket(IPT_VXLAN, inet->inet_num);
+	hlist_for_each_entry_rcu(proto, n, head, node) {
+		int ret;
+
+		if (proto->type != IPT_VXLAN || proto->portno != inet->inet_num)
+			continue;
+		ret = proto->handler(skb, &tpi);
+		if (ret <= 0)
+			return ret;
 
-	/* Is this VNI defined? */
-	vxlan = vxlan_find_vni(sock_net(sk), vxh->vx_vni);
-	if (!vxlan) {
-		netdev_dbg(skb->dev, "unknown vni %d\n", ntohl(vxh->vx_vni) >> 8);
-		goto drop;
 	}
 
+error:
+	/* Put UDP header back */
+	__skb_push(skb, sizeof(struct udphdr));
+	return 1;
+}
+
+/* Callback from net/ipv4/udp.c to receive packets */
+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 iphdr *oip;
+	struct pcpu_tstats *stats;
+	int err;
+
+	/* Is this VNI defined? */
+	vxlan = vxlan_find_vni(net, tpi->key);
+	if (!vxlan)
+		return 1;
+
 	if (!pskb_may_pull(skb, ETH_HLEN)) {
 		vxlan->tunnel.dev->stats.rx_length_errors++;
 		vxlan->tunnel.dev->stats.rx_errors++;
@@ -571,11 +598,6 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
 	netif_rx(skb);
 
 	return 0;
-error:
-	/* Put UDP header back */
-	__skb_push(skb, sizeof(struct udphdr));
-
-	return 1;
 drop:
 	/* Consume bad packet */
 	kfree_skb(skb);
@@ -1014,7 +1036,6 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
 
 	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;
@@ -1209,6 +1230,12 @@ static struct pernet_operations vxlan_net_ops = {
 	.size = sizeof(struct vxlan_net),
 };
 
+static struct ipt_protocol vxlan_protocol = {
+	.handler        = vxlan_rcv,
+	.priority       = 0,
+	.type           = IPT_VXLAN,
+};
+
 static int __init vxlan_init_module(void)
 {
 	int rc;
@@ -1223,8 +1250,16 @@ static int __init vxlan_init_module(void)
 	if (rc)
 		goto out2;
 
+	vxlan_protocol.portno = vxlan_port;
+	rtnl_lock();
+	rc = ipt_add_protocol(&vxlan_protocol);
+	rtnl_unlock();
+	if (rc)
+		goto out3;
 	return 0;
 
+out3:
+	rtnl_link_unregister(&vxlan_link_ops);
 out2:
 	unregister_pernet_device(&vxlan_net_ops);
 out1:
@@ -1234,6 +1269,9 @@ module_init(vxlan_init_module);
 
 static void __exit vxlan_cleanup_module(void)
 {
+	rtnl_lock();
+	ipt_del_protocol(&vxlan_protocol);
+	rtnl_unlock();
 	rtnl_link_unregister(&vxlan_link_ops);
 	unregister_pernet_device(&vxlan_net_ops);
 }
-- 
1.7.10




More information about the dev mailing list