Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xfrm: make gc_thresh configurable in all namespaces

The xfrm gc threshold can be configured via xfrm{4,6}_gc_thresh
sysctl but currently only in init_net, other namespaces always
use the default value. This can substantially limit the number
of IPsec tunnels that can be effectively used.

Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>

authored by

Michal Kubecek and committed by
Steffen Klassert
8d068875 1f53c808

+95 -8
+1
include/net/netns/ipv4.h
··· 22 22 struct ctl_table_header *frags_hdr; 23 23 struct ctl_table_header *ipv4_hdr; 24 24 struct ctl_table_header *route_hdr; 25 + struct ctl_table_header *xfrm4_hdr; 25 26 #endif 26 27 struct ipv4_devconf *devconf_all; 27 28 struct ipv4_devconf *devconf_dflt;
+1
include/net/netns/ipv6.h
··· 16 16 struct ctl_table_header *route_hdr; 17 17 struct ctl_table_header *icmp_hdr; 18 18 struct ctl_table_header *frags_hdr; 19 + struct ctl_table_header *xfrm6_hdr; 19 20 #endif 20 21 int bindv6only; 21 22 int flush_delay;
+46 -3
net/ipv4/xfrm4_policy.c
··· 262 262 { } 263 263 }; 264 264 265 - static struct ctl_table_header *sysctl_hdr; 265 + static int __net_init xfrm4_net_init(struct net *net) 266 + { 267 + struct ctl_table *table; 268 + struct ctl_table_header *hdr; 269 + 270 + table = xfrm4_policy_table; 271 + if (!net_eq(net, &init_net)) { 272 + table = kmemdup(table, sizeof(xfrm4_policy_table), GFP_KERNEL); 273 + if (!table) 274 + goto err_alloc; 275 + 276 + table[0].data = &net->xfrm.xfrm4_dst_ops.gc_thresh; 277 + } 278 + 279 + hdr = register_net_sysctl(net, "net/ipv4", table); 280 + if (!hdr) 281 + goto err_reg; 282 + 283 + net->ipv4.xfrm4_hdr = hdr; 284 + return 0; 285 + 286 + err_reg: 287 + if (!net_eq(net, &init_net)) 288 + kfree(table); 289 + err_alloc: 290 + return -ENOMEM; 291 + } 292 + 293 + static void __net_exit xfrm4_net_exit(struct net *net) 294 + { 295 + struct ctl_table *table; 296 + 297 + if (net->ipv4.xfrm4_hdr == NULL) 298 + return; 299 + 300 + table = net->ipv4.xfrm4_hdr->ctl_table_arg; 301 + unregister_net_sysctl_table(net->ipv4.xfrm4_hdr); 302 + if (!net_eq(net, &init_net)) 303 + kfree(table); 304 + } 305 + 306 + static struct pernet_operations __net_initdata xfrm4_net_ops = { 307 + .init = xfrm4_net_init, 308 + .exit = xfrm4_net_exit, 309 + }; 266 310 #endif 267 311 268 312 static void __init xfrm4_policy_init(void) ··· 321 277 xfrm4_state_init(); 322 278 xfrm4_policy_init(); 323 279 #ifdef CONFIG_SYSCTL 324 - sysctl_hdr = register_net_sysctl(&init_net, "net/ipv4", 325 - xfrm4_policy_table); 280 + register_pernet_subsys(&xfrm4_net_ops); 326 281 #endif 327 282 } 328 283
+47 -5
net/ipv6/xfrm6_policy.c
··· 320 320 { } 321 321 }; 322 322 323 - static struct ctl_table_header *sysctl_hdr; 323 + static int __net_init xfrm6_net_init(struct net *net) 324 + { 325 + struct ctl_table *table; 326 + struct ctl_table_header *hdr; 327 + 328 + table = xfrm6_policy_table; 329 + if (!net_eq(net, &init_net)) { 330 + table = kmemdup(table, sizeof(xfrm6_policy_table), GFP_KERNEL); 331 + if (!table) 332 + goto err_alloc; 333 + 334 + table[0].data = &net->xfrm.xfrm6_dst_ops.gc_thresh; 335 + } 336 + 337 + hdr = register_net_sysctl(net, "net/ipv6", table); 338 + if (!hdr) 339 + goto err_reg; 340 + 341 + net->ipv6.sysctl.xfrm6_hdr = hdr; 342 + return 0; 343 + 344 + err_reg: 345 + if (!net_eq(net, &init_net)) 346 + kfree(table); 347 + err_alloc: 348 + return -ENOMEM; 349 + } 350 + 351 + static void __net_exit xfrm6_net_exit(struct net *net) 352 + { 353 + struct ctl_table *table; 354 + 355 + if (net->ipv6.sysctl.xfrm6_hdr == NULL) 356 + return; 357 + 358 + table = net->ipv6.sysctl.xfrm6_hdr->ctl_table_arg; 359 + unregister_net_sysctl_table(net->ipv6.sysctl.xfrm6_hdr); 360 + if (!net_eq(net, &init_net)) 361 + kfree(table); 362 + } 363 + 364 + static struct pernet_operations xfrm6_net_ops = { 365 + .init = xfrm6_net_init, 366 + .exit = xfrm6_net_exit, 367 + }; 324 368 #endif 325 369 326 370 int __init xfrm6_init(void) ··· 383 339 goto out_policy; 384 340 385 341 #ifdef CONFIG_SYSCTL 386 - sysctl_hdr = register_net_sysctl(&init_net, "net/ipv6", 387 - xfrm6_policy_table); 342 + register_pernet_subsys(&xfrm6_net_ops); 388 343 #endif 389 344 out: 390 345 return ret; ··· 395 352 void xfrm6_fini(void) 396 353 { 397 354 #ifdef CONFIG_SYSCTL 398 - if (sysctl_hdr) 399 - unregister_net_sysctl_table(sysctl_hdr); 355 + unregister_pernet_subsys(&xfrm6_net_ops); 400 356 #endif 401 357 xfrm6_policy_fini(); 402 358 xfrm6_state_fini();