git: 32b8381d711c - main - ixv: Report the programmed VF RSS configuration
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 18 Sep 2026 22:41:06 UTC
The branch main has been updated by kbowling:
URL: https://cgit.FreeBSD.org/src/commit/?id=32b8381d711cb668791ff307de1df1ca333b39ba
commit 32b8381d711cb668791ff307de1df1ca333b39ba
Author: Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-09-15 00:15:12 +0000
Commit: Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-09-18 22:40:17 +0000
ixv: Report the programmed VF RSS configuration
Provide the iflib RSS query methods for X550 and newer VFs, whose RSS key
and hash types are programmed by the VF. Cache those values and answer
queries under the context lock, without register reads or mailbox
transactions. Invalidate the snapshot at init, stop, and when an admin
check requests recovery after losing the PF mailbox or detecting reset.
Reject queries while the snapshot or mailbox is unavailable.
Program the common RSS key and cache the values written to the registers.
The key remains stable across resets, including live MTU and capability
changes for which hn(4) can retain its copy without another VF handoff.
Serialize the key in register byte order and report the six supported
IPv4/IPv6 TCP/UDP hash selections from the programmed MRQC, rather than
claiming that every globally requested hash type is enabled. A single
receive queue still performs Toeplitz hashing. Older VFs retain
EOPNOTSUPP because their PF-owned RSS settings are not available here.
This allows hn(4) to synchronize synthetic RSS with the actual VF
settings instead of suppressing otherwise usable receive hash metadata.
Reviewed by: gallatin
MFC after: 2 weeks
Sponsored by: BBOX.io
Differential Revision: https://reviews.freebsd.org/D59692
---
sys/dev/ixgbe/if_ixv.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++---
sys/dev/ixgbe/ixgbe.h | 3 ++
2 files changed, 78 insertions(+), 4 deletions(-)
diff --git a/sys/dev/ixgbe/if_ixv.c b/sys/dev/ixgbe/if_ixv.c
index 378a0c18cbf6..c5359045133b 100644
--- a/sys/dev/ixgbe/if_ixv.c
+++ b/sys/dev/ixgbe/if_ixv.c
@@ -128,6 +128,8 @@ static void ixv_if_update_admin_status(if_ctx_t);
static int ixv_if_msix_intr_assign(if_ctx_t, int);
static int ixv_if_mtu_set(if_ctx_t, uint32_t);
+static int ixv_if_get_rss_key(if_ctx_t, struct ifrsskey *);
+static int ixv_if_get_rss_hash(if_ctx_t, struct ifrsshash *);
static void ixv_reconcile_mac(struct ixgbe_softc *, if_t);
static void ixv_if_init(if_ctx_t);
static void ixv_if_local_timer(if_ctx_t, uint16_t);
@@ -220,6 +222,8 @@ static device_method_t ixv_if_methods[] = {
DEVMETHOD(ifdi_multi_set, ixv_if_multi_set),
DEVMETHOD(ifdi_promisc_set, ixv_if_promisc_set),
DEVMETHOD(ifdi_mtu_set, ixv_if_mtu_set),
+ DEVMETHOD(ifdi_get_rss_key, ixv_if_get_rss_key),
+ DEVMETHOD(ifdi_get_rss_hash, ixv_if_get_rss_hash),
DEVMETHOD(ifdi_media_status, ixv_if_media_status),
DEVMETHOD(ifdi_media_change, ixv_if_media_change),
DEVMETHOD(ifdi_timer, ixv_if_local_timer),
@@ -630,6 +634,69 @@ ixv_if_mtu_set(if_ctx_t ctx, uint32_t mtu)
return error;
} /* ixv_if_mtu_set */
+static int
+ixv_rss_query_status(if_ctx_t ctx)
+{
+ struct ixgbe_softc *sc = iflib_get_softc(ctx);
+
+ sx_assert(iflib_ctx_lock_get(ctx), SA_XLOCKED);
+ /* Older VFs share PF-controlled RSS settings which we cannot query. */
+ if (sc->hw.mac.type < ixgbe_mac_X550_vf)
+ return (EOPNOTSUPP);
+ if (atomic_load_acq_32(&sc->vf_mbx_ready) == 0 ||
+ sc->vf_rss_mrqc == 0)
+ return (ENXIO);
+ return (0);
+}
+
+static int
+ixv_if_get_rss_key(if_ctx_t ctx, struct ifrsskey *ifrk)
+{
+ struct ixgbe_softc *sc = iflib_get_softc(ctx);
+ int error;
+
+ error = ixv_rss_query_status(ctx);
+ if (error != 0)
+ return (error);
+ ifrk->ifrk_func = RSS_FUNC_TOEPLITZ;
+ ifrk->ifrk_keylen = sizeof(sc->vf_rss_key);
+ _Static_assert(sizeof(ifrk->ifrk_key) >= sizeof(sc->vf_rss_key),
+ "RSS query buffer too small");
+ bzero(ifrk->ifrk_key, sizeof(ifrk->ifrk_key));
+ /* Preserve the byte order of the programmed registers. */
+ for (u_int i = 0; i < nitems(sc->vf_rss_key); i++)
+ le32enc(ifrk->ifrk_key + i * sizeof(u32), sc->vf_rss_key[i]);
+ return (0);
+}
+
+static int
+ixv_if_get_rss_hash(if_ctx_t ctx, struct ifrsshash *ifrh)
+{
+ struct ixgbe_softc *sc = iflib_get_softc(ctx);
+ u32 mrqc;
+ int error;
+
+ error = ixv_rss_query_status(ctx);
+ if (error != 0)
+ return (error);
+ ifrh->ifrh_func = RSS_FUNC_TOEPLITZ;
+ ifrh->ifrh_types = 0;
+ mrqc = sc->vf_rss_mrqc;
+ if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV4)
+ ifrh->ifrh_types |= RSS_TYPE_IPV4;
+ if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV4_TCP)
+ ifrh->ifrh_types |= RSS_TYPE_TCP_IPV4;
+ if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV4_UDP)
+ ifrh->ifrh_types |= RSS_TYPE_UDP_IPV4;
+ if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV6)
+ ifrh->ifrh_types |= RSS_TYPE_IPV6;
+ if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV6_TCP)
+ ifrh->ifrh_types |= RSS_TYPE_TCP_IPV6;
+ if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV6_UDP)
+ ifrh->ifrh_types |= RSS_TYPE_UDP_IPV6;
+ return (0);
+}
+
static void
ixv_reconcile_mac(struct ixgbe_softc *sc, if_t ifp)
{
@@ -674,6 +741,7 @@ ixv_if_init(if_ctx_t ctx)
int error = 0;
INIT_DEBUGOUT("ixv_if_init: begin");
+ sc->vf_rss_mrqc = 0;
ixv_mbx_retry_prepare(sc);
hw->adapter_stopped = false;
hw->mac.ops.stop_adapter(hw);
@@ -1358,6 +1426,7 @@ ixv_if_update_admin_status(if_ctx_t ctx)
if (status != IXGBE_SUCCESS && sc->hw.adapter_stopped == false) {
/* Mailbox's Clear To Send status is lost or timeout occurred.
* We need reinitialization. */
+ sc->vf_rss_mrqc = 0;
iflib_request_reset(ctx);
iflib_admin_intr_deferred(ctx);
}
@@ -1416,6 +1485,7 @@ ixv_if_stop(if_ctx_t ctx)
bool mailbox_ready, reset_seen;
INIT_DEBUGOUT("ixv_stop: begin\n");
+ sc->vf_rss_mrqc = 0;
ixv_mbx_retry_stop(sc);
ixv_if_disable_intr(ctx);
@@ -1783,16 +1853,16 @@ static void
ixv_initialize_rss_mapping(struct ixgbe_softc *sc)
{
struct ixgbe_hw *hw = &sc->hw;
- u32 reta = 0, mrqc, rss_key[10];
+ u32 reta = 0, mrqc;
int queue_id;
int i, j;
u32 rss_hash_config;
- rss_getkey((uint8_t *)rss_key);
+ rss_getkey((uint8_t *)sc->vf_rss_key);
/* Now fill out hash function seeds */
- for (i = 0; i < 10; i++)
- IXGBE_WRITE_REG(hw, IXGBE_VFRSSRK(i), rss_key[i]);
+ for (u_int k = 0; k < nitems(sc->vf_rss_key); k++)
+ IXGBE_WRITE_REG(hw, IXGBE_VFRSSRK(k), sc->vf_rss_key[k]);
/* Set up the redirection table */
for (i = 0, j = 0; i < 64; i++, j++) {
@@ -1863,6 +1933,7 @@ ixv_initialize_rss_mapping(struct ixgbe_softc *sc)
"%s: RSS_HASHTYPE_RSS_UDP_IPV6_EX defined,"
" but not supported\n", __func__);
IXGBE_WRITE_REG(hw, IXGBE_VFMRQC, mrqc);
+ sc->vf_rss_mrqc = mrqc;
} /* ixv_initialize_rss_mapping */
#define BSIZEPKT_ROUNDUP ((1<<IXGBE_SRRCTL_BSIZEPKT_SHIFT)-1)
diff --git a/sys/dev/ixgbe/ixgbe.h b/sys/dev/ixgbe/ixgbe.h
index fb0ac15f5008..28d9adeeb7a5 100644
--- a/sys/dev/ixgbe/ixgbe.h
+++ b/sys/dev/ixgbe/ixgbe.h
@@ -435,6 +435,9 @@ struct ixgbe_softc {
bool vf_mcast_overflow_warned;
u8 vf_link_mbx_failures;
u8 vf_link_poll_tick;
+ /* VF-owned RSS programming, protected by the iflib context lock. */
+ u32 vf_rss_key[10];
+ u32 vf_rss_mrqc;
/* Info about the interface */
int advertise; /* link speeds */