netns xfrm: deal with dst entries in netns
Subsystems (3)
PATCH 1/1 netns xfrm: deal with dst entries in netns
GC is non-existent in netns, so after you hit GC threshold, no new dst entries will be created until someone triggers cleanup in init_net.
Make xfrm4_dst_ops and xfrm6_dst_ops per-netns. This is not done in a generic way, because it woule waste (AF_MAX - 2) * sizeof(struct dst_ops) bytes per-netns.
Reorder GC threshold initialization so it'd be done before registering XFRM policies.
---
include/net/netns/xfrm.h | 6 ++++ net/ipv4/xfrm4_policy.c | 14 ++++++----- net/ipv6/xfrm6_policy.c | 25 +++++++++++-------- net/xfrm/xfrm_policy.c | 59 ++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 84 insertions(+), 20 deletions(-)
include/net/netns/xfrm.h +6 -0
@@ -5,6 +5,7 @@#include <linux/wait.h> #include <linux/workqueue.h> #include <linux/xfrm.h> +#include <net/dst_ops.h> struct ctl_table_header ;
@@ -42,6 +43,11 @@ struct netns_xfrm {unsigned int policy_count[XFRM_POLICY_MAX *2 ];struct work_struct policy_hash_work; +struct dst_ops xfrm4_dst_ops; +#if defined(CONFIG_IPV6 ) || defined(CONFIG_IPV6_MODULE ) +struct dst_ops xfrm6_dst_ops; +#endif +struct sock *nlsk;struct sock *nlsk_stash;
net/ipv4/xfrm4_policy.c +8 -6
@@ -15,7 +15,6 @@#include <net/xfrm.h> #include <net/ip.h> -static struct dst_ops xfrm4_dst_ops;static struct xfrm_policy_afinfo xfrm4_policy_afinfo; static struct dst_entry *xfrm4_dst_lookup(struct net *net, int tos,
@@ -190,8 +189,10 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)static inline int xfrm4_garbage_collect (struct dst_ops *ops) { - xfrm4_policy_afinfo.garbage_collect (&init_net); -return (atomic_read (&xfrm4_dst_ops.entries) > xfrm4_dst_ops.gc_thresh*2 ); + struct net *net = container_of(ops, struct net, xfrm.xfrm4_dst_ops); + + xfrm4_policy_afinfo.garbage_collect (net); +return (atomic_read (&ops->entries) > ops->gc_thresh *2 ); }static void xfrm4_update_pmtu (struct dst_entry *dst,u32 mtu)
@@ -268,7 +269,7 @@ static struct xfrm_policy_afinfo xfrm4_policy_afinfo = {static struct ctl_table xfrm4_policy_table[] = { { .procname ="xfrm4_gc_thresh" , - .data = &xfrm4_dst_ops.gc_thresh, + .data = &init_net.xfrm.xfrm4_dst_ops.gc_thresh, .maxlen =sizeof (int ), .mode =0644 , .proc_handler = proc_dointvec,
@@ -295,8 +296,6 @@ static void __exit xfrm4_policy_fini(void)void __init xfrm4_init (int rt_max_size) { -xfrm4_state_init (); -xfrm4_policy_init ();/* * Select a default value for the gc_thresh based on the main route * table hash size. It seems to me the worst case scenario is when
@@ -308,6 +307,9 @@ void __init xfrm4_init(int rt_max_size)* and start cleaning when were 1/2 full */ xfrm4_dst_ops.gc_thresh = rt_max_size/2 ; + +xfrm4_state_init (); +xfrm4_policy_init ();#ifdef CONFIG_SYSCTL sysctl_hdr =register_net_sysctl_table (&init_net, net_ipv4_ctl_path, xfrm4_policy_table);
net/ipv6/xfrm6_policy.c +14 -11
@@ -24,7 +24,6 @@#include <net/mip6.h> #endif -static struct dst_ops xfrm6_dst_ops;static struct xfrm_policy_afinfo xfrm6_policy_afinfo; static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos,
@@ -224,8 +223,10 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)static inline int xfrm6_garbage_collect (struct dst_ops *ops) { - xfrm6_policy_afinfo.garbage_collect (&init_net); -return (atomic_read (&xfrm6_dst_ops.entries) > xfrm6_dst_ops.gc_thresh*2 ); + struct net *net = container_of(ops, struct net, xfrm.xfrm6_dst_ops); + + xfrm6_policy_afinfo.garbage_collect (net); +return (atomic_read (&ops->entries) > ops->gc_thresh *2 ); }static void xfrm6_update_pmtu (struct dst_entry *dst,u32 mtu)
@@ -310,7 +311,7 @@ static void xfrm6_policy_fini(void)static struct ctl_table xfrm6_policy_table[] = { { .procname ="xfrm6_gc_thresh" , - .data = &xfrm6_dst_ops.gc_thresh, + .data = &init_net.xfrm.xfrm6_dst_ops.gc_thresh, .maxlen =sizeof (int ), .mode =0644 , .proc_handler = proc_dointvec,
@@ -326,13 +327,6 @@ int __init xfrm6_init(void)int ret;unsigned int gc_thresh; - ret =xfrm6_policy_init (); -if (ret) - goto out; - - ret =xfrm6_state_init (); -if (ret) - goto out_policy;/* * We need a good default value for the xfrm6 gc threshold. * In ipv4 we set it to the route hash table size * 8, which
@@ -346,6 +340,15 @@ int __init xfrm6_init(void)*/ gc_thresh =FIB6_TABLE_HASHSZ *8 ; xfrm6_dst_ops.gc_thresh = (gc_thresh <1024 ) ?1024 : gc_thresh; + + ret =xfrm6_policy_init (); +if (ret) + goto out; + + ret =xfrm6_state_init (); +if (ret) + goto out_policy; +#ifdef CONFIG_SYSCTL sysctl_hdr =register_net_sysctl_table (&init_net, net_ipv6_ctl_path, xfrm6_policy_table);
net/xfrm/xfrm_policy.c +56 -3
108 lines not on this page · raw message
From: Alexey Dobriyan <[email protected]>
Date: Sun, 24 Jan 2010 17:40:14 +0200
Quoted 11 lines
GC is non-existent in netns, so after you hit GC threshold, no new dst entries will be created until someone triggers cleanup in
init_net.Make
xfrm4_dst_opsandxfrm6_dst_opsper-netns. This is not done in a generic way, because it woule waste (AF_MAX- 2) *sizeof(struct dst_ops)bytes per-netns.Reorder GC threshold initialization so it'd be done before registering XFRM policies.
Signed-off-by Alexey Dobriyan <[email protected]>
Applied, thanks Alexey.