Skip to content

Commit 61b1ab4

Browse files
Hans Schillstromhorms
authored andcommitted
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>
1 parent fee1cc0 commit 61b1ab4

File tree

13 files changed

+354
-33
lines changed

13 files changed

+354
-33
lines changed

include/net/ip_vs.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,15 @@
2828
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
2929
#include <net/netfilter/nf_conntrack.h>
3030
#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+
}
3140

3241
/* Connections' size value needed by ip_vs_ctl.c */
3342
extern int ip_vs_conn_tab_size;
@@ -922,6 +931,8 @@ extern char ip_vs_backup_mcast_ifn[IP_VS_IFNAME_MAXLEN];
922931
extern int start_sync_thread(int state, char *mcast_ifn, __u8 syncid);
923932
extern int stop_sync_thread(int state);
924933
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);
925936

926937

927938
/*

include/net/net_namespace.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <net/netns/conntrack.h>
2121
#endif
2222
#include <net/netns/xfrm.h>
23+
#include <net/netns/ip_vs.h>
2324

2425
struct proc_dir_entry;
2526
struct net_device;
@@ -94,6 +95,7 @@ struct net {
9495
#ifdef CONFIG_XFRM
9596
struct netns_xfrm xfrm;
9697
#endif
98+
struct netns_ipvs *ipvs;
9799
};
98100

99101

include/net/netns/ip_vs.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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_ */

net/netfilter/ipvs/ip_vs_app.c

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -569,15 +569,35 @@ static const struct file_operations ip_vs_app_fops = {
569569
};
570570
#endif
571571

572-
int __init ip_vs_app_init(void)
572+
static int __net_init __ip_vs_app_init(struct net *net)
573573
{
574-
/* we will replace it with proc_net_ipvs_create() soon */
575-
proc_net_fops_create(&init_net, "ip_vs_app", 0, &ip_vs_app_fops);
574+
if (!net_eq(net, &init_net)) /* netns not enabled yet */
575+
return -EPERM;
576+
577+
proc_net_fops_create(net, "ip_vs_app", 0, &ip_vs_app_fops);
576578
return 0;
577579
}
578580

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+
579599

580600
void ip_vs_app_cleanup(void)
581601
{
582-
proc_net_remove(&init_net, "ip_vs_app");
602+
unregister_pernet_subsys(&ip_vs_app_ops);
583603
}

net/netfilter/ipvs/ip_vs_conn.c

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,11 +1201,36 @@ static void ip_vs_conn_flush(void)
12011201
goto flush_again;
12021202
}
12031203
}
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;
12041211

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+
};
12051229

12061230
int __init ip_vs_conn_init(void)
12071231
{
12081232
int idx;
1233+
int retc;
12091234

12101235
/* Compute size and mask */
12111236
ip_vs_conn_tab_size = 1 << ip_vs_conn_tab_bits;
@@ -1243,24 +1268,21 @@ int __init ip_vs_conn_init(void)
12431268
rwlock_init(&__ip_vs_conntbl_lock_array[idx].l);
12441269
}
12451270

1246-
proc_net_fops_create(&init_net, "ip_vs_conn", 0, &ip_vs_conn_fops);
1247-
proc_net_fops_create(&init_net, "ip_vs_conn_sync", 0, &ip_vs_conn_sync_fops);
1271+
retc = register_pernet_subsys(&ipvs_conn_ops);
12481272

12491273
/* calculate the random value for connection hash */
12501274
get_random_bytes(&ip_vs_conn_rnd, sizeof(ip_vs_conn_rnd));
12511275

1252-
return 0;
1276+
return retc;
12531277
}
12541278

1255-
12561279
void ip_vs_conn_cleanup(void)
12571280
{
1281+
unregister_pernet_subsys(&ipvs_conn_ops);
12581282
/* flush all the connection entries first */
12591283
ip_vs_conn_flush();
12601284

12611285
/* Release the empty cache */
12621286
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");
12651287
vfree(ip_vs_conn_tab);
12661288
}

net/netfilter/ipvs/ip_vs_core.c

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include <net/icmp.h> /* for icmp_send */
4242
#include <net/route.h>
4343
#include <net/ip6_checksum.h>
44+
#include <net/netns/generic.h> /* net_generic() */
4445

4546
#include <linux/netfilter.h>
4647
#include <linux/netfilter_ipv4.h>
@@ -68,6 +69,12 @@ EXPORT_SYMBOL(ip_vs_conn_put);
6869
EXPORT_SYMBOL(ip_vs_get_debug_level);
6970
#endif
7071

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);
7178

7279
/* ID used in ICMP lookups */
7380
#define icmp_id(icmph) (((icmph)->un).echo.id)
@@ -1813,6 +1820,44 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
18131820
#endif
18141821
};
18151822

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+
};
18161861

