gre: Simplify net namespace operations.
authorJesse Gross <jesse@nicira.com>
Wed, 3 Feb 2010 22:39:29 +0000 (17:39 -0500)
committerJesse Gross <jesse@nicira.com>
Thu, 4 Feb 2010 21:08:48 +0000 (16:08 -0500)
Ports commit cfb8fb "net: Simplify ip_gre pernet operations." from
the mainline kernel.

datapath/linux-2.6/compat-2.6/include/net/net_namespace.h
datapath/linux-2.6/compat-2.6/include/net/netns/generic.h
datapath/linux-2.6/compat-2.6/ip_gre.c
datapath/linux-2.6/compat-2.6/net_namespace-ip_gre.c

index 9b66c91..92a4e02 100644 (file)
@@ -2,25 +2,28 @@
 #define __NET_NAMESPACE_WRAPPER_H 1
 
 #include <linux/version.h>
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
 #include_next <net/net_namespace.h>
 #endif
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
 struct net;
 
-struct pernet_operations {
+struct extended_pernet_operations {
        struct list_head list;
        int (*init)(struct net *net);
        void (*exit)(struct net *net);
+       int *id;
+       size_t size;
 };
-#endif /* linux kernel < 2.6.24 */
+#define pernet_operations extended_pernet_operations
+
+#define register_pernet_device rpl_register_pernet_device
+int rpl_register_pernet_device(struct extended_pernet_operations *ops);
 
-extern int register_pernet_gen_device(int *id, struct pernet_operations *);
-extern void unregister_pernet_gen_device(int id, struct pernet_operations *);
+#define unregister_pernet_device rpl_unregister_pernet_device
+void rpl_unregister_pernet_device(struct extended_pernet_operations *ops);
 
-#endif /* linux kernel < 2.6.26 */
+#endif /* linux kernel < 2.6.33 */
 
 #endif
index f70bc87..7aedf31 100644 (file)
@@ -2,15 +2,18 @@
 #define __NET_NETNS_GENERIC_WRAPPER_H 1
 
 #include <linux/version.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+#include_next <net/netns/generic.h>
+#endif
 
-struct net;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
 
-extern void *net_generic(struct net *net, int id);
-extern int net_assign_generic(struct net *net, int id, void *data);
+#define net_assign_generic rpl_net_assign_generic
+int rpl_net_assign_generic(struct net *net, int id, void *data);
 
-#else
-#include_next <net/netns/generic.h>
-#endif /* linux kernel < 2.6.26 */
+#define net_generic rpl_net_generic
+void *rpl_net_generic(struct net *net, int id);
+
+#endif /* linux kernel < 2.6.33 */
 
 #endif
index 9a7ea96..ec0f0c5 100644 (file)
@@ -1465,17 +1465,8 @@ static void ipgre_destroy_tunnels(struct ipgre_net *ign, struct list_head *head)
 
 static int ipgre_init_net(struct net *net)
 {
+       struct ipgre_net *ign = net_generic(net, ipgre_net_id);
        int err;
-       struct ipgre_net *ign;
-
-       err = -ENOMEM;
-       ign = kzalloc(sizeof(struct ipgre_net), GFP_KERNEL);
-       if (ign == NULL)
-               goto err_alloc;
-
-       err = net_assign_generic(net, ipgre_net_id, ign);
-       if (err < 0)
-               goto err_assign;
 
        ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), GRE_IOCTL_DEVICE,
                                           ipgre_tunnel_setup);
@@ -1502,10 +1493,6 @@ static int ipgre_init_net(struct net *net)
 err_reg_dev:
        free_netdev(ign->fb_tunnel_dev);
 err_alloc_dev:
-       /* nothing */
-err_assign:
-       kfree(ign);
-err_alloc:
        return err;
 }
 
@@ -1519,12 +1506,13 @@ static void ipgre_exit_net(struct net *net)
        ipgre_destroy_tunnels(ign, &list);
        unregister_netdevice_many(&list);
        rtnl_unlock();
-       kfree(ign);
 }
 
 static struct pernet_operations ipgre_net_ops = {
        .init = ipgre_init_net,
        .exit = ipgre_exit_net,
+       .id   = &ipgre_net_id,
+       .size = sizeof(struct ipgre_net),
 };
 
 static int ipgre_tap_init(struct net_device *dev)
@@ -1866,7 +1854,7 @@ static int __init ipgre_init(void)
                return -EAGAIN;
        }
 
-       err = register_pernet_gen_device(&ipgre_net_id, &ipgre_net_ops);
+       err = register_pernet_device(&ipgre_net_ops);
        if (err < 0)
                goto gen_device_failed;
 
