[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