diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 319557789a40aab7b47609035ceb600dc6ab8dc0..6fc13d905c5ffaced2e1658038ab97934d61f42d 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -19,6 +19,7 @@ #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) #include #endif +#include struct proc_dir_entry; struct net_device; @@ -73,6 +74,9 @@ struct net { #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) struct netns_ct ct; #endif +#endif +#ifdef CONFIG_XFRM + struct netns_xfrm xfrm; #endif struct net_generic *gen; }; diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h new file mode 100644 index 0000000000000000000000000000000000000000..1cb0024a3b47003cd6c3aeef48c1bc6f18846f82 --- /dev/null +++ b/include/net/netns/xfrm.h @@ -0,0 +1,7 @@ +#ifndef __NETNS_XFRM_H +#define __NETNS_XFRM_H + +struct netns_xfrm { +}; + +#endif diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 45e11b3631e4228b6fec6ebf761e4b5a23259700..9107d6f5c297d4dee5d93310192b3d216bdcab6b 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1269,7 +1269,8 @@ struct xfrm6_tunnel { extern void xfrm_init(void); extern void xfrm4_init(void); -extern void xfrm_state_init(void); +extern int xfrm_state_init(struct net *net); +extern void xfrm_state_fini(struct net *net); extern void xfrm4_state_init(void); #ifdef CONFIG_XFRM extern int xfrm6_init(void); diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index ea3456daa9cbde20daa67cc67cac2b36a78e99a3..8e7671b9e76e651a4f74a3ddbe54633ba6f99fa2 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -2394,12 +2394,13 @@ static int __init xfrm_statistics_init(void) } #endif -static void __init xfrm_policy_init(void) +static int __net_init xfrm_policy_init(struct net *net) { unsigned int hmask, sz; int dir; - xfrm_dst_cache = kmem_cache_create("xfrm_dst_cache", + if (net_eq(net, &init_net)) + xfrm_dst_cache = kmem_cache_create("xfrm_dst_cache", sizeof(struct xfrm_dst), 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); @@ -2425,16 +2426,50 @@ static void __init xfrm_policy_init(void) } INIT_LIST_HEAD(&xfrm_policy_all); - register_netdevice_notifier(&xfrm_dev_notifier); + if (net_eq(net, &init_net)) + register_netdevice_notifier(&xfrm_dev_notifier); + return 0; +} + +static void xfrm_policy_fini(struct net *net) +{ } +static int __net_init xfrm_net_init(struct net *net) +{ + int rv; + + rv = xfrm_state_init(net); + if (rv < 0) + goto out_state; + rv = xfrm_policy_init(net); + if (rv < 0) + goto out_policy; + return 0; + +out_policy: + xfrm_state_fini(net); +out_state: + return rv; +} + +static void __net_exit xfrm_net_exit(struct net *net) +{ + xfrm_policy_fini(net); + xfrm_state_fini(net); +} + +static struct pernet_operations __net_initdata xfrm_net_ops = { + .init = xfrm_net_init, + .exit = xfrm_net_exit, +}; + void __init xfrm_init(void) { + register_pernet_subsys(&xfrm_net_ops); #ifdef CONFIG_XFRM_STATISTICS xfrm_statistics_init(); #endif - xfrm_state_init(); - xfrm_policy_init(); xfrm_input_init(); #ifdef CONFIG_XFRM_STATISTICS xfrm_proc_init(); diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index cd9d9171ded75bb06d190b0d50474b75e00f9772..268fe3f9e498af8eb50561e31d1b87ef8f55fc73 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -2080,7 +2080,7 @@ int xfrm_init_state(struct xfrm_state *x) EXPORT_SYMBOL(xfrm_init_state); -void __init xfrm_state_init(void) +int __net_init xfrm_state_init(struct net *net) { unsigned int sz; @@ -2094,6 +2094,11 @@ void __init xfrm_state_init(void) xfrm_state_hmask = ((sz / sizeof(struct hlist_head)) - 1); INIT_WORK(&xfrm_state_gc_work, xfrm_state_gc_task); + return 0; +} + +void xfrm_state_fini(struct net *net) +{ } #ifdef CONFIG_AUDITSYSCALL