Commit 960fb622 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

net: provide a per host RSS key generic infrastructure

RSS (Receive Side Scaling) typically uses Toeplitz hash and a 40 or 52 bytes
RSS key.

Some drivers use a constant (and well known key), some drivers use a random
key per port, making bonding setups hard to tune. Well known keys increase
attack surface, considering that number of queues is usually a power of two.

This patch provides infrastructure to help drivers doing the right thing.

netdev_rss_key_fill() should be used by drivers to initialize their RSS key,
even if they provide ethtool -X support to let user redefine the key later.

A new /proc/sys/net/core/netdev_rss_key file can be used to get the host
RSS key even for drivers not providing ethtool -x support, in case some
applications want to precisely setup flows to match some RX queues.

Tested:

myhost:~# cat /proc/sys/net/core/netdev_rss_key
11:63:99:bb:79:fb:a5:a7:07:45:b2:20:bf:02:42:2d:08:1a:dd:19:2b:6b:23:ac:56:28:9d:70:c3:ac:e8:16:4b:b7:c1:10:53:a4:78:41:36:40:74:b6:15:ca:27:44:aa:b3:4d:72

myhost:~# ethtool -x eth0
RX flow hash indirection table for eth0 with 8 RX ring(s):
    0:      0     1     2     3     4     5     6     7
RSS hash key:
11:63:99:bb:79:fb:a5:a7:07:45:b2:20:bf:02:42:2d:08:1a:dd:19:2b:6b:23:ac:56:28:9d:70:c3:ac:e8:16:4b:b7:c1:10:53:a4:78:41
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ca245024
...@@ -142,6 +142,28 @@ netdev_max_backlog ...@@ -142,6 +142,28 @@ netdev_max_backlog
Maximum number of packets, queued on the INPUT side, when the interface Maximum number of packets, queued on the INPUT side, when the interface
receives packets faster than kernel can process them. receives packets faster than kernel can process them.
netdev_rss_key
--------------
RSS (Receive Side Scaling) enabled drivers use a 40 bytes host key that is
randomly generated.
Some user space might need to gather its content even if drivers do not
provide ethtool -x support yet.
myhost:~# cat /proc/sys/net/core/netdev_rss_key
84:50:f4:00:a8:15:d1:a7:e9:7f:1d:60:35:c7:47:25:42:97:74:ca:56:bb:b6:a1:d8: ... (52 bytes total)
File contains nul bytes if no driver ever called netdev_rss_key_fill() function.
Note:
/proc/sys/net/core/netdev_rss_key contains 52 bytes of key,
but most drivers only use 40 bytes of it.
myhost:~# ethtool -x eth0
RX flow hash indirection table for eth0 with 8 RX ring(s):
0: 0 1 2 3 4 5 6 7
RSS hash key:
84:50:f4:00:a8:15:d1:a7:e9:7f:1d:60:35:c7:47:25:42:97:74:ca:56:bb:b6:a1:d8:43:e3:c9:0c:fd:17:55:c2:3a:4d:69:ed:f1:42:89
netdev_tstamp_prequeue netdev_tstamp_prequeue
---------------------- ----------------------
......
...@@ -3422,6 +3422,12 @@ void netdev_upper_dev_unlink(struct net_device *dev, ...@@ -3422,6 +3422,12 @@ void netdev_upper_dev_unlink(struct net_device *dev,
void netdev_adjacent_rename_links(struct net_device *dev, char *oldname); void netdev_adjacent_rename_links(struct net_device *dev, char *oldname);
void *netdev_lower_dev_get_private(struct net_device *dev, void *netdev_lower_dev_get_private(struct net_device *dev,
struct net_device *lower_dev); struct net_device *lower_dev);
/* RSS keys are 40 or 52 bytes long */
#define NETDEV_RSS_KEY_LEN 52
extern u8 netdev_rss_key[NETDEV_RSS_KEY_LEN];
void netdev_rss_key_fill(void *buffer, size_t len);
int dev_get_nest_level(struct net_device *dev, int dev_get_nest_level(struct net_device *dev,
bool (*type_check)(struct net_device *dev)); bool (*type_check)(struct net_device *dev));
int skb_checksum_help(struct sk_buff *skb); int skb_checksum_help(struct sk_buff *skb);
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/net.h>
/* /*
* Some useful ethtool_ops methods that're device independent. * Some useful ethtool_ops methods that're device independent.
...@@ -573,6 +574,16 @@ static int ethtool_copy_validate_indir(u32 *indir, void __user *useraddr, ...@@ -573,6 +574,16 @@ static int ethtool_copy_validate_indir(u32 *indir, void __user *useraddr,
return 0; return 0;
} }
u8 netdev_rss_key[NETDEV_RSS_KEY_LEN];
void netdev_rss_key_fill(void *buffer, size_t len)
{
BUG_ON(len > sizeof(netdev_rss_key));
net_get_random_once(netdev_rss_key, sizeof(netdev_rss_key));
memcpy(buffer, netdev_rss_key, len);
}
EXPORT_SYMBOL(netdev_rss_key_fill);
static noinline_for_stack int ethtool_get_rxfh_indir(struct net_device *dev, static noinline_for_stack int ethtool_get_rxfh_indir(struct net_device *dev,
void __user *useraddr) void __user *useraddr)
{ {
......
...@@ -217,6 +217,18 @@ static int set_default_qdisc(struct ctl_table *table, int write, ...@@ -217,6 +217,18 @@ static int set_default_qdisc(struct ctl_table *table, int write,
} }
#endif #endif
static int proc_do_rss_key(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
struct ctl_table fake_table;
char buf[NETDEV_RSS_KEY_LEN * 3];
snprintf(buf, sizeof(buf), "%*phC", NETDEV_RSS_KEY_LEN, netdev_rss_key);
fake_table.data = buf;
fake_table.maxlen = sizeof(buf);
return proc_dostring(&fake_table, write, buffer, lenp, ppos);
}
static struct ctl_table net_core_table[] = { static struct ctl_table net_core_table[] = {
#ifdef CONFIG_NET #ifdef CONFIG_NET
{ {
...@@ -265,6 +277,13 @@ static struct ctl_table net_core_table[] = { ...@@ -265,6 +277,13 @@ static struct ctl_table net_core_table[] = {
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec .proc_handler = proc_dointvec
}, },
{
.procname = "netdev_rss_key",
.data = &netdev_rss_key,
.maxlen = sizeof(int),
.mode = 0444,
.proc_handler = proc_do_rss_key,
},
#ifdef CONFIG_BPF_JIT #ifdef CONFIG_BPF_JIT
{ {
.procname = "bpf_jit_enable", .procname = "bpf_jit_enable",
......
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