aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Schillstrom <hans.schillstrom@ericsson.com>2011-01-03 08:44:42 -0500
committerSimon Horman <horms@verge.net.au>2011-01-12 20:30:26 -0500
commit61b1ab4583e275af216c8454b9256de680499b19 (patch)
tree43e7cd6c71030c4d94c4e02dd34de77e57943a2d
parentfee1cc0895fd7bde875a86bbc3a1e82089e540b8 (diff)
IPVS: netns, add basic init per netns.
Preparation for network name-space init, in this stage some empty functions exists. In most files there is a check if it is root ns i.e. init_net if (!net_eq(net, &init_net)) return ... this will be removed by the last patch, when enabling name-space. *v3 ip_vs_conn.c merge error corrected. net_ipvs #ifdef removed as sugested by Jan Engelhardt [ horms@verge.net.au: Removed whitespace-change-only hunks ] Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com> Acked-by: Julian Anastasov <ja@ssi.bg> Signed-off-by: Simon Horman <horms@verge.net.au>
-rw-r--r--include/net/ip_vs.h11
-rw-r--r--include/net/net_namespace.h2
-rw-r--r--include/net/netns/ip_vs.h25
-rw-r--r--net/netfilter/ipvs/ip_vs_app.c28
-rw-r--r--net/netfilter/ipvs/ip_vs_conn.c34
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c63
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c49
-rw-r--r--net/netfilter/ipvs/ip_vs_est.c20
-rw-r--r--net/netfilter/ipvs/ip_vs_ftp.c34
-rw-r--r--net/netfilter/ipvs/ip_vs_lblc.c37
-rw-r--r--net/netfilter/ipvs/ip_vs_lblcr.c38
-rw-r--r--net/netfilter/ipvs/ip_vs_proto.c19
-rw-r--r--net/netfilter/ipvs/ip_vs_sync.c27
13 files changed, 354 insertions, 33 deletions
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index d858264217ba..c1c2ece3ed94 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -28,6 +28,15 @@
28#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) 28#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
29#include <net/netfilter/nf_conntrack.h> 29#include <net/netfilter/nf_conntrack.h>
30#endif 30#endif
31#include <net/net_namespace.h> /* Netw namespace */
32
33/*
34 * Generic access of ipvs struct
35 */
36static inline struct netns_ipvs *net_ipvs(struct net* net)
37{
38 return net->ipvs;
39}
31 40
32/* Connections' size value needed by ip_vs_ctl.c */ 41/* Connections' size value needed by ip_vs_ctl.c */
33extern int ip_vs_conn_tab_size; 42extern int ip_vs_conn_tab_size;
@@ -922,6 +931,8 @@ extern char ip_vs_backup_mcast_ifn[IP_VS_IFNAME_MAXLEN];
922extern int start_sync_thread(int state, char *mcast_ifn, __u8 syncid); 931extern int start_sync_thread(int state, char *mcast_ifn, __u8 syncid);
923extern int stop_sync_thread(int state); 932extern int stop_sync_thread(int state);
924extern void ip_vs_sync_conn(struct ip_vs_conn *cp); 933extern void ip_vs_sync_conn(struct ip_vs_conn *cp);
934extern int ip_vs_sync_init(void);
935extern void ip_vs_sync_cleanup(void);
925 936
926 937
927/* 938/*
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 1bf812b21fb7..b3b4a34cb2cc 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -20,6 +20,7 @@
20#include <net/netns/conntrack.h> 20#include <net/netns/conntrack.h>
21#endif 21#endif
22#include <net/netns/xfrm.h> 22#include <net/netns/xfrm.h>
23#include <net/netns/ip_vs.h>
23 24
24struct proc_dir_entry; 25struct proc_dir_entry;
25struct net_device; 26struct net_device;
@@ -94,6 +95,7 @@ struct net {
94#ifdef CONFIG_XFRM 95#ifdef CONFIG_XFRM
95 struct netns_xfrm xfrm; 96 struct netns_xfrm xfrm;
96#endif 97#endif
98 struct netns_ipvs *ipvs;
97}; 99};
98 100
99 101
diff --git a/include/net/netns/ip_vs.h b/include/net/netns/ip_vs.h
new file mode 100644
index 000000000000..12fe84087cec
--- /dev/null
+++ b/include/net/netns/ip_vs.h
@@ -0,0 +1,25 @@
1/*
2 * IP Virtual Server
3 * Data structure for network namspace
4 *
5 */
6
7#ifndef IP_VS_H_
8#define IP_VS_H_
9
10#include <linux/list.h>
11#include <linux/mutex.h>
12#include <linux/list_nulls.h>
13#include <linux/ip_vs.h>
14#include <asm/atomic.h>
15#include <linux/in.h>
16
17struct ip_vs_stats;
18struct ip_vs_sync_buff;
19struct ctl_table_header;
20
21struct netns_ipvs {
22 int gen; /* Generation */
23};
24
25#endif /* IP_VS_H_ */
diff --git a/net/netfilter/ipvs/ip_vs_app.c b/net/netfilter/ipvs/ip_vs_app.c
index a475edee0912..40b09ccc4896 100644
--- a/net/netfilter/ipvs/ip_vs_app.c
+++ b/net/netfilter/ipvs/ip_vs_app.c
@@ -569,15 +569,35 @@ static const struct file_operations ip_vs_app_fops = {
569}; 569};
570#endif 570#endif
571 571
572int __init ip_vs_app_init(void) 572static int __net_init __ip_vs_app_init(struct net *net)
573{ 573{
574 /* we will replace it with proc_net_ipvs_create() soon */ 574 if (!net_eq(net, &init_net)) /* netns not enabled yet */
575 proc_net_fops_create(&init_net, "ip_vs_app", 0, &ip_vs_app_fops); 575 return -EPERM;
576
577 proc_net_fops_create(net, "ip_vs_app", 0, &ip_vs_app_fops);
576 return 0; 578 return 0;
577} 579}
578 580
581static void __net_exit __ip_vs_app_cleanup(struct net *net)
582{
583 proc_net_remove(net, "ip_vs_app");
584}
585
586static struct pernet_operations ip_vs_app_ops = {
587 .init = __ip_vs_app_init,
588 .exit = __ip_vs_app_cleanup,
589};
590
591int __init ip_vs_app_init(void)
592{
593 int rv;
594
595 rv = register_pernet_subsys(&ip_vs_app_ops);
596 return rv;
597}
598
579 599
580void ip_vs_app_cleanup(void) 600void ip_vs_app_cleanup(void)
581{ 601{
582 proc_net_remove(&init_net, "ip_vs_app"); 602 unregister_pernet_subsys(&ip_vs_app_ops);
583} 603}
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index 66e4662925d5..7c1b502f8d8d 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -1201,11 +1201,36 @@ static void ip_vs_conn_flush(void)
1201 goto flush_again; 1201 goto flush_again;
1202 } 1202 }
1203} 1203}
1204/*
1205 * per netns init and exit
1206 */
1207int __net_init __ip_vs_conn_init(struct net *net)
1208{
1209 if (!net_eq(net, &init_net)) /* netns not enabled yet */
1210 return -EPERM;
1204 1211
1212 proc_net_fops_create(net, "ip_vs_conn", 0, &ip_vs_conn_fops);
1213 proc_net_fops_create(net, "ip_vs_conn_sync", 0, &ip_vs_conn_sync_fops);
1214 return 0;
1215}
1216
1217static void __net_exit __ip_vs_conn_cleanup(struct net *net)
1218{
1219 if (!net_eq(net, &init_net)) /* netns not enabled yet */
1220 return;
1221
1222 proc_net_remove(net, "ip_vs_conn");
1223 proc_net_remove(net, "ip_vs_conn_sync");
1224}
1225static struct pernet_operations ipvs_conn_ops = {
1226 .init = __ip_vs_conn_init,
1227 .exit = __ip_vs_conn_cleanup,
1228};
1205 1229
1206int __init ip_vs_conn_init(void) 1230int __init ip_vs_conn_init(void)
1207{ 1231{
1208 int idx; 1232 int idx;
1233 int retc;
1209 1234
1210 /* Compute size and mask */ 1235 /* Compute size and mask */
1211 ip_vs_conn_tab_size = 1 << ip_vs_conn_tab_bits; 1236 ip_vs_conn_tab_size = 1 << ip_vs_conn_tab_bits;
@@ -1243,24 +1268,21 @@ int __init ip_vs_conn_init(void)
1243 rwlock_init(&__ip_vs_conntbl_lock_array[idx].l); 1268 rwlock_init(&__ip_vs_conntbl_lock_array[idx].l);
1244 } 1269 }
1245 1270
1246 proc_net_fops_create(&init_net, "ip_vs_conn", 0, &ip_vs_conn_fops); 1271 retc = register_pernet_subsys(&ipvs_conn_ops);
1247 proc_net_fops_create(&init_net, "ip_vs_conn_sync", 0, &ip_vs_conn_sync_fops);
1248 1272
1249 /* calculate the random value for connection hash */ 1273 /* calculate the random value for connection hash */
1250 get_random_bytes(&ip_vs_conn_rnd, sizeof(ip_vs_conn_rnd)); 1274 get_random_bytes(&ip_vs_conn_rnd, sizeof(ip_vs_conn_rnd));
1251 1275
1252 return 0; 1276 return retc;
1253} 1277}
1254 1278
1255
1256void ip_vs_conn_cleanup(void) 1279void ip_vs_conn_cleanup(void)
1257{ 1280{
1281 unregister_pernet_subsys(&ipvs_conn_ops);
1258 /* flush all the connection entries first */ 1282 /* flush all the connection entries first */
1259 ip_vs_conn_flush(); 1283 ip_vs_conn_flush();
1260 1284
1261 /* Release the empty cache */ 1285 /* Release the empty cache */
1262 kmem_cache_destroy(ip_vs_conn_cachep); 1286 kmem_cache_destroy(ip_vs_conn_cachep);
1263 proc_net_remove(&init_net, "ip_vs_conn");
1264 proc_net_remove(&init_net, "ip_vs_conn_sync");
1265 vfree(ip_vs_conn_tab); 1287 vfree(ip_vs_conn_tab);
1266} 1288}
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 5287771d0647..206f40c548d7 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -41,6 +41,7 @@
41#include <net/icmp.h> /* for icmp_send */ 41#include <net/icmp.h> /* for icmp_send */
42#include <net/route.h> 42#include <net/route.h>
43#include <net/ip6_checksum.h> 43#include <net/ip6_checksum.h>
44#include <net/netns/generic.h> /* net_generic() */
44 45
45#include <linux/netfilter.h> 46#include <linux/netfilter.h>
46#include <linux/netfilter_ipv4.h> 47#include <linux/netfilter_ipv4.h>
@@ -68,6 +69,12 @@ EXPORT_SYMBOL(ip_vs_conn_put);
68EXPORT_SYMBOL(ip_vs_get_debug_level); 69EXPORT_SYMBOL(ip_vs_get_debug_level);
69#endif 70#endif
70 71
72int ip_vs_net_id __read_mostly;
73#ifdef IP_VS_GENERIC_NETNS
74EXPORT_SYMBOL(ip_vs_net_id);
75#endif
76/* netns cnt used for uniqueness */
77static atomic_t ipvs_netns_cnt = ATOMIC_INIT(0);
71 78
72/* ID used in ICMP lookups */ 79/* ID used in ICMP lookups */
73#define icmp_id(icmph) (((icmph)->un).echo.id) 80#define icmp_id(icmph) (((icmph)->un).echo.id)
@@ -1813,6 +1820,44 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
1813#endif 1820#endif
1814}; 1821};
1815 1822
1823/*
1824 * Initialize IP Virtual Server netns mem.
1825 */
1826static int __net_init __ip_vs_init(struct net *net)
1827{
1828 struct netns_ipvs *ipvs;
1829
1830 if (!net_eq(net, &init_net)) {
1831 pr_err("The final patch for enabling netns is missing\n");
1832 return -EPERM;
1833 }
1834 ipvs = net_generic(net, ip_vs_net_id);
1835 if (ipvs == NULL) {
1836 pr_err("%s(): no memory.\n", __func__);
1837 return -ENOMEM;
1838 }
1839 /* Counters used for creating unique names */
1840 ipvs->gen = atomic_read(&ipvs_netns_cnt);
1841 atomic_inc(&ipvs_netns_cnt);
1842 net->ipvs = ipvs;
1843 printk(KERN_INFO "IPVS: Creating netns size=%lu id=%d\n",
1844 sizeof(struct netns_ipvs), ipvs->gen);
1845 return 0;
1846}
1847
1848static void __net_exit __ip_vs_cleanup(struct net *net)
1849{
1850 struct netns_ipvs *ipvs = net_ipvs(net);
1851
1852 IP_VS_DBG(10, "ipvs netns %d released\n", ipvs->gen);
1853}
1854
1855static struct pernet_operations ipvs_core_ops = {
1856 .init = __ip_vs_init,
1857 .exit = __ip_vs_cleanup,
1858 .id = &ip_vs_net_id,
1859 .size = sizeof(struct netns_ipvs),
1860};
1816 1861
1817/* 1862/*
1818 * Initialize IP Virtual Server 1863 * Initialize IP Virtual Server
@@ -1821,8 +1866,11 @@ static int __init ip_vs_init(void)
1821{ 1866{
1822 int ret; 1867 int ret;
1823 1868
1824 ip_vs_estimator_init(); 1869 ret = register_pernet_subsys(&ipvs_core_ops); /* Alloc ip_vs struct */
1870 if (ret < 0)
1871 return ret;
1825 1872
1873 ip_vs_estimator_init();
1826 ret = ip_vs_control_init(); 1874 ret = ip_vs_control_init();
1827 if (ret < 0) { 1875 if (ret < 0) {
1828 pr_err("can't setup control.\n"); 1876 pr_err("can't setup control.\n");
@@ -1843,15 +1891,23 @@ static int __init ip_vs_init(void)
1843 goto cleanup_app; 1891 goto cleanup_app;
1844 } 1892 }
1845 1893
1894 ret = ip_vs_sync_init();
1895 if (ret < 0) {
1896 pr_err("can't setup sync data.\n");
1897 goto cleanup_conn;
1898 }
1899
1846 ret = nf_register_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); 1900 ret = nf_register_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
1847 if (ret < 0) { 1901 if (ret < 0) {
1848 pr_err("can't register hooks.\n"); 1902 pr_err("can't register hooks.\n");
1849 goto cleanup_conn; 1903 goto cleanup_sync;
1850 } 1904 }
1851 1905
1852 pr_info("ipvs loaded.\n"); 1906 pr_info("ipvs loaded.\n");
1853 return ret; 1907 return ret;
1854 1908
1909cleanup_sync:
1910 ip_vs_sync_cleanup();
1855 cleanup_conn: 1911 cleanup_conn:
1856 ip_vs_conn_cleanup(); 1912 ip_vs_conn_cleanup();
1857 cleanup_app: 1913 cleanup_app:
@@ -1861,17 +1917,20 @@ static int __init ip_vs_init(void)
1861 ip_vs_control_cleanup(); 1917 ip_vs_control_cleanup();
1862 cleanup_estimator: 1918 cleanup_estimator:
1863 ip_vs_estimator_cleanup(); 1919 ip_vs_estimator_cleanup();
1920 unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */
1864 return ret; 1921 return ret;
1865} 1922}
1866 1923
1867static void __exit ip_vs_cleanup(void) 1924static void __exit ip_vs_cleanup(void)
1868{ 1925{
1869 nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); 1926 nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
1927 ip_vs_sync_cleanup();
1870 ip_vs_conn_cleanup(); 1928 ip_vs_conn_cleanup();
1871 ip_vs_app_cleanup(); 1929 ip_vs_app_cleanup();
1872 ip_vs_protocol_cleanup(); 1930 ip_vs_protocol_cleanup();
1873 ip_vs_control_cleanup(); 1931 ip_vs_control_cleanup();
1874 ip_vs_estimator_cleanup(); 1932 ip_vs_estimator_cleanup();
1933 unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */
1875 pr_info("ipvs unloaded.\n"); 1934 pr_info("ipvs unloaded.\n");
1876} 1935}
1877 1936
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index ca49e928f302..ceeef4352d34 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -3406,6 +3406,42 @@ static void ip_vs_genl_unregister(void)
3406 3406
3407/* End of Generic Netlink interface definitions */ 3407/* End of Generic Netlink interface definitions */
3408 3408
3409/*
3410 * per netns intit/exit func.
3411 */
3412int __net_init __ip_vs_control_init(struct net *net)
3413{
3414 if (!net_eq(net, &init_net)) /* netns not enabled yet */
3415 return -EPERM;
3416
3417 proc_net_fops_create(net, "ip_vs", 0, &ip_vs_info_fops);
3418 proc_net_fops_create(net, "ip_vs_stats", 0, &ip_vs_stats_fops);
3419 sysctl_header = register_net_sysctl_table(net, net_vs_ctl_path,
3420 vs_vars);
3421 if (sysctl_header == NULL)
3422 goto err_reg;
3423 ip_vs_new_estimator(&ip_vs_stats);
3424 return 0;
3425
3426err_reg:
3427 return -ENOMEM;
3428}
3429
3430static void __net_exit __ip_vs_control_cleanup(struct net *net)
3431{
3432 if (!net_eq(net, &init_net)) /* netns not enabled yet */
3433 return;
3434
3435 ip_vs_kill_estimator(&ip_vs_stats);
3436 unregister_net_sysctl_table(sysctl_header);
3437 proc_net_remove(net, "ip_vs_stats");
3438 proc_net_remove(net, "ip_vs");
3439}
3440
3441static struct pernet_operations ipvs_control_ops = {
3442 .init = __ip_vs_control_init,
3443 .exit = __ip_vs_control_cleanup,
3444};
3409 3445
3410int __init ip_vs_control_init(void) 3446int __init ip_vs_control_init(void)
3411{ 3447{
@@ -3437,12 +3473,9 @@ int __init ip_vs_control_init(void)
3437 return ret; 3473 return ret;
3438 } 3474 }
3439 3475
3440 proc_net_fops_create(&init_net, "ip_vs", 0, &ip_vs_info_fops); 3476 ret = register_pernet_subsys(&ipvs_control_ops);
3441 proc_net_fops_create(&init_net, "ip_vs_stats",0, &ip_vs_stats_fops); 3477 if (ret)
3442 3478 return ret;
3443 sysctl_header = register_sysctl_paths(net_vs_ctl_path, vs_vars);
3444
3445 ip_vs_new_estimator(&ip_vs_stats);
3446 3479
3447 /* Hook the defense timer */ 3480 /* Hook the defense timer */
3448 schedule_delayed_work(&defense_work, DEFENSE_TIMER_PERIOD); 3481 schedule_delayed_work(&defense_work, DEFENSE_TIMER_PERIOD);
@@ -3459,9 +3492,7 @@ void ip_vs_control_cleanup(void)
3459 cancel_delayed_work_sync(&defense_work); 3492 cancel_delayed_work_sync(&defense_work);
3460 cancel_work_sync(&defense_work.work); 3493 cancel_work_sync(&defense_work.work);
3461 ip_vs_kill_estimator(&ip_vs_stats); 3494 ip_vs_kill_estimator(&ip_vs_stats);
3462 unregister_sysctl_table(sysctl_header); 3495 unregister_pernet_subsys(&ipvs_control_ops);
3463 proc_net_remove(&init_net, "ip_vs_stats");
3464 proc_net_remove(&init_net, "ip_vs");
3465 ip_vs_genl_unregister(); 3496 ip_vs_genl_unregister();
3466 nf_unregister_sockopt(&ip_vs_sockopts); 3497 nf_unregister_sockopt(&ip_vs_sockopts);
3467 LeaveFunction(2); 3498 LeaveFunction(2);
diff --git a/net/netfilter/ipvs/ip_vs_est.c b/net/netfilter/ipvs/ip_vs_est.c
index ff28801962e0..7417a0c1408b 100644
--- a/net/netfilter/ipvs/ip_vs_est.c
+++ b/net/netfilter/ipvs/ip_vs_est.c
@@ -157,13 +157,31 @@ void ip_vs_zero_estimator(struct ip_vs_stats *stats)
157 est->outbps = 0; 157 est->outbps = 0;
158} 158}
159 159
160static int __net_init __ip_vs_estimator_init(struct net *net)
161{
162 if (!net_eq(net, &init_net)) /* netns not enabled yet */
163 return -EPERM;
164
165 return 0;
166}
167
168static struct pernet_operations ip_vs_app_ops = {
169 .init = __ip_vs_estimator_init,
170};
171
160int __init ip_vs_estimator_init(void) 172int __init ip_vs_estimator_init(void)
161{ 173{
174 int rv;
175
176 rv = register_pernet_subsys(&ip_vs_app_ops);
177 if (rv < 0)
178 return rv;
162 mod_timer(&est_timer, jiffies + 2 * HZ); 179 mod_timer(&est_timer, jiffies + 2 * HZ);
163 return 0; 180 return rv;
164} 181}
165 182
166void ip_vs_estimator_cleanup(void) 183void ip_vs_estimator_cleanup(void)
167{ 184{
168 del_timer_sync(&est_timer); 185 del_timer_sync(&est_timer);
186 unregister_pernet_subsys(&ip_vs_app_ops);
169} 187}
diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c
index 84aef65b37d1..0e762f322aa3 100644
--- a/net/netfilter/ipvs/ip_vs_ftp.c
+++ b/net/netfilter/ipvs/ip_vs_ftp.c
@@ -399,15 +399,17 @@ static struct ip_vs_app ip_vs_ftp = {
399 .pkt_in = ip_vs_ftp_in, 399 .pkt_in = ip_vs_ftp_in,
400}; 400};
401 401
402
403/* 402/*
404 * ip_vs_ftp initialization 403 * per netns ip_vs_ftp initialization
405 */ 404 */
406static int __init ip_vs_ftp_init(void) 405static int __net_init __ip_vs_ftp_init(struct net *net)
407{ 406{
408 int i, ret; 407 int i, ret;
409 struct ip_vs_app *app = &ip_vs_ftp; 408 struct ip_vs_app *app = &ip_vs_ftp;
410 409
410 if (!net_eq(net, &init_net)) /* netns not enabled yet */
411 return -EPERM;
412
411 ret = register_ip_vs_app(app); 413 ret = register_ip_vs_app(app);
412 if (ret) 414 if (ret)
413 return ret; 415 return ret;
@@ -427,14 +429,38 @@ static int __init ip_vs_ftp_init(void)
427 429
428 return ret; 430 return ret;
429} 431}
432/*
433 * netns exit
434 */
435static void __ip_vs_ftp_exit(struct net *net)
436{
437 struct ip_vs_app *app = &ip_vs_ftp;
438
439 if (!net_eq(net, &init_net)) /* netns not enabled yet */
440 return;
441
442 unregister_ip_vs_app(app);
443}
444
445static struct pernet_operations ip_vs_ftp_ops = {
446 .init = __ip_vs_ftp_init,
447 .exit = __ip_vs_ftp_exit,
448};
430 449
450int __init ip_vs_ftp_init(void)
451{
452 int rv;
453
454 rv = register_pernet_subsys(&ip_vs_ftp_ops);
455 return rv;
456}
431 457
432/* 458/*
433 * ip_vs_ftp finish. 459 * ip_vs_ftp finish.
434 */ 460 */
435static void __exit ip_vs_ftp_exit(void) 461static void __exit ip_vs_ftp_exit(void)
436{ 462{
437 unregister_ip_vs_app(&ip_vs_ftp); 463 unregister_pernet_subsys(&ip_vs_ftp_ops);
438} 464}
439 465
440 466
diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c
index 9323f8944199..84278fb4e055 100644
--- a/net/netfilter/ipvs/ip_vs_lblc.c
+++ b/net/netfilter/ipvs/ip_vs_lblc.c
@@ -543,23 +543,54 @@ static struct ip_vs_scheduler ip_vs_lblc_scheduler =
543 .schedule = ip_vs_lblc_schedule, 543 .schedule = ip_vs_lblc_schedule,
544}; 544};
545 545
546/*
547 * per netns init.
548 */
549static int __net_init __ip_vs_lblc_init(struct net *net)
550{
551 if (!net_eq(net, &init_net)) /* netns not enabled yet */
552 return -EPERM;
553
554 sysctl_header = register_net_sysctl_table(net, net_vs_ctl_path,
555 vs_vars_table);
556 if (!sysctl_header)
557 return -ENOMEM;
558
559 return 0;
560}
561
562static void __net_exit __ip_vs_lblc_exit(struct net *net)
563{
564 if (!net_eq(net, &init_net)) /* netns not enabled yet */
565 return;
566
567 unregister_net_sysctl_table(sysctl_header);
568}
569
570static struct pernet_operations ip_vs_lblc_ops = {
571 .init = __ip_vs_lblc_init,
572 .exit = __ip_vs_lblc_exit,
573};
546 574
547static int __init ip_vs_lblc_init(void) 575static int __init ip_vs_lblc_init(void)
548{ 576{
549 int ret; 577 int ret;
550 578
551 sysctl_header = register_sysctl_paths(net_vs_ctl_path, vs_vars_table); 579 ret = register_pernet_subsys(&ip_vs_lblc_ops);
580 if (ret)
581 return ret;
582
552 ret = register_ip_vs_scheduler(&ip_vs_lblc_scheduler); 583 ret = register_ip_vs_scheduler(&ip_vs_lblc_scheduler);
553 if (ret) 584 if (ret)
554 unregister_sysctl_table(sysctl_header); 585 unregister_pernet_subsys(&ip_vs_lblc_ops);
555 return ret; 586 return ret;
556} 587}
557 588
558 589
559static void __exit ip_vs_lblc_cleanup(void) 590static void __exit ip_vs_lblc_cleanup(void)
560{ 591{
561 unregister_sysctl_table(sysctl_header);
562 unregister_ip_vs_scheduler(&ip_vs_lblc_scheduler); 592 unregister_ip_vs_scheduler(&ip_vs_lblc_scheduler);
593 unregister_pernet_subsys(&ip_vs_lblc_ops);
563} 594}
564 595
565 596
diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c
index dbeed8ea421a..7c7396a6acbf 100644
--- a/net/netfilter/ipvs/ip_vs_lblcr.c
+++ b/net/netfilter/ipvs/ip_vs_lblcr.c
@@ -744,23 +744,53 @@ static struct ip_vs_scheduler ip_vs_lblcr_scheduler =
744 .schedule = ip_vs_lblcr_schedule, 744 .schedule = ip_vs_lblcr_schedule,
745}; 745};
746 746
747/*
748 * per netns init.
749 */
750static int __net_init __ip_vs_lblcr_init(struct net *net)
751{
752 if (!net_eq(net, &init_net)) /* netns not enabled yet */
753 return -EPERM;
754
755 sysctl_header = register_net_sysctl_table(net, net_vs_ctl_path,
756 vs_vars_table);
757 if (!sysctl_header)
758 return -ENOMEM;
759
760 return 0;
761}
762
763static void __net_exit __ip_vs_lblcr_exit(struct net *net)
764{
765 if (!net_eq(net, &init_net)) /* netns not enabled yet */
766 return;
767
768 unregister_net_sysctl_table(sysctl_header);
769}
770
771static struct pernet_operations ip_vs_lblcr_ops = {
772 .init = __ip_vs_lblcr_init,
773 .exit = __ip_vs_lblcr_exit,
774};
747 775
748static int __init ip_vs_lblcr_init(void) 776static int __init ip_vs_lblcr_init(void)
749{ 777{
750 int ret; 778 int ret;
751 779
752 sysctl_header = register_sysctl_paths(net_vs_ctl_path, vs_vars_table); 780 ret = register_pernet_subsys(&ip_vs_lblcr_ops);
781 if (ret)
782 return ret;
783
753 ret = register_ip_vs_scheduler(&ip_vs_lblcr_scheduler); 784 ret = register_ip_vs_scheduler(&ip_vs_lblcr_scheduler);
754 if (ret) 785 if (ret)
755 unregister_sysctl_table(sysctl_header); 786 unregister_pernet_subsys(&ip_vs_lblcr_ops);
756 return ret; 787 return ret;
757} 788}
758 789
759
760static void __exit ip_vs_lblcr_cleanup(void) 790static void __exit ip_vs_lblcr_cleanup(void)
761{ 791{
762 unregister_sysctl_table(sysctl_header);
763 unregister_ip_vs_scheduler(&ip_vs_lblcr_scheduler); 792 unregister_ip_vs_scheduler(&ip_vs_lblcr_scheduler);
793 unregister_pernet_subsys(&ip_vs_lblcr_ops);
764} 794}
765 795
766 796
diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c
index c53998390877..45392942d0e7 100644
--- a/net/netfilter/ipvs/ip_vs_proto.c
+++ b/net/netfilter/ipvs/ip_vs_proto.c
@@ -236,6 +236,23 @@ ip_vs_tcpudp_debug_packet(int af, struct ip_vs_protocol *pp,
236 ip_vs_tcpudp_debug_packet_v4(pp, skb, offset, msg); 236 ip_vs_tcpudp_debug_packet_v4(pp, skb, offset, msg);
237} 237}
238 238
239/*
240 * per network name-space init
241 */
242static int __net_init __ip_vs_protocol_init(struct net *net)
243{
244 return 0;
245}
246
247static void __net_exit __ip_vs_protocol_cleanup(struct net *net)
248{
249 /* empty */
250}
251
252static struct pernet_operations ipvs_proto_ops = {
253 .init = __ip_vs_protocol_init,
254 .exit = __ip_vs_protocol_cleanup,
255};
239 256
240int __init ip_vs_protocol_init(void) 257int __init ip_vs_protocol_init(void)
241{ 258{
@@ -265,6 +282,7 @@ int __init ip_vs_protocol_init(void)
265 REGISTER_PROTOCOL(&ip_vs_protocol_esp); 282 REGISTER_PROTOCOL(&ip_vs_protocol_esp);
266#endif 283#endif
267 pr_info("Registered protocols (%s)\n", &protocols[2]); 284 pr_info("Registered protocols (%s)\n", &protocols[2]);
285 return register_pernet_subsys(&ipvs_proto_ops);
268 286
269 return 0; 287 return 0;
270} 288}
@@ -275,6 +293,7 @@ void ip_vs_protocol_cleanup(void)
275 struct ip_vs_protocol *pp; 293 struct ip_vs_protocol *pp;
276 int i; 294 int i;
277 295
296 unregister_pernet_subsys(&ipvs_proto_ops);
278 /* unregister all the ipvs protocols */ 297 /* unregister all the ipvs protocols */
279 for (i = 0; i < IP_VS_PROTO_TAB_SIZE; i++) { 298 for (i = 0; i < IP_VS_PROTO_TAB_SIZE; i++) {
280 while ((pp = ip_vs_proto_table[i]) != NULL) 299 while ((pp = ip_vs_proto_table[i]) != NULL)
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index c1c167ab73ee..3668739a6d06 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1639,3 +1639,30 @@ int stop_sync_thread(int state)
1639 1639
1640 return 0; 1640 return 0;
1641} 1641}
1642
1643/*
1644 * Initialize data struct for each netns
1645 */
1646static int __net_init __ip_vs_sync_init(struct net *net)
1647{
1648 return 0;
1649}
1650
1651static void __ip_vs_sync_cleanup(struct net *net)
1652{
1653}
1654static struct pernet_operations ipvs_sync_ops = {
1655 .init = __ip_vs_sync_init,
1656 .exit = __ip_vs_sync_cleanup,
1657};
1658
1659
1660int __init ip_vs_sync_init(void)
1661{
1662 return register_pernet_subsys(&ipvs_sync_ops);
1663}
1664
1665void __exit ip_vs_sync_cleanup(void)
1666{
1667 unregister_pernet_subsys(&ipvs_sync_ops);
1668}