diff options
author | Hans Schillstrom <hans.schillstrom@ericsson.com> | 2011-01-03 08:44:42 -0500 |
---|---|---|
committer | Simon Horman <horms@verge.net.au> | 2011-01-12 20:30:26 -0500 |
commit | 61b1ab4583e275af216c8454b9256de680499b19 (patch) | |
tree | 43e7cd6c71030c4d94c4e02dd34de77e57943a2d | |
parent | fee1cc0895fd7bde875a86bbc3a1e82089e540b8 (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.h | 11 | ||||
-rw-r--r-- | include/net/net_namespace.h | 2 | ||||
-rw-r--r-- | include/net/netns/ip_vs.h | 25 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_app.c | 28 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_conn.c | 34 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_core.c | 63 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_ctl.c | 49 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_est.c | 20 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_ftp.c | 34 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_lblc.c | 37 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_lblcr.c | 38 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_proto.c | 19 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_sync.c | 27 |
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 | */ | ||
36 | static 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 */ |
33 | extern int ip_vs_conn_tab_size; | 42 | extern int ip_vs_conn_tab_size; |
@@ -922,6 +931,8 @@ extern char ip_vs_backup_mcast_ifn[IP_VS_IFNAME_MAXLEN]; | |||
922 | extern int start_sync_thread(int state, char *mcast_ifn, __u8 syncid); | 931 | extern int start_sync_thread(int state, char *mcast_ifn, __u8 syncid); |
923 | extern int stop_sync_thread(int state); | 932 | extern int stop_sync_thread(int state); |
924 | extern void ip_vs_sync_conn(struct ip_vs_conn *cp); | 933 | extern void ip_vs_sync_conn(struct ip_vs_conn *cp); |
934 | extern int ip_vs_sync_init(void); | ||
935 | extern 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 | ||
24 | struct proc_dir_entry; | 25 | struct proc_dir_entry; |
25 | struct net_device; | 26 | struct 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 | |||
17 | struct ip_vs_stats; | ||
18 | struct ip_vs_sync_buff; | ||
19 | struct ctl_table_header; | ||
20 | |||
21 | struct 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 | ||
572 | int __init ip_vs_app_init(void) | 572 | static 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 | ||
581 | static void __net_exit __ip_vs_app_cleanup(struct net *net) | ||
582 | { | ||
583 | proc_net_remove(net, "ip_vs_app"); | ||
584 | } | ||
585 | |||
586 | static struct pernet_operations ip_vs_app_ops = { | ||
587 | .init = __ip_vs_app_init, | ||
588 | .exit = __ip_vs_app_cleanup, | ||
589 | }; | ||
590 | |||
591 | int __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 | ||
580 | void ip_vs_app_cleanup(void) | 600 | void 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 | */ | ||
1207 | int __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 | |||
1217 | static 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 | } | ||
1225 | static struct pernet_operations ipvs_conn_ops = { | ||
1226 | .init = __ip_vs_conn_init, | ||
1227 | .exit = __ip_vs_conn_cleanup, | ||
1228 | }; | ||
1205 | 1229 | ||
1206 | int __init ip_vs_conn_init(void) | 1230 | int __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 | |||
1256 | void ip_vs_conn_cleanup(void) | 1279 | void 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); | |||
68 | EXPORT_SYMBOL(ip_vs_get_debug_level); | 69 | EXPORT_SYMBOL(ip_vs_get_debug_level); |
69 | #endif | 70 | #endif |
70 | 71 | ||
72 | int ip_vs_net_id __read_mostly; | ||
73 | #ifdef IP_VS_GENERIC_NETNS | ||
74 | EXPORT_SYMBOL(ip_vs_net_id); | ||
75 | #endif | ||
76 | /* netns cnt used for uniqueness */ | ||
77 | static 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 | */ | ||
1826 | static 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 | |||
1848 | static 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 | |||
1855 | static 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 | ||
1909 | cleanup_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 | ||
1867 | static void __exit ip_vs_cleanup(void) | 1924 | static 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 | */ | ||
3412 | int __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 | |||
3426 | err_reg: | ||
3427 | return -ENOMEM; | ||
3428 | } | ||
3429 | |||
3430 | static 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 | |||
3441 | static struct pernet_operations ipvs_control_ops = { | ||
3442 | .init = __ip_vs_control_init, | ||
3443 | .exit = __ip_vs_control_cleanup, | ||
3444 | }; | ||
3409 | 3445 | ||
3410 | int __init ip_vs_control_init(void) | 3446 | int __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 | ||
160 | static 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 | |||
168 | static struct pernet_operations ip_vs_app_ops = { | ||
169 | .init = __ip_vs_estimator_init, | ||
170 | }; | ||
171 | |||
160 | int __init ip_vs_estimator_init(void) | 172 | int __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 | ||
166 | void ip_vs_estimator_cleanup(void) | 183 | void 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 | */ |
406 | static int __init ip_vs_ftp_init(void) | 405 | static 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 | */ | ||
435 | static 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 | |||
445 | static struct pernet_operations ip_vs_ftp_ops = { | ||
446 | .init = __ip_vs_ftp_init, | ||
447 | .exit = __ip_vs_ftp_exit, | ||
448 | }; | ||
430 | 449 | ||
450 | int __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 | */ |
435 | static void __exit ip_vs_ftp_exit(void) | 461 | static 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 | */ | ||
549 | static 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 | |||
562 | static 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 | |||
570 | static struct pernet_operations ip_vs_lblc_ops = { | ||
571 | .init = __ip_vs_lblc_init, | ||
572 | .exit = __ip_vs_lblc_exit, | ||
573 | }; | ||
546 | 574 | ||
547 | static int __init ip_vs_lblc_init(void) | 575 | static 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 | ||
559 | static void __exit ip_vs_lblc_cleanup(void) | 590 | static 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 | */ | ||
750 | static 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 | |||
763 | static 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 | |||
771 | static struct pernet_operations ip_vs_lblcr_ops = { | ||
772 | .init = __ip_vs_lblcr_init, | ||
773 | .exit = __ip_vs_lblcr_exit, | ||
774 | }; | ||
747 | 775 | ||
748 | static int __init ip_vs_lblcr_init(void) | 776 | static 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 | |||
760 | static void __exit ip_vs_lblcr_cleanup(void) | 790 | static 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 | */ | ||
242 | static int __net_init __ip_vs_protocol_init(struct net *net) | ||
243 | { | ||
244 | return 0; | ||
245 | } | ||
246 | |||
247 | static void __net_exit __ip_vs_protocol_cleanup(struct net *net) | ||
248 | { | ||
249 | /* empty */ | ||
250 | } | ||
251 | |||
252 | static struct pernet_operations ipvs_proto_ops = { | ||
253 | .init = __ip_vs_protocol_init, | ||
254 | .exit = __ip_vs_protocol_cleanup, | ||
255 | }; | ||
239 | 256 | ||
240 | int __init ip_vs_protocol_init(void) | 257 | int __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 | */ | ||
1646 | static int __net_init __ip_vs_sync_init(struct net *net) | ||
1647 | { | ||
1648 | return 0; | ||
1649 | } | ||
1650 | |||
1651 | static void __ip_vs_sync_cleanup(struct net *net) | ||
1652 | { | ||
1653 | } | ||
1654 | static struct pernet_operations ipvs_sync_ops = { | ||
1655 | .init = __ip_vs_sync_init, | ||
1656 | .exit = __ip_vs_sync_cleanup, | ||
1657 | }; | ||
1658 | |||
1659 | |||
1660 | int __init ip_vs_sync_init(void) | ||
1661 | { | ||
1662 | return register_pernet_subsys(&ipvs_sync_ops); | ||
1663 | } | ||
1664 | |||
1665 | void __exit ip_vs_sync_cleanup(void) | ||
1666 | { | ||
1667 | unregister_pernet_subsys(&ipvs_sync_ops); | ||
1668 | } | ||