18171862
/*
18181863
* Initialize IP Virtual Server
@@ -1821,8 +1866,11 @@ static int __init ip_vs_init(void)
18211866
{
18221867
int ret;
18231868

1824-
ip_vs_estimator_init();
1869+
ret = register_pernet_subsys(&ipvs_core_ops); /* Alloc ip_vs struct */
1870+
if (ret < 0)
1871+
return ret;
18251872

1873+
ip_vs_estimator_init();
18261874
ret = ip_vs_control_init();
18271875
if (ret < 0) {
18281876
pr_err("can't setup control.\n");
@@ -1843,15 +1891,23 @@ static int __init ip_vs_init(void)
18431891
goto cleanup_app;
18441892
}
18451893

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+
18461900
ret = nf_register_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
18471901
if (ret < 0) {
18481902
pr_err("can't register hooks.\n");
1849-
goto cleanup_conn;
1903+
goto cleanup_sync;
18501904
}
18511905

18521906
pr_info("ipvs loaded.\n");
18531907
return ret;
18541908

1909+
cleanup_sync:
1910+
ip_vs_sync_cleanup();
18551911
cleanup_conn:
18561912
ip_vs_conn_cleanup();
18571913
cleanup_app:
@@ -1861,17 +1917,20 @@ static int __init ip_vs_init(void)
18611917
ip_vs_control_cleanup();
18621918
cleanup_estimator:
18631919
ip_vs_estimator_cleanup();
1920+
unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */
18641921
return ret;
18651922
}
18661923

18671924
static void __exit ip_vs_cleanup(void)
18681925
{
18691926
nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
1927+
ip_vs_sync_cleanup();
18701928
ip_vs_conn_cleanup();
18711929
ip_vs_app_cleanup();
18721930
ip_vs_protocol_cleanup();
18731931
ip_vs_control_cleanup();
18741932
ip_vs_estimator_cleanup();
1933+
unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */
18751934
pr_info("ipvs unloaded.\n");
18761935
}
18771936

net/netfilter/ipvs/ip_vs_ctl.c

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3406,6 +3406,42 @@ static void ip_vs_genl_unregister(void)
34063406

34073407
/* End of Generic Netlink interface definitions */
34083408

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+
};
34093445

34103446
int __init ip_vs_control_init(void)
34113447
{
@@ -3437,12 +3473,9 @@ int __init ip_vs_control_init(void)
34373473
return ret;
34383474
}
34393475

3440-
proc_net_fops_create(&init_net, "ip_vs", 0, &ip_vs_info_fops);
3441-
proc_net_fops_create(&init_net, "ip_vs_stats",0, &ip_vs_stats_fops);
3442-
3443-
sysctl_header = register_sysctl_paths(net_vs_ctl_path, vs_vars);
3444-
3445-
ip_vs_new_estimator(&ip_vs_stats);
3476+
ret = register_pernet_subsys(&ipvs_control_ops);
3477+
if (ret)
3478+
return ret;
34463479

34473480
/* Hook the defense timer */
34483481
schedule_delayed_work(&defense_work, DEFENSE_TIMER_PERIOD);
@@ -3459,9 +3492,7 @@ void ip_vs_control_cleanup(void)
34593492
cancel_delayed_work_sync(&defense_work);
34603493
cancel_work_sync(&defense_work.work);
34613494
ip_vs_kill_estimator(&ip_vs_stats);
3462-
unregister_sysctl_table(sysctl_header);
3463-
proc_net_remove(&init_net, "ip_vs_stats");
3464-
proc_net_remove(&init_net, "ip_vs");
3495+
unregister_pernet_subsys(&ipvs_control_ops);
34653496
ip_vs_genl_unregister();
34663497
nf_unregister_sockopt(&ip_vs_sockopts);
34673498
LeaveFunction(2);

net/netfilter/ipvs/ip_vs_est.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,13 +157,31 @@ void ip_vs_zero_estimator(struct ip_vs_stats *stats)
157157
est->outbps = 0;
158158
}
159159

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+
160172
int __init ip_vs_estimator_init(void)
161173
{
174+
int rv;
175+
176+
rv = register_pernet_subsys(&ip_vs_app_ops);
177+
if (rv < 0)
178+
return rv;
162179
mod_timer(&est_timer, jiffies + 2 * HZ);
163-
return 0;
180+
return rv;
164181
}
165182

166183
void ip_vs_estimator_cleanup(void)
167184
{
168185
del_timer_sync(&est_timer);
186+
unregister_pernet_subsys(&ip_vs_app_ops);
169187
}

0 commit comments

Comments
 (0)