net: introduce default_rps_mask netns attribute
authorPaolo Abeni <pabeni@redhat.com>
Tue, 7 Feb 2023 18:44:57 +0000 (19:44 +0100)
committerJakub Kicinski <kuba@kernel.org>
Fri, 10 Feb 2023 01:45:55 +0000 (17:45 -0800)
If RPS is enabled, this allows configuring a default rps
mask, which is effective since receive queue creation time.

A default RPS mask allows the system admin to ensure proper
isolation, avoiding races at network namespace or device
creation time.

The default RPS mask is initially empty, and can be
modified via a newly added sysctl entry.

Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Simon Horman <simon.horman@corigine.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Documentation/admin-guide/sysctl/net.rst
include/linux/netdevice.h
net/core/net-sysfs.c
net/core/sysctl_net_core.c

index 6394f5dc2303d4dc0fdb42acafdfce50fc01cef1..466c560b0c3044ddc5509c9cc13b80ca3905bbbc 100644 (file)
@@ -215,6 +215,12 @@ rmem_max
 
 The maximum receive socket buffer size in bytes.
 
+rps_default_mask
+----------------
+
+The default RPS CPU mask used on newly created network devices. An empty
+mask means RPS disabled by default.
+
 tstamp_allow_data
 -----------------
 Allow processes to receive tx timestamps looped together with the original
index d5ef4c1fedd2473316c330c74f2b2a303d5cb109..38ab96ae0d68b7e0bd175fd21d05418f4c713c71 100644 (file)
@@ -223,6 +223,7 @@ 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;
index 2126970a4bfde9aa82ee5dbc5bca540ac84b7b1e..4b361ac6a252a72f8f827609bbc96140b8c57d67 100644 (file)
@@ -1083,6 +1083,13 @@ 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
        kobject_uevent(kobj, KOBJ_ADD);
 
        return error;
index 6935ecdc84b0d9d221af9bb624a5f3fac71fe808..7130e6d9e263ac7999580f76374082716b62db64 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/vmalloc.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/sched/isolation.h>
 
 #include <net/ip.h>
 #include <net/sock.h>
@@ -45,7 +46,7 @@ EXPORT_SYMBOL(sysctl_fb_tunnels_only_for_init_net);
 int sysctl_devconf_inherit_init_net __read_mostly;
 EXPORT_SYMBOL(sysctl_devconf_inherit_init_net);
 
-#if IS_ENABLED(CONFIG_NET_FLOW_LIMIT)
+#if IS_ENABLED(CONFIG_NET_FLOW_LIMIT) || IS_ENABLED(CONFIG_RPS)
 static void dump_cpumask(void *buffer, size_t *lenp, loff_t *ppos,
                         struct cpumask *mask)
 {
@@ -73,6 +74,31 @@ static void dump_cpumask(void *buffer, size_t *lenp, loff_t *ppos,
 #endif
 
 #ifdef CONFIG_RPS
+struct cpumask rps_default_mask;
+
+static int rps_default_mask_sysctl(struct ctl_table *table, int write,
+                                  void *buffer, size_t *lenp, loff_t *ppos)
+{
+       int err = 0;
+
+       rtnl_lock();
+       if (write) {
+               err = cpumask_parse(buffer, &rps_default_mask);
+               if (err)
+                       goto done;
+
+               err = rps_cpumask_housekeeping(&rps_default_mask);
+               if (err)
+                       goto done;
+       } else {
+               dump_cpumask(buffer, lenp, ppos, &rps_default_mask);
+       }
+
+done:
+       rtnl_unlock();
+       return err;
+}
+
 static int rps_sock_flow_sysctl(struct ctl_table *table, int write,
                                void *buffer, size_t *lenp, loff_t *ppos)
 {
@@ -482,6 +508,11 @@ static struct ctl_table net_core_table[] = {
                .mode           = 0644,
                .proc_handler   = rps_sock_flow_sysctl
        },
+       {
+               .procname       = "rps_default_mask",
+               .mode           = 0644,
+               .proc_handler   = rps_default_mask_sysctl
+       },
 #endif
 #ifdef CONFIG_NET_FLOW_LIMIT
        {
@@ -685,6 +716,10 @@ static __net_initdata struct pernet_operations sysctl_core_ops = {
 
 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);
        return register_pernet_subsys(&sysctl_core_ops);
 }