From: "Björn Töpel" <bjorn@kernel.org>
To: Michael Chan <michael.chan@broadcom.com>,
Pavan Chebbi <pavan.chebbi@broadcom.com>,
Andrew Lunn <andrew+netdev@lunn.ch>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Simon Horman <horms@kernel.org>,
linux-kernel@vger.kernel.org, netdev@vger.kernel.org,
linux-kselftest@vger.kernel.org
Cc: "Björn Töpel" <bjorn@kernel.org>,
"Willem de Bruijn" <willemb@google.com>
Subject: [PATCH net-next 3/5] netdevsim: Add RSS context support with dynamic table sizing
Date: Tue, 3 Mar 2026 19:15:31 +0100 [thread overview]
Message-ID: <20260303181535.2671734-4-bjorn@kernel.org> (raw)
In-Reply-To: <20260303181535.2671734-1-bjorn@kernel.org>
Add RSS indirection table, hash key, and non-default RSS context
support to netdevsim. The create/modify/remove context callbacks are
no-ops; the core manages context state in its xarray.
The table size is dynamic: roundup_pow_of_two(channels) * 16, capped
at NSIM_RSS_INDIR_MAX (128). This mimics drivers like bnxt where the
table size changes with the queue count.
nsim_set_channels() uses the core resize helpers to fold/unfold tables
on channel count changes, exercising the full resize path.
Signed-off-by: Björn Töpel <bjorn@kernel.org>
---
drivers/net/netdevsim/ethtool.c | 119 +++++++++++++++++++++++++++++-
drivers/net/netdevsim/netdevsim.h | 4 +
2 files changed, 121 insertions(+), 2 deletions(-)
diff --git a/drivers/net/netdevsim/ethtool.c b/drivers/net/netdevsim/ethtool.c
index 36a201533aae..c6d60b467054 100644
--- a/drivers/net/netdevsim/ethtool.c
+++ b/drivers/net/netdevsim/ethtool.c
@@ -2,6 +2,7 @@
// Copyright (c) 2020 Facebook
#include <linux/debugfs.h>
+#include <linux/ethtool.h>
#include <linux/random.h>
#include <net/netdev_queues.h>
@@ -117,19 +118,121 @@ nsim_wake_queues(struct net_device *dev)
rcu_read_unlock();
}
+static u32 nsim_get_rx_ring_count(struct net_device *dev)
+{
+ struct netdevsim *ns = netdev_priv(dev);
+
+ return ns->ethtool.channels;
+}
+
+static u32 nsim_rss_indir_size(u32 channels)
+{
+ return min_t(u32, roundup_pow_of_two(channels) * 16, NSIM_RSS_INDIR_MAX);
+}
+
+static u32 nsim_get_rxfh_indir_size(struct net_device *dev)
+{
+ struct netdevsim *ns = netdev_priv(dev);
+
+ return nsim_rss_indir_size(ns->ethtool.channels);
+}
+
+static u32 nsim_get_rxfh_key_size(struct net_device *dev)
+{
+ return NSIM_RSS_HKEY_SIZE;
+}
+
+static int nsim_get_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh)
+{
+ u32 indir_size = nsim_get_rxfh_indir_size(dev);
+ struct netdevsim *ns = netdev_priv(dev);
+
+ rxfh->hfunc = ETH_RSS_HASH_TOP;
+
+ if (rxfh->indir)
+ memcpy(rxfh->indir, ns->ethtool.rss_indir_tbl, indir_size * sizeof(u32));
+ if (rxfh->key)
+ memcpy(rxfh->key, ns->ethtool.rss_hkey, NSIM_RSS_HKEY_SIZE);
+
+ return 0;
+}
+
+static int nsim_set_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh,
+ struct netlink_ext_ack *extack)
+{
+ u32 indir_size = nsim_get_rxfh_indir_size(dev);
+ struct netdevsim *ns = netdev_priv(dev);
+
+ if (rxfh->indir)
+ memcpy(ns->ethtool.rss_indir_tbl, rxfh->indir, indir_size * sizeof(u32));
+ if (rxfh->key)
+ memcpy(ns->ethtool.rss_hkey, rxfh->key, NSIM_RSS_HKEY_SIZE);
+
+ return 0;
+}
+
+static int nsim_create_rxfh_context(struct net_device *dev, struct ethtool_rxfh_context *ctx,
+ const struct ethtool_rxfh_param *rxfh,
+ struct netlink_ext_ack *extack)
+{
+ return 0;
+}
+
+static int nsim_modify_rxfh_context(struct net_device *dev, struct ethtool_rxfh_context *ctx,
+ const struct ethtool_rxfh_param *rxfh,
+ struct netlink_ext_ack *extack)
+{
+ return 0;
+}
+
+static int nsim_remove_rxfh_context(struct net_device *dev, struct ethtool_rxfh_context *ctx,
+ u32 rss_context, struct netlink_ext_ack *extack)
+{
+ return 0;
+}
+
+static void nsim_rss_init(struct netdevsim *ns)
+{
+ u32 i, indir_size = nsim_rss_indir_size(ns->ethtool.channels);
+
+ for (i = 0; i < indir_size; i++)
+ ns->ethtool.rss_indir_tbl[i] = ethtool_rxfh_indir_default(i, ns->ethtool.channels);
+}
+
static int
nsim_set_channels(struct net_device *dev, struct ethtool_channels *ch)
{
struct netdevsim *ns = netdev_priv(dev);
+ u32 old_indir_size, new_indir_size;
int err;
- err = netif_set_real_num_queues(dev, ch->combined_count,
- ch->combined_count);
+ old_indir_size = nsim_get_rxfh_indir_size(dev);
+ new_indir_size = nsim_rss_indir_size(ch->combined_count);
+
+ if (old_indir_size != new_indir_size) {
+ if (netif_is_rxfh_configured(dev) &&
+ ethtool_rxfh_indir_can_resize(ns->ethtool.rss_indir_tbl,
+ old_indir_size, new_indir_size))
+ return -EINVAL;
+
+ err = ethtool_rxfh_contexts_resize_all(dev, new_indir_size);
+ if (err)
+ return err;
+
+ if (netif_is_rxfh_configured(dev))
+ ethtool_rxfh_indir_resize(ns->ethtool.rss_indir_tbl,
+ old_indir_size, new_indir_size);
+ }
+
+ err = netif_set_real_num_queues(dev, ch->combined_count, ch->combined_count);
if (err)
return err;
ns->ethtool.channels = ch->combined_count;
+ if (old_indir_size != new_indir_size && !netif_is_rxfh_configured(dev))
+ nsim_rss_init(ns);
+
/* Only wake up queues if devices are linked */
if (rcu_access_pointer(ns->peer))
nsim_wake_queues(dev);
@@ -209,6 +312,7 @@ static const struct ethtool_ops nsim_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_ALL_PARAMS,
.supported_ring_params = ETHTOOL_RING_USE_TCP_DATA_SPLIT |
ETHTOOL_RING_USE_HDS_THRS,
+ .rxfh_indir_space = NSIM_RSS_INDIR_MAX,
.get_pause_stats = nsim_get_pause_stats,
.get_pauseparam = nsim_get_pauseparam,
.set_pauseparam = nsim_set_pauseparam,
@@ -218,10 +322,18 @@ static const struct ethtool_ops nsim_ethtool_ops = {
.set_ringparam = nsim_set_ringparam,
.get_channels = nsim_get_channels,
.set_channels = nsim_set_channels,
+ .get_rx_ring_count = nsim_get_rx_ring_count,
.get_fecparam = nsim_get_fecparam,
.set_fecparam = nsim_set_fecparam,
.get_fec_stats = nsim_get_fec_stats,
.get_ts_info = nsim_get_ts_info,
+ .get_rxfh_indir_size = nsim_get_rxfh_indir_size,
+ .get_rxfh_key_size = nsim_get_rxfh_key_size,
+ .get_rxfh = nsim_get_rxfh,
+ .set_rxfh = nsim_set_rxfh,
+ .create_rxfh_context = nsim_create_rxfh_context,
+ .modify_rxfh_context = nsim_modify_rxfh_context,
+ .remove_rxfh_context = nsim_remove_rxfh_context,
};
static void nsim_ethtool_ring_init(struct netdevsim *ns)
@@ -250,6 +362,9 @@ void nsim_ethtool_init(struct netdevsim *ns)
ns->ethtool.channels = ns->nsim_bus_dev->num_queues;
+ nsim_rss_init(ns);
+ get_random_bytes(ns->ethtool.rss_hkey, NSIM_RSS_HKEY_SIZE);
+
ethtool = debugfs_create_dir("ethtool", ns->nsim_dev_port->ddir);
debugfs_create_u32("get_err", 0600, ethtool, &ns->ethtool.get_err);
diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h
index f767fc8a7505..3c6dd9a98deb 100644
--- a/drivers/net/netdevsim/netdevsim.h
+++ b/drivers/net/netdevsim/netdevsim.h
@@ -82,6 +82,8 @@ struct nsim_ethtool_pauseparam {
bool report_stats_tx;
};
+#define NSIM_RSS_INDIR_MAX 128
+#define NSIM_RSS_HKEY_SIZE 40
struct nsim_ethtool {
u32 get_err;
u32 set_err;
@@ -90,6 +92,8 @@ struct nsim_ethtool {
struct ethtool_coalesce coalesce;
struct ethtool_ringparam ring;
struct ethtool_fecparam fec;
+ u32 rss_indir_tbl[NSIM_RSS_INDIR_MAX];
+ u8 rss_hkey[NSIM_RSS_HKEY_SIZE];
};
struct nsim_rq {
--
2.53.0
next prev parent reply other threads:[~2026-03-03 18:15 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-03 18:15 [PATCH net-next 0/5] ethtool: Dynamic RSS context indirection table resizing Björn Töpel
2026-03-03 18:15 ` [PATCH net-next 1/5] ethtool: Add RSS indirection table resize helpers Björn Töpel
2026-03-04 0:03 ` Jakub Kicinski
2026-03-04 11:37 ` Björn Töpel
2026-03-04 17:09 ` Jakub Kicinski
2026-03-03 18:15 ` [PATCH net-next 2/5] bnxt_en: Resize RSS contexts on channel count change Björn Töpel
2026-03-03 19:20 ` Michael Chan
2026-03-04 11:38 ` Björn Töpel
2026-03-04 0:05 ` Jakub Kicinski
2026-03-04 11:39 ` Björn Töpel
2026-03-03 18:15 ` Björn Töpel [this message]
2026-03-04 0:07 ` [PATCH net-next 3/5] netdevsim: Add RSS context support with dynamic table sizing Jakub Kicinski
2026-03-04 11:40 ` Björn Töpel
2026-03-03 18:15 ` [PATCH net-next 4/5] selftests: netdevsim: Add RSS indirection table resize test Björn Töpel
2026-03-04 0:07 ` Jakub Kicinski
2026-03-03 18:15 ` [PATCH net-next 5/5] selftests: rss_drv: Add RSS indirection table resize tests Björn Töpel
2026-03-04 0:16 ` Jakub Kicinski
2026-03-04 8:23 ` [PATCH net-next 0/5] ethtool: Dynamic RSS context indirection table resizing Pavan Chebbi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260303181535.2671734-4-bjorn@kernel.org \
--to=bjorn@kernel.org \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=michael.chan@broadcom.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=pavan.chebbi@broadcom.com \
--cc=willemb@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox