DPDK-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* RE: DPDK release candidate 26.07-rc3
From: Xu, HailinX @ 2026-07-20  9:58 UTC (permalink / raw)
  To: Thomas Monjalon, dpdk
  Cc: Hosamani, Manjunathgouda, Puttaswamy, Rajesh T, Richardson, Bruce,
	Mcnamara, John
In-Reply-To: <74T0wdLsQL6DTJtar0xt1g@monjalon.net>

> -----Original Message-----
> From: Thomas Monjalon <thomas@monjalon.net>
> Sent: Monday, July 13, 2026 4:12 AM
> To: announce@dpdk.org
> Subject: DPDK release candidate 26.07-rc3
> 
> A new DPDK release candidate is ready for testing:
> 	https://git.dpdk.org/dpdk/tag/?id=v26.07-rc3
> 
> There are 88 new patches in this snapshot.
> 
> Release notes:
> 	https://doc.dpdk.org/guides/rel_notes/release_26_07.html
> 
> Please test and report issues on bugs.dpdk.org.
> 
> You may share some release validation results by replying to this message at
> dev@dpdk.org and by adding tested hardware in the release notes.
> 
> Only documentation changes and critical fixes are expected at this stage.
> 
> Thank you everyone
> 
Update the test status for Intel part. dpdk26.07-rc3 all validation test done. found 1 new issue.

New issues:
  1. vf_vlan/test_vf_vlan_strip_avx512: Failed to strip vlan packet!!!            -> has fix patch
      https://patches.dpdk.org/project/dpdk/patch/20260715225234.482186-1-anurag.mandal@intel.com

* Build & CFLAG compile: cover the build test with latest GCC/Clang version on the following OS(all passed)
  - Ubuntu25.10/Ubuntu26.04
  - RHEL9.6/RHEL10
  - Fedora43
  - FreeBSD15.0
  - SUSE16
  - OpenAnolis8.10
  - OpenEuler24.04-SP2
  - AzureLinux3.0

* Function tests: All test done and found 1 issues.
  - ICE-(E810, E825, E830, E835, E2100) PF/VF: test scenarios including basic/RTE_FLOW/TSO/Jumboframe/checksum offload/mac_filter/VLAN/VXLAN/RSS/Switch/Package Management/Flow Director/Advanced Tx/Advanced RSS/ACL/DCF/Flexible Descriptor, etc.
  - i40E-(XXV710, X722) PF/VF: test scenarios including basic/RTE_FLOW/TSO/Jumboframe/checksum offload/mac_filter/VLAN/VXLAN/RSS, etc. 
  - IXGBE-(E610, X550) PF/VF: test scenarios including basic/TSO/Jumboframe/checksum offload/mac_filter/VLAN/VXLAN/RSS, etc. 
  - IGC-(i226) PF: test scenarios including basic/RTE_FLOW/TSO/Jumboframe/checksum offload/mac_filter/VLAN/VXLAN/RSS, etc.
  - IPsec: test scenarios including ipsec/ipsec-gw/ipsec library basic test - QAT&SW/FIB library, etc.
  - Virtio: both function and performance test are covered. Such as PVP/Virtio_loopback/virtio-user loopback/virtio-net VM2VM perf testing/VMAWARE ESXI 9.0, etc.
  - Cryptodev: test scenarios including Cryptodev API testing/CompressDev ISA-L/QAT/ZLIB PMD Testing/FIPS, etc.
  - Other: test scenarios including AF_XDP, Power, CBDMA, DSA

* Performance test: All test done and passed
  - Thoughput Performance
  - Cryptodev Latency
  - PF/VF NIC single core
  - XXV710/E810/E825/E2100 NIC Performance


Regards,
Xu, Hailin

^ permalink raw reply

* Re: [RFC 0/5] fib: shared and resizable tbl8 pool
From: Maxime Leroy @ 2026-07-20 10:09 UTC (permalink / raw)
  To: Medvedkin, Vladimir; +Cc: rjarry@redhat.com, dev@dpdk.org
In-Reply-To: <BL0PR11MB2993F871DC00713CA2ABF51296C72@BL0PR11MB2993.namprd11.prod.outlook.com>

Hi Vladimir,

On Thu, Jul 16, 2026 at 4:25 PM Medvedkin, Vladimir
<vladimir.medvedkin@intel.com> wrote:
>
> Hi Maxime,
>
> Thanks for working on this RFC. I have mixed feelings about the series. Here some conceptual thoughts:
>
> On the positive side, I like the consolidation of the common tbl8 code between the ipv4 dir24_8 and ipv6 trie implementations. Removing duplicated code is always good. General approach to the implementation is good too, no extra indirection for TBL8 on lookup, backward compatibility with the current "legacy" way to allocate tbl8 (although needs to carefully zero-init config).
>
> However, I have concerns about both the scope of the public API and the resizing implementation.
>
> First, I am not yet convinced that this feature belongs in the public FIB API, TBL8 is an implementation detail of the currently supported dir24_8 and trie backends. This series exposes part of internal algorithms to a public as a generic FIB resource, although a future FIB algorithm may have nothing to do with 8-bit stride trie level.

tbl8 is already public and users already have to reason about it:
num_tbl8 is in the merged config (rte_fib.h / rte_fib6.h) and must be
sized at create, and sizing it from a route count is not possible
(only routes longer than /24 consume groups, nested routes share
levels, byte-aligned prefixes need one extra transient group; for the
same route count the need ranges from 0 to 13 * disjoint deep routes
for IPv6).

Robin Jarry's in-flight RFC adding tbl8 usage statistics is there for
the same reason. So the resizable pool makes an already-public,
unsizable knob usable, which stands even for a single FIB.

> As discussed in the other thread, the main use case appears to be sharing tbl8 capacity between many VRFs represented by separate FIB instances. In my view, separate FIB instance per VRF is not necessarily the best design. A shared TBL8 pool mitigates part of a problem, but does not solve the problem entirely. I understand that the previous RFC for multiVRF support in FIB, while having shared TBL8 internally, have problems with high memory consumption. I am currently working on v2, so I suggest returning to the shared pool discussion after that series is available.

Separate FIB instance per VRF is a legitimate model (isolation,
per-VRF lifecycle and config) and is what applications use today; and
a shared tbl8 pool is the mechanism both designs need underneath, your
previous multi-VRF RFC already had shared TBL8 internally.

To concede a point: a single-FIB multi-VRF lookup could be useful to
grout, but its advantage is an AVX-512 optimization on x86, not what
grout relies on, and an architecture-specific performance optimization
should not define the FIB API.

I would also rather not hold a ready, opt-in feature indefinitely on a
v2 with no posted schedule. Being able to size a FIB correctly,
without silently running out of or leaking tbl8, is a foundational
need for any real router, not a niche one; a single known user only
reflects that the capability does not exist upstream yet.

> So, on one hand, it addresses a real use case, and a useful feature should not be rejected merely because it initially has only one known user. On the other hand, if the feature remains specific to a single application, the additional API and implementation complexity will be carried by the library and exposed to every FIB user. It may also make the API more difficult to understand by presenting TBL8 pools as a general FIB concept. Maybe, if we decide to add this after multi VRF rework, it is worth to add this as an internal API (not as a generic FIB API)? I'd like to hear more opinions on this.
>
> Second, regarding resizing, I don't think the current implementation is applicable.
> For example, build_common_root() computes tbl_ptr from its local cur_tbl. After the first level, cur_tbl can point into the current tbl8. A subsequent tbl8_alloc() may resize the pool, publish the new base, wait for an RCU grace period, and free the old allocation. Control then returns to build_common_root(), which writes through the old tbl_ptr. Same problem exists in other places like in write_edge().

Correct, the mid-insert resize is a use-after-free:
build_common_root() and write_edge() cache raw pointers into
pool->tbl8 across tbl8_alloc(), which can realloc and free the old
base.

But it is one symptom of a wider gap that is already in upstream,
independent of this series: the trie install is not safe against a
tbl8 allocation failure at all.

On current main, when tbl8_alloc() fails mid install_to_dp(), the
group already taken is leaked and the tbl24 entry is left dangling;
trie_modify() rolls back only the RIB node, never the dataplane. A
failed byte-aligned add on a tight pool then wrongly refuses a later
add that would fit. I filed it with a reproducer (fib6 autotest, fails
on main): https://bugs.dpdk.org/show_bug.cgi?id=1970

Two consequences for the resize discussion:
- the mid-install-failure fragility is not introduced by the shared or
resizable pool, it predates it.
- memory is finite, so a resizable pool eventually cannot grow and
hits the very same mid-install failure at max_tbl8 or on -ENOMEM.
Moving growth before the insert removes the UAF, but not this.

So the correct fix is to make the install atomic, not to reserve a
guessed amount: install_to_dp() should allocate every group it needs
before publishing any of them (freeing the unpublished ones on
failure), or reserve the exact peak up front.

That closes bug 1970 and removes the mid-insert resize hazard for the
pool in the same place. A rollback-after-publish approach is not
viable: readers are lock-free (RCU), so undoing already-published
writes would expose an inconsistent dataplane during the rollback
window.

I would rather see 1970 fixed in the trie first; the pool resize then
sits cleanly on top instead of trying to work around a non-atomic
install.

> I'm also not convinced in grow-only resizing without shrinking.
>

Grow-only is deliberate and already a significant improvement on its
own: today the only way to enlarge a FIB's tbl8 capacity is to destroy
and recreate it and reinsert every route, which is not usable on a
live dataplane. Grow-only removes that, at runtime, without
disruption.

Shrink is intentionally out of scope, as the cover letter states. With
the current LIFO free-list the freed groups do not form a contiguous
tail, so shrinking would be best-effort at best: a single in-use group
near the top pins the whole tail. Doing it properly needs a different
allocation strategy to avoid those holes (e.g. a min-heap of free
indices) plus compaction, and compaction relocates live groups and
rewrites every reference to them, i.e. the same pointer-invalidation
hazard as above. That is future work, an addition on top, not a
prerequisite for grow-only to be useful.

Regards,

Maxime

>
> -----Original Message-----
> From: Maxime Leroy <maxime@leroys.fr>
> Sent: Thursday, July 16, 2026 8:31 AM
> To: Medvedkin, Vladimir <vladimir.medvedkin@intel.com>
> Cc: rjarry@redhat.com; dev@dpdk.org
> Subject: Re: [RFC 0/5] fib: shared and resizable tbl8 pool
>
> Hi Vladimir,
>
> On Tue, Mar 31, 2026 at 11:41 PM Maxime Leroy <maxime@leroys.fr> wrote:
> >
> > This RFC proposes an optional shared tbl8 pool for FIB/FIB6, to
> > address the difficulty of sizing num_tbl8 upfront.
> >
> > In practice, tbl8 usage depends on prefix distribution and evolves
> > over time. In multi-VRF environments, some VRFs are elephants (full
> > table, thousands of tbl8 groups) while others consume very little
> > (mostly /24 or shorter). Per-FIB sizing forces each instance to
> > provision for its worst case, leading to significant memory waste.
> >
> > A shared pool solves this: all FIBs draw from the same tbl8 memory, so
> > elephant VRFs use what they need while light VRFs cost almost nothing.
> > The sharing granularity is flexible: one pool per VRF, per address
> > family, a global pool, or no sharing at all.
> >
> > This series adds:
> >
> >   - A shared tbl8 pool, replacing per-backend allocation
> >     (bitmap in dir24_8, stack in trie) with a common
> >     refcounted O(1) stack allocator.
> >   - An optional resizable mode (grow via alloc + copy + QSBR
> >     synchronize), removing the need to guess peak usage at
> >     creation time.
> >   - A stats API (rte_fib_tbl8_pool_get_stats()) exposing
> >     used/total/max counters.
> >
> > All features are opt-in:
> >
> >   - Existing per-FIB allocation remains the default.
> >   - Shared pool is enabled via the tbl8_pool config field.
> >   - Resize is enabled by setting max_tbl8 > 0 with QSBR.
> >
> > Shrinking (reducing pool capacity after usage drops) is not part of
> > this series. It would always be best-effort since there is no
> > compaction: if any tbl8 group near the end of the pool is still in
> > use, the pool cannot shrink. The current LIFO free-list makes this
> > less likely by immediately reusing freed high indices, which prevents
> > a contiguous free tail from forming. A different allocation strategy
> > (e.g. a min-heap favoring low indices) could improve shrink
> > opportunities, but is better addressed separately.
> >
> > A working integration in Grout is available:
> > https://github.com/DPDK/grout/pull/581 (still a draft)
> >
> > Maxime Leroy (5):
> >   test/fib6: zero-initialize config struct
> >   fib: share tbl8 definitions between fib and fib6
> >   fib: add shared tbl8 pool
> >   fib: add resizable tbl8 pool
> >   fib: add tbl8 pool stats API
> >
> >  app/test/test_fib6.c        |  10 +-
> >  lib/fib/dir24_8.c           | 234 ++++++++++---------------
> >  lib/fib/dir24_8.h           |  17 +-
> >  lib/fib/fib_tbl8.h          |  50 ++++++
> >  lib/fib/fib_tbl8_pool.c     | 337 ++++++++++++++++++++++++++++++++++++
> >  lib/fib/fib_tbl8_pool.h     | 113 ++++++++++++
> >  lib/fib/meson.build         |   5 +-
> >  lib/fib/rte_fib.h           |   3 +
> >  lib/fib/rte_fib6.h          |   3 +
> >  lib/fib/rte_fib_tbl8_pool.h | 149 ++++++++++++++++
> >  lib/fib/trie.c              | 230 +++++++++---------------
> >  lib/fib/trie.h              |  15 +-
> >  12 files changed, 844 insertions(+), 322 deletions(-)  create mode
> > 100644 lib/fib/fib_tbl8.h  create mode 100644 lib/fib/fib_tbl8_pool.c
> > create mode 100644 lib/fib/fib_tbl8_pool.h  create mode 100644
> > lib/fib/rte_fib_tbl8_pool.h
> >
>
> I’m following up on this RFC, which I sent at the end of March. Could you please review it and let me know whether you have any feedback or concerns?
>
> Thanks,
>
> -------------------------------
> Maxime Leroy
> maxime@leroys.fr



