diff --git a/net/core/dev.h b/net/core/dev.h index 04fb0e9a571e..f159a7c7beaa 100644 --- a/net/core/dev.h +++ b/net/core/dev.h @@ -95,6 +95,7 @@ extern int netdev_unregister_timeout_secs; extern int weight_p; extern int dev_weight_rx_bias; extern int dev_weight_tx_bias; +extern bool netdev_rss_key_initialized; extern struct rw_semaphore dev_addr_sem; diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index 23310581f494..473c162736d6 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -337,10 +337,15 @@ static int proc_do_rss_key(const struct ctl_table *table, int write, { char buf[NETDEV_RSS_KEY_LEN * 3]; struct ctl_table fake_table; + bool initialized; char *pos = buf; + initialized = READ_ONCE(netdev_rss_key_initialized); + /* Pair with smp_wmb() in netdev_rss_key_fill(). */ + smp_rmb(); + for (int i = 0; i < NETDEV_RSS_KEY_LEN; i++) { - pos = hex_byte_pack(pos, netdev_rss_key[i]); + pos = hex_byte_pack(pos, initialized ? netdev_rss_key[i] : 0); *pos++ = ':'; } *(--pos) = 0; diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 4b0bc503f930..b2820f02ca27 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -34,6 +34,7 @@ #include #include +#include "../core/dev.h" #include "common.h" /* State held across locks and calls for commands which have devlink fallback */ @@ -1302,11 +1303,17 @@ static int ethtool_copy_validate_indir(u32 *indir, void __user *useraddr, } u8 netdev_rss_key[NETDEV_RSS_KEY_LEN] __read_mostly; +bool netdev_rss_key_initialized __read_mostly; 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)); + if (unlikely(!READ_ONCE(netdev_rss_key_initialized))) { + /* Pair with smp_rmb() in proc_do_rss_key(). */ + smp_wmb(); + WRITE_ONCE(netdev_rss_key_initialized, true); + } memcpy(buffer, netdev_rss_key, len); } EXPORT_SYMBOL(netdev_rss_key_fill);