On Wed, Jul 08, 2026 at 07:19:26PM -0400, Dawid Wesierski wrote:
> Runtime queue setup on E810 VFs causes queue state corruption when
> queues are dynamically reconfigured while the hardware rate limiter
> is actively pacing TX queues. Queue configuration messages to the PF
> via virtchnl can race with ongoing TX operations, leading to undefined
> behavior.
>
> Rather than gating this behind a devarg that an application would have
> to know to set (and could just as easily avoid triggering the race by
> not calling rte_eth_{rx,tx}_queue_setup() on a running port), stop
> advertising RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP and
> RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP as soon as the application
> commits a per-queue bandwidth rte_tm hierarchy, i.e. as soon as the
> condition that causes the race actually exists. iavf_dev_info_get() is
> re-queried by the ethdev layer on every rx/tx_queue_setup() call, so
> this is enough for the generic layer to start rejecting runtime queue
> (re)configuration with -EBUSY once queue rate limiting is active, and
> to automatically allow it again once the rte_tm hierarchy is torn
> down.
>
> vf->qtc_map, already used elsewhere to look up a queue's TC mapping,
> is repurposed as the "queue bandwidth committed" signal since it's set
> by iavf_hierarchy_commit() exactly when a per-queue bandwidth mapping
> has been pushed to the PF, regardless of whether the port was stopped
> at the time. Fix two related issues found while making it load-bearing
> for this check:
>
> - iavf_hierarchy_commit() replaced vf->qtc_map on every successful
> commit without freeing the previous allocation, leaking memory.
> - vf->qtc_map was never released on VF teardown, so
> iavf_uninit_vf()/iavf_init_vf() (e.g. across a VF reset) could leave
> a stale pointer referencing freed unrelated memory, and the runtime
> queue setup capability would never be re-advertised after a reset.
>
> Both are fixed by freeing vf->qtc_map before replacing it in
> iavf_hierarchy_commit(), and freeing and clearing it in
> iavf_uninit_vf().
>
> Signed-off-by: Marek Kasiewicz <[email protected]>
> Signed-off-by: Dawid Wesierski <[email protected]>
> ---
Acked-by: Bruce Richardson <[email protected]>
However, this patch needs a rebase since some of the changes to cleanup
the qtc_map were made in a previously-applied patch.
> doc/guides/nics/intel_vf.rst | 10 ++++++++++
> doc/guides/rel_notes/release_26_07.rst | 3 +++
> drivers/net/intel/iavf/iavf_ethdev.c | 23 ++++++++++++++++++++---
> drivers/net/intel/iavf/iavf_tm.c | 2 ++
> 4 files changed, 35 insertions(+), 3 deletions(-)
>
> diff --git a/doc/guides/nics/intel_vf.rst b/doc/guides/nics/intel_vf.rst
> index e010f852cf..a47e3f6736 100644
> --- a/doc/guides/nics/intel_vf.rst
> +++ b/doc/guides/nics/intel_vf.rst
> @@ -150,6 +150,16 @@ Intel\ |reg| E800 Series Ethernet devices:
> for example: ``-a 18:00.0,quanta_size=2048``.
> The default value is 1024, and quanta size should be set as the product of
> 64 in legacy host interface mode.
>
> +* Runtime (post-start) Rx/Tx queue setup can race with the hardware Tx rate
> + limiter on E810 VFs and corrupt queue state.
> + Once an application commits a per-queue bandwidth ``rte_tm`` hierarchy,
> + the driver automatically stops advertising
> + ``RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP`` and
> + ``RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP``,
> + so ``rte_eth_rx_queue_setup()``/``rte_eth_tx_queue_setup()``
> + are rejected with ``-EBUSY`` on a running port for as long as queue rate
> + limiting is active.
> +
> * When using the Intel out-of-tree "ice" PF/kernel driver v1.13.7 or later,
> to create VFs with >16 queues (aka. "large VFs"),
> it is necessary to change the rss_lut_vf_addr setting in sysfs from the
> default of 64 to 512.
> diff --git a/doc/guides/rel_notes/release_26_07.rst
> b/doc/guides/rel_notes/release_26_07.rst
> index 6352ef27ab..7ea80112f4 100644
> --- a/doc/guides/rel_notes/release_26_07.rst
> +++ b/doc/guides/rel_notes/release_26_07.rst
> @@ -143,6 +143,9 @@ New Features
>
> * Added support for transmitting LLDP packets based on mbuf packet type.
> * Implemented AVX2 context descriptor transmit paths.
> + * Runtime Rx/Tx queue setup is now automatically disabled while a
> + per-queue bandwidth ``rte_tm`` hierarchy is committed, to avoid
> + corrupting queue state on E810 VFs.
>
> * **Updated Intel ice driver.**
>
> diff --git a/drivers/net/intel/iavf/iavf_ethdev.c
> b/drivers/net/intel/iavf/iavf_ethdev.c
> index 80e740ef29..5d0c361978 100644
> --- a/drivers/net/intel/iavf/iavf_ethdev.c
> +++ b/drivers/net/intel/iavf/iavf_ethdev.c
> @@ -1160,9 +1160,18 @@ iavf_dev_info_get(struct rte_eth_dev *dev, struct
> rte_eth_dev_info *dev_info)
> dev_info->reta_size = vf->vf_res->rss_lut_size;
> dev_info->flow_type_rss_offloads = IAVF_RSS_OFFLOAD_ALL;
> dev_info->max_mac_addrs = IAVF_NUM_MACADDR_MAX;
> - dev_info->dev_capa =
> - RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
> - RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP;
> + /*
> + * Runtime queue setup can race with the hardware Tx rate limiter on
> + * E810 VFs and corrupt queue state. Once a per-queue bandwidth rte_tm
> + * hierarchy has been committed (vf->qtc_map is set), stop advertising
> + * the capability so the ethdev layer rejects further
> rx/tx_queue_setup()
> + * calls on a running port with -EBUSY. The capability is re-advertised
> + * automatically once the rte_tm hierarchy is torn down.
> + */
> + if (vf->qtc_map == NULL)
> + dev_info->dev_capa =
> + RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
> + RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP;
> dev_info->rx_offload_capa =
> RTE_ETH_RX_OFFLOAD_VLAN_STRIP |
> RTE_ETH_RX_OFFLOAD_QINQ_STRIP |
> @@ -2756,6 +2765,14 @@ iavf_uninit_vf(struct rte_eth_dev *dev)
> rte_free(vf->qos_cap);
> vf->qos_cap = NULL;
>
> + /*
> + * Drop the committed queue/TC bandwidth mapping so a subsequent
> + * iavf_init_vf() (e.g. after a device reset) starts with runtime
> + * Rx/Tx queue setup available again (see iavf_dev_info_get()).
> + */
> + rte_free(vf->qtc_map);
> + vf->qtc_map = NULL;
> +
> rte_free(vf->rss_lut);
> vf->rss_lut = NULL;
> rte_free(vf->rss_key);
> diff --git a/drivers/net/intel/iavf/iavf_tm.c
> b/drivers/net/intel/iavf/iavf_tm.c
> index e3492ec491..c9d856e937 100644
> --- a/drivers/net/intel/iavf/iavf_tm.c
> +++ b/drivers/net/intel/iavf/iavf_tm.c
> @@ -905,6 +905,8 @@ static int iavf_hierarchy_commit(struct rte_eth_dev *dev,
> if (ret_val)
> goto fail_clear;
>
> + /* replace the previously committed mapping, if any */
> + rte_free(vf->qtc_map);
> vf->qtc_map = qtc_map;
> if (adapter->stopped == 1)
> vf->tm_conf.committed = true;
> --
> 2.47.3
>