-- 
-------------------------------
Maxime Leroy
maxime@leroys.fr

^ permalink raw reply

* AVX512 block copy performance?
From: Morten Brørup @ 2026-07-20 10:10 UTC (permalink / raw)
  To: bruce.richardson, Konstantin Ananyev, Vipin Varghese
  Cc: dev, Leyi Rong, qi.z.zhang, wenzhuo.lu, ferruh.yigit,
	bruce.richardson, beilei.xing
In-Reply-To: <20210114063951.2580-4-leyi.rong@intel.com>

> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Leyi Rong
> Sent: Thursday, 14 January 2021 07.40
> 
> Optimize Tx path by using AVX512 instructions and vectorize the
> tx free bufs process.
> 
> Signed-off-by: Leyi Rong <leyi.rong@intel.com>
> Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> ---

[...]

> +static __rte_always_inline int
> +i40e_tx_free_bufs_avx512(struct i40e_tx_queue *txq)
> +{
> +	struct i40e_vec_tx_entry *txep;
> +	uint32_t n;
> +	uint32_t i;
> +	int nb_free = 0;
> +	struct rte_mbuf *m, *free[RTE_I40E_TX_MAX_FREE_BUF_SZ];
> +
> +	/* check DD bits on threshold descriptor */
> +	if ((txq->tx_ring[txq->tx_next_dd].cmd_type_offset_bsz &
> +			rte_cpu_to_le_64(I40E_TXD_QW1_DTYPE_MASK)) !=
> +			rte_cpu_to_le_64(I40E_TX_DESC_DTYPE_DESC_DONE))
> +		return 0;
> +
> +	n = txq->tx_rs_thresh;
> +
> +	 /* first buffer to free from S/W ring is at index
> +	  * tx_next_dd - (tx_rs_thresh-1)
> +	  */
> +	txep = (void *)txq->sw_ring;
> +	txep += txq->tx_next_dd - (n - 1);
> +
> +	if (txq->offloads & DEV_TX_OFFLOAD_MBUF_FAST_FREE && (n & 31) ==
> 0) {
> +		struct rte_mempool *mp = txep[0].mbuf->pool;
> +		void **cache_objs;
> +		struct rte_mempool_cache *cache =
> rte_mempool_default_cache(mp,
> +				rte_lcore_id());
> +
> +		if (!cache || cache->len == 0)
> +			goto normal;
> +
> +		cache_objs = &cache->objs[cache->len];
> +
> +		if (n > RTE_MEMPOOL_CACHE_MAX_SIZE) {
> +			rte_mempool_ops_enqueue_bulk(mp, (void *)txep, n);
> +			goto done;
> +		}
> +
> +		/* The cache follows the following algorithm
> +		 *   1. Add the objects to the cache
> +		 *   2. Anything greater than the cache min value (if it
> +		 *   crosses the cache flush threshold) is flushed to the
> ring.
> +		 */
> +		/* Add elements back into the cache */
> +		uint32_t copied = 0;
> +		/* n is multiple of 32 */
> +		while (copied < n) {
> +			const __m512i a = _mm512_load_si512(&txep[copied]);
> +			const __m512i b = _mm512_load_si512(&txep[copied +
> 8]);
> +			const __m512i c = _mm512_load_si512(&txep[copied +
> 16]);
> +			const __m512i d = _mm512_load_si512(&txep[copied +
> 24]);
> +
> +			_mm512_storeu_si512(&cache_objs[copied], a);
> +			_mm512_storeu_si512(&cache_objs[copied + 8], b);
> +			_mm512_storeu_si512(&cache_objs[copied + 16], c);
> +			_mm512_storeu_si512(&cache_objs[copied + 24], d);
> +			copied += 32;
> +		}

Do you have any indications about how this copy loop performs, compared to e.g. the 64-byte block copy in rte_memcpy() [1]?

[1]: https://github.com/DPDK/dpdk/blob/v26.07-rc4/lib/eal/x86/include/rte_memcpy.h#L657

I'm wondering if it would be worth adding something similar to the mempool library, for speeding up mbuf alloc/free.

> +		cache->len += n;
> +
> +		if (cache->len >= cache->flushthresh) {
> +			rte_mempool_ops_enqueue_bulk
> +				(mp, &cache->objs[cache->size],
> +				cache->len - cache->size);
> +			cache->len = cache->size;
> +		}
> +		goto done;
> +	}
> +
> +normal:

^ permalink raw reply

* Re: AVX512 block copy performance?
From: Bruce Richardson @ 2026-07-20 10:19 UTC (permalink / raw)
  To: Morten Brørup
  Cc: Konstantin Ananyev, Vipin Varghese, dev, Leyi Rong, qi.z.zhang,
	wenzhuo.lu, ferruh.yigit, beilei.xing
In-Reply-To: <98CBD80474FA8B44BF855DF32C47DC35F6597E@smartserver.smartshare.dk>

On Mon, Jul 20, 2026 at 12:10:34PM +0200, Morten Brørup wrote:
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Leyi Rong
> > Sent: Thursday, 14 January 2021 07.40
> > 
> > Optimize Tx path by using AVX512 instructions and vectorize the
> > tx free bufs process.
> > 
> > Signed-off-by: Leyi Rong <leyi.rong@intel.com>
> > Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> > ---
> 
> [...]
> 
> > +static __rte_always_inline int
> > +i40e_tx_free_bufs_avx512(struct i40e_tx_queue *txq)
> > +{
> > +	struct i40e_vec_tx_entry *txep;
> > +	uint32_t n;
> > +	uint32_t i;
> > +	int nb_free = 0;
> > +	struct rte_mbuf *m, *free[RTE_I40E_TX_MAX_FREE_BUF_SZ];
> > +
> > +	/* check DD bits on threshold descriptor */
> > +	if ((txq->tx_ring[txq->tx_next_dd].cmd_type_offset_bsz &
> > +			rte_cpu_to_le_64(I40E_TXD_QW1_DTYPE_MASK)) !=
> > +			rte_cpu_to_le_64(I40E_TX_DESC_DTYPE_DESC_DONE))
> > +		return 0;
> > +
> > +	n = txq->tx_rs_thresh;
> > +
> > +	 /* first buffer to free from S/W ring is at index
> > +	  * tx_next_dd - (tx_rs_thresh-1)
> > +	  */
> > +	txep = (void *)txq->sw_ring;
> > +	txep += txq->tx_next_dd - (n - 1);
> > +
> > +	if (txq->offloads & DEV_TX_OFFLOAD_MBUF_FAST_FREE && (n & 31) ==
> > 0) {
> > +		struct rte_mempool *mp = txep[0].mbuf->pool;
> > +		void **cache_objs;
> > +		struct rte_mempool_cache *cache =
> > rte_mempool_default_cache(mp,
> > +				rte_lcore_id());
> > +
> > +		if (!cache || cache->len == 0)
> > +			goto normal;
> > +
> > +		cache_objs = &cache->objs[cache->len];
> > +
> > +		if (n > RTE_MEMPOOL_CACHE_MAX_SIZE) {
> > +			rte_mempool_ops_enqueue_bulk(mp, (void *)txep, n);
> > +			goto done;
> > +		}
> > +
> > +		/* The cache follows the following algorithm
> > +		 *   1. Add the objects to the cache
> > +		 *   2. Anything greater than the cache min value (if it
> > +		 *   crosses the cache flush threshold) is flushed to the
> > ring.
> > +		 */
> > +		/* Add elements back into the cache */
> > +		uint32_t copied = 0;
> > +		/* n is multiple of 32 */
> > +		while (copied < n) {
> > +			const __m512i a = _mm512_load_si512(&txep[copied]);
> > +			const __m512i b = _mm512_load_si512(&txep[copied +
> > 8]);
> > +			const __m512i c = _mm512_load_si512(&txep[copied +
> > 16]);
> > +			const __m512i d = _mm512_load_si512(&txep[copied +
> > 24]);
> > +
> > +			_mm512_storeu_si512(&cache_objs[copied], a);
> > +			_mm512_storeu_si512(&cache_objs[copied + 8], b);
> > +			_mm512_storeu_si512(&cache_objs[copied + 16], c);
> > +			_mm512_storeu_si512(&cache_objs[copied + 24], d);
> > +			copied += 32;
> > +		}
> 
> Do you have any indications about how this copy loop performs, compared to e.g. the 64-byte block copy in rte_memcpy() [1]?
> 
> [1]: https://github.com/DPDK/dpdk/blob/v26.07-rc4/lib/eal/x86/include/rte_memcpy.h#L657
> 
> I'm wondering if it would be worth adding something similar to the mempool library, for speeding up mbuf alloc/free.
> 
Possibly, but you also need to put in an additional checks for AVX-512 at
runtime. The reason that we are doing the 64-byte copies explicitly here is
that we are already in a function which is already using AVX-512 and for
which we have no penalty or branch to check for its presence. The check is
done at function pointer selection time for us. For inline copies, you may
have a cost for that, though hopefully it could be very minimal. Only way to
know is to test it out!

/Bruce

^ permalink raw reply

* RE: [PATCH] net/iavf: harden reset recovery and data path on link flap
From: Loftus, Ciara @ 2026-07-20 10:29 UTC (permalink / raw)
  To: Mandal, Anurag, dev@dpdk.org; +Cc: Richardson, Bruce, Medvedkin, Vladimir
In-Reply-To: <20260717211526.716220-1-anurag.mandal@intel.com>

> Subject: [PATCH] net/iavf: harden reset recovery and data path on link flap
> 
> During PF-initiated reset or a remote/ToR switch link-flap, the VF
> might miss the reset event, race on the no_poll gate, leak in-flight
> Tx descriptors, and stay down if dev_start ran before the PF VSI was
> ready.
> 
> This patch builds on the earlier reset-recovery fixes with the
> following:
> 
> - Reset detection: complement the ARQLEN1 check with VFGEN_RSTAT
>   (VIRTCHNL_VFR_INPROGRESS) and poll at a 5 ms interval, matching the
>   kernel iavf driver, so fast ARQ flips are not missed. When the VFR
>   is still not observed, recover anyway instead of bailing out,
>   keeping PF and VF state in sync.
> 
> - no_poll: make the flag atomic (RTE_ATOMIC) with release/acquire
>   ordering so the data-plane lcores observe gate changes reliably.
> 
> - Tx drain: add iavf_dev_tx_drain() to flush in-flight Tx descriptors
>   on link-down and impending-reset events before teardown, preventing
>   MDD events and descriptor leaks.
> 
> - Deferred start: when dev_start fails during recovery (PF VSI inactive),
>   defer it via start_pending and resume on the next link-up event so the
>   VF comes back without manual intervention.
> 
> - AdminQ: discard zeroed (opcode 0) descriptors seen during PF-initiated
>   resets to avoid the "Request 0 is not supported" log flood.

Could you consider splitting this patch into a series of smaller patches.
There are several independent fixes/improvements here but I think it would
be better to split them out.
Also consider if a Fixes tag is relevant for any of them.

> 
> Signed-off-by: Anurag Mandal <anurag.mandal@intel.com>
> ---
>  drivers/net/intel/iavf/iavf.h        |  4 +-
>  drivers/net/intel/iavf/iavf_ethdev.c | 88 +++++++++++++++++++++++-----
>  drivers/net/intel/iavf/iavf_rxtx.c   | 77 +++++++++++++++++++++++-
>  drivers/net/intel/iavf/iavf_rxtx.h   |  6 ++
>  drivers/net/intel/iavf/iavf_vchnl.c  | 40 ++++++++++++-
>  5 files changed, 195 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/net/intel/iavf/iavf.h b/drivers/net/intel/iavf/iavf.h
> index 293adaf6c9..037bc8436f 100644
> --- a/drivers/net/intel/iavf/iavf.h
> +++ b/drivers/net/intel/iavf/iavf.h
> @@ -293,6 +293,7 @@ struct iavf_info {
>  	bool in_reset_recovery;
>  	bool reset_pending;
>  	bool pf_reset_in_progress;
> +	bool start_pending;
> 
>  	uint32_t ptp_caps;
>  	rte_spinlock_t phc_time_aq_lock;
> @@ -391,7 +392,7 @@ struct iavf_adapter {
>  	alignas(RTE_CACHE_LINE_MIN_SIZE) uint32_t
> ptype_tbl[IAVF_MAX_PKT_TYPE];
>  	bool stopped;
>  	bool closed;
> -	bool no_poll;
> +	RTE_ATOMIC(bool)no_poll;
>  	enum iavf_rx_func_type rx_func_type;
>  	enum iavf_tx_func_type tx_func_type;
>  	uint16_t fdir_ref_cnt;
> @@ -533,4 +534,5 @@ void iavf_handle_hw_reset(struct rte_eth_dev *dev,
> bool vf_initiated_reset);
>  void iavf_set_no_poll(struct iavf_adapter *adapter, bool link_change);
>  bool is_iavf_supported(struct rte_eth_dev *dev);
>  void iavf_hash_uninit(struct iavf_adapter *ad);
> +void iavf_resume_pending_start(struct rte_eth_dev *dev);
>  #endif /* _IAVF_ETHDEV_H_ */
> diff --git a/drivers/net/intel/iavf/iavf_ethdev.c
> b/drivers/net/intel/iavf/iavf_ethdev.c
> index d601ec3b6a..eaabef41ed 100644
> --- a/drivers/net/intel/iavf/iavf_ethdev.c
> +++ b/drivers/net/intel/iavf/iavf_ethdev.c
> @@ -3212,7 +3212,9 @@ iavf_dev_close(struct rte_eth_dev *dev)
>  	/* remove RSS configuration */
>  	iavf_hash_uninit(adapter);
> 
> -	iavf_flow_flush(dev, NULL);
> +	/* Skip the virtchnl-emitting teardow on a PF-initiated reset */
> +	if (!vf->pf_reset_in_progress)
> +		iavf_flow_flush(dev, NULL);

This change for instance is probably worthy of a Fixes tag since we should
never send virtchnl messages during a PF initiated reset recovery.

>  	iavf_flow_uninit(adapter);
> 
>  	/*
> @@ -3335,8 +3337,27 @@ iavf_dev_reset(struct rte_eth_dev *dev)
>  static inline bool
>  iavf_is_reset(struct iavf_hw *hw)
>  {
> -	return !(IAVF_READ_REG(hw, IAVF_VF_ARQLEN1) &
> -		IAVF_VF_ARQLEN1_ARQENABLE_MASK);
> +	uint32_t rstat;
> +
> +	/* ARQ has been disabled by the PF as part of the VFR. */
> +	if (!(IAVF_READ_REG(hw, IAVF_VF_ARQLEN1) &
> +		IAVF_VF_ARQLEN1_ARQENABLE_MASK))
> +		return true;
> +
> +	/*
> +	 * VFGEN_RSTAT reports VIRTCHNL_VFR_INPROGRESS.
> +	 * At times, the PF flips ARQENABLE so quickly
> +	 * around a VFR that the ARQLEN1 sample window
> +	 * misses it. Using VFGEN_RSTAT, as a
> +	 * complementary indicator, help to prevent
> +	 * from declaring "reset not start" when a

Here you refer to the "reset not start" log however this log is removed
later in the patch so the comment is no longer relevant.

> +	 * reset really did happen.
> +	 */
> +	rstat = (IAVF_READ_REG(hw, IAVF_VFGEN_RSTAT) &
> +		 IAVF_VFGEN_RSTAT_VFR_STATE_MASK) >>
> +		IAVF_VFGEN_RSTAT_VFR_STATE_SHIFT;
> +
> +	return rstat == VIRTCHNL_VFR_INPROGRESS;
>  }
> 
>  static bool
> @@ -3345,11 +3366,17 @@ iavf_is_reset_detected(struct iavf_adapter
> *adapter)
>  	struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(adapter);
>  	int i;
> 
> -	/* poll until we see the reset actually happen */
> -	for (i = 0; i < IAVF_RESET_DETECTED_CNT; i++) {
> +	/*
> +	 * Poll until we see the reset actually happen.
> +	 * Poll every 5 ms to catch the fast ARQ flips.
> +	 * Total wait time is unchanged (~10 s) since

The statement "wait time is unchanged" is referring back to the old code from
the new code which is confusing. That type of comment belongs in the commit
message, where both the old and new code can be referenced.

> +	 * the count is scale up by the same factor
> +	 * that the per-iteration delay shrinks.
> +	 */
> +	for (i = 0; i < IAVF_RESET_DETECTED_CNT * 4; i++) {
>  		if (iavf_is_reset(hw))
>  			return true;
> -		rte_delay_ms(20);
> +		rte_delay_us(5000);
>  	}
> 
>  	return false;
> @@ -3400,14 +3427,13 @@ iavf_handle_hw_reset(struct rte_eth_dev *dev,
> bool vf_initiated_reset)
>  		if (!dev->data->dev_started)
>  			return;
> 
> -		if (!iavf_is_reset_detected(adapter)) {
> -			PMD_DRV_LOG(DEBUG, "reset not start");
> -			return;
> -		}
> +		if (!iavf_is_reset_detected(adapter))
> +			PMD_DRV_LOG(WARNING, "VFR not observed;
> recovering anyway");
>  	}
> 
>  	vf->in_reset_recovery = true;
>  	vf->pf_reset_in_progress = !vf_initiated_reset;
> +	vf->start_pending = false;
>  	iavf_set_no_poll(adapter, false);
> 
>  	/* Call the pre reset callback */
> @@ -3428,10 +3454,17 @@ iavf_handle_hw_reset(struct rte_eth_dev *dev,
> bool vf_initiated_reset)
>  	if (!vf_initiated_reset || restart_device) {
>  		/* start the device */
>  		ret = iavf_dev_start(dev);
> -		if (ret)
> -			goto error;
> -
> -		dev->data->dev_started = 1;
> +		if (ret == 0) {
> +			dev->data->dev_started = 1;
> +		} else {
> +			PMD_DRV_LOG(WARNING,
> +				    "dev_start failed during reset recovery
> (rc=%d);"
> +				    "deferring to next link-up event",
> +				    ret);
> +			vf->start_pending = true;
> +			dev->data->dev_started = 0;
> +			ret = 0;
> +		}
>  	}
> 
>  	/* Restore settings after the reset */
> @@ -3573,9 +3606,13 @@ void
>  iavf_set_no_poll(struct iavf_adapter *adapter, bool link_change)
>  {
>  	struct iavf_info *vf = &adapter->vf;
> +	bool no_poll;
> 
> -	adapter->no_poll = (link_change & !vf->link_up) ||
> +	no_poll = (link_change & !vf->link_up) ||
>  		vf->vf_reset || vf->in_reset_recovery;
> +
> +	rte_atomic_store_explicit(&adapter->no_poll, no_poll,
> +				  rte_memory_order_release);
>  }
> 
>  static int
> @@ -3645,6 +3682,27 @@ bool is_iavf_supported(struct rte_eth_dev *dev)
>  	return !strcmp(dev->device->driver->name,
> rte_iavf_pmd.driver.name);
>  }
> 
> +void
> +iavf_resume_pending_start(struct rte_eth_dev *dev)
> +{
> +	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data-
> >dev_private);
> +	int ret;
> +
> +	if (!(vf->link_up && vf->start_pending))
> +		return;
> +
> +	PMD_DRV_LOG(DEBUG, "PF link back up; resuming deferred
> dev_start");
> +	ret = iavf_dev_start(dev);
> +	if (ret == 0) {
> +		dev->data->dev_started = 1;
> +		vf->start_pending = false;
> +	} else {
> +		PMD_DRV_LOG(ERR,
> +			    "deferred dev_start failed (ret=%d); will retry on
> next link-up",
> +			    ret);
> +	}
> +}
> +
>  RTE_PMD_REGISTER_PCI(net_iavf, rte_iavf_pmd);
>  RTE_PMD_REGISTER_PCI_TABLE(net_iavf, pci_id_iavf_map);
>  RTE_PMD_REGISTER_KMOD_DEP(net_iavf, "* igb_uio | vfio-pci");
> diff --git a/drivers/net/intel/iavf/iavf_rxtx.c
> b/drivers/net/intel/iavf/iavf_rxtx.c
> index 4f2ffe6188..1dbc7aa74a 100644
> --- a/drivers/net/intel/iavf/iavf_rxtx.c
> +++ b/drivers/net/intel/iavf/iavf_rxtx.c
> @@ -3722,7 +3722,9 @@ iavf_recv_pkts_no_poll(void *rx_queue, struct
> rte_mbuf **rx_pkts,
>  	struct ci_rx_queue *rxq = rx_queue;
>  	enum iavf_rx_func_type rx_func_type;
> 
> -	if (!rxq->iavf_vsi || rxq->iavf_vsi->adapter->no_poll)
> +	if (!rxq->iavf_vsi ||
> +	    rte_atomic_load_explicit(&rxq->iavf_vsi->adapter->no_poll,
> +				     rte_memory_order_acquire))
>  		return 0;
> 
>  	rx_func_type = rxq->iavf_vsi->adapter->rx_func_type;
> @@ -3738,7 +3740,9 @@ iavf_xmit_pkts_no_poll(void *tx_queue, struct
> rte_mbuf **tx_pkts,
>  	struct ci_tx_queue *txq = tx_queue;
>  	enum iavf_tx_func_type tx_func_type;
> 
> -	if (!txq->iavf_vsi || txq->iavf_vsi->adapter->no_poll)
> +	if (!txq->iavf_vsi ||
> +	    rte_atomic_load_explicit(&txq->iavf_vsi->adapter->no_poll,
> +				     rte_memory_order_acquire))
>  		return 0;
> 
>  	tx_func_type = txq->iavf_vsi->adapter->tx_func_type;
> @@ -4025,6 +4029,75 @@ iavf_tx_done_cleanup_full(struct ci_tx_queue
> *txq,
>  	return (int)pkt_cnt;
>  }
> 
> +/*
> + * iavf_dev_tx_drain - drain in-flight Tx descriptors after a link-down or
> + * impending PF reset event.
> + */
> +void
> +iavf_dev_tx_drain(struct rte_eth_dev *dev)
> +{
> +	struct ci_tx_queue *txq;
> +	uint64_t hz, deadline;
> +	int idle_iters = 0;
> +	uint16_t qid;
> +
> +	/*
> +	 * Allow any Tx burst already in flight on a data-plane lcore to
> +	 * write its remaining descriptors and notify. After
> +	 * this window, the no_poll gate set by the caller is observed at
> +	 * the next burst-entry and no new descriptors will be posted.
> +	 */
> +	rte_delay_us_block(IAVF_TX_DRAIN_SETTLE_US);
> +
> +	hz = rte_get_timer_hz();
> +	deadline = rte_get_timer_cycles() +
> +		(hz * IAVF_TX_DRAIN_TIMEOUT_US) / 1000000ULL;
> +
> +	while (rte_get_timer_cycles() < deadline) {
> +		bool any_pending = false;
> +		bool any_progress = false;
> +
> +		for (qid = 0; qid < dev->data->nb_tx_queues; qid++) {
> +			txq = dev->data->tx_queues[qid];
> +			if (txq == NULL ||
> +			    dev->data->tx_queue_state[qid] !=
> +				RTE_ETH_QUEUE_STATE_STARTED)
> +				continue;
> +
> +			/*
> +			 * nb_tx_free == nb_tx_desc - 1 means the ring is
> +			 * empty (one descriptor is always reserved).
> +			 */
> +			if (txq->nb_tx_free >= txq->nb_tx_desc - 1)
> +				continue;
> +
> +			any_pending = true;
> +			if (ci_tx_xmit_cleanup(txq) == 0)
> +				any_progress = true;
> +		}
> +
> +		if (!any_pending)
> +			return;
> +
> +		if (any_progress) {
> +			idle_iters = 0;
> +		} else if (++idle_iters >= IAVF_TX_DRAIN_IDLE_MAX) {
> +			/*
> +			 * HW has not advanced the RS-bit write-back for
> +			 * several polling intervals; either the queue is
> +			 * quiescent except for the sub-rs_thresh tail
> +			 * (which we cannot observe here) or HW is no
> +			 * longer fetching. Further polling is unlikely to
> +			 * help, and the PF teardown path has its own
> +			 * grace period for the remainder.
> +			 */
> +			break;
> +		}
> +
> +		rte_delay_us_block(IAVF_TX_DRAIN_POLL_US);
> +	}
> +}
> +
>  int
>  iavf_dev_tx_done_cleanup(void *txq, uint32_t free_cnt)
>  {
> diff --git a/drivers/net/intel/iavf/iavf_rxtx.h
> b/drivers/net/intel/iavf/iavf_rxtx.h
> index 22ea415f44..4088bc421c 100644
> --- a/drivers/net/intel/iavf/iavf_rxtx.h
> +++ b/drivers/net/intel/iavf/iavf_rxtx.h
> @@ -506,6 +506,11 @@ enum iavf_tx_ctx_desc_tunnel_l4_tunnel_type {
>  /* Valid indicator bit for the time_stamp_low field */
>  #define IAVF_RX_FLX_DESC_TS_VALID	(0x1UL)
> 
> +#define IAVF_TX_DRAIN_TIMEOUT_US	10000	/* total drain budget:
> 10 ms */
> +#define IAVF_TX_DRAIN_SETTLE_US		100	/* let in-flight burst
> land  */
> +#define IAVF_TX_DRAIN_POLL_US		50	/* poll interval
> */
> +#define IAVF_TX_DRAIN_IDLE_MAX		20	/* ~1 ms of no RS
> write-back */
> +
>  int iavf_dev_rx_queue_setup(struct rte_eth_dev *dev,
>  			   uint16_t queue_idx,
>  			   uint16_t nb_desc,
> @@ -641,6 +646,7 @@ void iavf_set_default_ptype_table(struct rte_eth_dev
> *dev);
>  void iavf_rx_queue_release_mbufs_vec(struct ci_rx_queue *rxq);
>  void iavf_rx_queue_release_mbufs_neon(struct ci_rx_queue *rxq);
>  enum rte_vect_max_simd iavf_get_max_simd_bitwidth(void);
> +void iavf_dev_tx_drain(struct rte_eth_dev *dev);
> 
>  static inline
>  void iavf_dump_rx_descriptor(struct ci_rx_queue *rxq,
> diff --git a/drivers/net/intel/iavf/iavf_vchnl.c
> b/drivers/net/intel/iavf/iavf_vchnl.c
> index f8fffa7802..513c3e18dd 100644
> --- a/drivers/net/intel/iavf/iavf_vchnl.c
> +++ b/drivers/net/intel/iavf/iavf_vchnl.c
> @@ -260,7 +260,7 @@ iavf_handle_link_change_event(struct rte_eth_dev
> *dev,
>  	 * (link is down or a VF reset is in progress); the watchdog drives
>  	 * auto-reset recovery, so it must remain armed in those cases.
>  	 */
> -	if (vf->link_up && !vf->vf_reset)
> +	if (vf->link_up && !vf->vf_reset && !vf->in_reset_recovery)
>  		iavf_dev_watchdog_disable(adapter);
>  	else
>  		iavf_dev_watchdog_enable(adapter);
> @@ -268,9 +268,27 @@ iavf_handle_link_change_event(struct rte_eth_dev
> *dev,
>  	if (adapter->devargs.no_poll_on_link_down) {
>  		iavf_set_no_poll(adapter, true);
>  		PMD_DRV_LOG(DEBUG, "VF no poll turned %s",
> -			    adapter->no_poll ? "on" : "off");
> +			    rte_atomic_load_explicit(&adapter->no_poll,
> +
> rte_memory_order_relaxed) ?
> +						     "on" : "off");
> +		if (!vf->link_up)
> +			iavf_dev_tx_drain(dev);
>  	}
> 
> +	/*
> +	 * Resume a deferred dev_start.
> +	 * iavf_handle_hw_reset() sets vf->start_pending when
> +	 * reset recovery completed dev_init() but iavf_dev_start()
> +	 * itself failed (typically -EIO from
> VIRTCHNL_OP_CONFIG_VSI_QUEUES
> +	 * when the PF VSI was inactive).
> +	 * A link-up event implies the PF VSI is active again, so retry now.
> +	 * Run before the LSC event post so the port is ready to accept Tx
> +	 * by the time the app's link-up callback fires; no_poll has already
> +	 * been cleared above so bursts go through as soon as
> +	 * dev_start sets dev_started=1.
> +	 */
> +	iavf_resume_pending_start(dev);
> +
>  	iavf_dev_event_post(dev, RTE_ETH_EVENT_INTR_LSC, NULL, 0);
> 
>  	PMD_DRV_LOG(INFO, "Link status update:%s",
> @@ -327,6 +345,8 @@ iavf_read_msg_from_pf(struct iavf_adapter
> *adapter, uint16_t buf_len,
>  			if (!vf->vf_reset) {
>  				vf->vf_reset = true;
>  				iavf_set_no_poll(adapter, false);
> +				if (adapter->devargs.no_poll_on_link_down)
> +					iavf_dev_tx_drain(vf->eth_dev);
>  				iavf_dev_event_post(vf->eth_dev,
>  					RTE_ETH_EVENT_INTR_RESET,
>  					NULL, 0);
> @@ -565,6 +585,9 @@ iavf_handle_pf_event_msg(struct rte_eth_dev *dev,
> uint8_t *msg,
>  		if (!vf->vf_reset) {
>  			vf->vf_reset = true;
>  			iavf_set_no_poll(adapter, false);
> +			iavf_dev_watchdog_enable(adapter);
> +			if (adapter->devargs.no_poll_on_link_down)
> +				iavf_dev_tx_drain(dev);
>  			iavf_dev_event_post(dev,
> RTE_ETH_EVENT_INTR_RESET,
>  				NULL, 0);
>  		}
> @@ -614,6 +637,19 @@ iavf_handle_virtchnl_msg(struct rte_eth_dev *dev)
>  			break;
>  		}
>  		aq_opc = rte_le_to_cpu_16(info.desc.opcode);
> +
> +		/*
> +		 * During PF-initiated resets, iavf_clean_arq_element() has
> +		 * been observed to return IAVF_SUCCESS with a fully zeroed
> +		 * descriptor (opcode 0).
> +		 * Without this guard, such descriptors would fall through
> +		 * to the default case of the dispatch switch below and the
> +		 * "Request 0 is not supported yet" log flood reported in
> +		 * the field would be produced. These are discarded now.
> +		 */
> +		if (aq_opc == 0)
> +			continue;
> +
>  		/* For the message sent from pf to vf, opcode is stored in
>  		 * cookie_high of struct iavf_aq_desc, while return error code
>  		 * are stored in cookie_low, Which is done by PF driver.
> --
> 2.34.1


^ permalink raw reply

* RE: mempool cache change
From: Morten Brørup @ 2026-07-20 10:54 UTC (permalink / raw)
  To: Bruce Richardson
  Cc: Kishore Padmanabha, fengchengwen, dev, Wisam Jaddo,
	Andrew Rybchenko, Thomas Monjalon
In-Reply-To: <al3YgIWkXNihHGMv@bricha3-mobl1.ger.corp.intel.com>

> From: Bruce Richardson [mailto:bruce.richardson@intel.com]
> Sent: Monday, 20 July 2026 10.13
> 
> On Sat, Jul 18, 2026 at 04:07:05PM +0200, Morten Brørup wrote:
> > > From: Kishore Padmanabha [mailto:kishore.padmanabha@broadcom.com]
> > > Sent: Friday, 17 July 2026 19.10
> > >
> > > Hi Bruce,
> > >
> > > The below patch works fine for us. We tested all the different
> packet
> > > sizes.
> > > Thanks for the patch. Do you want to push this patch since it is
> not
> > > changing the ABI/API?
> >
> > Too late in the release process.
> >
> > Let's postpone the discussion for DPDK 26.11, where API/ABI breakage
> is allowed.
> 
> Agreed. Let's not unnecessarily rush this.
> 
> >
> > I'm not strongly opposed to Bruce's algorithm, targeting a fill level
> of 25 % from the edges and flushing/refilling up to 75 % of the cache
> when necessary. It does have its advantages for some mempool access
> patterns (which are not exotic).
> > I just prefer the current algorithm, targeting a fill level of 50 %
> and only flushing/refilling up to 50 % of the cache when necessary. It
> performs better at random get/put access patterns, and the backend
> transactions are smaller.
> >
> > For DPDK 26.11, where we can break the API/ABI, we can simply double
> RTE_MEMPOOL_CACHE_MAX_SIZE to 1024, to compensate for reducing the
> effective cache size from 150 % to 100 %.
> > The mempool cache objs array will no longer be
> [RTE_MEMPOOL_CACHE_MAX_SIZE * 2], but only
> [RTE_MEMPOOL_CACHE_MAX_SIZE], so doubling RTE_MEMPOOL_CACHE_MAX_SIZE
> will not increase the memory footprint, but allow using a cache size up
> to 1024.
> 
> My concern with this approach is that it won't automatically fix the
> problem if we have users who experience a performance regression due to
> the
> mempool changes. While testpmd allows the mbcache size to be provided
> via
> parameter, end applications are likely to have it hardcoded. That means
> that if an app does experience a regression, the author/user has to be
> either aware of the mempool changes, or has to debug it down to the
> mempool
> and then know to increase the mempool cache size in the app.
> 
> It's not an insurmountable problem, but one that needs to be very
> clearly
> called out in our documentation, what the change is, how it may affect
> things and how to fix it.

The release notes [1] do mention that the mempool algorithm has changed, and how some applications should adapt to it.
They also do mention that the effective mempool cache size has changed, but not that applications can restore the previously 50 % larger effective cache size by simply requesting a 50 % larger cache.

Maybe we should move the notes about the mempool changes from the New Features section to the API Changes section, and mention how to increase the cache size to regain the reduction in effective size?

[1]: https://github.com/DPDK/dpdk/blob/v26.07-rc4/doc/guides/rel_notes/release_26_07.rst?plain=1#L80

> 
> On the other hand, in realworld, i.e. not just testpmd/l3fwd cases
> doing
> little packet processesing, I would be fairly hopeful that regressions
> are
> going to be few and very small.

Yes.
And some real world applications (most run-to-completion applications?) will get fewer mempool cache misses with the new algorithm.
Best case a performance improvement exceeding the performance cost of the reduced effective cache size.

> 
> >
> > Please also note that the current implementation is carefully
> designed to keep the transfers to/from the mempool backend CPU cache
> aligned (assuming cache->size is 2^N and large enough).
> > Refer to the parameters passed to
> rte_mempool_ops_enqueue/dequeue_bulk().
> > E.g. with mempool cache size 256, backend transfers are 128 objects,
> 16 full cache lines.
> > Using CPU cache aligned transfers has a few advantages:
> > - There are no cache line ownership issues across different CPU cores
> repeatedly accessing the backend.
> > - The mempool backend drivers can be performance optimized for
> transferring full CPU cache lines. (Both source and destination
> addresses, and number of objects copied, are CPU cache aligned.
> Assuming all transfers go via the mempool cache.)
> >
> > These details should be fine tuned in the implementation, if we do
> proceed with Bruce's algorithm.
> >
> Yep, good points.
> 
> /Bruce

PS:
I have some API/ABI breaking mempool optimizations in the pipeline for DPDK 26.11.
But let's try to concentrate on DPDK 26.07 for now. ;-)


^ permalink raw reply

* Re: [PATCH 2/2] net/tap: drain queue FD in Rx interrupt mode
From: Stephen Hemminger @ 2026-07-20 11:16 UTC (permalink / raw)
  To: Maxime Leroy; +Cc: dev, stable
In-Reply-To: <CAHHRULUiZp2bLHONoDPhqexWd_ptXRLAQYVC=V3ojXonhecq1g@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 7183 bytes --]

the coding style against bool is more of a keenel thing.

On Mon, Jul 20, 2026, 10:33 Maxime Leroy <maxime@leroys.fr> wrote:

> On Fri, Jul 17, 2026 at 2:34 PM Stephen Hemminger
> <stephen@networkplumber.org> wrote:
> >
> > Don't use int as a boolean. Use bool. Ideally find unused pad hole for it
>
> Agreed int-as-a-boolean is not great. But bool in a structure is
> discouraged by coding_style.rst:
>
>    "Uses of bool in structures are not preferred as is wastes space and
>     it's also not clear as to what type size the bool is."  (Ref: LKML)
>
> and that very LKML reference is Linus recommending the opposite of
> bool for struct members:
>
>    "please don't use bool in structures at all. [...] Use bool mainly as a
>     return type from functions [...]. [...] just make sure the base type is
>     unsigned [...] you can specify the base type as you wish [...] for
>     packing."
>
> The current tap PMD follows that too: the existing flags (persist,
> flow_init, flow_isolate) are all int, and stdbool.h is not even
> included in the headers.
>
> So for v2 I'll use uint8_t for intr_mode and intr_mode_set: fixed
> 1-byte size, unambiguous representation, and it fits the existing
> padding so neither struct grows (pmd_internals stays 144 bytes,
> rx_queue stays 80). That matches both the guide and the referenced
> LKML guidance.
>
> I can also add a third patch at the end of the series converting the
> existing int flags (persist, flow_init, flow_isolate) to uint8_t, to
> make the driver consistent
>
> >
> > On Fri, Jul 17, 2026, 11:59 AM Maxime Leroy <maxime@leroys.fr> wrote:
> >>
> >> The tap Rx path is driven by a SIGIO trigger: pmd_rx_burst() returns
> >> without reading the queue fd unless tap_trigger, bumped by the O_ASYNC
> >> signal handler, has advanced. That avoids a readv() on every empty poll.
> >>
> >> In Rx interrupt mode the application blocks on the queue fd through
> epoll
> >> and polls only after a wakeup. The epoll wakeup and the trigger are
> >> distinct signals, so the burst can return 0 right after a wakeup because
> >> the trigger has not advanced, leaving the fd readable with no further
> >> edge: traffic stalls.
> >>
> >> When the port is configured for Rx interrupts, drain the fd
> >> unconditionally in the burst and do not arm the SIGIO trigger on the
> data
> >> queue fd. A data queue fd can be closed and recreated on a later setup,
> >> so the mode must stay constant to keep every fd on the same SIGIO
> policy:
> >> it is fixed at configure time and a later change is rejected. Close and
> >> reopen the port to switch modes.
> >>
> >> Fixes: 4870a8cdd968 ("net/tap: support Rx interrupt")
> >> Cc: stable@dpdk.org
> >>
> >> Signed-off-by: Maxime Leroy <maxime@leroys.fr>
> >> ---
> >>  drivers/net/tap/rte_eth_tap.c | 18 +++++++++++++++++-
> >>  drivers/net/tap/rte_eth_tap.h |  2 ++
> >>  2 files changed, 19 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/drivers/net/tap/rte_eth_tap.c
> b/drivers/net/tap/rte_eth_tap.c
> >> index 99ede19e49..ea9ef76335 100644
> >> --- a/drivers/net/tap/rte_eth_tap.c
> >> +++ b/drivers/net/tap/rte_eth_tap.c
> >> @@ -254,6 +254,10 @@ tun_alloc(struct pmd_internals *pmd, int
> is_keepalive, int persistent)
> >>                 goto error;
> >>         }
> >>
> >> +       /* interrupt mode wakes through epoll on the data queue fd, not
> the SIGIO trigger */
> >> +       if (pmd->intr_mode)
> >> +               return fd;
> >> +
> >>         /* Find a free realtime signal */
> >>         for (signo = SIGRTMIN + 1; signo < SIGRTMAX; signo++) {
> >>                 struct sigaction sa;
> >> @@ -477,7 +481,7 @@ pmd_rx_burst(void *queue, struct rte_mbuf **bufs,
> uint16_t nb_pkts)
> >>         unsigned long num_rx_bytes = 0;
> >>         uint32_t trigger = tap_trigger;
> >>
> >> -       if (trigger == rxq->trigger_seen)
> >> +       if (!rxq->intr_mode && trigger == rxq->trigger_seen)
> >>                 return 0;
> >>
> >>         process_private = rte_eth_devices[rxq->in_port].process_private;
> >> @@ -937,6 +941,16 @@ tap_dev_configure(struct rte_eth_dev *dev)
> >>         struct pmd_internals *pmd = dev->data->dev_private;
> >>         int intr_mode = !!dev->data->dev_conf.intr_conf.rxq;
> >>
> >> +       /* The queue fd is created once and its SIGIO trigger is armed
> for poll
> >> +        * mode only; the interrupt mode cannot be toggled on an
> existing port.
> >> +        */
> >> +       if (pmd->intr_mode_set && pmd->intr_mode != intr_mode) {
> >> +               TAP_LOG(ERR,
> >> +                       "%s: Rx interrupt mode is fixed after
> configure, close and reopen the port to change it",
> >> +                       dev->device->name);
> >> +               return -ENOTSUP;
> >> +       }
> >> +
> >>         if (dev->data->nb_rx_queues != dev->data->nb_tx_queues) {
> >>                 TAP_LOG(ERR,
> >>                         "%s: number of rx queues %d must be equal to
> number of tx queues %d",
> >> @@ -947,6 +961,7 @@ tap_dev_configure(struct rte_eth_dev *dev)
> >>         }
> >>
> >>         pmd->intr_mode = intr_mode;
> >> +       pmd->intr_mode_set = 1;
> >>
> >>         TAP_LOG(INFO, "%s: %s: TX configured queues number: %u",
> >>                 dev->device->name, pmd->name, dev->data->nb_tx_queues);
> >> @@ -1620,6 +1635,7 @@ tap_rx_queue_setup(struct rte_eth_dev *dev,
> >>         rxq->queue_id = rx_queue_id;
> >>         rxq->max_rx_segs = max_rx_segs;
> >>         rxq->rxmode = &dev->data->dev_conf.rxmode;
> >> +       rxq->intr_mode = internals->intr_mode;
> >>
> >>         dev->data->rx_queues[rx_queue_id] = rxq;
> >>         int fd = tap_setup_queue(dev, rx_queue_id, 1);
> >> diff --git a/drivers/net/tap/rte_eth_tap.h
> b/drivers/net/tap/rte_eth_tap.h
> >> index 3180719c34..abe22aac9f 100644
> >> --- a/drivers/net/tap/rte_eth_tap.h
> >> +++ b/drivers/net/tap/rte_eth_tap.h
> >> @@ -50,6 +50,7 @@ struct rx_queue {
> >>         uint16_t queue_id;              /* queue ID*/
> >>         struct queue_stats stats;        /* Stats for this RX queue */
> >>         uint16_t max_rx_segs;           /* max scatter segments per
> packet */
> >> +       uint16_t intr_mode;             /* 1 when Rx queue interrupts
> are used */
> >>         struct rte_eth_rxmode *rxmode;  /* RX features */
> >>         struct rte_mbuf *pool;          /* mbufs pool for this queue */
> >>         struct tun_pi pi;               /* packet info for iovecs */
> >> @@ -94,6 +95,7 @@ struct pmd_internals {
> >>
> >>         struct rte_intr_handle *intr_handle;         /* LSC interrupt
> handle. */
> >>         int intr_mode;                    /* Rx queue interrupt mode */
> >> +       int intr_mode_set;                /* intr_mode locked after
> configure */
> >>         int ka_fd;                        /* keep-alive file descriptor
> */
> >>         struct rte_mempool *gso_ctx_mp;     /* Mempool for GSO packets
> */
> >>  };
> >> --
> >> 2.43.0
> >>
>
>
> --
> -------------------------------
> Maxime Leroy
> maxime@leroys.fr
>

[-- Attachment #2: Type: text/html, Size: 9351 bytes --]

^ permalink raw reply

* [PATCH] doc: drop recommendation against bool in structures
From: Maxime Leroy @ 2026-07-20 11:46 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Thomas Monjalon, David Marchand, Maxime Leroy

The coding style advised against bool in structures, citing space and
type-size concerns inherited from the Linux kernel. That does not match
DPDK practice: bool is already used in over 1400 structure fields across
the tree, including core APIs such as rte_flow. Drop the note so the
style guide reflects actual usage.

Signed-off-by: Maxime Leroy <maxime@leroys.fr>
---
 doc/guides/contributing/coding_style.rst | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/doc/guides/contributing/coding_style.rst b/doc/guides/contributing/coding_style.rst
index 976a1e1de3..11de3bb39a 100644
--- a/doc/guides/contributing/coding_style.rst
+++ b/doc/guides/contributing/coding_style.rst
@@ -313,15 +313,6 @@ Structure Declarations
 * Use of the structures should be by separate variable declarations and those declarations must be extern if they are declared in a header file.
 * Externally visible structure definitions should have the structure name prefixed by ``rte_`` to avoid namespace collisions.
 
-.. note::
-
-    Avoid using ``bool`` in structures because it wastes space and
-    the type size is unclear. A preferred use of
-    ``bool`` is mainly as a return type from functions that return true/false,
-    and maybe local variable functions.
-
-    Ref: `LKML <https://lkml.org/lkml/2017/11/21/384>`_
-
 Queues
 ~~~~~~
 
-- 
2.43.0


^ permalink raw reply related

* [PATCH] net/mlx5: revert fallback to Verbs Tx allocation
From: Thomas Monjalon @ 2026-07-20 11:49 UTC (permalink / raw)
  To: dev
  Cc: stable, Pier Damouny, Dariusz Sosnowski, Viacheslav Ovsiienko,
	Bing Zhao, Ori Kam, Suanming Mou, Matan Azrad, Banoth Saikumar

On Windows, DevX CQ creation was failing because
of a different allocation fallback behaviour.

Fixes: 4abc12b9331c ("net/mlx5: fall back to Verbs Tx allocation without DevX")
Cc: stable@dpdk.org

Reported-by: Pier Damouny <pdamouny@nvidia.com>
Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
 .mailmap                        | 1 -
 drivers/net/mlx5/mlx5_trigger.c | 2 +-
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/.mailmap b/.mailmap
index a610456351..fcb3d1bb3f 100644
--- a/.mailmap
+++ b/.mailmap
@@ -184,7 +184,6 @@ Ayuj Verma <ayverma@marvell.com> <ayuj.verma@caviumnetworks.com>
 Balakrishna Bhamidipati <bbhamidipati@marvell.com>
 Balasubramanian Manoharan <balasubramanian.manoharan@caviumnetworks.com>
 Balazs Nemeth <bnemeth@redhat.com> <balazs.nemeth@intel.com>
-Banoth Saikumar <banoth.saikumar@oracle.com>
 Bao-Long Tran <longtb5@viettel.com.vn>
 Baoyuan Li <updoing@sina.com>
 Bar Neuman <bneuman@nvidia.com>
diff --git a/drivers/net/mlx5/mlx5_trigger.c b/drivers/net/mlx5/mlx5_trigger.c
index c2804c5897..25847c8ba2 100644
--- a/drivers/net/mlx5/mlx5_trigger.c
+++ b/drivers/net/mlx5/mlx5_trigger.c
@@ -1201,7 +1201,7 @@ static int mlx5_dev_allocate_consec_tx_mem(struct rte_eth_dev *dev)
 	void *umem_buf = NULL;
 
 	/* Legacy per queue allocation, do nothing here. */
-	if (priv->sh->config.txq_mem_algn == 0 || !mlx5_devx_obj_ops_en(priv->sh))
+	if (priv->sh->config.txq_mem_algn == 0)
 		return 0;
 	alignment = (size_t)1 << priv->sh->config.txq_mem_algn;
 	total_size = priv->consec_tx_mem.sq_total_size + priv->consec_tx_mem.cq_total_size;
-- 
2.54.0


^ permalink raw reply related

* Re: [PATCH] net/mlx5: revert fallback to Verbs Tx allocation
From: Dariusz Sosnowski @ 2026-07-20 12:04 UTC (permalink / raw)
  To: Thomas Monjalon
  Cc: dev, stable, Pier Damouny, Viacheslav Ovsiienko, Bing Zhao,
	Ori Kam, Suanming Mou, Matan Azrad, Banoth Saikumar
In-Reply-To: <20260720114929.2998238-1-thomas@monjalon.net>

On Mon, Jul 20, 2026 at 01:49:29PM +0200, Thomas Monjalon wrote:
> On Windows, DevX CQ creation was failing because
> of a different allocation fallback behaviour.
> 
> Fixes: 4abc12b9331c ("net/mlx5: fall back to Verbs Tx allocation without DevX")
> Cc: stable@dpdk.org
> 
> Reported-by: Pier Damouny <pdamouny@nvidia.com>
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>

Acked-by: Dariusz Sosnowski <dsosnowski@nvidia.com>

^ permalink raw reply

* Re: [PATCH] net/mlx5: revert fallback to Verbs Tx allocation
From: Thomas Monjalon @ 2026-07-20 12:06 UTC (permalink / raw)
  To: Dariusz Sosnowski, Pier Damouny
  Cc: dev, stable, Viacheslav Ovsiienko, Bing Zhao, Ori Kam,
	Suanming Mou, Matan Azrad, Banoth Saikumar
In-Reply-To: <ekuco7abfynbgdovhotzbvbgynu3ldld65jlh7cpxwl4iz2amj@bzdg33appnnl>

20/07/2026 14:04, Dariusz Sosnowski:
> On Mon, Jul 20, 2026 at 01:49:29PM +0200, Thomas Monjalon wrote:
> > On Windows, DevX CQ creation was failing because
> > of a different allocation fallback behaviour.
> > 
> > Fixes: 4abc12b9331c ("net/mlx5: fall back to Verbs Tx allocation without DevX")
> > Cc: stable@dpdk.org
> > 
> > Reported-by: Pier Damouny <pdamouny@nvidia.com>
> > Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> 
> Acked-by: Dariusz Sosnowski <dsosnowski@nvidia.com>

Applied




^ permalink raw reply

* [PATCH v2 0/3] net/tap: fix Rx queue interrupt support
From: Maxime Leroy @ 2026-07-20 12:06 UTC (permalink / raw)
  To: dev; +Cc: Maxime Leroy
In-Reply-To: <20260717095842.419130-1-maxime@leroys.fr>

The tap PMD registers each queue file descriptor for Rx interrupts but the
feature is not usable through the generic API. This series fixes two
distinct issues against the original Rx interrupt support, plus a small
type cleanup.

Patch 1 adds the missing rx_queue_intr_enable/disable ops. Without them
rte_eth_dev_rx_intr_enable() returns -ENOTSUP, so applications that arm
queues before sleeping (l3fwd-power and similar) treat tap as having no
interrupt support and fall back to polling.

Patch 2 fixes a traffic stall specific to interrupt mode: the Rx burst
skips reading the queue fd until the SIGIO trigger advances, but in
interrupt mode the application wakes through epoll, a distinct signal, so
the burst can return 0 right after a wakeup and the fd stays readable with
no further edge. The fd is now drained unconditionally in interrupt mode
and the SIGIO trigger is not armed on the data queue fds.

Patch 3 converts the driver's int-as-boolean fields to bool.

Patches 1 and 2 are candidates for stable.

v2:
 - use bool for the new interrupt-mode fields instead of int (Stephen);
   both fit existing padding, so neither struct grows
 - add patch 3 converting the existing int booleans to bool

The coding_style.rst note that discouraged bool in structures no longer
matches DPDK practice; it is dropped by a separate patch.

Maxime Leroy (3):
  net/tap: support Rx queue interrupt enable/disable
  net/tap: drain queue FD in Rx interrupt mode
  net/tap: use bool for boolean flags

 drivers/net/tap/rte_eth_tap.c | 25 +++++++++++++++++++-
 drivers/net/tap/rte_eth_tap.h | 11 ++++++---
 drivers/net/tap/tap_flow.c    |  4 ++--
 drivers/net/tap/tap_intr.c    | 44 +++++++++++++++++++++++++++++++++++
 4 files changed, 78 insertions(+), 6 deletions(-)

-- 
2.43.0


^ permalink raw reply

* [PATCH v2 1/3] net/tap: support Rx queue interrupt enable/disable
From: Maxime Leroy @ 2026-07-20 12:06 UTC (permalink / raw)
  To: dev; +Cc: Maxime Leroy, stable, Stephen Hemminger, Pascal Mazon,
	Moti Haimovsky
In-Reply-To: <20260720120700.801099-1-maxime@leroys.fr>

The driver registers each queue file descriptor for Rx interrupts but
never provided the rx_queue_intr_enable/disable ops, so
rte_eth_dev_rx_intr_enable() returned -ENOTSUP. Applications that arm
queues before sleeping (l3fwd-power and similar) treat that as "no
interrupt support" and fall back to polling, even though the epoll wait
on the queue fd works. The advertised Rx interrupt feature is therefore
unusable through the generic API.

The queue fd is kept readable by the kernel whenever data is available
and is drained by the Rx burst itself, so there is no interrupt source to
arm or mask. Record whether the port was configured for Rx interrupts and
implement both ops to succeed in that mode and return -ENOTSUP otherwise,
so the generic Rx interrupt API works and applications can block on the
queue fd.

Fixes: 4870a8cdd968 ("net/tap: support Rx interrupt")
Cc: stable@dpdk.org

Signed-off-by: Maxime Leroy <maxime@leroys.fr>
---
 drivers/net/tap/rte_eth_tap.c |  5 ++++
 drivers/net/tap/rte_eth_tap.h |  3 +++
 drivers/net/tap/tap_intr.c    | 44 +++++++++++++++++++++++++++++++++++
 3 files changed, 52 insertions(+)

diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
index b93452f168..dc56c974da 100644
--- a/drivers/net/tap/rte_eth_tap.c
+++ b/drivers/net/tap/rte_eth_tap.c
@@ -935,6 +935,7 @@ static int
 tap_dev_configure(struct rte_eth_dev *dev)
 {
 	struct pmd_internals *pmd = dev->data->dev_private;
+	bool intr_mode = dev->data->dev_conf.intr_conf.rxq;
 
 	if (dev->data->nb_rx_queues != dev->data->nb_tx_queues) {
 		TAP_LOG(ERR,
@@ -945,6 +946,8 @@ tap_dev_configure(struct rte_eth_dev *dev)
 		return -1;
 	}
 
+	pmd->intr_mode = intr_mode;
+
 	TAP_LOG(INFO, "%s: %s: TX configured queues number: %u",
 		dev->device->name, pmd->name, dev->data->nb_tx_queues);
 
@@ -2098,6 +2101,8 @@ static const struct eth_dev_ops ops = {
 	.tx_queue_stop          = tap_tx_queue_stop,
 	.rx_queue_release       = tap_rx_queue_release,
 	.tx_queue_release       = tap_tx_queue_release,
+	.rx_queue_intr_enable   = tap_rx_queue_intr_enable,
+	.rx_queue_intr_disable  = tap_rx_queue_intr_disable,
 	.flow_ctrl_get          = tap_flow_ctrl_get,
 	.flow_ctrl_set          = tap_flow_ctrl_set,
 	.link_update            = tap_link_update,
diff --git a/drivers/net/tap/rte_eth_tap.h b/drivers/net/tap/rte_eth_tap.h
index f53a5ad077..51fd2339fc 100644
--- a/drivers/net/tap/rte_eth_tap.h
+++ b/drivers/net/tap/rte_eth_tap.h
@@ -93,6 +93,7 @@ struct pmd_internals {
 
 
 	struct rte_intr_handle *intr_handle;         /* LSC interrupt handle. */
+	bool intr_mode;                   /* Rx queue interrupt mode */
 	int ka_fd;                        /* keep-alive file descriptor */
 	struct rte_mempool *gso_ctx_mp;     /* Mempool for GSO packets */
 };
@@ -104,5 +105,7 @@ struct pmd_process_private {
 /* tap_intr.c */
 
 int tap_rx_intr_vec_set(struct rte_eth_dev *dev, int set);
+int tap_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id);
+int tap_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id);
 
 #endif /* _RTE_ETH_TAP_H_ */
diff --git a/drivers/net/tap/tap_intr.c b/drivers/net/tap/tap_intr.c
index 1908f71f97..7db22b69f5 100644
--- a/drivers/net/tap/tap_intr.c
+++ b/drivers/net/tap/tap_intr.c
@@ -112,3 +112,47 @@ tap_rx_intr_vec_set(struct rte_eth_dev *dev, int set)
 		return tap_rx_intr_vec_install(dev);
 	return 0;
 }
+
+/**
+ * Arm a queue for Rx interrupts.
+ *
+ * @param dev
+ *   Pointer to the tap rte_eth_dev device structure.
+ * @param queue_id
+ *   Rx queue index.
+ *
+ * @return
+ *   0 on success, -ENOTSUP if the port was not configured for Rx interrupts.
+ */
+int
+tap_rx_queue_intr_enable(struct rte_eth_dev *dev,
+			 uint16_t queue_id __rte_unused)
+{
+	struct pmd_internals *pmd = dev->data->dev_private;
+
+	if (!pmd->intr_mode)
+		return -ENOTSUP;
+	return 0;
+}
+
+/**
+ * Disarm a queue from Rx interrupts.
+ *
+ * @param dev
+ *   Pointer to the tap rte_eth_dev device structure.
+ * @param queue_id
+ *   Rx queue index.
+ *
+ * @return
+ *   0 on success, -ENOTSUP if the port was not configured for Rx interrupts.
+ */
+int
+tap_rx_queue_intr_disable(struct rte_eth_dev *dev,
+			  uint16_t queue_id __rte_unused)
+{
+	struct pmd_internals *pmd = dev->data->dev_private;
+
+	if (!pmd->intr_mode)
+		return -ENOTSUP;
+	return 0;
+}
-- 
2.43.0


^ permalink raw reply related

* [PATCH v2 2/3] net/tap: drain queue FD in Rx interrupt mode
From: Maxime Leroy @ 2026-07-20 12:06 UTC (permalink / raw)
  To: dev; +Cc: Maxime Leroy, stable, Stephen Hemminger, Moti Haimovsky,
	Pascal Mazon
In-Reply-To: <20260720120700.801099-1-maxime@leroys.fr>

The tap Rx path is driven by a SIGIO trigger: pmd_rx_burst() returns
without reading the queue fd unless tap_trigger, bumped by the O_ASYNC
signal handler, has advanced. That avoids a readv() on every empty poll.

In Rx interrupt mode the application blocks on the queue fd through epoll
and polls only after a wakeup. The epoll wakeup and the trigger are
distinct signals, so the burst can return 0 right after a wakeup because
the trigger has not advanced, leaving the fd readable with no further
edge: traffic stalls.

When the port is configured for Rx interrupts, drain the fd
unconditionally in the burst and do not arm the SIGIO trigger on the data
queue fd. A data queue fd can be closed and recreated on a later setup,
so the mode must stay constant to keep every fd on the same SIGIO policy:
it is fixed at configure time and a later change is rejected. Close and
reopen the port to switch modes.

Fixes: 4870a8cdd968 ("net/tap: support Rx interrupt")
Cc: stable@dpdk.org

Signed-off-by: Maxime Leroy <maxime@leroys.fr>
---
 drivers/net/tap/rte_eth_tap.c | 20 +++++++++++++++++++-
 drivers/net/tap/rte_eth_tap.h |  2 ++
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
index dc56c974da..882bb5aa71 100644
--- a/drivers/net/tap/rte_eth_tap.c
+++ b/drivers/net/tap/rte_eth_tap.c
@@ -254,6 +254,12 @@ tun_alloc(struct pmd_internals *pmd, int is_keepalive, int persistent)
 		goto error;
 	}
 
+	/* data queue fds in interrupt mode wake through epoll, not the SIGIO
+	 * trigger; the keep-alive fd always keeps SIGIO
+	 */
+	if (!is_keepalive && pmd->intr_mode)
+		return fd;
+
 	/* Find a free realtime signal */
 	for (signo = SIGRTMIN + 1; signo < SIGRTMAX; signo++) {
 		struct sigaction sa;
@@ -477,7 +483,7 @@ pmd_rx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 	unsigned long num_rx_bytes = 0;
 	uint32_t trigger = tap_trigger;
 
-	if (trigger == rxq->trigger_seen)
+	if (!rxq->intr_mode && trigger == rxq->trigger_seen)
 		return 0;
 
 	process_private = rte_eth_devices[rxq->in_port].process_private;
@@ -937,6 +943,16 @@ tap_dev_configure(struct rte_eth_dev *dev)
 	struct pmd_internals *pmd = dev->data->dev_private;
 	bool intr_mode = dev->data->dev_conf.intr_conf.rxq;
 
+	/* The queue fd is created once and its SIGIO trigger is armed for poll
+	 * mode only; the interrupt mode cannot be toggled on an existing port.
+	 */
+	if (pmd->intr_mode_set && pmd->intr_mode != intr_mode) {
+		TAP_LOG(ERR,
+			"%s: Rx interrupt mode is fixed after configure, close and reopen the port to change it",
+			dev->device->name);
+		return -ENOTSUP;
+	}
+
 	if (dev->data->nb_rx_queues != dev->data->nb_tx_queues) {
 		TAP_LOG(ERR,
 			"%s: number of rx queues %d must be equal to number of tx queues %d",
@@ -947,6 +963,7 @@ tap_dev_configure(struct rte_eth_dev *dev)
 	}
 
 	pmd->intr_mode = intr_mode;
+	pmd->intr_mode_set = true;
 
 	TAP_LOG(INFO, "%s: %s: TX configured queues number: %u",
 		dev->device->name, pmd->name, dev->data->nb_tx_queues);
@@ -1620,6 +1637,7 @@ tap_rx_queue_setup(struct rte_eth_dev *dev,
 	rxq->queue_id = rx_queue_id;
 	rxq->max_rx_segs = max_rx_segs;
 	rxq->rxmode = &dev->data->dev_conf.rxmode;
+	rxq->intr_mode = internals->intr_mode;
 
 	dev->data->rx_queues[rx_queue_id] = rxq;
 	int fd = tap_setup_queue(dev, rx_queue_id, 1);
diff --git a/drivers/net/tap/rte_eth_tap.h b/drivers/net/tap/rte_eth_tap.h
index 51fd2339fc..aae9eea510 100644
--- a/drivers/net/tap/rte_eth_tap.h
+++ b/drivers/net/tap/rte_eth_tap.h
@@ -50,6 +50,7 @@ struct rx_queue {
 	uint16_t queue_id;		/* queue ID*/
 	struct queue_stats stats;        /* Stats for this RX queue */
 	uint16_t max_rx_segs;           /* max scatter segments per packet */
+	bool intr_mode;                 /* 1 when Rx queue interrupts are used */
 	struct rte_eth_rxmode *rxmode;  /* RX features */
 	struct rte_mbuf *pool;          /* mbufs pool for this queue */
 	struct tun_pi pi;               /* packet info for iovecs */
@@ -94,6 +95,7 @@ struct pmd_internals {
 
 	struct rte_intr_handle *intr_handle;         /* LSC interrupt handle. */
 	bool intr_mode;                   /* Rx queue interrupt mode */
+	bool intr_mode_set;               /* intr_mode locked after configure */
 	int ka_fd;                        /* keep-alive file descriptor */
 	struct rte_mempool *gso_ctx_mp;     /* Mempool for GSO packets */
 };
-- 
2.43.0


^ permalink raw reply related

* [PATCH v2 3/3] net/tap: use bool for boolean flags
From: Maxime Leroy @ 2026-07-20 12:06 UTC (permalink / raw)
  To: dev; +Cc: Maxime Leroy, Stephen Hemminger
In-Reply-To: <20260720120700.801099-1-maxime@leroys.fr>

persist, flow_init and flow_isolate only ever hold true or false but were
declared as int. Use bool, consistent with the interrupt-mode flags added
in this series and with common DPDK practice.

Signed-off-by: Maxime Leroy <maxime@leroys.fr>
---
 drivers/net/tap/rte_eth_tap.h | 6 +++---
 drivers/net/tap/tap_flow.c    | 4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/net/tap/rte_eth_tap.h b/drivers/net/tap/rte_eth_tap.h
index aae9eea510..80419aad8c 100644
--- a/drivers/net/tap/rte_eth_tap.h
+++ b/drivers/net/tap/rte_eth_tap.h
@@ -72,7 +72,7 @@ struct pmd_internals {
 	char remote_iface[IFNAMSIZ];	  /* Remote netdevice name */
 	char name[IFNAMSIZ];		  /* Internal Tap device name */
 	int type;                         /* Type field - TUN|TAP */
-	int persist;			  /* 1 if keep link up, else 0 */
+	bool persist;			  /* 1 if keep link up, else 0 */
 	struct rte_ether_addr eth_addr;   /* Mac address of the device port */
 	struct rte_ether_addr *mc_addrs;  /* multicast address list */
 	uint32_t nb_mc_addrs;             /* multicast address count */
@@ -82,8 +82,8 @@ struct pmd_internals {
 	int nlsk_fd;                      /* Netlink socket fd */
 
 #ifdef HAVE_TCA_FLOWER
-	int flow_init;                    /* 1 if qdiscs were created */
-	int flow_isolate;                 /* 1 if flow isolation is enabled */
+	bool flow_init;                   /* 1 if qdiscs were created */
+	bool flow_isolate;                /* 1 if flow isolation is enabled */
 
 	struct tap_rss *rss;		  /* BPF program */
 
diff --git a/drivers/net/tap/tap_flow.c b/drivers/net/tap/tap_flow.c
index a9d8e09562..a0ffb35bdd 100644
--- a/drivers/net/tap/tap_flow.c
+++ b/drivers/net/tap/tap_flow.c
@@ -1521,7 +1521,7 @@ tap_flow_isolate(struct rte_eth_dev *dev,
 	}
 	return 0;
 error:
-	pmd->flow_isolate = 0;
+	pmd->flow_isolate = false;
 	return rte_flow_error_set(
 		error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
 		"TC rule creation failed");
@@ -1914,7 +1914,7 @@ tap_flow_init(struct pmd_internals *pmd)
 		return -1;
 	}
 
-	pmd->flow_init = 1;
+	pmd->flow_init = true;
 
 	return 0;
 }
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH] doc: drop recommendation against bool in structures
From: Bruce Richardson @ 2026-07-20 12:13 UTC (permalink / raw)
  To: Maxime Leroy; +Cc: dev, Stephen Hemminger, Thomas Monjalon, David Marchand
In-Reply-To: <20260720114602.787429-1-maxime@leroys.fr>

On Mon, Jul 20, 2026 at 01:46:02PM +0200, Maxime Leroy wrote:
> The coding style advised against bool in structures, citing space and
> type-size concerns inherited from the Linux kernel. That does not match
> DPDK practice: bool is already used in over 1400 structure fields across
> the tree, including core APIs such as rte_flow. Drop the note so the
> style guide reflects actual usage.
> 
> Signed-off-by: Maxime Leroy <maxime@leroys.fr>
> ---

Definite +1

Acked-by: Bruce Richardson <bruce.richardson@intel.com>

>  doc/guides/contributing/coding_style.rst | 9 ---------
>  1 file changed, 9 deletions(-)
> 
> diff --git a/doc/guides/contributing/coding_style.rst b/doc/guides/contributing/coding_style.rst
> index 976a1e1de3..11de3bb39a 100644
> --- a/doc/guides/contributing/coding_style.rst
> +++ b/doc/guides/contributing/coding_style.rst
> @@ -313,15 +313,6 @@ Structure Declarations
>  * Use of the structures should be by separate variable declarations and those declarations must be extern if they are declared in a header file.
>  * Externally visible structure definitions should have the structure name prefixed by ``rte_`` to avoid namespace collisions.
>  
> -.. note::
> -
> -    Avoid using ``bool`` in structures because it wastes space and
> -    the type size is unclear. A preferred use of
> -    ``bool`` is mainly as a return type from functions that return true/false,
> -    and maybe local variable functions.
> -
> -    Ref: `LKML <https://lkml.org/lkml/2017/11/21/384>`_
> -
>  Queues
>  ~~~~~~
>  
> -- 
> 2.43.0
> 

^ permalink raw reply

* RE: [PATCH] doc: drop recommendation against bool in structures
From: Morten Brørup @ 2026-07-20 12:51 UTC (permalink / raw)
  To: Bruce Richardson, Maxime Leroy
  Cc: dev, Stephen Hemminger, Thomas Monjalon, David Marchand
In-Reply-To: <al4Q3f3Lfbv8i8V-@bricha3-mobl1.ger.corp.intel.com>

> From: Bruce Richardson [mailto:bruce.richardson@intel.com]
> Sent: Monday, 20 July 2026 14.13
> 
> On Mon, Jul 20, 2026 at 01:46:02PM +0200, Maxime Leroy wrote:
> > The coding style advised against bool in structures, citing space and
> > type-size concerns inherited from the Linux kernel. That does not
> match
> > DPDK practice: bool is already used in over 1400 structure fields
> across
> > the tree, including core APIs such as rte_flow. Drop the note so the
> > style guide reflects actual usage.

The note is still valid, although massively violated.
Could we paraphrase the note as an advice/recommendation, instead of completely removing it?
The intention is to make developers consider alternatives when adding a Boolean field to a structure.
Maybe it could be expanded with a few example alternatives:
uint8_t value, or
uintN_t value:1 (bitfield).

> >
> > Signed-off-by: Maxime Leroy <maxime@leroys.fr>
> > ---
> 
> Definite +1
> 
> Acked-by: Bruce Richardson <bruce.richardson@intel.com>
> 
> >  doc/guides/contributing/coding_style.rst | 9 ---------
> >  1 file changed, 9 deletions(-)
> >
> > diff --git a/doc/guides/contributing/coding_style.rst
> b/doc/guides/contributing/coding_style.rst
> > index 976a1e1de3..11de3bb39a 100644
> > --- a/doc/guides/contributing/coding_style.rst
> > +++ b/doc/guides/contributing/coding_style.rst
> > @@ -313,15 +313,6 @@ Structure Declarations
> >  * Use of the structures should be by separate variable declarations
> and those declarations must be extern if they are declared in a header
> file.
> >  * Externally visible structure definitions should have the structure
> name prefixed by ``rte_`` to avoid namespace collisions.
> >
> > -.. note::
> > -
> > -    Avoid using ``bool`` in structures because it wastes space and
> > -    the type size is unclear. A preferred use of
> > -    ``bool`` is mainly as a return type from functions that return
> true/false,
> > -    and maybe local variable functions.
> > -
> > -    Ref: `LKML <https://lkml.org/lkml/2017/11/21/384>`_
> > -
> >  Queues
> >  ~~~~~~
> >
> > --
> > 2.43.0
> >

^ permalink raw reply

* Re: [PATCH] doc: drop recommendation against bool in structures
From: Bruce Richardson @ 2026-07-20 12:57 UTC (permalink / raw)
  To: Morten Brørup
  Cc: Maxime Leroy, dev, Stephen Hemminger, Thomas Monjalon,
	David Marchand
In-Reply-To: <98CBD80474FA8B44BF855DF32C47DC35F65980@smartserver.smartshare.dk>

On Mon, Jul 20, 2026 at 02:51:09PM +0200, Morten Brørup wrote:
> > From: Bruce Richardson [mailto:bruce.richardson@intel.com]
> > Sent: Monday, 20 July 2026 14.13
> > 
> > On Mon, Jul 20, 2026 at 01:46:02PM +0200, Maxime Leroy wrote:
> > > The coding style advised against bool in structures, citing space and
> > > type-size concerns inherited from the Linux kernel. That does not
> > match
> > > DPDK practice: bool is already used in over 1400 structure fields
> > across
> > > the tree, including core APIs such as rte_flow. Drop the note so the
> > > style guide reflects actual usage.
> 
> The note is still valid, although massively violated.
> Could we paraphrase the note as an advice/recommendation, instead of completely removing it?
> The intention is to make developers consider alternatives when adding a Boolean field to a structure.
> Maybe it could be expanded with a few example alternatives:
> uint8_t value, or
> uintN_t value:1 (bitfield).
> 
I don't think we want those alternative approaches. If something is a
boolean value, then let's just store it as a bool and be done with it. If
we store it as an int type then we need comments documenting that it's
actually a flag. If it's a bit type, then the field becomes just that
little bit more awkward to manage - though still a good choice if the
struct is size-sensitive.

Because of this, I'd be in favour of just removing the text and then
letting the developer choose the best field type for the job. If bool is a
bad choice for a given situation, that should be caught in review.

/Bruce

^ permalink raw reply

* RE: [PATCH] doc: drop recommendation against bool in structures
From: Morten Brørup @ 2026-07-20 12:59 UTC (permalink / raw)
  To: Bruce Richardson
  Cc: Maxime Leroy, dev, Stephen Hemminger, Thomas Monjalon,
	David Marchand
In-Reply-To: <al4bRFcOPwqXGPhM@bricha3-mobl1.ger.corp.intel.com>

> From: Bruce Richardson [mailto:bruce.richardson@intel.com]
> Sent: Monday, 20 July 2026 14.58
> 
> On Mon, Jul 20, 2026 at 02:51:09PM +0200, Morten Brørup wrote:
> > > From: Bruce Richardson [mailto:bruce.richardson@intel.com]
> > > Sent: Monday, 20 July 2026 14.13
> > >
> > > On Mon, Jul 20, 2026 at 01:46:02PM +0200, Maxime Leroy wrote:
> > > > The coding style advised against bool in structures, citing space
> and
> > > > type-size concerns inherited from the Linux kernel. That does not
> > > match
> > > > DPDK practice: bool is already used in over 1400 structure fields
> > > across
> > > > the tree, including core APIs such as rte_flow. Drop the note so
> the
> > > > style guide reflects actual usage.
> >
> > The note is still valid, although massively violated.
> > Could we paraphrase the note as an advice/recommendation, instead of
> completely removing it?
> > The intention is to make developers consider alternatives when adding
> a Boolean field to a structure.
> > Maybe it could be expanded with a few example alternatives:
> > uint8_t value, or
> > uintN_t value:1 (bitfield).
> >
> I don't think we want those alternative approaches. If something is a
> boolean value, then let's just store it as a bool and be done with it.
> If
> we store it as an int type then we need comments documenting that it's
> actually a flag. If it's a bit type, then the field becomes just that
> little bit more awkward to manage - though still a good choice if the
> struct is size-sensitive.
> 
> Because of this, I'd be in favour of just removing the text and then
> letting the developer choose the best field type for the job. If bool
> is a
> bad choice for a given situation, that should be caught in review.
> 
> /Bruce

OK, I'll buy that.

Acked-by: Morten Brørup <mb@smartsharesystems.com>


^ permalink raw reply

* [PATCH v1 0/2] net/dpaa2: fix RSS for plain and tunnelled traffic
From: Maxime Leroy @ 2026-07-20 13:34 UTC (permalink / raw)
  To: dev; +Cc: thomas, david.marchand, hemant.agrawal, Maxime Leroy
In-Reply-To: <20260630123857.392884-1-maxime@leroys.fr>

The RTE_ETH_RSS_LEVEL_INNERMOST support merged in 618a06c53d47 maps the
inner level to hdr_index = HDR_INDEX_LAST in the IP key extracts. The
hardware only resolves that index when several IP headers are stacked, so
a non-tunnelled frame, which carries a single IP header, resolves to
nothing: its RSS hash is constant and every such frame lands on a single
Rx queue. This breaks RSS for plain traffic, which the ethdev API
requires INNERMOST to hash, since a plain frame's innermost header is its
only IP header.

dpaa2 cannot express strict inner-only hashing and keep plain traffic
spread at the same time: the only index that resolves for a single header
is the outer one (index 0). This series therefore reverts the INNERMOST
support and, rather than exposing the RSS level selector, always extracts
both the outer IP (index 0) and the innermost IP (HDR_INDEX_LAST) as the
PMD default. Plain frames keep being hashed on their only IP header;
tunnelled frames are additionally spread on their inner IP.

The tradeoff, documented in the dpaa2 guide, is that two tunnelled flows
sharing an inner IP but differing in their outer IP may hash to different
queues. A future generic RSS level (for example OUTER_INNER) could expose
the distinction explicitly if other PMDs are interested.

Note on timing: the reverted INNERMOST support is present only in the
26.07 release candidates (currently rc4) and has never appeared in a DPDK
release. This series should be applied before 26.07 is released, so the
broken behaviour never ships and no cross-release regression is left
behind.

Maxime Leroy (2):
  net/dpaa2: revert inner RSS level support
  net/dpaa2: hash inner IP for tunnelled traffic

 doc/guides/nics/dpaa2.rst              |  3 +
 doc/guides/rel_notes/release_26_07.rst |  3 +-
 drivers/net/dpaa2/base/dpaa2_hw_dpni.c | 82 ++++++++++----------------
 drivers/net/dpaa2/dpaa2_ethdev.c       |  3 +-
 4 files changed, 36 insertions(+), 55 deletions(-)

-- 
2.43.0


^ permalink raw reply

* [PATCH v1 1/2] net/dpaa2: revert inner RSS level support
From: Maxime Leroy @ 2026-07-20 13:34 UTC (permalink / raw)
  To: dev; +Cc: thomas, david.marchand, hemant.agrawal, Maxime Leroy
In-Reply-To: <20260630123857.392884-1-maxime@leroys.fr>

This reverts commit 618a06c53d479ae576ff01c7d274b10c60b3d3d5.

RTE_ETH_RSS_LEVEL_INNERMOST was mapped to the innermost IP instance by
programming the IP key extracts with hdr_index = HDR_INDEX_LAST. The
hardware only resolves that index when several IP headers are stacked.
A non-tunnelled frame carries a single IP header, so the extract
resolves to nothing, the RSS hash is constant and every such frame is
steered to a single Rx queue.

The ethdev API defines INNERMOST by encapsulation level, not by the
presence of a tunnel: a plain frame's innermost header is its only IP
header and must be hashed. The dpaa2 hardware cannot honour that and
keep true inner-only semantics for tunnelled traffic at the same time,
so the level cannot be implemented correctly as merged.

Revert it. Hashing the outer plus the inner IP under the PMD default
level, which spreads both plain and tunnelled traffic, is added in a
follow-up.

Signed-off-by: Maxime Leroy <maxime@leroys.fr>
---
 doc/guides/rel_notes/release_26_07.rst |  1 -
 drivers/net/dpaa2/base/dpaa2_hw_dpni.c | 23 -----------------------
 drivers/net/dpaa2/dpaa2_ethdev.c       |  3 +--
 3 files changed, 1 insertion(+), 26 deletions(-)

diff --git a/doc/guides/rel_notes/release_26_07.rst b/doc/guides/rel_notes/release_26_07.rst
index 6badd6d91b..6a528e4a0d 100644
--- a/doc/guides/rel_notes/release_26_07.rst
+++ b/doc/guides/rel_notes/release_26_07.rst
@@ -162,7 +162,6 @@ New Features
 
 * **Updated NXP dpaa2 driver.**
 
-  * Added inner RSS level support for tunnelled traffic.
   * Added RSS RETA query and update support.
   * Removed the software VLAN strip offload:
     ``RTE_ETH_RX_OFFLOAD_VLAN_STRIP`` is no longer advertised,
diff --git a/drivers/net/dpaa2/base/dpaa2_hw_dpni.c b/drivers/net/dpaa2/base/dpaa2_hw_dpni.c
index 07f4a3d414..26ad105c73 100644
--- a/drivers/net/dpaa2/base/dpaa2_hw_dpni.c
+++ b/drivers/net/dpaa2/base/dpaa2_hw_dpni.c
@@ -236,13 +236,6 @@ dpaa2_remove_flow_dist(struct rte_eth_dev *eth_dev,
 	return ret;
 }
 
-/* dpkg from_hdr.hdr_index value selecting the innermost IP instance (see
- * fsl_dpkg.h, where hdr_index is only defined for NET_PROT_IP/IPv4/IPv6/
- * VLAN/MPLS). Used to hash on the inner IP of tunnelled traffic when
- * RTE_ETH_RSS_LEVEL_INNERMOST is requested.
- */
-#define DPAA2_DIST_HDR_INDEX_LAST 0xff
-
 int
 dpaa2_distset_to_dpkg_profile_cfg(
 		uint64_t req_dist_set,
@@ -257,18 +250,8 @@ dpaa2_distset_to_dpkg_profile_cfg(
 	int esp_configured = 0;
 	int ah_configured = 0;
 	int pppoe_configured = 0;
-	uint8_t hdr_index = 0;
 
 	memset(kg_cfg, 0, sizeof(struct dpkg_profile_cfg));
-
-	/* RTE_ETH_RSS_LEVEL_INNERMOST asks for the inner header to be hashed.
-	 * Map it to the innermost IP instance in the key extracts; the level
-	 * bits are not protocol bits, so strip them before the loop.
-	 */
-	if ((req_dist_set & RTE_ETH_RSS_LEVEL_MASK) == RTE_ETH_RSS_LEVEL_INNERMOST)
-		hdr_index = DPAA2_DIST_HDR_INDEX_LAST;
-	req_dist_set &= ~RTE_ETH_RSS_LEVEL_MASK;
-
 	while (req_dist_set) {
 		if (req_dist_set % 2 != 0) {
 			dist_field = 1ULL << loop;
@@ -406,8 +389,6 @@ dpaa2_distset_to_dpkg_profile_cfg(
 
 				kg_cfg->extracts[i].extract.from_hdr.prot =
 					NET_PROT_IP;
-				kg_cfg->extracts[i].extract.from_hdr.hdr_index =
-					hdr_index;
 				kg_cfg->extracts[i].extract.from_hdr.field =
 					NH_FLD_IP_SRC;
 				kg_cfg->extracts[i].type =
@@ -418,8 +399,6 @@ dpaa2_distset_to_dpkg_profile_cfg(
 
 				kg_cfg->extracts[i].extract.from_hdr.prot =
 					NET_PROT_IP;
-				kg_cfg->extracts[i].extract.from_hdr.hdr_index =
-					hdr_index;
 				kg_cfg->extracts[i].extract.from_hdr.field =
 					NH_FLD_IP_DST;
 				kg_cfg->extracts[i].type =
@@ -430,8 +409,6 @@ dpaa2_distset_to_dpkg_profile_cfg(
 
 				kg_cfg->extracts[i].extract.from_hdr.prot =
 					NET_PROT_IP;
-				kg_cfg->extracts[i].extract.from_hdr.hdr_index =
-					hdr_index;
 				kg_cfg->extracts[i].extract.from_hdr.field =
 					NH_FLD_IP_PROTO;
 				kg_cfg->extracts[i].type =
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index 53ea060a4c..f211357919 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -453,8 +453,7 @@ dpaa2_dev_info_get(struct rte_eth_dev *dev,
 	dev_info->max_hash_mac_addrs = 0;
 	dev_info->max_vfs = 0;
 	dev_info->max_vmdq_pools = RTE_ETH_16_POOLS;
-	dev_info->flow_type_rss_offloads = DPAA2_RSS_OFFLOAD_ALL |
-		RTE_ETH_RSS_LEVEL_OUTERMOST | RTE_ETH_RSS_LEVEL_INNERMOST;
+	dev_info->flow_type_rss_offloads = DPAA2_RSS_OFFLOAD_ALL;
 	/* DPAA2 has no software-visible indirection table: incoming packets are
 	 * dispatched to FQs via 'queue_id = hash % dist_size'. We expose the
 	 * standard RETA API as an emulation that only accepts uniform patterns
-- 
2.43.0


^ permalink raw reply related

* [PATCH v1 2/2] net/dpaa2: hash inner IP for tunnelled traffic
From: Maxime Leroy @ 2026-07-20 13:34 UTC (permalink / raw)
  To: dev; +Cc: thomas, david.marchand, hemant.agrawal, Maxime Leroy
In-Reply-To: <20260630123857.392884-1-maxime@leroys.fr>

The RSS key only extracted the outer IP header. Tunnelled traffic whose
outer headers are fixed then carries no entropy for the hash, so every
flow lands on a single Rx queue.

Extract both the outer IP (header index 0) and the innermost IP instance
(HDR_INDEX_LAST). Plain frames keep being hashed on their only IP header;
the inner extract resolves to nothing and adds no entropy. Tunnelled
frames are also hashed on their inner IP and spread across the Rx queues.

This is the PMD default hash: dpaa2 does not expose the ethdev RSS level
selector, so it applies to every RSS request. The hardware cannot hash
the inner IP alone, as HDR_INDEX_LAST only resolves when several IP
headers are stacked and a plain frame would hash to a constant. Folding
the outer IP into the key is therefore unavoidable, and two tunnelled
flows that share an inner IP but differ in their outer IP may hash to
different queues. This is documented in the dpaa2 guide.

Signed-off-by: Maxime Leroy <maxime@leroys.fr>
---
 doc/guides/nics/dpaa2.rst              |  3 ++
 doc/guides/rel_notes/release_26_07.rst |  2 +
 drivers/net/dpaa2/base/dpaa2_hw_dpni.c | 63 +++++++++++++-------------
 3 files changed, 37 insertions(+), 31 deletions(-)

diff --git a/doc/guides/nics/dpaa2.rst b/doc/guides/nics/dpaa2.rst
index ae8b32af2c..aaaf5f9713 100644
--- a/doc/guides/nics/dpaa2.rst
+++ b/doc/guides/nics/dpaa2.rst
@@ -588,6 +588,9 @@ Other Limitations
 
 - RSS hash key cannot be modified.
 - RSS RETA cannot be configured.
+- RSS hashes on both the outer and the inner IP header. Tunnelled flows
+  that share the same inner IP but differ in their outer IP may therefore
+  be steered to different Rx queues.
 
 .. _dpaa2_dptmapi:
 
diff --git a/doc/guides/rel_notes/release_26_07.rst b/doc/guides/rel_notes/release_26_07.rst
index 6a528e4a0d..c952512023 100644
--- a/doc/guides/rel_notes/release_26_07.rst
+++ b/doc/guides/rel_notes/release_26_07.rst
@@ -163,6 +163,8 @@ New Features
 * **Updated NXP dpaa2 driver.**
 
   * Added RSS RETA query and update support.
+  * Added the inner IP header to the RSS hash so tunnelled traffic is
+    distributed across the Rx queues.
   * Removed the software VLAN strip offload:
     ``RTE_ETH_RX_OFFLOAD_VLAN_STRIP`` is no longer advertised,
     as no hardware strip backs it.
diff --git a/drivers/net/dpaa2/base/dpaa2_hw_dpni.c b/drivers/net/dpaa2/base/dpaa2_hw_dpni.c
index 26ad105c73..5bb9ad4591 100644
--- a/drivers/net/dpaa2/base/dpaa2_hw_dpni.c
+++ b/drivers/net/dpaa2/base/dpaa2_hw_dpni.c
@@ -236,6 +236,9 @@ dpaa2_remove_flow_dist(struct rte_eth_dev *eth_dev,
 	return ret;
 }
 
+/* hdr_index selecting the innermost IP instance in a dpkg extract */
+#define DPAA2_DIST_HDR_INDEX_LAST 0xff
+
 int
 dpaa2_distset_to_dpkg_profile_cfg(
 		uint64_t req_dist_set,
@@ -381,42 +384,40 @@ dpaa2_distset_to_dpkg_profile_cfg(
 			case RTE_ETH_RSS_IPV6:
 			case RTE_ETH_RSS_FRAG_IPV6:
 			case RTE_ETH_RSS_NONFRAG_IPV6_OTHER:
-			case RTE_ETH_RSS_IPV6_EX:
+			case RTE_ETH_RSS_IPV6_EX: {
+				static const uint32_t ip_fields[] = {
+					NH_FLD_IP_SRC, NH_FLD_IP_DST,
+					NH_FLD_IP_PROTO };
+				static const uint8_t ip_hdr_index[] = {
+					0, DPAA2_DIST_HDR_INDEX_LAST };
+				unsigned int f, h;
 
 				if (l3_configured)
 					break;
 				l3_configured = 1;
 
-				kg_cfg->extracts[i].extract.from_hdr.prot =
-					NET_PROT_IP;
-				kg_cfg->extracts[i].extract.from_hdr.field =
-					NH_FLD_IP_SRC;
-				kg_cfg->extracts[i].type =
-					DPKG_EXTRACT_FROM_HDR;
-				kg_cfg->extracts[i].extract.from_hdr.type =
-					DPKG_FULL_FIELD;
-				i++;
-
-				kg_cfg->extracts[i].extract.from_hdr.prot =
-					NET_PROT_IP;
-				kg_cfg->extracts[i].extract.from_hdr.field =
-					NH_FLD_IP_DST;
-				kg_cfg->extracts[i].type =
-					DPKG_EXTRACT_FROM_HDR;
-				kg_cfg->extracts[i].extract.from_hdr.type =
-					DPKG_FULL_FIELD;
-				i++;
-
-				kg_cfg->extracts[i].extract.from_hdr.prot =
-					NET_PROT_IP;
-				kg_cfg->extracts[i].extract.from_hdr.field =
-					NH_FLD_IP_PROTO;
-				kg_cfg->extracts[i].type =
-					DPKG_EXTRACT_FROM_HDR;
-				kg_cfg->extracts[i].extract.from_hdr.type =
-					DPKG_FULL_FIELD;
-				i++;
-			break;
+				/* Hash on the outer IP (index 0) and the innermost
+				 * IP instance. A plain frame has a single IP header,
+				 * so only the outer extract resolves; a tunnelled
+				 * frame resolves both and is also spread on its inner
+				 * IP.
+				 */
+				for (h = 0; h < RTE_DIM(ip_hdr_index); h++)
+					for (f = 0; f < RTE_DIM(ip_fields); f++) {
+						kg_cfg->extracts[i].extract.from_hdr.prot =
+							NET_PROT_IP;
+						kg_cfg->extracts[i].extract.from_hdr.hdr_index =
+							ip_hdr_index[h];
+						kg_cfg->extracts[i].extract.from_hdr.field =
+							ip_fields[f];
+						kg_cfg->extracts[i].type =
+							DPKG_EXTRACT_FROM_HDR;
+						kg_cfg->extracts[i].extract.from_hdr.type =
+							DPKG_FULL_FIELD;
+						i++;
+					}
+				break;
+			}
 
 			case RTE_ETH_RSS_NONFRAG_IPV4_TCP:
 			case RTE_ETH_RSS_NONFRAG_IPV6_TCP:
-- 
2.43.0


^ permalink raw reply related

* [DPDK/ethdev Bug 1971] [net/mlx5] PF initialization inside DPDK app conflicts with kernel bond on neighbouring port
From: bugzilla @ 2026-07-20 14:55 UTC (permalink / raw)
  To: dev

http://bugs.dpdk.org/show_bug.cgi?id=1971

            Bug ID: 1971
           Summary: [net/mlx5] PF initialization inside DPDK app conflicts
                    with kernel bond on neighbouring port
           Product: DPDK
           Version: 26.07
          Hardware: x86
                OS: Linux
            Status: UNCONFIRMED
          Severity: normal
          Priority: Normal
         Component: ethdev
          Assignee: dev@dpdk.org
          Reporter: volodia.bond@gmail.com
  Target Milestone: ---

## Overview

Seems like false positive detection of PF being a part of kernel bond and/or
wrong IBV device is assigned to DPDK ports when initialized along kernel bond.

Works with DPDK 25.03, possible regression after DPDK 26.03.

## Hardware and environment
* Debian 13 (trixie)
* 2 x ConnectX-6 Dx (MT2892 Family)
* Ethtool Info: 
```
driver: mlx5_core
version: 6.12.94+deb13-amd64
firmware-version: 22.48.1000 (MT_0000000436)
```
* DPDK: main@bcd1686caa94aed1edf9f25dd1cc51175cedd1b7 (20.07.2026)
* Kernel devices: ens6f0np0 (38.00.0), ens6f1np1 (38.00.1), ens11f0np0
(98:00.0), ens11f0np0 (98:00.1)

* Network setup (might be simplified, but dunno if vlan/LAG matters)
```
# 1 port from each ConnectX-6 is bonded, remaining ports are used by DPDK.

S (server) <-> SW <-> C (client)

1. kernel bond <-> [ens6f1np1 + ens11f1np1] <-> trunk LAG, vlan.111
2. DPDK <-> [ens6f0np0 + ens11f0np0] <-> trunk LAG, vlan.222 

C (client) should reach:
1. server bond IP via (ens6f1np1 | ens11f1np1) on vlan.111
2. [OPTIONAL] DPDK ports (ens6f0np0 | ens11f0np0) on vlan.222
```

## Steps to reproduce

1. Initilal state - testpmd is not running, no bond device present
2. Initialize bond device (IP network should match client subnet):
```
ip link del dev bond0 >/dev/null 2>&1 
ip link add bond0 type bond mode balance-rr 
ip link set ens6f1np1 down 
ip link set ens11f1np1 down 
ip link set ens6f1np1 master bond0 
ip link set ens11f1np1 master bond0 
ip link set bond0 up 
ip link add link bond0 name test.111 type vlan id 111 
ip addr add dev test.111 11.11.0.2/16 ip link set dev test.111 up
```
3. Start testpmd on non-bonded devices:
```
dpdk-testpmd --in-memory --no-telemetry -a 0000:38:00.0 -a 0000:98:00.0 -- -a
--forward-mode rxonly
```
4. Start C -> S pings via vlan.111 (targeting kernel bond)
5. Start tcpdump on bonded interfaces: 
```
tcpdump -eni ens6f1np1
tcpdump -eni ens11f1np1
```

## Expected results
Bond device is accessible, ping is working, ICMP traffic is captured by
tcpdump.

## Actual results
No pings to bond device, no ICMP packets captured.

-- 
You are receiving this mail because:
You are the assignee for the bug.

^ permalink raw reply

* please help backporting some patches to stable release 24.11.7
From: luca.boccassi @ 2026-07-20 17:45 UTC (permalink / raw)
  To: dpdk
  Cc: dpdk stable, Geoff Thorpe, Hemant Agrawal, Roy Pledge,
	Sachin Saxena, Shreyansh Jain

Hi commit authors (and maintainers),

Despite being selected by the DPDK maintenance tool ./devtools/git-log-fixes.sh
I didn't apply following commits from DPDK main to 24.11
stable branch, as conflicts or build errors occur.

Can authors check your patches in the following list and either:
    - Backport your patches to the 24.11 branch, or
    - Indicate that the patch should not be backported

Please do either of the above by 07/27/26.

You can find the a temporary work-in-progress branch of the coming 24.11.7
release at:
    https://github.com/bluca/dpdk-stable
It is recommended to backport on top of that to minimize further conflicts or
misunderstandings.

Some notes on stable backports:

A backport should contain a reference to the DPDK main branch commit
in it's commit message in the following fashion:
    [ upstream commit <commit's dpdk main branch SHA-1 checksum> ]

For example:
    https://git.dpdk.org/dpdk-stable/commit/?h=18.11&id=d90e6ae6f936ecdc2fd3811ff9f26aec7f3c06eb

When sending the backported patch, please indicate the target branch in the
subject line, as we have multiple branches, for example:
    [PATCH 24.11] foo/bar: fix baz

With git format-patch, this can be achieved by appending the parameter:
    --subject-prefix='PATCH 24.11'

Send the backported patch to "stable@dpdk.org" but not "dev@dpdk.org".

FYI, branch 24.11 is located at tree:
   https://git.dpdk.org/dpdk-stable

Thanks.

Luca Boccassi

---
b1401a464b  Hemant Agrawal   bus/dpaa: fix FQID endianness

^ permalink raw reply

* RE: [PATCH v3] net/enic: check notify set return value during init
From: Hyong Youb Kim (hyonkim) @ 2026-07-20 22:56 UTC (permalink / raw)
  To: Alexey Simakov
  Cc: david.marchand@redhat.com, dev@dpdk.org, John Daley (johndale),
	ssujith@cisco.com, stable@dpdk.org
In-Reply-To: <20260720093338.92744-2-bigalex934@gmail.com>



> -----Original Message-----
> From: Alexey Simakov <bigalex934@gmail.com>
> Sent: Monday, July 20, 2026 6:34 PM
> To: Hyong Youb Kim (hyonkim) <hyonkim@cisco.com>
> Cc: david.marchand@redhat.com; dev@dpdk.org; John Daley (johndale)
> <johndale@cisco.com>; ssujith@cisco.com; stable@dpdk.org; Alexey Simakov
> <bigalex934@gmail.com>
> Subject: [PATCH v3] net/enic: check notify set return value during init
> 
> The return value of vnic_dev_notify_set() is silently ignored in
> enic_dev_init(), so a memory allocation failure or hardware command
> error goes unnoticed and the driver continues with uninitialized
> notification state.
> 
> Check the return value and propagate the error to abort probe when
> notification setup fails.
> 
> Fixes: fefed3d1e62c ("enic: new driver")
> Cc: stable@dpdk.org
> 
> Signed-off-by: Alexey Simakov <bigalex934@gmail.com>
> ---
> 
> v3 changes: add log message
> 
> v2 link: https://patches.dpdk.org/project/dpdk/patch/20260715103105.39417-
> 1-bigalex934@gmail.com/
> v2 changes: validate return code of vnic_dev_notify_set() in driver init section
> 
> v1 link: https://patches.dpdk.org/project/dpdk/patch/20260707112014.82821-
> 1-bigalex934@gmail.com/
> 
>  drivers/net/enic/enic_main.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
> index 2696fa77d4..2a1a65d8da 100644
> --- a/drivers/net/enic/enic_main.c
> +++ b/drivers/net/enic/enic_main.c
> @@ -1887,7 +1887,11 @@ static int enic_dev_init(struct enic *enic)
>  	LIST_INIT(&enic->flows);
> 
>  	/* set up link status checking */
> -	vnic_dev_notify_set(enic->vdev, -1); /* No Intr for notify */
> +	err = vnic_dev_notify_set(enic->vdev, -1); /* No Intr for notify */
> +	if (err) {
> +		dev_err(enic, "failed to enable notify buffer\n");
> +		return err;
> +	}
> 

Acked-by: Hyong Youb Kim <hyonkim@cisco.com>

Thanks.
-Hyong

>  	enic->overlay_offload = false;
>  	/*
> --
> 2.53.0


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox