net: default_rps_mask follow-up
Subsystems (3)
Paolo Abeni
maintainerv2 cover net: default_rps_mask follow-up
The first patch namespacify the setting. In the common case, once proper isolation is in place in the main namespace, forwarding to/from each child netns will allways happen on the desidered CPUs.
Any additional RPS stage inside the child namespace will not provide additional isolation and could hurt performance badly if picking a CPU on a remote node.
The 2nd patch adds more self-tests coverage.
Paolo Abeni (2):
net: make default_rps_mask a per netns attribute
self-tests: more rps self tests
include/linux/netdevice.h | 1 - include/net/netns/core.h | 5 ++ net/core/net-sysfs.c | 23 ++++++--- net/core/sysctl_net_core.c | 51 ++++++++++++++----- .../testing/selftests/net/rps_default_mask.sh | 41 ++++++++++----- 5 files changed, 88 insertions(+), 33 deletions(-)
Signature · 1 line
2.39.1
Paolo Abeni
maintainerPATCH v2 1/2 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.
---
v1 -> v2:
- fix build issue for !CONFIG_CPUMASK_OFFSTACK build
--- include/linux/netdevice.h | 1 - include/net/netns/core.h | 5 ++++ net/core/net-sysfs.c | 23 +++++++++++------ net/core/sysctl_net_core.c | 51 ++++++++++++++++++++++++++++---------- 4 files changed, 59 insertions(+), 21 deletions(-)
include/linux/netdevice.h +0 -1
@@ -224,7 +224,6 @@ struct net_device_core_stats {#include <linux/static_key.h> extern struct static_key_false rps_needed;extern struct static_key_false rfs_needed; -extern struct cpumask rps_default_mask;#endif struct neighbour ;
include/net/netns/core.h +5 -0
@@ -6,6 +6,7 @@struct ctl_table_header ;struct prot_inuse ; +struct cpumask ;struct netns_core {/* core sysctls */
@@ -17,6 +18,10 @@ struct netns_core {#ifdef CONFIG_PROC_FS struct prot_inuse __percpu *prot_inuse;#endif + +#if IS_ENABLED (CONFIG_RPS ) &&IS_ENABLED (CONFIG_SYSCTL ) +struct cpumask *rps_default_mask; +#endif };#endif
net/core/net-sysfs.c +16 -7
@@ -1060,6 +1060,18 @@ static const struct kobj_type rx_queue_ktype = { .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) {struct netdev_rx_queue *queue = dev->_rx + index;
@@ -1083,13 +1095,10 @@ static int rx_queue_add_kobject(struct net_device *dev, int index) goto err; } -#if IS_ENABLED (CONFIG_RPS ) &&IS_ENABLED (CONFIG_SYSCTL ) -if (!cpumask_empty (&rps_default_mask)) { - error =netdev_rx_queue_set_rps_mask (queue, &rps_default_mask); -if (error) - goto err; - } -#endif + error =rx_queue_default_mask (dev, queue); +if (error) + goto err; +kobject_uevent (kobj,KOBJ_ADD );return error;
net/core/sysctl_net_core.c +38 -13
95 lines not on this page · raw message
Signature · 1 line
2.39.1
Re: [PATCH v2 net-next 1/2] net: make default_rps_mask a per netns attribute
Quoted 10 lines · Paolo Abeni
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 Paolo Abeni <[email protected]>
...
Quoted 28 lines
net/core/sysctl_net_core.c +16
-1@@ -74,24 +74,47 @@ static void dump_cpumask(void *buffer, size_t *lenp, loff_t *ppos,#endif #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,void *buffer,size_t *lenp,loff_t *ppos)
net/core/sysctl_net_core.c static void dump_cpumask(void *buffer, size_t *lenp, loff_t *ppos, · line 104
Quoted 10 lines
net/core/sysctl_net_core.c +4
-1{ +struct net *net = (struct net *)table->data;int err =0 ;rtnl_lock ();if (write) { - err =cpumask_parse (buffer, &rps_default_mask); +struct cpumask *rps_default_mask =rps_default_mask_cow_alloc (net); + + err = -ENOMEM ;
nit: Would it be nicer to set err to -ENOMEM inside the if clause?
I think that is the only path where it is used.
Quoted 18 lines
net/core/sysctl_net_core.c +7
-2+if (!rps_default_mask) + goto done; + + err =cpumask_parse (buffer, rps_default_mask);if (err) goto done; - err =rps_cpumask_housekeeping (&rps_default_mask); + err =rps_cpumask_housekeeping (rps_default_mask);if (err) goto done; }else { -dump_cpumask (buffer, lenp, ppos, &rps_default_mask); +dump_cpumask (buffer, lenp, ppos, + net->core.rps_default_mask ? : cpu_none_mask); } done:
...
Paolo Abeni
maintainerPATCH v2 2/2 self-tests: more rps self tests
In reply to Paolo AbeniExplicitly check for child netns and main ns independency
--- .../testing/selftests/net/rps_default_mask.sh | 41 +++++++++++++------ 1 file changed, 29 insertions(+), 12 deletions(-)
tools/testing/selftests/net/rps_default_mask.sh +29 -12
@@ -8,7 +8,9 @@ ret=0 [ $cpus -gt 2 ] || exit $ksft_skip readonly INITIAL_RPS_DEFAULT_MASK=$(cat /proc/sys/net/core/rps_default_mask) -readonly NETNS="ns-$(mktemp -u XXXXXX)" +readonly TAG="$(mktemp -u XXXXXX)" +readonly VETH="veth${TAG}" +readonly NETNS="ns-${TAG}" setup() { ip netns add "${NETNS}"
@@ -21,11 +23,15 @@ cleanup() { } chk_rps() { - local rps_mask expected_rps_mask=$3 - local dev_name=$2 + local rps_mask expected_rps_mask=$4 + local dev_name=$3 + local netns=$2 + local cmd="cat" local msg=$1 - rps_mask=$(ip netns exec $NETNS cat /sys/class/net/$dev_name/queues/rx-0/rps_cpus) + [ -n "$netns" ] && cmd="ip netns exec $netns $cmd" + + rps_mask=$($cmd /sys/class/net/$dev_name/queues/rx-0/rps_cpus) printf "%-60s" "$msg" if [ $rps_mask -eq $expected_rps_mask ]; then echo "[ ok ]"
@@ -39,19 +45,30 @@ trap cleanup EXIT echo 0 > /proc/sys/net/core/rps_default_mask setup -chk_rps "empty rps_default_mask" lo 0 +chk_rps "empty rps_default_mask" $NETNS lo 0 cleanup echo 1 > /proc/sys/net/core/rps_default_mask setup -chk_rps "non zero rps_default_mask" lo 1 +chk_rps "changing rps_default_mask dont affect existing devices" "" lo $INITIAL_RPS_DEFAULT_MASK echo 3 > /proc/sys/net/core/rps_default_mask -chk_rps "changing rps_default_mask dont affect existing netns" lo 1 +chk_rps "changing rps_default_mask dont affect existing netns" $NETNS lo 0 + +ip link add name $VETH type veth peer netns $NETNS name $VETH +ip link set dev $VETH up +ip -n $NETNS link set dev $VETH up +chk_rps "changing rps_default_mask affect newly created devices" "" $VETH 3 +chk_rps "changing rps_default_mask don't affect newly child netns[II]" $NETNS $VETH 0 +ip netns del $NETNS + +setup +chk_rps "rps_default_mask is 0 by default in child netns" "$NETNS" lo 0 + +ip netns exec $NETNS sysctl -qw net.core.rps_default_mask=1 +ip link add name $VETH type veth peer netns $NETNS name $VETH +chk_rps "changing rps_default_mask in child ns don't affect the main one" "" lo $INITIAL_RPS_DEFAULT_MASK +chk_rps "changing rps_default_mask in child ns affects new childns devices" $NETNS $VETH 1 +chk_rps "changing rps_default_mask in child ns don't affect existing devices" $NETNS lo 0 -ip -n $NETNS link add type veth -ip -n $NETNS link set dev veth0 up -ip -n $NETNS link set dev veth1 up -chk_rps "changing rps_default_mask affect newly created devices" veth0 3 -chk_rps "changing rps_default_mask affect newly created devices[II]" veth1 3 exit $ret
Signature · 1 line
2.39.1