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

Signed-off-by: Pravin B Shelar <[email protected]>
---
 drivers/net/vxlan.c |  105 ++++++++++++++++++---------------------------------
 1 file changed, 37 insertions(+), 68 deletions(-)

diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index a56e00d..8faaeb8 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -43,8 +43,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 */
@@ -62,8 +60,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 */
@@ -80,7 +78,6 @@ struct vxlan_fdb {
 /* Pseudo network device */
 struct vxlan_dev {
        struct ip_tunnel tunnel;
-       struct hlist_node hlist;
        __u16             port_min;     /* source port range */
        __u16             port_max;
        bool              learn;
@@ -94,30 +91,6 @@ struct vxlan_dev {
        struct hlist_head fdb_head[FDB_HASH_SIZE];
 };
 
-/* 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,
@@ -412,19 +385,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(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;
                }
 
@@ -534,12 +506,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;
 
@@ -930,6 +903,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] = {
@@ -990,22 +965,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]);
@@ -1051,20 +1023,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)
@@ -1126,8 +1085,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,
 };
@@ -1175,18 +1134,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;
 }
@@ -1194,11 +1163,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 = {
@@ -1209,17 +1180,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.10

_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev

Reply via email to