@@ -1887,7 +1875,7 @@ out:
 tap_ops_failed:
        rtnl_link_unregister(&ipgre_link_ops);
 rtnl_link_failed:
-       unregister_pernet_gen_device(ipgre_net_id, &ipgre_net_ops);
+       unregister_pernet_device(&ipgre_net_ops);
 #endif
 gen_device_failed:
        inet_del_protocol(&ipgre_protocol, IPPROTO_GRE);
@@ -1901,7 +1889,7 @@ static void __exit ipgre_fini(void)
        rtnl_link_unregister(&ipgre_tap_ops);
        rtnl_link_unregister(&ipgre_link_ops);
 #endif
-       unregister_pernet_gen_device(ipgre_net_id, &ipgre_net_ops);
+       unregister_pernet_device(&ipgre_net_ops);
        if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0)
                printk(KERN_INFO "ipgre close: can't remove protocol\n");
 }
index 323b644..a7a211c 100644 (file)
 #include <linux/version.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
 
 #include <linux/sched.h>
 #include <net/net_namespace.h>
 #include <net/netns/generic.h>
 
+#undef pernet_operations
+#undef register_pernet_device
+#undef unregister_pernet_device
+#undef net_assign_generic
+#undef net_generic
+
 /* This trivial implementation assumes that there is only a single pernet
- * generic device registered and that the caller is well behaved.  It only
- * weakly attempts to check that these conditions are true. */
+ * device registered and that the caller is well behaved.  It only weakly
+ * attempts to check that these conditions are true. */
 
-static bool device_registered;
+static struct extended_pernet_operations *dev_ops;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
 static void *ng_data;
+#else
+static struct pernet_operations new_ops;
+#endif
 
-int register_pernet_gen_device(int *id, struct pernet_operations *ops)
+static int device_init_net(struct net *net)
 {
-       BUG_ON(device_registered);
+       int err;
+       if (dev_ops->id && dev_ops->size) {
+               void *data = kzalloc(dev_ops->size, GFP_KERNEL);
+               if (!data)
+                       return -ENOMEM;
+
+               err = rpl_net_assign_generic(net, *dev_ops->id, data);
+               if (err) {
+                       kfree(data);
+                       return err;
+               }
+       }
+       if (dev_ops->init)
+               return dev_ops->init(net);
+       return 0;
+}
 
-       *id = 1;
-       device_registered = true;
+static void device_exit_net(struct net *net)
+{
+       if (dev_ops->id && dev_ops->size) {
+               int id = *dev_ops->id;
+               kfree(rpl_net_generic(net, id));
+       }
 
-       if (ops->init == NULL)
-               return 0;
-       return ops->init(NULL);
+       if (dev_ops->exit)
+               return dev_ops->exit(net);
 }
 
-void unregister_pernet_gen_device(int id, struct pernet_operations *ops)
+int rpl_register_pernet_device(struct extended_pernet_operations *ops)
 {
-       device_registered = false;
-       if (ops->exit)
-               ops->exit(NULL);
+       BUG_ON(dev_ops);
+       dev_ops = ops;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+       if (dev_ops->id)
+               *dev_ops->id = 1;
+
+       return device_init_net(NULL);
+#else
+       memcpy(&new_ops, dev_ops, sizeof new_ops);
+       new_ops.init = device_init_net;
+       new_ops.exit = device_exit_net;
+
+       if (ops->id)
+               return register_pernet_gen_device(dev_ops->id, &new_ops);
+       else
+               return register_pernet_device(&new_ops);
+#endif
 }
 
-int net_assign_generic(struct net *net, int id, void *data)
+void rpl_unregister_pernet_device(struct extended_pernet_operations *ops)
 {
+       BUG_ON(!dev_ops);
+       BUG_ON(dev_ops != ops);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+       device_exit_net(NULL);
+#else
+       if (ops->id)
+               unregister_pernet_gen_device(*dev_ops->id, &new_ops);
+       else
+               unregister_pernet_device(&new_ops);
+#endif
+
+       dev_ops = NULL;
+}
+
+int rpl_net_assign_generic(struct net *net, int id, void *data)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
        BUG_ON(id != 1);
 
        ng_data = data;
        return 0;
+#else
+       return net_assign_generic(net, id, data);
+#endif
 }
 
-void *net_generic(struct net *net, int id)
+void *rpl_net_generic(struct net *net, int id)
 {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
        BUG_ON(id != 1);
 
        return ng_data;
+#else
+       return net_generic(net, id);
+#endif
 }
 
-#endif /* kernel < 2.6.26 */
+#endif /* kernel < 2.6.33 */