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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.