Commit 50bcfe8d authored by Paolo Abeni's avatar Paolo Abeni Committed by David S. Miller

net: make default_rps_mask a per netns attribute

That really was meant to be a per netns attribute from the beginning.

The idea is that once proper isolation is in place in the main
namespace, additional demux in the child namespaces will be redundant.
Let's make child netns default rps mask empty by default.

To avoid bloating the netns with a possibly large cpumask, allocate
it on-demand during the first write operation.
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e469b626
...@@ -224,7 +224,6 @@ struct net_device_core_stats { ...@@ -224,7 +224,6 @@ struct net_device_core_stats {
#include <linux/static_key.h> #include <linux/static_key.h>
extern struct static_key_false rps_needed; extern struct static_key_false rps_needed;
extern struct static_key_false rfs_needed; extern struct static_key_false rfs_needed;
extern struct cpumask rps_default_mask;
#endif #endif
struct neighbour; struct neighbour;
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
struct ctl_table_header; struct ctl_table_header;
struct prot_inuse; struct prot_inuse;
struct cpumask;
struct netns_core { struct netns_core {
/* core sysctls */ /* core sysctls */
...@@ -17,6 +18,10 @@ struct netns_core { ...@@ -17,6 +18,10 @@ struct netns_core {
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
struct prot_inuse __percpu *prot_inuse; struct prot_inuse __percpu *prot_inuse;
#endif #endif
#if IS_ENABLED(CONFIG_RPS) && IS_ENABLED(CONFIG_SYSCTL)
struct cpumask *rps_default_mask;
#endif
}; };
#endif #endif
...@@ -1060,6 +1060,18 @@ static const struct kobj_type rx_queue_ktype = { ...@@ -1060,6 +1060,18 @@ static const struct kobj_type rx_queue_ktype = {
.get_ownership = rx_queue_get_ownership, .get_ownership = rx_queue_get_ownership,
}; };
static int rx_queue_default_mask(struct net_device *dev,
struct netdev_rx_queue *queue)
{
#if IS_ENABLED(CONFIG_RPS) && IS_ENABLED(CONFIG_SYSCTL)
struct cpumask *rps_default_mask = READ_ONCE(dev_net(dev)->core.rps_default_mask);
if (rps_default_mask && !cpumask_empty(rps_default_mask))
return netdev_rx_queue_set_rps_mask(queue, rps_default_mask);
#endif
return 0;
}
static int rx_queue_add_kobject(struct net_device *dev, int index) static int rx_queue_add_kobject(struct net_device *dev, int index)
{ {
struct netdev_rx_queue *queue = dev->_rx + index; struct netdev_rx_queue *queue = dev->_rx + index;
...@@ -1083,13 +1095,10 @@ static int rx_queue_add_kobject(struct net_device *dev, int index) ...@@ -1083,13 +1095,10 @@ static int rx_queue_add_kobject(struct net_device *dev, int index)
goto err; goto err;
} }
#if IS_ENABLED(CONFIG_RPS) && IS_ENABLED(CONFIG_SYSCTL) error = rx_queue_default_mask(dev, queue);
if (!cpumask_empty(&rps_default_mask)) {
error = netdev_rx_queue_set_rps_mask(queue, &rps_default_mask);
if (error) if (error)
goto err; goto err;
}
#endif
kobject_uevent(kobj, KOBJ_ADD); kobject_uevent(kobj, KOBJ_ADD);
return error; return error;
......
...@@ -74,24 +74,47 @@ static void dump_cpumask(void *buffer, size_t *lenp, loff_t *ppos, ...@@ -74,24 +74,47 @@ static void dump_cpumask(void *buffer, size_t *lenp, loff_t *ppos,
#endif #endif
#ifdef CONFIG_RPS #ifdef CONFIG_RPS
struct cpumask rps_default_mask;
static struct cpumask *rps_default_mask_cow_alloc(struct net *net)
{
struct cpumask *rps_default_mask;
if (net->core.rps_default_mask)
return net->core.rps_default_mask;
rps_default_mask = kzalloc(cpumask_size(), GFP_KERNEL);
if (!rps_default_mask)
return NULL;
/* pairs with READ_ONCE in rx_queue_default_mask() */
WRITE_ONCE(net->core.rps_default_mask, rps_default_mask);
return rps_default_mask;
}
static int rps_default_mask_sysctl(struct ctl_table *table, int write, static int rps_default_mask_sysctl(struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos) void *buffer, size_t *lenp, loff_t *ppos)
{ {
struct net *net = (struct net *)table->data;
int err = 0; int err = 0;
rtnl_lock(); rtnl_lock();
if (write) { if (write) {
err = cpumask_parse(buffer, &rps_default_mask); struct cpumask *rps_default_mask = rps_default_mask_cow_alloc(net);
err = -ENOMEM;
if (!rps_default_mask)
goto done;
err = cpumask_parse(buffer, rps_default_mask);
if (err) if (err)
goto done; goto done;
err = rps_cpumask_housekeeping(&rps_default_mask); err = rps_cpumask_housekeeping(rps_default_mask);
if (err) if (err)
goto done; goto done;
} else { } else {
dump_cpumask(buffer, lenp, ppos, &rps_default_mask); dump_cpumask(buffer, lenp, ppos,
net->core.rps_default_mask ? : cpu_none_mask);
} }
done: done:
...@@ -508,11 +531,6 @@ static struct ctl_table net_core_table[] = { ...@@ -508,11 +531,6 @@ static struct ctl_table net_core_table[] = {
.mode = 0644, .mode = 0644,
.proc_handler = rps_sock_flow_sysctl .proc_handler = rps_sock_flow_sysctl
}, },
{
.procname = "rps_default_mask",
.mode = 0644,
.proc_handler = rps_default_mask_sysctl
},
#endif #endif
#ifdef CONFIG_NET_FLOW_LIMIT #ifdef CONFIG_NET_FLOW_LIMIT
{ {
...@@ -639,6 +657,14 @@ static struct ctl_table net_core_table[] = { ...@@ -639,6 +657,14 @@ static struct ctl_table net_core_table[] = {
}; };
static struct ctl_table netns_core_table[] = { static struct ctl_table netns_core_table[] = {
#if IS_ENABLED(CONFIG_RPS)
{
.procname = "rps_default_mask",
.data = &init_net,
.mode = 0644,
.proc_handler = rps_default_mask_sysctl
},
#endif
{ {
.procname = "somaxconn", .procname = "somaxconn",
.data = &init_net.core.sysctl_somaxconn, .data = &init_net.core.sysctl_somaxconn,
...@@ -706,6 +732,9 @@ static __net_exit void sysctl_core_net_exit(struct net *net) ...@@ -706,6 +732,9 @@ static __net_exit void sysctl_core_net_exit(struct net *net)
tbl = net->core.sysctl_hdr->ctl_table_arg; tbl = net->core.sysctl_hdr->ctl_table_arg;
unregister_net_sysctl_table(net->core.sysctl_hdr); unregister_net_sysctl_table(net->core.sysctl_hdr);
BUG_ON(tbl == netns_core_table); BUG_ON(tbl == netns_core_table);
#if IS_ENABLED(CONFIG_RPS)
kfree(net->core.rps_default_mask);
#endif
kfree(tbl); kfree(tbl);
} }
...@@ -716,10 +745,6 @@ static __net_initdata struct pernet_operations sysctl_core_ops = { ...@@ -716,10 +745,6 @@ static __net_initdata struct pernet_operations sysctl_core_ops = {
static __init int sysctl_core_init(void) static __init int sysctl_core_init(void)
{ {
#if IS_ENABLED(CONFIG_RPS)
cpumask_copy(&rps_default_mask, cpu_none_mask);
#endif
register_net_sysctl(&init_net, "net/core", net_core_table); register_net_sysctl(&init_net, "net/core", net_core_table);
return register_pernet_subsys(&sysctl_core_ops); return register_pernet_subsys(&sysctl_core_ops);
} }
......
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