Merge "next" branch into "master".
[sliver-openvswitch.git] / datapath / linux-2.6 / compat-2.6 / net_namespace-ip_gre.c
1 #include <linux/version.h>
2 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
3
4 #include <linux/sched.h>
5 #include <net/net_namespace.h>
6 #include <net/netns/generic.h>
7
8 #undef pernet_operations
9 #undef register_pernet_device
10 #undef unregister_pernet_device
11 #undef net_assign_generic
12 #undef net_generic
13
14 /* This trivial implementation assumes that there is only a single pernet
15  * device registered and that the caller is well behaved.  It only weakly
16  * attempts to check that these conditions are true. */
17
18 static struct extended_pernet_operations *dev_ops;
19 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
20 static void *ng_data;
21 #else
22 static struct pernet_operations new_ops;
23 #endif
24
25 static int device_init_net(struct net *net)
26 {
27         int err;
28         if (dev_ops->id && dev_ops->size) {
29                 void *data = kzalloc(dev_ops->size, GFP_KERNEL);
30                 if (!data)
31                         return -ENOMEM;
32
33                 err = rpl_net_assign_generic(net, *dev_ops->id, data);
34                 if (err) {
35                         kfree(data);
36                         return err;
37                 }
38         }
39         if (dev_ops->init)
40                 return dev_ops->init(net);
41         return 0;
42 }
43
44 static void device_exit_net(struct net *net)
45 {
46         if (dev_ops->exit)
47                 dev_ops->exit(net);
48
49         if (dev_ops->id && dev_ops->size) {
50                 int id = *dev_ops->id;
51                 kfree(rpl_net_generic(net, id));
52         }
53 }
54
55 int rpl_register_pernet_device(struct extended_pernet_operations *ops)
56 {
57         BUG_ON(dev_ops);
58         dev_ops = ops;
59
60 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
61         if (dev_ops->id)
62                 *dev_ops->id = 1;
63
64         return device_init_net(NULL);
65 #else
66         memcpy(&new_ops, dev_ops, sizeof new_ops);
67         new_ops.init = device_init_net;
68         new_ops.exit = device_exit_net;
69
70         if (ops->id)
71                 return register_pernet_gen_device(dev_ops->id, &new_ops);
72         else
73                 return register_pernet_device(&new_ops);
74 #endif
75 }
76
77 void rpl_unregister_pernet_device(struct extended_pernet_operations *ops)
78 {
79         BUG_ON(!dev_ops);
80         BUG_ON(dev_ops != ops);
81
82 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
83         device_exit_net(NULL);
84 #else
85         if (ops->id)
86                 unregister_pernet_gen_device(*dev_ops->id, &new_ops);
87         else
88                 unregister_pernet_device(&new_ops);
89 #endif
90
91         dev_ops = NULL;
92 }
93
94 int rpl_net_assign_generic(struct net *net, int id, void *data)
95 {
96 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
97         BUG_ON(id != 1);
98
99         ng_data = data;
100         return 0;
101 #else
102         return net_assign_generic(net, id, data);
103 #endif
104 }
105
106 void *rpl_net_generic(struct net *net, int id)
107 {
108 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
109         BUG_ON(id != 1);
110
111         return ng_data;
112 #else
113         return net_generic(net, id);
114 #endif
115 }
116
117 #endif /* kernel < 2.6.33 */