* DPDK 24.11.6 released
From: luca.boccassi @ 2026-05-19 10:27 UTC (permalink / raw)
To: announce
Hi all,
Here is a new stable release:
https://fast.dpdk.org/rel/dpdk-24.11.6.tar.xz
The git tree is at:
https://dpdk.org/browse/dpdk-stable/?h=24.11
Luca Boccassi
---
VERSION | 2 +-
doc/guides/rel_notes/release_24_11.rst | 17 +++++++++++++++++
lib/net/rte_net.c | 29 +++++++++++++++--------------
3 files changed, 33 insertions(+), 15 deletions(-)
Luca Boccassi (3):
docs: fix build issue due to missing spacing between paragraphs
Revert "net: fix packet type for stacked VLAN"
version: 24.11.6
^ permalink raw reply
* Re: [PATCH v2 1/2] spinlock: remove volatile qualifier
From: Thomas Monjalon @ 2026-05-19 10:35 UTC (permalink / raw)
To: Robin Jarry
Cc: Bruce Richardson, dev, Stephen Hemminger, Konstantin Ananyev,
stable
In-Reply-To: <DIMJH4P7RJRX.3PUWC7L1KC4I8@redhat.com>
19/05/2026 11:17, Robin Jarry:
> Bruce Richardson, May 18, 2026 at 17:28:
> > On Mon, May 18, 2026 at 05:25:43PM +0200, Thomas Monjalon wrote:
> >> 18/05/2026 17:14, Robin Jarry:
> >> > Thomas Monjalon, May 18, 2026 at 17:07:
> >> > > @@ -246,10 +246,9 @@ static inline void rte_spinlock_recursive_unlock(rte_spinlock_recursive_t *slr)
> >> > > __rte_no_thread_safety_analysis
> >> > > {
> >> > > if (--(slr->count) == 0) {
> >> >
> >> > This code is completely broken. Any thread can unlock without any check.
> >>
> >> Maybe, but I don't intend to fix recursive unlock in this patch.
> >> The subject is "remove volatile qualifier" (and unblock GCC 16).
> >>
> > As with regular mutexes, threads should not go around unlocking when not
> > holding the lock. Therefore, I think this is fine. [With regular spinlocks
> > we can't check since we don't track threads, therefore I think we just need
> > to assume a well-behaved app.]
>
> Ok, fair enough :)
>
> As Stephen suggested, maybe we could add some assertions?
>
> static inline void rte_spinlock_recursive_unlock(rte_spinlock_recursive_t *slr)
> __rte_no_thread_safety_analysis
> {
> + RTE_ASSERT(rte_atomic_load_explicit(&slr->user, rte_memory_order_relaxed) == rte_gettid());
> + RTE_ASSERT(slr->count > 0);
> +
OK I add it as a separate patch in v3.
^ permalink raw reply
* [PATCH v3 1/3] spinlock: remove volatile qualifier
From: Thomas Monjalon @ 2026-05-19 10:34 UTC (permalink / raw)
To: dev
Cc: Stephen Hemminger, Konstantin Ananyev, Bruce Richardson,
Robin Jarry, stable
In-Reply-To: <20260504083714.2904729-1-thomas@monjalon.net>
When compiling with C++20 standard requirement (default in GCC 16),
the increment and decrement of volatile variables are rejected:
rte_spinlock.h:241:14: error:
'++' expression of 'volatile'-qualified type is deprecated
rte_spinlock.h:252:21: error:
'--' expression of 'volatile'-qualified type is deprecated
rte_spinlock.h:278:14: error:
'++' expression of 'volatile'-qualified type is deprecated
The count field of rte_spinlock_recursive_t
does not need the volatile qualifier
because it is only accessed by the thread holding the lock,
which already provides the necessary memory ordering.
The user field can be accessed outside of the lock,
so it must handled as a C11 atomic variable.
The name is also changed from user to owner.
It will break if an application is accessing this field directly,
which should never happen.
Fixes: af75078fece3 ("first public release")
Cc: stable@dpdk.org
Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
v1: drop volatile keyword
v2: make user an atomic variable
v3: rename user as owner
---
lib/eal/include/generic/rte_spinlock.h | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/lib/eal/include/generic/rte_spinlock.h b/lib/eal/include/generic/rte_spinlock.h
index c907d4e45c..ffdcb8fa3d 100644
--- a/lib/eal/include/generic/rte_spinlock.h
+++ b/lib/eal/include/generic/rte_spinlock.h
@@ -197,8 +197,8 @@ rte_spinlock_trylock_tm(rte_spinlock_t *sl)
*/
typedef struct {
rte_spinlock_t sl; /**< the actual spinlock */
- volatile int user; /**< core id using lock, -1 for unused */
- volatile int count; /**< count of time this lock has been called */
+ RTE_ATOMIC(int) owner; /**< core id using lock, -1 for unused */
+ int count; /**< count of time this lock has been called */
} rte_spinlock_recursive_t;
/**
@@ -215,7 +215,7 @@ typedef struct {
static inline void rte_spinlock_recursive_init(rte_spinlock_recursive_t *slr)
{
rte_spinlock_init(&slr->sl);
- slr->user = -1;
+ rte_atomic_store_explicit(&slr->owner, -1, rte_memory_order_relaxed);
slr->count = 0;
}
@@ -230,9 +230,9 @@ static inline void rte_spinlock_recursive_lock(rte_spinlock_recursive_t *slr)
{
int id = rte_gettid();
- if (slr->user != id) {
+ if (rte_atomic_load_explicit(&slr->owner, rte_memory_order_relaxed) != id) {
rte_spinlock_lock(&slr->sl);
- slr->user = id;
+ rte_atomic_store_explicit(&slr->owner, id, rte_memory_order_relaxed);
}
slr->count++;
}
@@ -246,10 +246,9 @@ static inline void rte_spinlock_recursive_unlock(rte_spinlock_recursive_t *slr)
__rte_no_thread_safety_analysis
{
if (--(slr->count) == 0) {
- slr->user = -1;
+ rte_atomic_store_explicit(&slr->owner, -1, rte_memory_order_relaxed);
rte_spinlock_unlock(&slr->sl);
}
-
}
/**
@@ -266,10 +265,10 @@ static inline int rte_spinlock_recursive_trylock(rte_spinlock_recursive_t *slr)
{
int id = rte_gettid();
- if (slr->user != id) {
+ if (rte_atomic_load_explicit(&slr->owner, rte_memory_order_relaxed) != id) {
if (rte_spinlock_trylock(&slr->sl) == 0)
return 0;
- slr->user = id;
+ rte_atomic_store_explicit(&slr->owner, id, rte_memory_order_relaxed);
}
slr->count++;
return 1;
--
2.54.0
^ permalink raw reply related
* [PATCH v3 2/3] spinlock: add debug checks in recursive unlock
From: Thomas Monjalon @ 2026-05-19 10:34 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger, Konstantin Ananyev, Bruce Richardson,
Robin Jarry
In-Reply-To: <20260519103640.3986710-1-thomas@monjalon.net>
The recursive unlock assumes that the caller owns the lock.
This behavior will be checked when RTE_ENABLE_ASSERT is on.
There is an additional check for the count which should be positive
if no corruption happened.
Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
v3: new patch in the series
---
lib/eal/include/generic/rte_spinlock.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/lib/eal/include/generic/rte_spinlock.h b/lib/eal/include/generic/rte_spinlock.h
index ffdcb8fa3d..e7cd18a8e2 100644
--- a/lib/eal/include/generic/rte_spinlock.h
+++ b/lib/eal/include/generic/rte_spinlock.h
@@ -21,6 +21,7 @@
#ifdef RTE_FORCE_INTRINSICS
#include <rte_common.h>
#endif
+#include <rte_debug.h>
#include <rte_lock_annotations.h>
#include <rte_pause.h>
#include <rte_stdatomic.h>
@@ -245,6 +246,8 @@ static inline void rte_spinlock_recursive_lock(rte_spinlock_recursive_t *slr)
static inline void rte_spinlock_recursive_unlock(rte_spinlock_recursive_t *slr)
__rte_no_thread_safety_analysis
{
+ RTE_ASSERT(rte_atomic_load_explicit(&slr->owner, rte_memory_order_relaxed) == rte_gettid());
+ RTE_ASSERT(slr->count > 0);
if (--(slr->count) == 0) {
rte_atomic_store_explicit(&slr->owner, -1, rte_memory_order_relaxed);
rte_spinlock_unlock(&slr->sl);
--
2.54.0
^ permalink raw reply related
* [PATCH v3 3/3] spinlock: fix API comments
From: Thomas Monjalon @ 2026-05-19 10:34 UTC (permalink / raw)
To: dev
Cc: Stephen Hemminger, Konstantin Ananyev, Bruce Richardson,
Robin Jarry, stable, Cunming Liang, Olivier Matz
In-Reply-To: <20260519103640.3986710-1-thomas@monjalon.net>
This is not a read-write lock.
The user field stores the thread ID, not the core ID
since a change in DPDK 2.0.0.
The implementation is architecture-specific in some cases only.
Fixes: ca2e2dab079a ("spinlock: support non-EAL thread")
Fixes: af75078fece3 ("first public release")
Cc: stable@dpdk.org
Reported-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---
lib/eal/include/generic/rte_spinlock.h | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/lib/eal/include/generic/rte_spinlock.h b/lib/eal/include/generic/rte_spinlock.h
index e7cd18a8e2..dd3d2d046c 100644
--- a/lib/eal/include/generic/rte_spinlock.h
+++ b/lib/eal/include/generic/rte_spinlock.h
@@ -7,12 +7,16 @@
/**
* @file
+ * DPDK spinlocks
*
- * RTE Spinlocks
+ * This is an API for spinlocks.
+ * This kind of lock simply waits in a loop
+ * repeatedly checking until the lock becomes available.
*
- * This file defines an API for read-write locks, which are implemented
- * in an architecture-specific way. This kind of lock simply waits in
- * a loop repeatedly checking until the lock becomes available.
+ * Some functions may have an architecture-specific implementation
+ * if RTE_FORCE_INTRINSICS is disabled.
+ * The hardware transactional memory (lock elision) functions have _tm suffix
+ * and are implemented in architecture-specific files.
*
* All locks must be initialised before use, and only initialised once.
*/
@@ -198,7 +202,7 @@ rte_spinlock_trylock_tm(rte_spinlock_t *sl)
*/
typedef struct {
rte_spinlock_t sl; /**< the actual spinlock */
- RTE_ATOMIC(int) owner; /**< core id using lock, -1 for unused */
+ RTE_ATOMIC(int) owner; /**< thread id owning lock, -1 for unused */
int count; /**< count of time this lock has been called */
} rte_spinlock_recursive_t;
--
2.54.0
^ permalink raw reply related
* Re: [PATCH v2] net/intel: optimize for fast-free hint
From: Bruce Richardson @ 2026-05-19 11:01 UTC (permalink / raw)
To: Morten Brørup; +Cc: dev
In-Reply-To: <98CBD80474FA8B44BF855DF32C47DC35F657DE@smartserver.smartshare.dk>
On Wed, Apr 08, 2026 at 09:27:11PM +0200, Morten Brørup wrote:
> > From: Bruce Richardson [mailto:bruce.richardson@intel.com]
> > Sent: Wednesday, 8 April 2026 15.25
> >
> > When the fast-free hint is provided to the driver we know that the
> > mbufs
> > have refcnt of 1 and are from the same mempool. Therefore, we can
> > optimize a bit for this case by:
> >
> > * resetting the necessary mbuf fields, ie. nb_seg and next pointer when
> > we are accessing the mbuf on writing the descriptor.
> > * on cleanup of buffers after transmit, we can just write those buffers
> > straight to the mempool without accessing them.
> >
> > Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
>
> A bunch of review thoughts inline below.
> The ones regarding instrumentation should be fixed.
> The rest might be irrelevant and/or nonsense.
>
See inline below. Summary:
* ack for mempool functions for instrumentation
* ack for referencing the mp pointer rather than the offload flags
* nak for setting the mbuf pointers for null, it's unnecessary with this
design.
* ack for removing the prefetches
Thanks for the detailed review. Preparing v3 now.
/Bruce
> > ---
> > V2: Fix issues with original submission:
> > * missed check for NULL mbufs
> > * fixed issue with freeing directly from sw_ring in scalar path which
> > doesn't work as thats not a flag array of pointers
> > * fixed missing null assignment in case of large segments for TSO
> > ---
> > drivers/net/intel/common/tx.h | 21 ++++--
> > drivers/net/intel/common/tx_scalar.h | 95 ++++++++++++++++++++++------
> > 2 files changed, 90 insertions(+), 26 deletions(-)
> >
> > diff --git a/drivers/net/intel/common/tx.h
> > b/drivers/net/intel/common/tx.h
> > index 283bd58d5d..f2123f069c 100644
> > --- a/drivers/net/intel/common/tx.h
> > +++ b/drivers/net/intel/common/tx.h
> > @@ -363,13 +363,22 @@ ci_txq_release_all_mbufs(struct ci_tx_queue *txq,
> > bool use_ctx)
> > return;
> >
> > if (!txq->use_vec_entry) {
> > - /* Regular scalar path uses sw_ring with ci_tx_entry */
> > - for (uint16_t i = 0; i < txq->nb_tx_desc; i++) {
> > - if (txq->sw_ring[i].mbuf != NULL) {
> > - rte_pktmbuf_free_seg(txq->sw_ring[i].mbuf);
> > - txq->sw_ring[i].mbuf = NULL;
> > - }
> > + /* Free mbufs from (last_desc_cleaned + 1) to (tx_tail -
> > 1). */
> > + const uint16_t start = (txq->last_desc_cleaned + 1) % txq-
> > >nb_tx_desc;
> > + const uint16_t nb_desc = txq->nb_tx_desc;
> > + const uint16_t end = txq->tx_tail;
> > +
> > + uint16_t i = start;
> > + if (end < i) {
> > + for (; i < nb_desc; i++)
> > + if (txq->sw_ring[i].mbuf != NULL)
> > + rte_pktmbuf_free_seg(txq-
> > >sw_ring[i].mbuf);
> > + i = 0;
> > }
> > + for (; i < end; i++)
> > + if (txq->sw_ring[i].mbuf != NULL)
> > + rte_pktmbuf_free_seg(txq->sw_ring[i].mbuf);
> > + memset(txq->sw_ring, 0, sizeof(txq->sw_ring[0]) * nb_desc);
> > return;
> > }
>
> The above LGTM.
> IIRC, we already discussed it - or something very similar.
>
> >
> > diff --git a/drivers/net/intel/common/tx_scalar.h
> > b/drivers/net/intel/common/tx_scalar.h
> > index 9fcd2e4733..adbc4bafee 100644
> > --- a/drivers/net/intel/common/tx_scalar.h
> > +++ b/drivers/net/intel/common/tx_scalar.h
> > @@ -197,16 +197,63 @@ ci_tx_xmit_cleanup(struct ci_tx_queue *txq)
> > const uint16_t rs_idx = (last_desc_cleaned == nb_tx_desc - 1) ?
> > 0 :
> > (last_desc_cleaned + 1) >> txq->log2_rs_thresh;
> > - uint16_t desc_to_clean_to = (rs_idx << txq->log2_rs_thresh) +
> > (txq->tx_rs_thresh - 1);
> > + const uint16_t dd_idx = txq->rs_last_id[rs_idx];
> > + const uint16_t first_to_clean = rs_idx << txq->log2_rs_thresh;
> >
> > - /* Check if descriptor is done */
> > - if ((txd[txq->rs_last_id[rs_idx]].cmd_type_offset_bsz &
> > - rte_cpu_to_le_64(CI_TXD_QW1_DTYPE_M)) !=
> > - rte_cpu_to_le_64(CI_TX_DESC_DTYPE_DESC_DONE))
> > + /* Check if descriptor is done - all drivers use 0xF as done
> > value in bits 3:0 */
> > + if ((txd[dd_idx].cmd_type_offset_bsz &
> > rte_cpu_to_le_64(CI_TXD_QW1_DTYPE_M)) !=
> > + rte_cpu_to_le_64(CI_TX_DESC_DTYPE_DESC_DONE))
> > + /* Descriptor not yet processed by hardware */
> > return -1;
> >
> > + /* DD bit is set, descriptors are done. Now free the mbufs. */
> > + /* Note: nb_tx_desc is guaranteed to be a multiple of
> > tx_rs_thresh,
> > + * validated during queue setup. This means cleanup never wraps
> > around
> > + * the ring within a single burst (e.g., ring=256, rs_thresh=32
> > gives
> > + * bursts of 0-31, 32-63, ..., 224-255).
> > + */
> > + const uint16_t nb_to_clean = txq->tx_rs_thresh;
> > + struct ci_tx_entry *sw_ring = txq->sw_ring;
> > +
> > + if (txq->offloads & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE) {
> > + /* FAST_FREE path: mbufs are already reset, just return to
> > pool */
>
> Depending on which cache lines from txq have already been loaded, unless txq->offloads is hot in the CPU cache and txq->fast_free_mp is not, consider testing (mp != NULL) instead of (txq->offloads & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE).
> Like here:
> https://elixir.bootlin.com/dpdk/v26.03/source/drivers/net/intel/common/tx.h#L281
>
Ack. The offloads are on the second cacheline of the txq, I think, while
the fast_free_mp is on the first one. Therefore, checking the mp pointer
for null is slightly better.
> > + void *free[CI_TX_MAX_FREE_BUF_SZ];
> > + uint16_t nb_free = 0;
> > +
> > + /* Get cached mempool pointer, or cache it on first use */
> > + struct rte_mempool *mp =
> > + likely(txq->fast_free_mp != (void *)UINTPTR_MAX) ?
> > + txq->fast_free_mp :
> > + (txq->fast_free_mp = sw_ring[dd_idx].mbuf->pool);
> > +
> > + /* Pack non-NULL mbufs in-place at start of sw_ring range.
> > + * No modulo needed in loop since we're guaranteed not to
> > wrap.
> > + */
> > + for (uint16_t i = 0; i < nb_to_clean; i++) {
> > + struct rte_mbuf *m = sw_ring[first_to_clean +
> > i].mbuf;
> > + if (m == NULL)
> > + continue;
> > + free[nb_free++] = m;
>
> Should sw_ring[first_to_clean + i].mbuf be set to NULL here, instead of in ci_xmit_pkts()?
> I don't know, just want you to consider it.
No, we are ok just setting it there. The changes in this patch to the
ci_txq_release_all_mbufs() function mean that we assume all buffers between
tx_tail and last_desc_cleaned are invalid/freed (i.e. we free from
last-cleaned to tx_tail only), and so we don't need to set the invalid
slots to NULL. The NULL sentinel is only used where we have a valid slot
but which does not have an associated mbuf.
>
> > + if (unlikely(nb_free == CI_TX_MAX_FREE_BUF_SZ)) {
> > + rte_mempool_put_bulk(mp, free, nb_free);
>
> rte_mempool_put_bulk() -> rte_mbuf_raw_free_bulk(),
> for instrumentation.
>
Ack
> > + nb_free = 0;
> > + }
> > + }
> > +
> > + /* Bulk return to mempool using packed sw_ring entries
> > directly */
> > + if (nb_free > 0)
> > + rte_mempool_put_bulk(mp, free, nb_free);
>
> rte_mempool_put_bulk() -> rte_mbuf_raw_free_bulk(),
> for instrumentation.
Ack
>
> > + } else {
> > + /* Non-FAST_FREE path: use prefree_seg for refcount checks
> > */
> > + for (uint16_t i = 0; i < nb_to_clean; i++) {
> > + struct rte_mbuf *m = sw_ring[first_to_clean +
> > i].mbuf;
> > + if (m != NULL)
> > + rte_pktmbuf_free_seg(m);
>
> Should sw_ring[first_to_clean + i].mbuf be set to NULL here, instead of in ci_xmit_pkts()?
> I don't know, just want you to consider it.
>
As above, reason should hold for both fast-free and non-fast-free paths.
> > + }
> > + }
> > +
> > /* Update the txq to reflect the last descriptor that was cleaned
> > */
> > - txq->last_desc_cleaned = desc_to_clean_to;
> > + txq->last_desc_cleaned = first_to_clean + txq->tx_rs_thresh - 1;
> > txq->nb_tx_free += txq->tx_rs_thresh;
> >
> > return 0;
> > @@ -450,8 +497,6 @@ ci_xmit_pkts(struct ci_tx_queue *txq,
> > txd = &ci_tx_ring[tx_id];
> > tx_id = txe->next_id;
> >
> > - if (txe->mbuf)
> > - rte_pktmbuf_free_seg(txe->mbuf);
> > txe->mbuf = tx_pkt;
> > /* Setup TX Descriptor */
> > td_cmd |= CI_TX_DESC_CMD_EOP;
> > @@ -472,10 +517,7 @@ ci_xmit_pkts(struct ci_tx_queue *txq,
> >
> > txn = &sw_ring[txe->next_id];
> > RTE_MBUF_PREFETCH_TO_FREE(txn->mbuf);
>
> RTE_MBUF_PREFETCH_TO_FREE() doesn't seem relevant here anymore.
> I don't know if it fits into ci_tx_xmit_cleanup() instead.
Yes, dropping.
>
> > - if (txe->mbuf) {
> > - rte_pktmbuf_free_seg(txe->mbuf);
> > - txe->mbuf = NULL;
> > - }
> > + txe->mbuf = NULL;
>
> Already mentioned: Should txe->mbuf be set to NULL in ci_tx_xmit_cleanup() instead of in ci_tx_xmit_pkts()?
>
> >
> > write_txd(ctx_txd, cd_qw0, cd_qw1);
> >
> > @@ -489,10 +531,7 @@ ci_xmit_pkts(struct ci_tx_queue *txq,
> >
> > txn = &sw_ring[txe->next_id];
> > RTE_MBUF_PREFETCH_TO_FREE(txn->mbuf);
>
> RTE_MBUF_PREFETCH_TO_FREE() doesn't seem relevant here anymore.
> I don't know if it fits into ci_tx_xmit_cleanup() instead.
>
> > - if (txe->mbuf) {
> > - rte_pktmbuf_free_seg(txe->mbuf);
> > - txe->mbuf = NULL;
> > - }
> > + txe->mbuf = NULL;
>
> Already mentioned: Should txe->mbuf be set to NULL in ci_tx_xmit_cleanup() instead of in ci_tx_xmit_pkts()?
>
> >
> > ipsec_txd[0] = ipsec_qw0;
> > ipsec_txd[1] = ipsec_qw1;
> > @@ -507,10 +546,21 @@ ci_xmit_pkts(struct ci_tx_queue *txq,
> > txd = &ci_tx_ring[tx_id];
> > txn = &sw_ring[txe->next_id];
> >
> > - if (txe->mbuf)
> > - rte_pktmbuf_free_seg(txe->mbuf);
> > txe->mbuf = m_seg;
> >
> > + /* For FAST_FREE: reset mbuf fields while we have it
> > in cache.
> > + * FAST_FREE guarantees refcnt=1 and direct mbufs, so
> > we only
> > + * need to reset nb_segs and next pointer as per
> > rte_pktmbuf_prefree_seg.
> > + * Save next pointer before resetting since we need
> > it for loop iteration.
> > + */
> > + struct rte_mbuf *next_seg = m_seg->next;
> > + if (txq->offloads &
> > RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE) {
>
> Similar to comment further above: Is txq->offloads or txq->fast_free_mp hotter in the CPU cache here?
>
Updating as you suggest.
> > + if (m_seg->nb_segs != 1)
> > + m_seg->nb_segs = 1;
> > + if (next_seg != NULL)
> > + m_seg->next = NULL;
> > + }
> > +
> > /* Setup TX Descriptor */
> > /* Calculate segment length, using IPsec callback if
> > provided */
> > if (ipsec_ops != NULL)
> > @@ -528,18 +578,23 @@ ci_xmit_pkts(struct ci_tx_queue *txq,
> > ((uint64_t)CI_MAX_DATA_PER_TXD <<
> > CI_TXD_QW1_TX_BUF_SZ_S) |
> > ((uint64_t)td_tag <<
> > CI_TXD_QW1_L2TAG1_S);
> > write_txd(txd, buf_dma_addr,
> > cmd_type_offset_bsz);
> > + /* txe for this slot has already been written
> > (e.g. above outside
> > + * loop), so we write the extra NULL mbuf
> > pointer for this
> > + * descriptor after we increment txe below.
> > + */
> >
> > buf_dma_addr += CI_MAX_DATA_PER_TXD;
> > slen -= CI_MAX_DATA_PER_TXD;
> >
> > tx_id = txe->next_id;
> > txe = txn;
> > + txe->mbuf = NULL;
> > txd = &ci_tx_ring[tx_id];
> > txn = &sw_ring[txe->next_id];
> > }
> >
> > /* fill the last descriptor with End of Packet (EOP)
> > bit */
> > - if (m_seg->next == NULL)
> > + if (next_seg == NULL)
> > td_cmd |= CI_TX_DESC_CMD_EOP;
> >
> > const uint64_t cmd_type_offset_bsz =
> > CI_TX_DESC_DTYPE_DATA |
> > @@ -551,7 +606,7 @@ ci_xmit_pkts(struct ci_tx_queue *txq,
> >
> > tx_id = txe->next_id;
> > txe = txn;
> > - m_seg = m_seg->next;
> > + m_seg = next_seg;
> > } while (m_seg);
> > end_pkt:
> > txq->nb_tx_free = (uint16_t)(txq->nb_tx_free - nb_used);
> > --
> > 2.51.0
>
^ permalink raw reply
* Re: [PATCH v3 1/3] spinlock: remove volatile qualifier
From: Bruce Richardson @ 2026-05-19 11:03 UTC (permalink / raw)
To: Thomas Monjalon
Cc: dev, Stephen Hemminger, Konstantin Ananyev, Robin Jarry, stable
In-Reply-To: <20260519103640.3986710-1-thomas@monjalon.net>
On Tue, May 19, 2026 at 12:34:14PM +0200, Thomas Monjalon wrote:
> When compiling with C++20 standard requirement (default in GCC 16),
> the increment and decrement of volatile variables are rejected:
>
> rte_spinlock.h:241:14: error:
> '++' expression of 'volatile'-qualified type is deprecated
> rte_spinlock.h:252:21: error:
> '--' expression of 'volatile'-qualified type is deprecated
> rte_spinlock.h:278:14: error:
> '++' expression of 'volatile'-qualified type is deprecated
>
> The count field of rte_spinlock_recursive_t
> does not need the volatile qualifier
> because it is only accessed by the thread holding the lock,
> which already provides the necessary memory ordering.
>
> The user field can be accessed outside of the lock,
> so it must handled as a C11 atomic variable.
> The name is also changed from user to owner.
> It will break if an application is accessing this field directly,
> which should never happen.
>
> Fixes: af75078fece3 ("first public release")
> Cc: stable@dpdk.org
>
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> ---
> v1: drop volatile keyword
> v2: make user an atomic variable
> v3: rename user as owner
> ---
> lib/eal/include/generic/rte_spinlock.h | 17 ++++++++---------
> 1 file changed, 8 insertions(+), 9 deletions(-)
>
Series-acked-by: Bruce Richardson <bruce.richardson@intel.com>
^ permalink raw reply
* [PATCH v3] net/intel: optimize for fast-free hint
From: Bruce Richardson @ 2026-05-19 11:06 UTC (permalink / raw)
To: dev; +Cc: mb, Bruce Richardson
In-Reply-To: <20260123112032.2174361-1-bruce.richardson@intel.com>
When the fast-free hint is provided to the driver we know that the mbufs
have refcnt of 1 and are from the same mempool. Therefore, we can
optimize a bit for this case by:
* resetting the necessary mbuf fields, ie. nb_seg and next pointer when
we are accessing the mbuf on writing the descriptor.
* on cleanup of buffers after transmit, we can just write those buffers
straight to the mempool without accessing them.
* when doing buffer cleanup, we can follow the model of the vector
driver where we cleanup in fixed bursts which don't wrap, and where we
track the mbufs between tx_tail and last_cleaned as invalid, so we
don't need to set them to NULL. [We only set to NULL valid mbuf slots
where we have a context descriptor or segment not backed by an mbuf]
Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---
v3:
* used mbuf_raw_free_bulk rather than mempool function directly
* check for fast_free via mp pointer rather than flags
* remove unnecessary prefetches
V2: Fix issues with original submission:
* missed check for NULL mbufs
* fixed issue with freeing directly from sw_ring in scalar path which
doesn't work as thats not a flag array of pointers
* fixed missing null assignment in case of large segments for TSO
---
drivers/net/intel/common/tx.h | 21 ++++--
drivers/net/intel/common/tx_scalar.h | 99 +++++++++++++++++++++-------
2 files changed, 92 insertions(+), 28 deletions(-)
diff --git a/drivers/net/intel/common/tx.h b/drivers/net/intel/common/tx.h
index 23a8c39cf2..5fe71aed12 100644
--- a/drivers/net/intel/common/tx.h
+++ b/drivers/net/intel/common/tx.h
@@ -329,13 +329,22 @@ ci_txq_release_all_mbufs(struct ci_tx_queue *txq, bool use_ctx)
return;
if (!txq->use_vec_entry) {
- /* Regular scalar path uses sw_ring with ci_tx_entry */
- for (uint16_t i = 0; i < txq->nb_tx_desc; i++) {
- if (txq->sw_ring[i].mbuf != NULL) {
- rte_pktmbuf_free_seg(txq->sw_ring[i].mbuf);
- txq->sw_ring[i].mbuf = NULL;
- }
+ /* Free mbufs from (last_desc_cleaned + 1) to (tx_tail - 1). */
+ const uint16_t start = (txq->last_desc_cleaned + 1) % txq->nb_tx_desc;
+ const uint16_t nb_desc = txq->nb_tx_desc;
+ const uint16_t end = txq->tx_tail;
+
+ uint16_t i = start;
+ if (end < i) {
+ for (; i < nb_desc; i++)
+ if (txq->sw_ring[i].mbuf != NULL)
+ rte_pktmbuf_free_seg(txq->sw_ring[i].mbuf);
+ i = 0;
}
+ for (; i < end; i++)
+ if (txq->sw_ring[i].mbuf != NULL)
+ rte_pktmbuf_free_seg(txq->sw_ring[i].mbuf);
+ memset(txq->sw_ring, 0, sizeof(txq->sw_ring[0]) * nb_desc);
return;
}
diff --git a/drivers/net/intel/common/tx_scalar.h b/drivers/net/intel/common/tx_scalar.h
index 9fcd2e4733..d27df34dfa 100644
--- a/drivers/net/intel/common/tx_scalar.h
+++ b/drivers/net/intel/common/tx_scalar.h
@@ -197,16 +197,64 @@ ci_tx_xmit_cleanup(struct ci_tx_queue *txq)
const uint16_t rs_idx = (last_desc_cleaned == nb_tx_desc - 1) ?
0 :
(last_desc_cleaned + 1) >> txq->log2_rs_thresh;
- uint16_t desc_to_clean_to = (rs_idx << txq->log2_rs_thresh) + (txq->tx_rs_thresh - 1);
+ const uint16_t dd_idx = txq->rs_last_id[rs_idx];
+ const uint16_t first_to_clean = rs_idx << txq->log2_rs_thresh;
- /* Check if descriptor is done */
- if ((txd[txq->rs_last_id[rs_idx]].cmd_type_offset_bsz &
- rte_cpu_to_le_64(CI_TXD_QW1_DTYPE_M)) !=
- rte_cpu_to_le_64(CI_TX_DESC_DTYPE_DESC_DONE))
+ /* Check if descriptor is done - all drivers use 0xF as done value in bits 3:0 */
+ if ((txd[dd_idx].cmd_type_offset_bsz & rte_cpu_to_le_64(CI_TXD_QW1_DTYPE_M)) !=
+ rte_cpu_to_le_64(CI_TX_DESC_DTYPE_DESC_DONE))
+ /* Descriptor not yet processed by hardware */
return -1;
+ /* DD bit is set, descriptors are done. Now free the mbufs. */
+ /* Note: nb_tx_desc is guaranteed to be a multiple of tx_rs_thresh,
+ * validated during queue setup. This means cleanup never wraps around
+ * the ring within a single burst (e.g., ring=256, rs_thresh=32 gives
+ * bursts of 0-31, 32-63, ..., 224-255).
+ */
+ const uint16_t nb_to_clean = txq->tx_rs_thresh;
+ struct ci_tx_entry *sw_ring = txq->sw_ring;
+
+ /* fast_free_mp is NULL only when the fast free is disabled*/
+ if (txq->fast_free_mp != NULL) {
+ /* FAST_FREE path: mbufs are already reset, just return to pool */
+ struct rte_mbuf *free[CI_TX_MAX_FREE_BUF_SZ];
+ uint16_t nb_free = 0;
+
+ /* Get cached mempool pointer, or cache it on first use */
+ struct rte_mempool *mp =
+ likely(txq->fast_free_mp != (void *)UINTPTR_MAX) ?
+ txq->fast_free_mp :
+ (txq->fast_free_mp = sw_ring[dd_idx].mbuf->pool);
+
+ /* Pack non-NULL mbufs in-place at start of sw_ring range.
+ * No modulo needed in loop since we're guaranteed not to wrap.
+ */
+ for (uint16_t i = 0; i < nb_to_clean; i++) {
+ struct rte_mbuf *m = sw_ring[first_to_clean + i].mbuf;
+ if (m == NULL)
+ continue;
+ free[nb_free++] = m;
+ if (unlikely(nb_free == CI_TX_MAX_FREE_BUF_SZ)) {
+ rte_mbuf_raw_free_bulk(mp, free, nb_free);
+ nb_free = 0;
+ }
+ }
+
+ /* Bulk return to mempool using packed sw_ring entries directly */
+ if (nb_free > 0)
+ rte_mbuf_raw_free_bulk(mp, free, nb_free);
+ } else {
+ /* Non-FAST_FREE path: use free_seg for refcount checks and freeing */
+ for (uint16_t i = 0; i < nb_to_clean; i++) {
+ struct rte_mbuf *m = sw_ring[first_to_clean + i].mbuf;
+ if (m != NULL)
+ rte_pktmbuf_free_seg(m);
+ }
+ }
+
/* Update the txq to reflect the last descriptor that was cleaned */
- txq->last_desc_cleaned = desc_to_clean_to;
+ txq->last_desc_cleaned = first_to_clean + txq->tx_rs_thresh - 1;
txq->nb_tx_free += txq->tx_rs_thresh;
return 0;
@@ -450,8 +498,6 @@ ci_xmit_pkts(struct ci_tx_queue *txq,
txd = &ci_tx_ring[tx_id];
tx_id = txe->next_id;
- if (txe->mbuf)
- rte_pktmbuf_free_seg(txe->mbuf);
txe->mbuf = tx_pkt;
/* Setup TX Descriptor */
td_cmd |= CI_TX_DESC_CMD_EOP;
@@ -471,11 +517,7 @@ ci_xmit_pkts(struct ci_tx_queue *txq,
uint64_t *ctx_txd = RTE_CAST_PTR(uint64_t *, &ci_tx_ring[tx_id]);
txn = &sw_ring[txe->next_id];
- RTE_MBUF_PREFETCH_TO_FREE(txn->mbuf);
- if (txe->mbuf) {
- rte_pktmbuf_free_seg(txe->mbuf);
- txe->mbuf = NULL;
- }
+ txe->mbuf = NULL;
write_txd(ctx_txd, cd_qw0, cd_qw1);
@@ -488,11 +530,7 @@ ci_xmit_pkts(struct ci_tx_queue *txq,
uint64_t *ipsec_txd = RTE_CAST_PTR(uint64_t *, &ci_tx_ring[tx_id]);
txn = &sw_ring[txe->next_id];
- RTE_MBUF_PREFETCH_TO_FREE(txn->mbuf);
- if (txe->mbuf) {
- rte_pktmbuf_free_seg(txe->mbuf);
- txe->mbuf = NULL;
- }
+ txe->mbuf = NULL;
ipsec_txd[0] = ipsec_qw0;
ipsec_txd[1] = ipsec_qw1;
@@ -507,10 +545,22 @@ ci_xmit_pkts(struct ci_tx_queue *txq,
txd = &ci_tx_ring[tx_id];
txn = &sw_ring[txe->next_id];
- if (txe->mbuf)
- rte_pktmbuf_free_seg(txe->mbuf);
txe->mbuf = m_seg;
+ /* For FAST_FREE: reset mbuf fields while we have it in cache.
+ * [Fast free is indicated by txq->fast_free_mp being non-NULL.]
+ * FAST_FREE guarantees refcnt=1 and direct mbufs, so we only
+ * need to reset nb_segs and next pointer as per rte_pktmbuf_prefree_seg.
+ * Save next pointer before resetting since we need it for loop iteration.
+ */
+ struct rte_mbuf *next_seg = m_seg->next;
+ if (txq->fast_free_mp != NULL) {
+ if (m_seg->nb_segs != 1)
+ m_seg->nb_segs = 1;
+ if (next_seg != NULL)
+ m_seg->next = NULL;
+ }
+
/* Setup TX Descriptor */
/* Calculate segment length, using IPsec callback if provided */
if (ipsec_ops != NULL)
@@ -528,18 +578,23 @@ ci_xmit_pkts(struct ci_tx_queue *txq,
((uint64_t)CI_MAX_DATA_PER_TXD << CI_TXD_QW1_TX_BUF_SZ_S) |
((uint64_t)td_tag << CI_TXD_QW1_L2TAG1_S);
write_txd(txd, buf_dma_addr, cmd_type_offset_bsz);
+ /* txe for this slot has already been written (e.g. above outside
+ * loop), so we write the extra NULL mbuf pointer for this
+ * descriptor after we increment txe below.
+ */
buf_dma_addr += CI_MAX_DATA_PER_TXD;
slen -= CI_MAX_DATA_PER_TXD;
tx_id = txe->next_id;
txe = txn;
+ txe->mbuf = NULL;
txd = &ci_tx_ring[tx_id];
txn = &sw_ring[txe->next_id];
}
/* fill the last descriptor with End of Packet (EOP) bit */
- if (m_seg->next == NULL)
+ if (next_seg == NULL)
td_cmd |= CI_TX_DESC_CMD_EOP;
const uint64_t cmd_type_offset_bsz = CI_TX_DESC_DTYPE_DATA |
@@ -551,7 +606,7 @@ ci_xmit_pkts(struct ci_tx_queue *txq,
tx_id = txe->next_id;
txe = txn;
- m_seg = m_seg->next;
+ m_seg = next_seg;
} while (m_seg);
end_pkt:
txq->nb_tx_free = (uint16_t)(txq->nb_tx_free - nb_used);
--
2.53.0
^ permalink raw reply related
* Re: [PATCH v3 2/3] spinlock: add debug checks in recursive unlock
From: Thomas Monjalon @ 2026-05-19 11:19 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger, Konstantin Ananyev, Bruce Richardson,
Robin Jarry
In-Reply-To: <20260519103640.3986710-2-thomas@monjalon.net>
19/05/2026 12:34, Thomas Monjalon:
> The recursive unlock assumes that the caller owns the lock.
> This behavior will be checked when RTE_ENABLE_ASSERT is on.
> There is an additional check for the count which should be positive
> if no corruption happened.
>
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> ---
> v3: new patch in the series
Forgot:
Suggested-by: Stephen Hemminger <stephen@networkplumber.org>
Suggested-by: Robin Jarry <rjarry@redhat.com>
^ permalink raw reply
* [PATCH v2] ethdev: fix pointer check in GENEVE and RAW flow copy
From: Denis Lyulin @ 2026-05-19 7:23 UTC (permalink / raw)
To: stephen, Ori Kam, Thomas Monjalon, Andrew Rybchenko, Michael Baum,
Ferruh Yigit
Cc: dev, stable, lyulin.2003, adrien.mazarguil
When rte_flow_conv_item_spec() is called from rte_flow_conv_pattern(),
the spec, last and mask pointers are checked separately. If the API
is used incorrectly, the spec pointer may be NULL while last and mask
may be valid pointers. Also call of rte_flow_conv() with
RTE_FLOW_CONV_OP_ITEM_MASK and item->spec == NULL may lead to the
same problem.
In rte_flow_conv_item_spec() for GENVE_OPT and RAW item types the spec
pointer is used even if the function is called to copy last or mask.
It may cause a NULL pointer (spec) dereference.
This commit adds extra check of item->spec and if it is NULL, does not
copy further data relying on it
Fixes: 841a0445442d ("ethdev: fix GENEVE option item conversion")
Cc: michaelba@nvidia.com
Cc: adrien.mazarguil@6wind.com
Cc: stephen@networkplumber.org
Cc: stable@dpdk.org
Signed-off-by: Denis Lyulin <lyulin.2003@mail.ru>
---
lib/ethdev/rte_flow.c | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c
index fe8f43caff..7a51b667cf 100644
--- a/lib/ethdev/rte_flow.c
+++ b/lib/ethdev/rte_flow.c
@@ -672,13 +672,17 @@ rte_flow_conv_item_spec(void *buf, const size_t size,
}),
size > sizeof(*dst.raw) ? sizeof(*dst.raw) : size);
off = sizeof(*dst.raw);
- if (type == RTE_FLOW_CONV_ITEM_SPEC ||
- (type == RTE_FLOW_CONV_ITEM_MASK &&
- ((spec.raw->length & mask.raw->length) >=
- (last.raw->length & mask.raw->length))))
+ if (type == RTE_FLOW_CONV_ITEM_SPEC && spec.raw)
tmp = spec.raw->length & mask.raw->length;
- else
+ else if (type == RTE_FLOW_CONV_ITEM_MASK && spec.raw && last.raw &&
+ ((spec.raw->length & mask.raw->length) >=
+ (last.raw->length & mask.raw->length)))
+ tmp = spec.raw->length & mask.raw->length;
+ else if (last.raw)
tmp = last.raw->length & mask.raw->length;
+ else
+ tmp = 0;
+
if (tmp) {
off = RTE_ALIGN_CEIL(off, sizeof(*dst.raw->pattern));
if (size >= off + tmp) {
@@ -696,8 +700,8 @@ rte_flow_conv_item_spec(void *buf, const size_t size,
spec.geneve_opt = item->spec;
src.geneve_opt = data;
dst.geneve_opt = buf;
- tmp = spec.geneve_opt->option_len << 2;
- if (size > 0 && src.geneve_opt->data) {
+ tmp = spec.geneve_opt ? (spec.geneve_opt->option_len << 2) : 0;
+ if (size > 0 && tmp > 0 && src.geneve_opt->data) {
deep_src = (void *)((uintptr_t)(dst.geneve_opt + 1));
dst.geneve_opt->data = rte_memcpy(deep_src,
src.geneve_opt->data,
--
2.34.1
^ permalink raw reply related
* Re: [PATCH v3 2/3] spinlock: add debug checks in recursive unlock
From: Robin Jarry @ 2026-05-19 11:47 UTC (permalink / raw)
To: Thomas Monjalon, dev
Cc: Stephen Hemminger, Konstantin Ananyev, Bruce Richardson
In-Reply-To: <20260519103640.3986710-2-thomas@monjalon.net>
Thomas Monjalon, May 19, 2026 at 12:34:
> The recursive unlock assumes that the caller owns the lock.
> This behavior will be checked when RTE_ENABLE_ASSERT is on.
> There is an additional check for the count which should be positive
> if no corruption happened.
>
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> ---
> v3: new patch in the series
> ---
> lib/eal/include/generic/rte_spinlock.h | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/lib/eal/include/generic/rte_spinlock.h b/lib/eal/include/generic/rte_spinlock.h
> index ffdcb8fa3d..e7cd18a8e2 100644
> --- a/lib/eal/include/generic/rte_spinlock.h
> +++ b/lib/eal/include/generic/rte_spinlock.h
> @@ -21,6 +21,7 @@
> #ifdef RTE_FORCE_INTRINSICS
> #include <rte_common.h>
> #endif
> +#include <rte_debug.h>
> #include <rte_lock_annotations.h>
> #include <rte_pause.h>
> #include <rte_stdatomic.h>
> @@ -245,6 +246,8 @@ static inline void rte_spinlock_recursive_lock(rte_spinlock_recursive_t *slr)
> static inline void rte_spinlock_recursive_unlock(rte_spinlock_recursive_t *slr)
> __rte_no_thread_safety_analysis
> {
> + RTE_ASSERT(rte_atomic_load_explicit(&slr->owner, rte_memory_order_relaxed) == rte_gettid());
> + RTE_ASSERT(slr->count > 0);
> if (--(slr->count) == 0) {
> rte_atomic_store_explicit(&slr->owner, -1, rte_memory_order_relaxed);
> rte_spinlock_unlock(&slr->sl);
Acked-by: Robin Jarry <rjarry@redhat.com>
^ permalink raw reply
* RE: [PATCH] ring: fix zero-copy burst API documentation
From: Konstantin Ananyev @ 2026-05-19 11:57 UTC (permalink / raw)
To: jinzhiguang, Thomas Monjalon, Wathsala Vithanage, Dharmik Thakkar,
Honnappa Nagarahalli
Cc: dev@dpdk.org, stable@dpdk.org
In-Reply-To: <20260519114629.862-1-jinzhiguang@kylinos.cn>
> These are burst APIs relying on RTE_RING_QUEUE_VARIABLE behavior, they
> operate on a best-effort basis and return the actual number of
> objects processed (between 0 and n).
>
> Update description to match implementation.
>
> Fixes: 47bec9a5ca9f ("ring: add zero copy API")
>
> Signed-off-by: jinzhiguang <jinzhiguang@kylinos.cn>
> ---
> Cc: honnappa.nagarahalli@arm.com
> Cc: stable@dpdk.org
> ---
> .mailmap | 1 +
> lib/ring/rte_ring_peek_zc.h | 8 ++++----
> 2 files changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/.mailmap b/.mailmap
> index 4d26d9c286..a4f91f2131 100644
> --- a/.mailmap
> +++ b/.mailmap
> @@ -756,6 +756,7 @@ Jing Chen <jing.d.chen@intel.com>
> Jingguo Fu <jingguox.fu@intel.com>
> Jingjing Wu <jingjing.wu@intel.com>
> Jingzhao Ni <jingzhao.ni@arm.com>
> +jinzhiguang <jinzhiguang@kylinos.cn>
> Jiri Slaby <jslaby@suse.cz>
> Job Abraham <job.abraham@intel.com>
> Jochen Behrens <jochen.behrens@broadcom.com> <jbehrens@vmware.com>
> diff --git a/lib/ring/rte_ring_peek_zc.h b/lib/ring/rte_ring_peek_zc.h
> index 3254fe0481..fa566e8e0d 100644
> --- a/lib/ring/rte_ring_peek_zc.h
> +++ b/lib/ring/rte_ring_peek_zc.h
> @@ -235,7 +235,7 @@ rte_ring_enqueue_zc_bulk_start(struct rte_ring *r,
> unsigned int n,
> * If non-NULL, returns the amount of space in the ring after the
> * reservation operation has finished.
> * @return
> - * The number of objects that can be enqueued, either 0 or n
> + * Actual number of objects enqueued.
Here and in other places, probably better:
The actual number of objects that can be enqueued.
Acked-by: Konstantin Ananyev <konstantin.ananyev@huawei.com>
> */
> static __rte_always_inline unsigned int
> rte_ring_enqueue_zc_burst_elem_start(struct rte_ring *r, unsigned int esize,
> @@ -265,7 +265,7 @@ rte_ring_enqueue_zc_burst_elem_start(struct rte_ring
> *r, unsigned int esize,
> * If non-NULL, returns the amount of space in the ring after the
> * reservation operation has finished.
> * @return
> - * The number of objects that can be enqueued, either 0 or n.
> + * Actual number of objects enqueued.
> */
> static __rte_always_inline unsigned int
> rte_ring_enqueue_zc_burst_start(struct rte_ring *r, unsigned int n,
> @@ -442,7 +442,7 @@ rte_ring_dequeue_zc_bulk_start(struct rte_ring *r,
> unsigned int n,
> * If non-NULL, returns the number of remaining ring entries after the
> * dequeue has finished.
> * @return
> - * The number of objects that can be dequeued, either 0 or n.
> + * Actual number of objects dequeued.
> */
> static __rte_always_inline unsigned int
> rte_ring_dequeue_zc_burst_elem_start(struct rte_ring *r, unsigned int esize,
> @@ -471,7 +471,7 @@ rte_ring_dequeue_zc_burst_elem_start(struct rte_ring
> *r, unsigned int esize,
> * If non-NULL, returns the number of remaining ring entries after the
> * dequeue has finished.
> * @return
> - * The number of objects that can be dequeued, either 0 or n.
> + * Actual number of objects dequeued.
> */
> static __rte_always_inline unsigned int
> rte_ring_dequeue_zc_burst_start(struct rte_ring *r, unsigned int n,
> --
> 2.53.0
^ permalink raw reply
* [PATCH] ring: fix zero-copy burst API documentation
From: jinzhiguang @ 2026-05-19 11:46 UTC (permalink / raw)
To: Thomas Monjalon, Konstantin Ananyev, Wathsala Vithanage,
Dharmik Thakkar, Honnappa Nagarahalli
Cc: dev, jinzhiguang, stable
These are burst APIs relying on RTE_RING_QUEUE_VARIABLE behavior, they
operate on a best-effort basis and return the actual number of
objects processed (between 0 and n).
Update description to match implementation.
Fixes: 47bec9a5ca9f ("ring: add zero copy API")
Signed-off-by: jinzhiguang <jinzhiguang@kylinos.cn>
---
Cc: honnappa.nagarahalli@arm.com
Cc: stable@dpdk.org
---
.mailmap | 1 +
lib/ring/rte_ring_peek_zc.h | 8 ++++----
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/.mailmap b/.mailmap
index 4d26d9c286..a4f91f2131 100644
--- a/.mailmap
+++ b/.mailmap
@@ -756,6 +756,7 @@ Jing Chen <jing.d.chen@intel.com>
Jingguo Fu <jingguox.fu@intel.com>
Jingjing Wu <jingjing.wu@intel.com>
Jingzhao Ni <jingzhao.ni@arm.com>
+jinzhiguang <jinzhiguang@kylinos.cn>
Jiri Slaby <jslaby@suse.cz>
Job Abraham <job.abraham@intel.com>
Jochen Behrens <jochen.behrens@broadcom.com> <jbehrens@vmware.com>
diff --git a/lib/ring/rte_ring_peek_zc.h b/lib/ring/rte_ring_peek_zc.h
index 3254fe0481..fa566e8e0d 100644
--- a/lib/ring/rte_ring_peek_zc.h
+++ b/lib/ring/rte_ring_peek_zc.h
@@ -235,7 +235,7 @@ rte_ring_enqueue_zc_bulk_start(struct rte_ring *r, unsigned int n,
* If non-NULL, returns the amount of space in the ring after the
* reservation operation has finished.
* @return
- * The number of objects that can be enqueued, either 0 or n
+ * Actual number of objects enqueued.
*/
static __rte_always_inline unsigned int
rte_ring_enqueue_zc_burst_elem_start(struct rte_ring *r, unsigned int esize,
@@ -265,7 +265,7 @@ rte_ring_enqueue_zc_burst_elem_start(struct rte_ring *r, unsigned int esize,
* If non-NULL, returns the amount of space in the ring after the
* reservation operation has finished.
* @return
- * The number of objects that can be enqueued, either 0 or n.
+ * Actual number of objects enqueued.
*/
static __rte_always_inline unsigned int
rte_ring_enqueue_zc_burst_start(struct rte_ring *r, unsigned int n,
@@ -442,7 +442,7 @@ rte_ring_dequeue_zc_bulk_start(struct rte_ring *r, unsigned int n,
* If non-NULL, returns the number of remaining ring entries after the
* dequeue has finished.
* @return
- * The number of objects that can be dequeued, either 0 or n.
+ * Actual number of objects dequeued.
*/
static __rte_always_inline unsigned int
rte_ring_dequeue_zc_burst_elem_start(struct rte_ring *r, unsigned int esize,
@@ -471,7 +471,7 @@ rte_ring_dequeue_zc_burst_elem_start(struct rte_ring *r, unsigned int esize,
* If non-NULL, returns the number of remaining ring entries after the
* dequeue has finished.
* @return
- * The number of objects that can be dequeued, either 0 or n.
+ * Actual number of objects dequeued.
*/
static __rte_always_inline unsigned int
rte_ring_dequeue_zc_burst_start(struct rte_ring *r, unsigned int n,
--
2.53.0
^ permalink raw reply related
* Re: [PATCH V2 00/15] power: unify and improve lcore ID verification
From: lihuisong (C) @ 2026-05-19 13:09 UTC (permalink / raw)
To: Stephen Hemminger
Cc: anatoly.burakov, sivaprasad.tummala, dev, thomas, fengchengwen,
yangxingui, zhanjie9
In-Reply-To: <20260518105954.2309f802@phoenix.local>
Thanks for giving me this AI review feedback.
Some of them are still acceptable. will fix it in next version.
Is this summary from AI generated for each patche series?
May ask where you obtained this information about AI review?
On 5/19/2026 1:59 AM, Stephen Hemminger wrote:
> On Thu, 7 May 2026 10:42:15 +0800
> Huisong Li <lihuisong@huawei.com> wrote:
>
>> This patch series reworks the lcore ID verification logic within the
>> power library to ensure consistency and improve maintainability.
>>
>> Currently, various cpufreq drivers implement their own lcore ID checks,
>> which are limited to simple range validation and involve significant
>> code duplication. Moreover, these checks do not account for whether the
>> core is actually managed by the application.
>>
>> For the verification in cpufreq-related APIs and power QoS APIs, although
>> service cores do not typically invoke these APIs, they may operate in
>> polling modes where power management is required. To maintain compatibility
>> with applications using service cores, the validation logic now explicitly
>> allows both ROLE_RTE and ROLE_SERVICE.
>>
>> But the lcore ID in the pmd_mgmt library must be ROLE_RTE because it is
>> mainly used together with the data plane of ethdev PMD. So use
>> rte_lcore_is_enabled to verify.
>>
>> Key Changes:
>> 1. Add lcore role verification to individual cpufreq drivers.
>> 2. Introduces a unified macro in the power library to standardize lcore ID
>> checks.
>> 3. Moves verification logic from individualdrivers to the framework level.
>> This reduces code duplication.
>> 4. Allow the service cores to configure power QoS.
>> 5. Use rte_lcore_is_enabled to verfify the lcore ID in pmd_mgmt.
>>
>> ---
>> v2:
>> - Allow the service cores to set power API.
>>
>> ---
>>
>> Huisong Li (15):
>> eal: add interface to check if lcore is EAL managed
>> power/kvm_vm: validate lcore role in cpufreq API
>> power/acpi_cpufreq: validate lcore role in cpufreq API
>> power/amd_pstate: validate lcore role in cpufreq API
>> power/cppc_cpufreq: validate lcore role in cpufreq API
>> power/intel_pstate: validate lcore role in cpufreq API
>> power: add a common macro to verify lcore ID
>> power/cpufreq: add the lcore ID verification to framework
>> power/acpi_cpufreq: remove the verification of lcore ID
>> power/amd_pstate: remove the verification of lcore ID
>> power/cppc_cpufreq: remove the verification of lcore ID
>> power/intel_pstate: remove the verification of lcore ID
>> power/kvm_vm: remove the verification of lcore ID
>> power: allow the service core to config power QoS
>> power: add lcore ID check for PMD mgmt
>>
>> drivers/power/acpi/acpi_cpufreq.c | 65 -------------------
>> drivers/power/amd_pstate/amd_pstate_cpufreq.c | 65 -------------------
>> drivers/power/cppc/cppc_cpufreq.c | 65 -------------------
>> .../power/intel_pstate/intel_pstate_cpufreq.c | 65 -------------------
>> drivers/power/kvm_vm/kvm_vm.c | 10 ---
>> lib/eal/common/eal_common_lcore.c | 11 ++++
>> lib/eal/include/rte_lcore.h | 11 ++++
>> lib/power/power_common.h | 7 ++
>> lib/power/rte_power_cpufreq.c | 14 +++-
>> lib/power/rte_power_pmd_mgmt.c | 21 +++---
>> lib/power/rte_power_qos.c | 10 +--
>> 11 files changed, 55 insertions(+), 289 deletions(-)
>>
> Lots of AI review feedback on this one:
>
> Patch 01/15: eal: add interface to check if lcore is EAL managed
> =================================================================
>
> Warning: New public API rte_lcore_is_eal_managed() is exported as
> a stable ABI symbol (RTE_EXPORT_SYMBOL), but DPDK policy requires
> new public APIs to be introduced as experimental:
>
> +RTE_EXPORT_SYMBOL(rte_lcore_is_eal_managed)
> +int rte_lcore_is_eal_managed(unsigned int lcore_id)
>
> The declaration in rte_lcore.h is also missing the __rte_experimental
> attribute. The export should be:
>
> RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_lcore_is_eal_managed, 26.07)
> int rte_lcore_is_eal_managed(unsigned int lcore_id)
>
> and the prototype in lib/eal/include/rte_lcore.h should carry
> __rte_experimental.
>
> Warning: This series adds a new public API but does not update the
> release notes in doc/guides/rel_notes/release_26_07.rst (or whatever
> the current target release is). New API additions must be documented
> in the release notes under the "New Features" section.
>
>
> Patch 07/15: power: add a common macro to verify lcore ID
> =========================================================
>
> Info: The macro evaluates lcore_id twice (once in
> rte_lcore_is_eal_managed() and once in POWER_LOG). All current
> call-sites pass a plain variable so there is no observable bug, but
> a side-effecting argument would be evaluated twice. Same caveat
> applies to the existing RTE_ETH_VALID_PORTID_OR_ERR_RET pattern, so
> this is consistent with existing DPDK convention.
>
>
> Patch 14/15: power: allow the service core to config power QoS
> ==============================================================
>
> Info: The check changes from rte_lcore_is_enabled() (ROLE_RTE only)
> to rte_lcore_is_eal_managed() (ROLE_RTE + ROLE_SERVICE), so the log
> message wording changes from "is not enabled" to the macro's "is
> invalid" text. For a service core that was previously rejected, the
> new "invalid" wording is less informative than the prior message,
> but this is minor.
>
>
> Patch 15/15: power: add lcore ID check for PMD mgmt
> ====================================================
>
> Info: This patch tightens the validation from "lcore_id within
> RTE_MAX_LCORE range" to "lcore_id is ROLE_RTE". Combined with the
> Fixes: tag and Cc: stable, this is a behavioural change in stable
> branches: callers that previously passed a non-enabled lcore_id
> (ROLE_OFF / ROLE_SERVICE / ROLE_NON_EAL) will now receive -EINVAL
> where they previously succeeded into the function body. The commit
> message correctly justifies the data-plane (ROLE_RTE) requirement,
> but the behaviour change should be called out explicitly in the
> commit log so stable maintainers and downstream users are aware.
>
>
> Series-level observation
> ========================
>
> Info: Patches 02-06 add per-driver lcore role checks, and patches
> 09-13 remove the same checks once patch 08 lifts validation into
> the framework. The net effect is that each driver's lcore check is
> modified and then deleted within the same series. The series could
> be reorganized to:
>
> 1. Patch 01: add rte_lcore_is_eal_managed()
> 2. Patch 07: add the RTE_POWER_VALID_LCOREID_OR_ERR_RET macro
> 3. Patch 08: add validation to the framework (rte_power_cpufreq.c)
> 4. Patches 14, 15: pmd_mgmt and QoS adjustments
>
> skipping patches 02-06 and 09-13 entirely. This would reduce review
> load and avoid intermediate states where the same check exists in
> two places. If the current structure is intentional for incremental
> bisection, that rationale would be worth mentioning in a cover
> letter.
^ permalink raw reply
* Re: Re: [PATCH] ring: fix zero-copy burst API documentation
From: jinzhiguang @ 2026-05-19 13:13 UTC (permalink / raw)
To: Konstantin Ananyev, Thomas Monjalon, Wathsala Vithanage,
Dharmik Thakkar, Honnappa Nagarahalli
Cc: dev@dpdk.org, stable@dpdk.org
In-Reply-To: <b7fe1363840444ef93ec2c0be2734ff0@huawei.com>
>> diff --git a/lib/ring/rte_ring_peek_zc.h b/lib/ring/rte_ring_peek_zc.h
>> index 3254fe0481..fa566e8e0d 100644
>> --- a/lib/ring/rte_ring_peek_zc.h
>> +++ b/lib/ring/rte_ring_peek_zc.h
>> @@ -235,7 +235,7 @@ rte_ring_enqueue_zc_bulk_start(struct rte_ring *r,
>> unsigned int n,
>> * If non-NULL, returns the amount of space in the ring after the
>> * reservation operation has finished.
>> * @return
>> - * The number of objects that can be enqueued, either 0 or n
>> + * Actual number of objects enqueued.
> Here and in other places, probably better:
> The actual number of objects that can be enqueued.
> Acked-by: Konstantin Ananyev <konstantin.ananyev@huawei.com>
Thank you for the review. I will update it and send a v2.
>> */
>> static __rte_always_inline unsigned int
>> rte_ring_enqueue_zc_burst_elem_start(struct rte_ring *r, unsigned int esize,
>>
^ permalink raw reply
* [PATCH v2] ring: fix zero-copy burst API documentation
From: jinzhiguang @ 2026-05-19 13:18 UTC (permalink / raw)
To: Thomas Monjalon, Konstantin Ananyev, Wathsala Vithanage,
Dharmik Thakkar, Honnappa Nagarahalli
Cc: dev, jinzhiguang, stable
These are burst APIs relying on RTE_RING_QUEUE_VARIABLE behavior, they
operate on a best-effort basis and return the actual number of
objects processed (between 0 and n).
Update description to match implementation.
Fixes: 47bec9a5ca9f ("ring: add zero copy API")
Signed-off-by: jinzhiguang <jinzhiguang@kylinos.cn>
---
Cc: honnappa.nagarahalli@arm.com
Cc: stable@dpdk.org
---
.mailmap | 1 +
lib/ring/rte_ring_peek_zc.h | 8 ++++----
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/.mailmap b/.mailmap
index 4d26d9c286..a4f91f2131 100644
--- a/.mailmap
+++ b/.mailmap
@@ -756,6 +756,7 @@ Jing Chen <jing.d.chen@intel.com>
Jingguo Fu <jingguox.fu@intel.com>
Jingjing Wu <jingjing.wu@intel.com>
Jingzhao Ni <jingzhao.ni@arm.com>
+jinzhiguang <jinzhiguang@kylinos.cn>
Jiri Slaby <jslaby@suse.cz>
Job Abraham <job.abraham@intel.com>
Jochen Behrens <jochen.behrens@broadcom.com> <jbehrens@vmware.com>
diff --git a/lib/ring/rte_ring_peek_zc.h b/lib/ring/rte_ring_peek_zc.h
index 3254fe0481..43d6a53075 100644
--- a/lib/ring/rte_ring_peek_zc.h
+++ b/lib/ring/rte_ring_peek_zc.h
@@ -235,7 +235,7 @@ rte_ring_enqueue_zc_bulk_start(struct rte_ring *r, unsigned int n,
* If non-NULL, returns the amount of space in the ring after the
* reservation operation has finished.
* @return
- * The number of objects that can be enqueued, either 0 or n
+ * The actual number of objects that can be enqueued.
*/
static __rte_always_inline unsigned int
rte_ring_enqueue_zc_burst_elem_start(struct rte_ring *r, unsigned int esize,
@@ -265,7 +265,7 @@ rte_ring_enqueue_zc_burst_elem_start(struct rte_ring *r, unsigned int esize,
* If non-NULL, returns the amount of space in the ring after the
* reservation operation has finished.
* @return
- * The number of objects that can be enqueued, either 0 or n.
+ * The actual number of objects that can be enqueued.
*/
static __rte_always_inline unsigned int
rte_ring_enqueue_zc_burst_start(struct rte_ring *r, unsigned int n,
@@ -442,7 +442,7 @@ rte_ring_dequeue_zc_bulk_start(struct rte_ring *r, unsigned int n,
* If non-NULL, returns the number of remaining ring entries after the
* dequeue has finished.
* @return
- * The number of objects that can be dequeued, either 0 or n.
+ * The actual number of objects that can be dequeued.
*/
static __rte_always_inline unsigned int
rte_ring_dequeue_zc_burst_elem_start(struct rte_ring *r, unsigned int esize,
@@ -471,7 +471,7 @@ rte_ring_dequeue_zc_burst_elem_start(struct rte_ring *r, unsigned int esize,
* If non-NULL, returns the number of remaining ring entries after the
* dequeue has finished.
* @return
- * The number of objects that can be dequeued, either 0 or n.
+ * The actual number of objects that can be dequeued.
*/
static __rte_always_inline unsigned int
rte_ring_dequeue_zc_burst_start(struct rte_ring *r, unsigned int n,
--
2.53.0
^ permalink raw reply related
* Re: [PATCH v3 1/3] spinlock: remove volatile qualifier
From: Stephen Hemminger @ 2026-05-19 13:32 UTC (permalink / raw)
To: Thomas Monjalon
Cc: dev, Konstantin Ananyev, Bruce Richardson, Robin Jarry, stable
In-Reply-To: <20260519103640.3986710-1-thomas@monjalon.net>
On Tue, 19 May 2026 12:34:14 +0200
Thomas Monjalon <thomas@monjalon.net> wrote:
> When compiling with C++20 standard requirement (default in GCC 16),
> the increment and decrement of volatile variables are rejected:
>
> rte_spinlock.h:241:14: error:
> '++' expression of 'volatile'-qualified type is deprecated
> rte_spinlock.h:252:21: error:
> '--' expression of 'volatile'-qualified type is deprecated
> rte_spinlock.h:278:14: error:
> '++' expression of 'volatile'-qualified type is deprecated
>
> The count field of rte_spinlock_recursive_t
> does not need the volatile qualifier
> because it is only accessed by the thread holding the lock,
> which already provides the necessary memory ordering.
>
> The user field can be accessed outside of the lock,
> so it must handled as a C11 atomic variable.
> The name is also changed from user to owner.
> It will break if an application is accessing this field directly,
> which should never happen.
>
> Fixes: af75078fece3 ("first public release")
> Cc: stable@dpdk.org
>
> Signed
Series-acked-by: Stephen Hemminger <stephen@networkplumber.org>
^ permalink raw reply
* [PATCH v3] ring: fix zero-copy burst API documentation
From: jinzhiguang @ 2026-05-19 13:38 UTC (permalink / raw)
To: Thomas Monjalon, Konstantin Ananyev, Wathsala Vithanage,
Dharmik Thakkar, Honnappa Nagarahalli
Cc: dev, jinzhiguang, stable
In-Reply-To: <20260519114629.862-1-jinzhiguang@kylinos.cn>
These are burst APIs relying on RTE_RING_QUEUE_VARIABLE behavior, they
operate on a best-effort basis and return the actual number of
objects processed (between 0 and n).
Update description to match implementation.
Fixes: 47bec9a5ca9f ("ring: add zero copy API")
Acked-by: Konstantin Ananyev <konstantin.ananyev@huawei.com>
Signed-off-by: jinzhiguang <jinzhiguang@kylinos.cn>
---
Cc: honnappa.nagarahalli@arm.com
Cc: stable@dpdk.org
---
V3:
- Resend properly threaded to the v1 patch. (No code/text changes)
v2:
- Update description to match actual behavior per Maintainer's suggestion.
.mailmap | 1 +
lib/ring/rte_ring_peek_zc.h | 8 ++++----
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/.mailmap b/.mailmap
index 4d26d9c286..a4f91f2131 100644
--- a/.mailmap
+++ b/.mailmap
@@ -756,6 +756,7 @@ Jing Chen <jing.d.chen@intel.com>
Jingguo Fu <jingguox.fu@intel.com>
Jingjing Wu <jingjing.wu@intel.com>
Jingzhao Ni <jingzhao.ni@arm.com>
+jinzhiguang <jinzhiguang@kylinos.cn>
Jiri Slaby <jslaby@suse.cz>
Job Abraham <job.abraham@intel.com>
Jochen Behrens <jochen.behrens@broadcom.com> <jbehrens@vmware.com>
diff --git a/lib/ring/rte_ring_peek_zc.h b/lib/ring/rte_ring_peek_zc.h
index 3254fe0481..43d6a53075 100644
--- a/lib/ring/rte_ring_peek_zc.h
+++ b/lib/ring/rte_ring_peek_zc.h
@@ -235,7 +235,7 @@ rte_ring_enqueue_zc_bulk_start(struct rte_ring *r, unsigned int n,
* If non-NULL, returns the amount of space in the ring after the
* reservation operation has finished.
* @return
- * The number of objects that can be enqueued, either 0 or n
+ * The actual number of objects that can be enqueued.
*/
static __rte_always_inline unsigned int
rte_ring_enqueue_zc_burst_elem_start(struct rte_ring *r, unsigned int esize,
@@ -265,7 +265,7 @@ rte_ring_enqueue_zc_burst_elem_start(struct rte_ring *r, unsigned int esize,
* If non-NULL, returns the amount of space in the ring after the
* reservation operation has finished.
* @return
- * The number of objects that can be enqueued, either 0 or n.
+ * The actual number of objects that can be enqueued.
*/
static __rte_always_inline unsigned int
rte_ring_enqueue_zc_burst_start(struct rte_ring *r, unsigned int n,
@@ -442,7 +442,7 @@ rte_ring_dequeue_zc_bulk_start(struct rte_ring *r, unsigned int n,
* If non-NULL, returns the number of remaining ring entries after the
* dequeue has finished.
* @return
- * The number of objects that can be dequeued, either 0 or n.
+ * The actual number of objects that can be dequeued.
*/
static __rte_always_inline unsigned int
rte_ring_dequeue_zc_burst_elem_start(struct rte_ring *r, unsigned int esize,
@@ -471,7 +471,7 @@ rte_ring_dequeue_zc_burst_elem_start(struct rte_ring *r, unsigned int esize,
* If non-NULL, returns the number of remaining ring entries after the
* dequeue has finished.
* @return
- * The number of objects that can be dequeued, either 0 or n.
+ * The actual number of objects that can be dequeued.
*/
static __rte_always_inline unsigned int
rte_ring_dequeue_zc_burst_start(struct rte_ring *r, unsigned int n,
--
2.53.0
^ permalink raw reply related
* Re: [PATCH v2] ring: fix zero-copy burst API documentation
From: jinzhiguang @ 2026-05-19 13:42 UTC (permalink / raw)
To: Thomas Monjalon, Konstantin Ananyev, Wathsala Vithanage,
Dharmik Thakkar, Honnappa Nagarahalli
Cc: dev, stable
In-Reply-To: <20260519131846.1089-1-jinzhiguang@kylinos.cn>
Please ignore this patch. It was sent with incorrect threading.
> These are burst APIs relying on RTE_RING_QUEUE_VARIABLE behavior, they
> operate on a best-effort basis and return the actual number of
> objects processed (between 0 and n).
>
> Update description to match implementation.
>
> Fixes: 47bec9a5ca9f ("ring: add zero copy API")
>
> Signed-off-by: jinzhiguang <jinzhiguang@kylinos.cn>
> ---
> Cc: honnappa.nagarahalli@arm.com
> Cc: stable@dpdk.org
> ---
> .mailmap | 1 +
> lib/ring/rte_ring_peek_zc.h | 8 ++++----
> 2 files changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/.mailmap b/.mailmap
> index 4d26d9c286..a4f91f2131 100644
> --- a/.mailmap
> +++ b/.mailmap
> @@ -756,6 +756,7 @@ Jing Chen <jing.d.chen@intel.com>
> Jingguo Fu <jingguox.fu@intel.com>
> Jingjing Wu <jingjing.wu@intel.com>
> Jingzhao Ni <jingzhao.ni@arm.com>
> +jinzhiguang <jinzhiguang@kylinos.cn>
> Jiri Slaby <jslaby@suse.cz>
> Job Abraham <job.abraham@intel.com>
> Jochen Behrens <jochen.behrens@broadcom.com> <jbehrens@vmware.com>
> diff --git a/lib/ring/rte_ring_peek_zc.h b/lib/ring/rte_ring_peek_zc.h
> index 3254fe0481..43d6a53075 100644
> --- a/lib/ring/rte_ring_peek_zc.h
> +++ b/lib/ring/rte_ring_peek_zc.h
> @@ -235,7 +235,7 @@ rte_ring_enqueue_zc_bulk_start(struct rte_ring *r, unsigned int n,
> * If non-NULL, returns the amount of space in the ring after the
> * reservation operation has finished.
> * @return
> - * The number of objects that can be enqueued, either 0 or n
> + * The actual number of objects that can be enqueued.
> */
> static __rte_always_inline unsigned int
> rte_ring_enqueue_zc_burst_elem_start(struct rte_ring *r, unsigned int esize,
> @@ -265,7 +265,7 @@ rte_ring_enqueue_zc_burst_elem_start(struct rte_ring *r, unsigned int esize,
> * If non-NULL, returns the amount of space in the ring after the
> * reservation operation has finished.
> * @return
> - * The number of objects that can be enqueued, either 0 or n.
> + * The actual number of objects that can be enqueued.
> */
> static __rte_always_inline unsigned int
> rte_ring_enqueue_zc_burst_start(struct rte_ring *r, unsigned int n,
> @@ -442,7 +442,7 @@ rte_ring_dequeue_zc_bulk_start(struct rte_ring *r, unsigned int n,
> * If non-NULL, returns the number of remaining ring entries after the
> * dequeue has finished.
> * @return
> - * The number of objects that can be dequeued, either 0 or n.
> + * The actual number of objects that can be dequeued.
> */
> static __rte_always_inline unsigned int
> rte_ring_dequeue_zc_burst_elem_start(struct rte_ring *r, unsigned int esize,
> @@ -471,7 +471,7 @@ rte_ring_dequeue_zc_burst_elem_start(struct rte_ring *r, unsigned int esize,
> * If non-NULL, returns the number of remaining ring entries after the
> * dequeue has finished.
> * @return
> - * The number of objects that can be dequeued, either 0 or n.
> + * The actual number of objects that can be dequeued.
> */
> static __rte_always_inline unsigned int
> rte_ring_dequeue_zc_burst_start(struct rte_ring *r, unsigned int n,
^ permalink raw reply
* [PATCH v2] eal: silence -Wconstant-logical-operand in RTE_IS_POWER_OF_2
From: Stephen Hemminger @ 2026-05-19 13:49 UTC (permalink / raw)
To: dev
Cc: Stephen Hemminger, stable, Bruce Richardson, Jack Bond-Preston,
Pablo de Lara, Gavin Hu, Honnappa Nagarahalli
In-Reply-To: <20260518163401.580696-1-stephen@networkplumber.org>
Newer GCC warns when a non-boolean constant is an operand of &&, which
trips whenever RTE_IS_POWER_OF_2 is used in a static_assert with a
power-of-two literal. Make the zero check explicit.
Fixes: 7c872b96983a ("hash: validate hash bucket entries while compiling")
Cc: stable@dpdk.org
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
Acked-by: Jack Bond-Preston <jack.bond-preston@foss.arm.com>
---
v2 - use suggestion to make both sides comparisons
Note: AI incorrectly complains about multiple evaluations in this macro
but that has always been the case, and has to be macro
for use with static assert.
lib/eal/include/rte_bitops.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/eal/include/rte_bitops.h b/lib/eal/include/rte_bitops.h
index aa6ac73abb..b170447714 100644
--- a/lib/eal/include/rte_bitops.h
+++ b/lib/eal/include/rte_bitops.h
@@ -1299,7 +1299,7 @@ rte_fls_u64(uint64_t x)
/**
* Macro to return 1 if n is a power of 2, 0 otherwise
*/
-#define RTE_IS_POWER_OF_2(n) ((n) && !(((n) - 1) & (n)))
+#define RTE_IS_POWER_OF_2(n) ((n) != 0 && (((n) - 1) & (n)) == 0)
/**
* Returns true if n is a power of 2
--
2.53.0
^ permalink raw reply related
* Re: [PATCH v17 00/11] net/sxe2: fix logic errors and address feedback
From: Stephen Hemminger @ 2026-05-19 14:16 UTC (permalink / raw)
To: liujie5; +Cc: dev
In-Reply-To: <20260519030132.3780057-1-liujie5@linkdatatechnology.com>
On Tue, 19 May 2026 11:01:21 +0800
liujie5@linkdatatechnology.com wrote:
> From: Jie Liu <liujie5@linkdatatechnology.com>
>
> This patch set addresses the feedback received on the v10 submission
> for the sxe2 PMD. The primary focus is on fixing vector path selection,
> ensuring memory safety during mbuf initialization, and cleaning up
> redundant logic in the configuration functions.
>
> v17 Changes:
> - Fixed vector Rx burst function being overwritten by scalar selection.
> - Refactored Rx/Tx mode set functions to seed flags from caps first,
> eliminating tautological checks.
> - Added memset for mbuf_def in vector init to avoid uninitialized reads.
> - Converted pci_map_addr_info to designated initializers.
> - Removed dead Windows-only code in meson.build.
> - Added NULL checks for mbuf free for driver-wide consistency.
> - Updated burst_mode_get to accurately report AVX paths.
> - Adjusted SXE2_ETH_OVERHEAD to match actual VLAN capabilities.
>
> Jie Liu (11):
> mailmap: add Jie Liu
> doc: add sxe2 guide and release notes
> common/sxe2: add sxe2 basic structures
> drivers: add base driver skeleton
> drivers: add base driver probe skeleton
> drivers: support PCI BAR mapping
> common/sxe2: add ioctl interface for DMA map and unmap
> net/sxe2: support queue setup and control
> drivers: add data path for Rx and Tx
> net/sxe2: add vectorized Rx and Tx
> net/sxe2: implement Tx done cleanup
>
> .mailmap | 1 +
> doc/guides/nics/features/sxe2.ini | 29 +
> doc/guides/nics/index.rst | 1 +
> doc/guides/nics/sxe2.rst | 34 +
> doc/guides/rel_notes/release_26_07.rst | 4 +
> drivers/common/sxe2/meson.build | 15 +
> drivers/common/sxe2/sxe2_common.c | 683 +++++++++++++
> drivers/common/sxe2/sxe2_common.h | 85 ++
> drivers/common/sxe2/sxe2_common_log.h | 81 ++
> drivers/common/sxe2/sxe2_host_regs.h | 707 +++++++++++++
> drivers/common/sxe2/sxe2_internal_ver.h | 33 +
> drivers/common/sxe2/sxe2_ioctl_chnl.c | 325 ++++++
> drivers/common/sxe2/sxe2_ioctl_chnl.h | 130 +++
> drivers/common/sxe2/sxe2_ioctl_chnl_func.h | 62 ++
> drivers/common/sxe2/sxe2_osal.h | 153 +++
> drivers/meson.build | 1 +
> drivers/net/meson.build | 1 +
> drivers/net/sxe2/meson.build | 32 +
> drivers/net/sxe2/sxe2_cmd_chnl.c | 323 ++++++
> drivers/net/sxe2/sxe2_cmd_chnl.h | 37 +
> drivers/net/sxe2/sxe2_drv_cmd.h | 388 ++++++++
> drivers/net/sxe2/sxe2_ethdev.c | 968 ++++++++++++++++++
> drivers/net/sxe2/sxe2_ethdev.h | 318 ++++++
> drivers/net/sxe2/sxe2_irq.h | 48 +
> drivers/net/sxe2/sxe2_queue.c | 66 ++
> drivers/net/sxe2/sxe2_queue.h | 195 ++++
> drivers/net/sxe2/sxe2_rx.c | 554 +++++++++++
> drivers/net/sxe2/sxe2_rx.h | 32 +
> drivers/net/sxe2/sxe2_tx.c | 420 ++++++++
> drivers/net/sxe2/sxe2_tx.h | 32 +
> drivers/net/sxe2/sxe2_txrx.c | 351 +++++++
> drivers/net/sxe2/sxe2_txrx.h | 23 +
> drivers/net/sxe2/sxe2_txrx_common.h | 540 ++++++++++
> drivers/net/sxe2/sxe2_txrx_poll.c | 1044 ++++++++++++++++++++
> drivers/net/sxe2/sxe2_txrx_poll.h | 20 +
> drivers/net/sxe2/sxe2_txrx_vec.c | 201 ++++
> drivers/net/sxe2/sxe2_txrx_vec.h | 63 ++
> drivers/net/sxe2/sxe2_txrx_vec_common.h | 235 +++++
> drivers/net/sxe2/sxe2_txrx_vec_sse.c | 549 ++++++++++
> drivers/net/sxe2/sxe2_vsi.c | 214 ++++
> drivers/net/sxe2/sxe2_vsi.h | 204 ++++
> 41 files changed, 9202 insertions(+)
> create mode 100644 doc/guides/nics/features/sxe2.ini
> create mode 100644 doc/guides/nics/sxe2.rst
> create mode 100644 drivers/common/sxe2/meson.build
> create mode 100644 drivers/common/sxe2/sxe2_common.c
> create mode 100644 drivers/common/sxe2/sxe2_common.h
> create mode 100644 drivers/common/sxe2/sxe2_common_log.h
> create mode 100644 drivers/common/sxe2/sxe2_host_regs.h
> create mode 100644 drivers/common/sxe2/sxe2_internal_ver.h
> create mode 100644 drivers/common/sxe2/sxe2_ioctl_chnl.c
> create mode 100644 drivers/common/sxe2/sxe2_ioctl_chnl.h
> create mode 100644 drivers/common/sxe2/sxe2_ioctl_chnl_func.h
> create mode 100644 drivers/common/sxe2/sxe2_osal.h
> create mode 100644 drivers/net/sxe2/meson.build
> create mode 100644 drivers/net/sxe2/sxe2_cmd_chnl.c
> create mode 100644 drivers/net/sxe2/sxe2_cmd_chnl.h
> create mode 100644 drivers/net/sxe2/sxe2_drv_cmd.h
> create mode 100644 drivers/net/sxe2/sxe2_ethdev.c
> create mode 100644 drivers/net/sxe2/sxe2_ethdev.h
> create mode 100644 drivers/net/sxe2/sxe2_irq.h
> create mode 100644 drivers/net/sxe2/sxe2_queue.c
> create mode 100644 drivers/net/sxe2/sxe2_queue.h
> create mode 100644 drivers/net/sxe2/sxe2_rx.c
> create mode 100644 drivers/net/sxe2/sxe2_rx.h
> create mode 100644 drivers/net/sxe2/sxe2_tx.c
> create mode 100644 drivers/net/sxe2/sxe2_tx.h
> create mode 100644 drivers/net/sxe2/sxe2_txrx.c
> create mode 100644 drivers/net/sxe2/sxe2_txrx.h
> create mode 100644 drivers/net/sxe2/sxe2_txrx_common.h
> create mode 100644 drivers/net/sxe2/sxe2_txrx_poll.c
> create mode 100644 drivers/net/sxe2/sxe2_txrx_poll.h
> create mode 100644 drivers/net/sxe2/sxe2_txrx_vec.c
> create mode 100644 drivers/net/sxe2/sxe2_txrx_vec.h
> create mode 100644 drivers/net/sxe2/sxe2_txrx_vec_common.h
> create mode 100644 drivers/net/sxe2/sxe2_txrx_vec_sse.c
> create mode 100644 drivers/net/sxe2/sxe2_vsi.c
> create mode 100644 drivers/net/sxe2/sxe2_vsi.h
>
Overall I am pleased with this and no AI review feedback.
But noticed some discrepancy between documentation and implementation
around feature; so asked AI to double check that.
Addendum to v17 review: features matrix vs code
================================================
Patch 02/11: doc: add sxe2 guide and release notes
--------------------------------------------------
The doc/guides/nics/features/sxe2.ini file claims a number of
features that the code does not implement. Cross-referencing
each "Y"/"P" line against drivers/net/sxe2/sxe2_ethdev.c
(sxe2_dev_info_init) and the final dev_ops table:
VLAN offload = Y
Neither RTE_ETH_RX_OFFLOAD_VLAN_STRIP,
RTE_ETH_RX_OFFLOAD_VLAN_FILTER, nor
RTE_ETH_TX_OFFLOAD_VLAN_INSERT is in dev_info->rx_offload_capa
or dev_info->tx_offload_capa. Applications cannot request
these offloads. No .vlan_offload_set, .vlan_filter_set,
.vlan_strip_queue_set, or .vlan_tpid_set callbacks are
registered. The only references to the VLAN offload macros
are inside SXE2_RX_VEC_SUPPORT_OFFLOAD / SXE2_TX_VEC_SUPPORT_OFFLOAD
(the vector-path allow-list), where they are filtered, not
advertised.
QinQ offload = P
No RTE_ETH_RX_OFFLOAD_QINQ_STRIP / RTE_ETH_TX_OFFLOAD_QINQ_INSERT
in offload_capa. The Tx path does handle RTE_MBUF_F_TX_QINQ
in the descriptor builder, but with no offload-capability
advertisement an application has no way to request it.
Timestamp offload = P
RTE_ETH_RX_OFFLOAD_TIMESTAMP is not in rx_offload_capa.
No .timesync_enable / disable / read_rx_timestamp /
read_tx_timestamp / adjust_time / read_time / write_time
callbacks are registered. The only occurrence of the
timestamp offload symbol is inside SXE2_RX_VEC_NO_SUPPORT_OFFLOAD
(i.e. the list of things the vector path filters out).
FreeBSD = Y
drivers/common/sxe2/meson.build and drivers/net/sxe2/meson.build
set "reason = 'only supported on Linux'" when excluding
Windows. doc/guides/nics/sxe2.rst states the PMD "is
designed to operate alongside the sxe2 kernel network driver"
and "communicates with the kernel driver via ioctl
interfaces" — that kernel driver exists only for Linux.
Either (a) drop "FreeBSD = Y" and gate the meson build with
"if not is_linux: build = false", or (b) provide a FreeBSD
kernel companion and update the meson reason string.
Inner L3 checksum = P
Inner L4 checksum = P
These could plausibly map to RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM
/ RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM (which are in
tx_offload_capa) plus the TNL_TSO offloads. Worth confirming
the mapping is what is intended.
What the matrix gets right (verified):
Fast mbuf free = P -> RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE
advertised in tx_offload_capa.
Free Tx mbuf on demand = Y -> .tx_done_cleanup registered
(patch 11).
Burst mode info = Y -> .rx_burst_mode_get and
.tx_burst_mode_get registered.
Queue start/stop = Y -> .{rx,tx}_queue_{start,stop}
registered.
Buffer split on Rx = P -> RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT
in rx_offload_capa.
Scattered Rx = Y -> sxe2_rx_pkts_scattered{,_split}
burst functions present.
CRC offload = Y -> RTE_ETH_RX_OFFLOAD_KEEP_CRC in
rx_offload_capa.
L3 checksum offload = Y -> IPV4_CKSUM (rx+tx) in offload_capa.
L4 checksum offload = Y -> TCP/UDP_CKSUM (rx+tx) in
offload_capa.
Rx descriptor status = Y -> dev->rx_descriptor_status set
(typo'd name "sxe2_rx_desciptor_status"
— missing 'r' — but functionally
wired up).
Tx descriptor status = Y -> same; sxe2_tx_desciptor_status
with the same typo.
Suggested fix
-------------
For the v18, please either:
(1) Add the missing offload bits (VLAN_STRIP, VLAN_FILTER,
VLAN_INSERT, QINQ_STRIP, QINQ_INSERT, RX_TIMESTAMP) to
offload_capa and implement the corresponding callbacks; or
(2) Drop the corresponding rows ("VLAN offload",
"QinQ offload", "Timestamp offload") from sxe2.ini to "N"
or remove them entirely.
Also rename sxe2_{rx,tx}_desciptor_status -> _descriptor_status
to match the dev_ops field name, and decide what to do about
the FreeBSD / Linux-only contradiction.
^ permalink raw reply
* Re: [PATCH] net/ixgbe: fix flow control frame byte adjustment
From: Bruce Richardson @ 2026-05-19 14:44 UTC (permalink / raw)
To: Daniil Iskhakov
Cc: Anatoly Burakov, Vladimir Medvedkin, dev, stable, sdl.dpdk, rrv
In-Reply-To: <20260504145502.160806-1-dish@amicon.ru>
On Mon, May 04, 2026 at 05:55:02PM +0300, Daniil Iskhakov wrote:
> LXONTXC and LXOFFTXC are 32-bit counters for transmitted XON and
> XOFF packets. ixgbe_read_stats_registers() sums their deltas and uses
> the result to adjust the transmitted byte counters by the minimum
> Ethernet frame length.
>
> The sum is currently computed as:
>
> total = lxon + lxoff
>
> Since both operands are 32-bit, the addition is performed in 32 bits
> and may wrap before the result is stored in total. The wrapped value is
> then used in the byte adjustment, which may make the software byte
> counters incorrect.
>
> Make total 64-bit and cast lxon before the addition so the XON/XOFF
> packet sum and the following byte adjustment are computed without
> 32-bit overflow.
>
> Found by Linux Verification Center (linuxtesting.org) with SVACE.
>
> Fixes: af75078fece3 ("first public release")
> Cc: stable@dpdk.org
>
> Signed-off-by: Daniil Iskhakov <dish@amicon.ru>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
^ permalink raw reply
* [PATCH v18 00/11] net/sxe2: fix logic errors and address feedback
From: liujie5 @ 2026-05-19 14:47 UTC (permalink / raw)
To: stephen; +Cc: dev, Jie Liu
In-Reply-To: <20260519030132.3780057-12-liujie5@linkdatatechnology.com>
From: Jie Liu <liujie5@linkdatatechnology.com>
This patch set addresses the feedback received on the v10 submission
for the sxe2 PMD. The primary focus is on fixing vector path selection,
ensuring memory safety during mbuf initialization, and cleaning up
redundant logic in the configuration functions.
v18:
- update sxe2.ini.
v17 Changes:
- Fixed vector Rx burst function being overwritten by scalar selection.
- Refactored Rx/Tx mode set functions to seed flags from caps first,
eliminating tautological checks.
- Added memset for mbuf_def in vector init to avoid uninitialized reads.
- Converted pci_map_addr_info to designated initializers.
- Removed dead Windows-only code in meson.build.
- Added NULL checks for mbuf free for driver-wide consistency.
- Updated burst_mode_get to accurately report AVX paths.
- Adjusted SXE2_ETH_OVERHEAD to match actual VLAN capabilities.
Jie Liu (11):
mailmap: add Jie Liu
doc: add sxe2 guide and release notes
common/sxe2: add sxe2 basic structures
drivers: add base driver skeleton
drivers: add base driver probe skeleton
drivers: support PCI BAR mapping
common/sxe2: add ioctl interface for DMA map and unmap
net/sxe2: support queue setup and control
drivers: add data path for Rx and Tx
net/sxe2: add vectorized Rx and Tx
net/sxe2: implement Tx done cleanup
.mailmap | 1 +
doc/guides/nics/features/sxe2.ini | 23 +
doc/guides/nics/index.rst | 1 +
doc/guides/nics/sxe2.rst | 34 +
doc/guides/rel_notes/release_26_07.rst | 4 +
drivers/common/sxe2/meson.build | 15 +
drivers/common/sxe2/sxe2_common.c | 683 +++++++++++++
drivers/common/sxe2/sxe2_common.h | 85 ++
drivers/common/sxe2/sxe2_common_log.h | 81 ++
drivers/common/sxe2/sxe2_host_regs.h | 707 +++++++++++++
drivers/common/sxe2/sxe2_internal_ver.h | 33 +
drivers/common/sxe2/sxe2_ioctl_chnl.c | 325 ++++++
drivers/common/sxe2/sxe2_ioctl_chnl.h | 130 +++
drivers/common/sxe2/sxe2_ioctl_chnl_func.h | 62 ++
drivers/common/sxe2/sxe2_osal.h | 153 +++
drivers/meson.build | 1 +
drivers/net/meson.build | 1 +
drivers/net/sxe2/meson.build | 32 +
drivers/net/sxe2/sxe2_cmd_chnl.c | 323 ++++++
drivers/net/sxe2/sxe2_cmd_chnl.h | 37 +
drivers/net/sxe2/sxe2_drv_cmd.h | 388 ++++++++
drivers/net/sxe2/sxe2_ethdev.c | 968 ++++++++++++++++++
drivers/net/sxe2/sxe2_ethdev.h | 318 ++++++
drivers/net/sxe2/sxe2_irq.h | 48 +
drivers/net/sxe2/sxe2_queue.c | 66 ++
drivers/net/sxe2/sxe2_queue.h | 195 ++++
drivers/net/sxe2/sxe2_rx.c | 554 +++++++++++
drivers/net/sxe2/sxe2_rx.h | 32 +
drivers/net/sxe2/sxe2_tx.c | 420 ++++++++
drivers/net/sxe2/sxe2_tx.h | 32 +
drivers/net/sxe2/sxe2_txrx.c | 352 +++++++
drivers/net/sxe2/sxe2_txrx.h | 23 +
drivers/net/sxe2/sxe2_txrx_common.h | 540 ++++++++++
drivers/net/sxe2/sxe2_txrx_poll.c | 1044 ++++++++++++++++++++
drivers/net/sxe2/sxe2_txrx_poll.h | 20 +
drivers/net/sxe2/sxe2_txrx_vec.c | 201 ++++
drivers/net/sxe2/sxe2_txrx_vec.h | 63 ++
drivers/net/sxe2/sxe2_txrx_vec_common.h | 235 +++++
drivers/net/sxe2/sxe2_txrx_vec_sse.c | 549 ++++++++++
drivers/net/sxe2/sxe2_vsi.c | 214 ++++
drivers/net/sxe2/sxe2_vsi.h | 204 ++++
41 files changed, 9197 insertions(+)
create mode 100644 doc/guides/nics/features/sxe2.ini
create mode 100644 doc/guides/nics/sxe2.rst
create mode 100644 drivers/common/sxe2/meson.build
create mode 100644 drivers/common/sxe2/sxe2_common.c
create mode 100644 drivers/common/sxe2/sxe2_common.h
create mode 100644 drivers/common/sxe2/sxe2_common_log.h
create mode 100644 drivers/common/sxe2/sxe2_host_regs.h
create mode 100644 drivers/common/sxe2/sxe2_internal_ver.h
create mode 100644 drivers/common/sxe2/sxe2_ioctl_chnl.c
create mode 100644 drivers/common/sxe2/sxe2_ioctl_chnl.h
create mode 100644 drivers/common/sxe2/sxe2_ioctl_chnl_func.h
create mode 100644 drivers/common/sxe2/sxe2_osal.h
create mode 100644 drivers/net/sxe2/meson.build
create mode 100644 drivers/net/sxe2/sxe2_cmd_chnl.c
create mode 100644 drivers/net/sxe2/sxe2_cmd_chnl.h
create mode 100644 drivers/net/sxe2/sxe2_drv_cmd.h
create mode 100644 drivers/net/sxe2/sxe2_ethdev.c
create mode 100644 drivers/net/sxe2/sxe2_ethdev.h
create mode 100644 drivers/net/sxe2/sxe2_irq.h
create mode 100644 drivers/net/sxe2/sxe2_queue.c
create mode 100644 drivers/net/sxe2/sxe2_queue.h
create mode 100644 drivers/net/sxe2/sxe2_rx.c
create mode 100644 drivers/net/sxe2/sxe2_rx.h
create mode 100644 drivers/net/sxe2/sxe2_tx.c
create mode 100644 drivers/net/sxe2/sxe2_tx.h
create mode 100644 drivers/net/sxe2/sxe2_txrx.c
create mode 100644 drivers/net/sxe2/sxe2_txrx.h
create mode 100644 drivers/net/sxe2/sxe2_txrx_common.h
create mode 100644 drivers/net/sxe2/sxe2_txrx_poll.c
create mode 100644 drivers/net/sxe2/sxe2_txrx_poll.h
create mode 100644 drivers/net/sxe2/sxe2_txrx_vec.c
create mode 100644 drivers/net/sxe2/sxe2_txrx_vec.h
create mode 100644 drivers/net/sxe2/sxe2_txrx_vec_common.h
create mode 100644 drivers/net/sxe2/sxe2_txrx_vec_sse.c
create mode 100644 drivers/net/sxe2/sxe2_vsi.c
create mode 100644 drivers/net/sxe2/sxe2_vsi.h
--
2.47.3
^ permalink raw reply
* [PATCH v18 02/11] doc: add sxe2 guide and release notes
From: liujie5 @ 2026-05-19 14:48 UTC (permalink / raw)
To: stephen; +Cc: dev, Jie Liu
In-Reply-To: <20260519144810.3951202-1-liujie5@linkdatatechnology.com>
From: Jie Liu <liujie5@linkdatatechnology.com>
Add a new guide for SXE2 PMD in the nics directory.
The guide contains driver capabilities, prerequisites,
and compilation/usage instructions.
Update the release notes to announce the addition of the
sxe2 network driver.
Signed-off-by: Jie Liu <liujie5@linkdatatechnology.com>
---
doc/guides/nics/features/sxe2.ini | 23 +++++++++++++++++
doc/guides/nics/index.rst | 1 +
doc/guides/nics/sxe2.rst | 34 ++++++++++++++++++++++++++
doc/guides/rel_notes/release_26_07.rst | 4 +++
4 files changed, 62 insertions(+)
create mode 100644 doc/guides/nics/features/sxe2.ini
create mode 100644 doc/guides/nics/sxe2.rst
diff --git a/doc/guides/nics/features/sxe2.ini b/doc/guides/nics/features/sxe2.ini
new file mode 100644
index 0000000000..09ba2f558c
--- /dev/null
+++ b/doc/guides/nics/features/sxe2.ini
@@ -0,0 +1,23 @@
+;
+; Supported features of the 'sxe2' network poll mode driver.
+;
+; Refer to default.ini for the full list of available PMD features.
+;
+; A feature with "P" indicates only be supported when non-vector path
+; is selected.
+;
+[Features]
+Fast mbuf free = P
+Free Tx mbuf on demand = Y
+Burst mode info = Y
+Queue start/stop = Y
+Buffer split on Rx = P
+Scattered Rx = Y
+CRC offload = Y
+L3 checksum offload = Y
+L4 checksum offload = Y
+Rx descriptor status = Y
+Tx descriptor status = Y
+Linux = Y
+x86-32 = Y
+x86-64 = Y
diff --git a/doc/guides/nics/index.rst b/doc/guides/nics/index.rst
index cb818284fe..e20be478f8 100644
--- a/doc/guides/nics/index.rst
+++ b/doc/guides/nics/index.rst
@@ -68,6 +68,7 @@ Network Interface Controller Drivers
rnp
sfc_efx
softnic
+ sxe2
tap
thunderx
txgbe
diff --git a/doc/guides/nics/sxe2.rst b/doc/guides/nics/sxe2.rst
new file mode 100644
index 0000000000..7fcf9c085b
--- /dev/null
+++ b/doc/guides/nics/sxe2.rst
@@ -0,0 +1,34 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+ Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
+
+SXE2 Poll Mode Driver
+======================
+
+The sxe2 PMD (**librte_net_sxe2**) provides poll mode driver support for
+10/25/50/100 Gbps Network Adapters.
+The embedded switch, Physical Functions (PF),
+and SR-IOV Virtual Functions (VF) are supported.
+
+Implementation details
+----------------------
+
+The sxe2 PMD is designed to operate alongside the sxe2 kernel network driver.
+For management and control operations, the PMD communicates with the kernel
+driver via ioctl interfaces. These commands are processed by the kernel
+driver and subsequently dispatched to the hardware firmware for execution.
+
+For security and robustness, the driver's data path is optimized to operate
+using virtual addresses (IOVA as VA mode). However, to ensure full
+compatibility in system environments where an IOMMU is absent or disabled,
+the driver also provides an explicit path to support physical addressing
+(IOVA as PA mode).
+
+The hardware is capable of handling the corresponding IOVA addresses (either
+VA or PA) directly, as provided by the DPDK memory subsystem. This ensures
+that DPDK applications can only access memory segments explicitly allocated
+to the current process, preventing unauthorized access to random physical
+memory.
+
+This capability allows the PMD to coexist with kernel network interfaces
+which remain functional, although they stop receiving unicast packets as
+long as they share the same MAC address.
diff --git a/doc/guides/rel_notes/release_26_07.rst b/doc/guides/rel_notes/release_26_07.rst
index f012d47a4b..fa0f0f5cca 100644
--- a/doc/guides/rel_notes/release_26_07.rst
+++ b/doc/guides/rel_notes/release_26_07.rst
@@ -64,6 +64,10 @@ New Features
* ``--auto-probing`` enables the initial bus probing, which is the current default behavior.
+* **Added Linkdata sxe2 ethernet driver.**
+
+ Added network driver for the Linkdata Network Adapters.
+
Removed Items
-------------
--
2.47.3
^ permalink raw reply related
* [PATCH v18 01/11] mailmap: add Jie Liu
From: liujie5 @ 2026-05-19 14:48 UTC (permalink / raw)
To: stephen; +Cc: dev, Jie Liu
In-Reply-To: <20260519144810.3951202-1-liujie5@linkdatatechnology.com>
From: Jie Liu <liujie5@linkdatatechnology.com>
Signed-off-by: Jie Liu <liujie5@linkdatatechnology.com>
---
.mailmap | 1 +
1 file changed, 1 insertion(+)
diff --git a/.mailmap b/.mailmap
index 895412e568..d2c4485636 100644
--- a/.mailmap
+++ b/.mailmap
@@ -739,6 +739,7 @@ Jiawen Wu <jiawenwu@trustnetic.com>
Jiayu Hu <hujiayu.hu@foxmail.com> <jiayu.hu@intel.com>
Jie Hai <haijie1@huawei.com>
Jie Liu <jie2.liu@hxt-semitech.com>
+Jie Liu <liujie5@linkdatatechnology.com>
Jie Pan <panjie5@jd.com>
Jie Wang <jie1x.wang@intel.com>
Jie Zhou <jizh@linux.microsoft.com> <jizh@microsoft.com>
--
2.47.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox