Skip to content

Commit

Permalink
IPVS: netns, add basic init per netns.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Hans Schillstrom authored and Simon Horman committed Jan 13, 2011
1 parent fee1cc0 commit 61b1ab4
Show file tree
Hide file tree
Showing 13 changed files with 354 additions and 33 deletions.
11 changes: 11 additions & 0 deletions include/net/ip_vs.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
#include <net/netfilter/nf_conntrack.h>
#endif
#include <net/net_namespace.h> /* Netw namespace */

/*
* Generic access of ipvs struct
*/
static inline struct netns_ipvs *net_ipvs(struct net* net)
{
return net->ipvs;
}

/* Connections' size value needed by ip_vs_ctl.c */
extern int ip_vs_conn_tab_size;
Expand Down Expand Up @@ -922,6 +931,8 @@ extern char ip_vs_backup_mcast_ifn[IP_VS_IFNAME_MAXLEN];
extern int start_sync_thread(int state, char *mcast_ifn, __u8 syncid);
extern int stop_sync_thread(int state);
extern void ip_vs_sync_conn(struct ip_vs_conn *cp);
extern int ip_vs_sync_init(void);
extern void ip_vs_sync_cleanup(void);


/*
Expand Down
2 changes: 2 additions & 0 deletions include/net/net_namespace.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <net/netns/conntrack.h>
#endif
#include <net/netns/xfrm.h>
#include <net/netns/ip_vs.h>

struct proc_dir_entry;
struct net_device;
Expand Down Expand Up @@ -94,6 +95,7 @@ struct net {
#ifdef CONFIG_XFRM
struct netns_xfrm xfrm;
#endif
struct netns_ipvs *ipvs;
};


Expand Down
25 changes: 25 additions & 0 deletions include/net/netns/ip_vs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* IP Virtual Server
* Data structure for network namspace
*
*/

#ifndef IP_VS_H_
#define IP_VS_H_

#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/list_nulls.h>
#include <linux/ip_vs.h>
#include <asm/atomic.h>
#include <linux/in.h>

struct ip_vs_stats;
struct ip_vs_sync_buff;
struct ctl_table_header;

struct netns_ipvs {
int gen; /* Generation */
};

#endif /* IP_VS_H_ */
28 changes: 24 additions & 4 deletions net/netfilter/ipvs/ip_vs_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -569,15 +569,35 @@ static const struct file_operations ip_vs_app_fops = {
};
#endif

int __init ip_vs_app_init(void)
static int __net_init __ip_vs_app_init(struct net *net)
{
/* we will replace it with proc_net_ipvs_create() soon */
proc_net_fops_create(&init_net, "ip_vs_app", 0, &ip_vs_app_fops);
if (!net_eq(net, &init_net)) /* netns not enabled yet */
return -EPERM;

proc_net_fops_create(net, "ip_vs_app", 0, &ip_vs_app_fops);
return 0;
}

static void __net_exit __ip_vs_app_cleanup(struct net *net)
{
proc_net_remove(net, "ip_vs_app");
}

static struct pernet_operations ip_vs_app_ops = {
.init = __ip_vs_app_init,
.exit = __ip_vs_app_cleanup,
};

int __init ip_vs_app_init(void)
{
int rv;

rv = register_pernet_subsys(&ip_vs_app_ops);
return rv;
}


void ip_vs_app_cleanup(void)
{
proc_net_remove(&init_net, "ip_vs_app");
unregister_pernet_subsys(&ip_vs_app_ops);
}
34 changes: 28 additions & 6 deletions net/netfilter/ipvs/ip_vs_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -1201,11 +1201,36 @@ static void ip_vs_conn_flush(void)
goto flush_again;
}
}
/*
* per netns init and exit
*/
int __net_init __ip_vs_conn_init(struct net *net)
{
if (!net_eq(net, &init_net)) /* netns not enabled yet */
return -EPERM;

proc_net_fops_create(net, "ip_vs_conn", 0, &ip_vs_conn_fops);
proc_net_fops_create(net, "ip_vs_conn_sync", 0, &ip_vs_conn_sync_fops);
return 0;
}

static void __net_exit __ip_vs_conn_cleanup(struct net *net)
{
if (!net_eq(net, &init_net)) /* netns not enabled yet */
return;

proc_net_remove(net, "ip_vs_conn");
proc_net_remove(net, "ip_vs_conn_sync");
}
static struct pernet_operations ipvs_conn_ops = {
.init = __ip_vs_conn_init,
.exit = __ip_vs_conn_cleanup,
};

int __init ip_vs_conn_init(void)
{
int idx;
int retc;

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

proc_net_fops_create(&init_net, "ip_vs_conn", 0, &ip_vs_conn_fops);
proc_net_fops_create(&init_net, "ip_vs_conn_sync", 0, &ip_vs_conn_sync_fops);
retc = register_pernet_subsys(&ipvs_conn_ops);

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

return 0;
return retc;
}


void ip_vs_conn_cleanup(void)
{
unregister_pernet_subsys(&ipvs_conn_ops);
/* flush all the connection entries first */
ip_vs_conn_flush();

/* Release the empty cache */
kmem_cache_destroy(ip_vs_conn_cachep);
proc_net_remove(&init_net, "ip_vs_conn");
proc_net_remove(&init_net, "ip_vs_conn_sync");
vfree(ip_vs_conn_tab);
}
63 changes: 61 additions & 2 deletions net/netfilter/ipvs/ip_vs_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include <net/icmp.h> /* for icmp_send */
#include <net/route.h>
#include <net/ip6_checksum.h>
#include <net/netns/generic.h> /* net_generic() */

#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
Expand Down Expand Up @@ -68,6 +69,12 @@ EXPORT_SYMBOL(ip_vs_conn_put);
EXPORT_SYMBOL(ip_vs_get_debug_level);
#endif

int ip_vs_net_id __read_mostly;
#ifdef IP_VS_GENERIC_NETNS
EXPORT_SYMBOL(ip_vs_net_id);
#endif
/* netns cnt used for uniqueness */
static atomic_t ipvs_netns_cnt = ATOMIC_INIT(0);

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

/*
* Initialize IP Virtual Server netns mem.
*/
static int __net_init __ip_vs_init(struct net *net)
{
struct netns_ipvs *ipvs;

if (!net_eq(net, &init_net)) {
pr_err("The final patch for enabling netns is missing\n");
return -EPERM;
}
ipvs = net_generic(net, ip_vs_net_id);
if (ipvs == NULL) {
pr_err("%s(): no memory.\n", __func__);
return -ENOMEM;
}
/* Counters used for creating unique names */
ipvs->gen = atomic_read(&ipvs_netns_cnt);
atomic_inc(&ipvs_netns_cnt);
net->ipvs = ipvs;
printk(KERN_INFO "IPVS: Creating netns size=%lu id=%d\n",
sizeof(struct netns_ipvs), ipvs->gen);
return 0;
}

static void __net_exit __ip_vs_cleanup(struct net *net)
{
struct netns_ipvs *ipvs = net_ipvs(net);

IP_VS_DBG(10, "ipvs netns %d released\n", ipvs->gen);
}

static struct pernet_operations ipvs_core_ops = {
.init = __ip_vs_init,
.exit = __ip_vs_cleanup,
.id = &ip_vs_net_id,
.size = sizeof(struct netns_ipvs),
};

/*
* Initialize IP Virtual Server
Expand All @@ -1821,8 +1866,11 @@ static int __init ip_vs_init(void)
{
int ret;

ip_vs_estimator_init();
ret = register_pernet_subsys(&ipvs_core_ops); /* Alloc ip_vs struct */
if (ret < 0)
return ret;

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

ret = ip_vs_sync_init();
if (ret < 0) {
pr_err("can't setup sync data.\n");
goto cleanup_conn;
}

ret = nf_register_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
if (ret < 0) {
pr_err("can't register hooks.\n");
goto cleanup_conn;
goto cleanup_sync;
}

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

cleanup_sync:
ip_vs_sync_cleanup();
cleanup_conn:
ip_vs_conn_cleanup();
cleanup_app:
Expand All @@ -1861,17 +1917,20 @@ static int __init ip_vs_init(void)
ip_vs_control_cleanup();
cleanup_estimator:
ip_vs_estimator_cleanup();
unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */
return ret;
}

static void __exit ip_vs_cleanup(void)
{
nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
ip_vs_sync_cleanup();
ip_vs_conn_cleanup();
ip_vs_app_cleanup();
ip_vs_protocol_cleanup();
ip_vs_control_cleanup();
ip_vs_estimator_cleanup();
unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */
pr_info("ipvs unloaded.\n");
}

Expand Down
49 changes: 40 additions & 9 deletions net/netfilter/ipvs/ip_vs_ctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -3406,6 +3406,42 @@ static void ip_vs_genl_unregister(void)

/* End of Generic Netlink interface definitions */

/*
* per netns intit/exit func.
*/
int __net_init __ip_vs_control_init(struct net *net)
{
if (!net_eq(net, &init_net)) /* netns not enabled yet */
return -EPERM;

proc_net_fops_create(net, "ip_vs", 0, &ip_vs_info_fops);
proc_net_fops_create(net, "ip_vs_stats", 0, &ip_vs_stats_fops);
sysctl_header = register_net_sysctl_table(net, net_vs_ctl_path,
vs_vars);
if (sysctl_header == NULL)
goto err_reg;
ip_vs_new_estimator(&ip_vs_stats);
return 0;

err_reg:
return -ENOMEM;
}

static void __net_exit __ip_vs_control_cleanup(struct net *net)
{
if (!net_eq(net, &init_net)) /* netns not enabled yet */
return;

ip_vs_kill_estimator(&ip_vs_stats);
unregister_net_sysctl_table(sysctl_header);
proc_net_remove(net, "ip_vs_stats");
proc_net_remove(net, "ip_vs");
}

static struct pernet_operations ipvs_control_ops = {
.init = __ip_vs_control_init,
.exit = __ip_vs_control_cleanup,
};

int __init ip_vs_control_init(void)
{
Expand Down Expand Up @@ -3437,12 +3473,9 @@ int __init ip_vs_control_init(void)
return ret;
}

proc_net_fops_create(&init_net, "ip_vs", 0, &ip_vs_info_fops);
proc_net_fops_create(&init_net, "ip_vs_stats",0, &ip_vs_stats_fops);

sysctl_header = register_sysctl_paths(net_vs_ctl_path, vs_vars);

ip_vs_new_estimator(&ip_vs_stats);
ret = register_pernet_subsys(&ipvs_control_ops);
if (ret)
return ret;

/* Hook the defense timer */
schedule_delayed_work(&defense_work, DEFENSE_TIMER_PERIOD);
Expand All @@ -3459,9 +3492,7 @@ void ip_vs_control_cleanup(void)
cancel_delayed_work_sync(&defense_work);
cancel_work_sync(&defense_work.work);
ip_vs_kill_estimator(&ip_vs_stats);
unregister_sysctl_table(sysctl_header);
proc_net_remove(&init_net, "ip_vs_stats");
proc_net_remove(&init_net, "ip_vs");
unregister_pernet_subsys(&ipvs_control_ops);
ip_vs_genl_unregister();
nf_unregister_sockopt(&ip_vs_sockopts);
LeaveFunction(2);
Expand Down
20 changes: 19 additions & 1 deletion net/netfilter/ipvs/ip_vs_est.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,13 +157,31 @@ void ip_vs_zero_estimator(struct ip_vs_stats *stats)
est->outbps = 0;
}

static int __net_init __ip_vs_estimator_init(struct net *net)
{
if (!net_eq(net, &init_net)) /* netns not enabled yet */
return -EPERM;

return 0;
}

static struct pernet_operations ip_vs_app_ops = {
.init = __ip_vs_estimator_init,
};

int __init ip_vs_estimator_init(void)
{
int rv;

rv = register_pernet_subsys(&ip_vs_app_ops);
if (rv < 0)
return rv;
mod_timer(&est_timer, jiffies + 2 * HZ);
return 0;
return rv;
}

void ip_vs_estimator_cleanup(void)
{
del_timer_sync(&est_timer);
unregister_pernet_subsys(&ip_vs_app_ops);
}
Loading

0 comments on commit 61b1ab4

Please sign in to comment.