git: f908fbb9b267 - main - iavf: Honor PF-negotiated RSS sizes
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 17 Sep 2026 00:20:29 UTC
The branch main has been updated by kbowling:
URL: https://cgit.FreeBSD.org/src/commit/?id=f908fbb9b2671cbc6cf366c8287899940e3c88b5
commit f908fbb9b2671cbc6cf366c8287899940e3c88b5
Author: Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-09-16 23:34:27 +0000
Commit: Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-09-17 00:20:23 +0000
iavf: Honor PF-negotiated RSS sizes
Use the key and lookup table lengths returned by GET_VF_RESOURCES when
configuring RSS through virtchnl, as DPDK does. The Windows E835 PF
advertises a 40-byte key and rejects our fixed 52-byte CONFIG_RSS_KEY
request, leaving receive traffic on queue zero.
Validate the negotiated lengths before constructing AdminQ messages and
publish the lookup table size to iflib. Preserve register-mode RSS
selection and its fixed hardware sizes. Use aligned, zero initialized
key storage so an RSS kernel's 40-byte key does not leave an uninitialized
tail when the PF requests 52 bytes.
Validation: normal and RSS enabled iavf module builds passed. On an E835
VF under Hyper-V Server 2025, repeated IPv4 and IPv6 receive tests used all
three configured guest RX queues in both transparent hn and non-transparent
lagg modes. The RSS key rejection disappeared, IPv4 transmit tests passed,
and no TX watchdog fired. Each traffic case used three runs of 16 streams.
Obtained from: DPDK (negotiated RSS sizing)
MFC after: 2 weeks
Sponsored by: BBOX.io
---
sys/dev/iavf/iavf_lib.c | 15 ++++++++++++++-
sys/dev/iavf/iavf_vc_common.c | 8 ++++----
sys/dev/iavf/if_iavf_iflib.c | 3 +++
3 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/sys/dev/iavf/iavf_lib.c b/sys/dev/iavf/iavf_lib.c
index e7cd9222bd68..9d6d64829268 100644
--- a/sys/dev/iavf/iavf_lib.c
+++ b/sys/dev/iavf/iavf_lib.c
@@ -520,6 +520,19 @@ iavf_get_vsi_res_from_vf_res(struct iavf_sc *sc)
device_t dev = sc->dev;
sc->vsi_res = NULL;
+ /* Bound PF-sized messages and preserve iflib's table-mask assumption. */
+ if ((sc->vf_res->vf_cap_flags & (VIRTCHNL_VF_OFFLOAD_RSS_REG |
+ VIRTCHNL_VF_OFFLOAD_RSS_PF)) == VIRTCHNL_VF_OFFLOAD_RSS_PF &&
+ (sc->vf_res->rss_key_size == 0 ||
+ sc->vf_res->rss_key_size > IAVF_RSS_KEY_SIZE ||
+ sc->vf_res->rss_lut_size == 0 ||
+ sc->vf_res->rss_lut_size > IAVF_AQ_BUF_SZ -
+ sizeof(struct virtchnl_rss_lut) + 1 ||
+ !powerof2(sc->vf_res->rss_lut_size))) {
+ device_printf(dev, "Unsupported PF RSS sizes: key %u lut %u\n",
+ sc->vf_res->rss_key_size, sc->vf_res->rss_lut_size);
+ return (EINVAL);
+ }
for (int i = 0; i < sc->vf_res->num_vsis; i++) {
/* XXX: We only use the first VSI we find */
@@ -1090,7 +1103,7 @@ iavf_config_rss_reg(struct iavf_sc *sc)
u32 lut = 0;
u64 set_hena = 0, hena;
int i, j, que_id;
- u32 rss_seed[IAVF_RSS_KEY_SIZE_REG];
+ u32 rss_seed[IAVF_RSS_KEY_SIZE_REG] = {0};
u32 rss_hash_config;
/* Don't set up RSS if using a single queue */
diff --git a/sys/dev/iavf/iavf_vc_common.c b/sys/dev/iavf/iavf_vc_common.c
index 37b085f7ef08..9470d764d610 100644
--- a/sys/dev/iavf/iavf_vc_common.c
+++ b/sys/dev/iavf/iavf_vc_common.c
@@ -724,17 +724,17 @@ iavf_config_rss_key(struct iavf_sc *sc)
{
struct virtchnl_rss_key *rss_key_msg;
int msg_len, key_length;
- u8 rss_seed[IAVF_RSS_KEY_SIZE];
+ u32 rss_seed[IAVF_RSS_KEY_SIZE_REG] = {0};
#ifdef RSS
/* Fetch the configured RSS key */
rss_getkey((uint8_t *) &rss_seed);
#else
- iavf_get_default_rss_key((u32 *)rss_seed);
+ iavf_get_default_rss_key(rss_seed);
#endif
/* Send the fetched key */
- key_length = IAVF_RSS_KEY_SIZE;
+ key_length = sc->vf_res->rss_key_size;
msg_len = sizeof(struct virtchnl_rss_key) + (sizeof(u8) * key_length) - 1;
rss_key_msg = (struct virtchnl_rss_key *)
malloc(msg_len, M_IAVF, M_NOWAIT | M_ZERO);
@@ -804,7 +804,7 @@ iavf_config_rss_lut(struct iavf_sc *sc)
u32 lut;
int i, que_id;
- lut_length = IAVF_RSS_VSI_LUT_SIZE;
+ lut_length = sc->vf_res->rss_lut_size;
msg_len = sizeof(struct virtchnl_rss_lut) + (lut_length * sizeof(u8)) - 1;
rss_lut_msg = (struct virtchnl_rss_lut *)
malloc(msg_len, M_IAVF, M_NOWAIT | M_ZERO);
diff --git a/sys/dev/iavf/if_iavf_iflib.c b/sys/dev/iavf/if_iavf_iflib.c
index 25aee839648a..0838eabbec1f 100644
--- a/sys/dev/iavf/if_iavf_iflib.c
+++ b/sys/dev/iavf/if_iavf_iflib.c
@@ -401,6 +401,9 @@ iavf_if_attach_pre(if_ctx_t ctx)
scctx->isc_tx_tso_size_max = IAVF_TSO_SIZE;
scctx->isc_tx_tso_segsize_max = IAVF_MAX_DMA_SEG_SIZE;
scctx->isc_rss_table_size = IAVF_RSS_VSI_LUT_SIZE;
+ if ((sc->vf_res->vf_cap_flags & (VIRTCHNL_VF_OFFLOAD_RSS_REG |
+ VIRTCHNL_VF_OFFLOAD_RSS_PF)) == VIRTCHNL_VF_OFFLOAD_RSS_PF)
+ scctx->isc_rss_table_size = sc->vf_res->rss_lut_size;
scctx->isc_capabilities = scctx->isc_capenable = IAVF_CAPS;
scctx->isc_tx_csum_flags = CSUM_OFFLOAD;