Commit a44a4a00 authored by Neil Horman's avatar Neil Horman Committed by David S. Miller

xfrm: export xfrm garbage collector thresholds via sysctl

Export garbage collector thresholds for xfrm[4|6]_dst_ops

Had a problem reported to me recently in which a high volume of ipsec
connections on a system began reporting ENOBUFS for new connections
eventually.

It seemed that after about 2000 connections we started being unable to
create more.  A quick look revealed that the xfrm code used a dst_ops
structure that limited the gc_thresh value to 1024, and always
dropped route cache entries after 2x the gc_thresh.

It seems the most direct solution is to export the gc_thresh values in
the xfrm[4|6] dst_ops as sysctls, like the main routing table does, so
that higher volumes of connections can be supported.  This patch has
been tested and allows the reporter to increase their ipsec connection
volume successfully.
Reported-by: default avatarJoe Nall <joe@nall.com>
Signed-off-by: default avatarNeil Horman <nhorman@tuxdriver.com>

ipv4/xfrm4_policy.c |   18 ++++++++++++++++++
ipv6/xfrm6_policy.c |   18 ++++++++++++++++++
2 files changed, 36 insertions(+)
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8a729fce
...@@ -264,6 +264,20 @@ static struct xfrm_policy_afinfo xfrm4_policy_afinfo = { ...@@ -264,6 +264,20 @@ static struct xfrm_policy_afinfo xfrm4_policy_afinfo = {
.fill_dst = xfrm4_fill_dst, .fill_dst = xfrm4_fill_dst,
}; };
static struct ctl_table xfrm4_policy_table[] = {
{
.ctl_name = CTL_UNNUMBERED,
.procname = "xfrm4_gc_thresh",
.data = &xfrm4_dst_ops.gc_thresh,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec,
},
{ }
};
static struct ctl_table_header *sysctl_hdr;
static void __init xfrm4_policy_init(void) static void __init xfrm4_policy_init(void)
{ {
xfrm_policy_register_afinfo(&xfrm4_policy_afinfo); xfrm_policy_register_afinfo(&xfrm4_policy_afinfo);
...@@ -271,6 +285,8 @@ static void __init xfrm4_policy_init(void) ...@@ -271,6 +285,8 @@ static void __init xfrm4_policy_init(void)
static void __exit xfrm4_policy_fini(void) static void __exit xfrm4_policy_fini(void)
{ {
if (sysctl_hdr)
unregister_net_sysctl_table(sysctl_hdr);
xfrm_policy_unregister_afinfo(&xfrm4_policy_afinfo); xfrm_policy_unregister_afinfo(&xfrm4_policy_afinfo);
} }
...@@ -278,5 +294,7 @@ void __init xfrm4_init(void) ...@@ -278,5 +294,7 @@ void __init xfrm4_init(void)
{ {
xfrm4_state_init(); xfrm4_state_init();
xfrm4_policy_init(); xfrm4_policy_init();
sysctl_hdr = register_net_sysctl_table(&init_net, net_ipv4_ctl_path,
xfrm4_policy_table);
} }
...@@ -306,6 +306,20 @@ static void xfrm6_policy_fini(void) ...@@ -306,6 +306,20 @@ static void xfrm6_policy_fini(void)
xfrm_policy_unregister_afinfo(&xfrm6_policy_afinfo); xfrm_policy_unregister_afinfo(&xfrm6_policy_afinfo);
} }
static struct ctl_table xfrm6_policy_table[] = {
{
.ctl_name = CTL_UNNUMBERED,
.procname = "xfrm6_gc_thresh",
.data = &xfrm6_dst_ops.gc_thresh,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec,
},
{ }
};
static struct ctl_table_header *sysctl_hdr;
int __init xfrm6_init(void) int __init xfrm6_init(void)
{ {
int ret; int ret;
...@@ -317,6 +331,8 @@ int __init xfrm6_init(void) ...@@ -317,6 +331,8 @@ int __init xfrm6_init(void)
ret = xfrm6_state_init(); ret = xfrm6_state_init();
if (ret) if (ret)
goto out_policy; goto out_policy;
sysctl_hdr = register_net_sysctl_table(&init_net, net_ipv6_ctl_path,
xfrm6_policy_table);
out: out:
return ret; return ret;
out_policy: out_policy:
...@@ -326,6 +342,8 @@ out_policy: ...@@ -326,6 +342,8 @@ out_policy:
void xfrm6_fini(void) void xfrm6_fini(void)
{ {
if (sysctl_hdr)
unregister_net_sysctl_table(sysctl_hdr);
//xfrm6_input_fini(); //xfrm6_input_fini();
xfrm6_policy_fini(); xfrm6_policy_fini();
xfrm6_state_fini(); xfrm6_state_fini();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment