From: Junlong Wang <wang.junlong1@zte.com.cn>
To: stephen@networkplumber.org
Cc: dev@dpdk.org, Junlong Wang <wang.junlong1@zte.com.cn>
Subject: [PATCH v11 4/4] net/zxdh: optimize Tx xmit pkts performance
Date: Wed, 19 Aug 2026 17:53:03 +0800 [thread overview]
Message-ID: <20260819095304.3016940-5-wang.junlong1@zte.com.cn> (raw)
In-Reply-To: <20260819095304.3016940-1-wang.junlong1@zte.com.cn>
[-- Attachment #1.1.1: Type: text/plain, Size: 11217 bytes --]
1. Rework the Tx completion flush to walk descriptors one at a time and
free each completed segment with rte_pktmbuf_free_seg(), add prefetch
hints on the next descriptor cache line, switch the ring-held mbufs
in zxdh_dev_free_mbufs() to rte_pktmbuf_free_seg(), and drop the
unused uint64_t offloads field from struct zxdh_virtnet_rx.
2. The flush relies on `desc[k].id == k` already being set by the
enqueue paths (`zxdh_xmit_enqueue_push` writes `dp->id = id` and
`zxdh_xmit_enqueue_append` writes `start_dp[idx].id = idx`) and
preserved by the device. The flush performs no rewrite of the id
field, avoiding a write to the device-shared descriptor cache line.
3. Guard the walk with a `budget` counter initialised to `vq_nentries`,
break on `id >= size`, and mask the prefetch index with `(size - 1)`
so the walk and `free_cnt` stay bounded even if the device writes
an out-of-range or stale id.
4. Document the Tx xmit changes in the 26.11 release notes.
Signed-off-by: Junlong Wang <wang.junlong1@zte.com.cn>
---
doc/guides/rel_notes/release_26_11.rst | 2 +
drivers/net/zxdh/zxdh_ethdev.c | 4 +-
drivers/net/zxdh/zxdh_queue.h | 2 +-
drivers/net/zxdh/zxdh_rxtx.c | 136 ++++++++++---------------
4 files changed, 58 insertions(+), 86 deletions(-)
diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst
index 240300dff6..77cdbe13d1 100644
--- a/doc/guides/rel_notes/release_26_11.rst
+++ b/doc/guides/rel_notes/release_26_11.rst
@@ -73,6 +73,8 @@ New Features
* Removed unused xstats counters (``full``, ``norefill``,
``multicast_packets``, ``broadcast_packets``) from both Rx and Tx
queues.
+ * Optimized the packed-ring Tx xmit path with per-descriptor mbuf
+ free (``rte_pktmbuf_free_seg``) and prefetch hints.
Removed Items
-------------
diff --git a/drivers/net/zxdh/zxdh_ethdev.c b/drivers/net/zxdh/zxdh_ethdev.c
index 2ab6567d65..d0b9803de4 100644
--- a/drivers/net/zxdh/zxdh_ethdev.c
+++ b/drivers/net/zxdh/zxdh_ethdev.c
@@ -489,7 +489,7 @@ zxdh_dev_free_mbufs(struct rte_eth_dev *dev)
if (!vq)
continue;
while ((buf = zxdh_queue_detach_unused(vq)) != NULL)
- rte_pktmbuf_free(buf);
+ rte_pktmbuf_free_seg(buf);
PMD_DRV_LOG(DEBUG, "freeing %s[%d] used and unused buf",
"rxq", i * 2);
}
@@ -498,7 +498,7 @@ zxdh_dev_free_mbufs(struct rte_eth_dev *dev)
if (!vq)
continue;
while ((buf = zxdh_queue_detach_unused(vq)) != NULL)
- rte_pktmbuf_free(buf);
+ rte_pktmbuf_free_seg(buf);
PMD_DRV_LOG(DEBUG, "freeing %s[%d] used and unused buf",
"txq", i * 2 + 1);
}
diff --git a/drivers/net/zxdh/zxdh_queue.h b/drivers/net/zxdh/zxdh_queue.h
index 49970fbef2..e730965ece 100644
--- a/drivers/net/zxdh/zxdh_queue.h
+++ b/drivers/net/zxdh/zxdh_queue.h
@@ -124,7 +124,7 @@ struct zxdh_vring_packed {
struct zxdh_vq_desc_extra {
void *cookie;
- uint16_t ndescs;
+ uint16_t rsv;
uint16_t next;
};
diff --git a/drivers/net/zxdh/zxdh_rxtx.c b/drivers/net/zxdh/zxdh_rxtx.c
index 367924069f..34d5d6686d 100644
--- a/drivers/net/zxdh/zxdh_rxtx.c
+++ b/drivers/net/zxdh/zxdh_rxtx.c
@@ -114,6 +114,9 @@
RTE_MBUF_F_TX_SEC_OFFLOAD | \
RTE_MBUF_F_TX_UDP_SEG)
+
+#define NEXT_CACHELINE_OFF_16B (RTE_CACHE_LINE_SIZE / 16)
+
uint32_t zxdh_outer_l2_type[16] = {
0,
RTE_PTYPE_L2_ETHER,
@@ -201,43 +204,6 @@ uint32_t zxdh_inner_l4_type[16] = {
0,
};
-static void
-zxdh_xmit_cleanup_inorder_packed(struct zxdh_virtqueue *vq, int32_t num)
-{
- uint16_t used_idx = 0;
- uint16_t id = 0;
- uint16_t curr_id = 0;
- uint16_t free_cnt = 0;
- uint16_t size = vq->vq_nentries;
- struct zxdh_vring_packed_desc *desc = vq->vq_packed.ring.desc;
- struct zxdh_vq_desc_extra *dxp = NULL;
-
- used_idx = vq->vq_used_cons_idx;
- /* desc_is_used has a load-acquire or rte_io_rmb inside
- * and wait for used desc in virtqueue.
- */
- while (num > 0 && desc_is_used(&desc[used_idx], vq)) {
- id = desc[used_idx].id;
- do {
- curr_id = used_idx;
- dxp = &vq->vq_descx[used_idx];
- used_idx += dxp->ndescs;
- free_cnt += dxp->ndescs;
- num -= dxp->ndescs;
- if (used_idx >= size) {
- used_idx -= size;
- vq->used_wrap_counter ^= 1;
- }
- if (dxp->cookie != NULL) {
- rte_pktmbuf_free(dxp->cookie);
- dxp->cookie = NULL;
- }
- } while (curr_id != id);
- }
- vq->vq_used_cons_idx = used_idx;
- vq->vq_free_cnt += free_cnt;
-}
-
static inline uint16_t
zxdh_get_mtu(struct zxdh_virtqueue *vq)
{
@@ -334,7 +300,7 @@ zxdh_xmit_fill_net_hdr(struct zxdh_virtqueue *vq, struct rte_mbuf *cookie,
}
static inline void
-zxdh_enqueue_xmit_packed_fast(struct zxdh_virtnet_tx *txvq,
+zxdh_xmit_enqueue_push(struct zxdh_virtnet_tx *txvq,
struct rte_mbuf *cookie)
{
struct zxdh_virtqueue *vq = txvq->vq;
@@ -345,7 +311,6 @@ zxdh_enqueue_xmit_packed_fast(struct zxdh_virtnet_tx *txvq,
uint8_t hdr_len = vq->hw->dl_net_hdr_len;
struct zxdh_vring_packed_desc *dp = &vq->vq_packed.ring.desc[id];
- dxp->ndescs = 1;
dxp->cookie = cookie;
hdr = rte_pktmbuf_mtod_offset(cookie, struct zxdh_net_hdr_dl *, -hdr_len);
zxdh_xmit_fill_net_hdr(vq, cookie, hdr);
@@ -362,51 +327,56 @@ zxdh_enqueue_xmit_packed_fast(struct zxdh_virtnet_tx *txvq,
}
static inline void
-zxdh_enqueue_xmit_packed(struct zxdh_virtnet_tx *txvq,
+zxdh_xmit_enqueue_append(struct zxdh_virtnet_tx *txvq,
struct rte_mbuf *cookie,
uint16_t needed)
{
struct zxdh_tx_region *txr = txvq->zxdh_net_hdr_mz->addr;
struct zxdh_virtqueue *vq = txvq->vq;
- uint16_t id = vq->vq_avail_idx;
- struct zxdh_vq_desc_extra *dxp = &vq->vq_descx[id];
uint16_t head_idx = vq->vq_avail_idx;
uint16_t idx = head_idx;
struct zxdh_vring_packed_desc *start_dp = vq->vq_packed.ring.desc;
struct zxdh_vring_packed_desc *head_dp = &vq->vq_packed.ring.desc[idx];
struct zxdh_net_hdr_dl *hdr = NULL;
- uint16_t head_flags = cookie->next ? ZXDH_VRING_DESC_F_NEXT : 0;
+ uint16_t id = vq->vq_avail_idx;
+ struct zxdh_vq_desc_extra *dxp = &vq->vq_descx[id];
uint8_t hdr_len = vq->hw->dl_net_hdr_len;
+ uint16_t head_flags = 0;
- dxp->ndescs = needed;
- dxp->cookie = cookie;
- head_flags |= vq->cached_flags;
+ dxp->cookie = NULL;
+ /*
+ * Head descriptor has no mbuf cookie. Per-segment cookies are
+ * stored on the segment descs so zxdh_xmit_fast_flush() can free
+ * each via rte_pktmbuf_free_seg(). zxdh_queue_detach_unused() and
+ * zxdh_queue_rxvq_flush() both skip NULL cookies and are the only
+ * expected readers of head cookies.
+ */
+ /* setup first tx ring slot to point to header stored in reserved region. */
start_dp[idx].addr = txvq->zxdh_net_hdr_mem + RTE_PTR_DIFF(&txr[idx].tx_hdr, txr);
start_dp[idx].len = hdr_len;
- head_flags |= ZXDH_VRING_DESC_F_NEXT;
+ start_dp[idx].id = idx;
+ head_flags |= vq->cached_flags | ZXDH_VRING_DESC_F_NEXT;
hdr = (void *)&txr[idx].tx_hdr;
- rte_prefetch1(hdr);
+ zxdh_xmit_fill_net_hdr(vq, cookie, hdr);
+
idx++;
if (idx >= vq->vq_nentries) {
idx -= vq->vq_nentries;
vq->cached_flags ^= ZXDH_VRING_PACKED_DESC_F_AVAIL_USED;
}
- zxdh_xmit_fill_net_hdr(vq, cookie, hdr);
-
do {
start_dp[idx].addr = rte_pktmbuf_iova(cookie);
start_dp[idx].len = cookie->data_len;
- start_dp[idx].id = id;
- if (likely(idx != head_idx)) {
- uint16_t flags = cookie->next ? ZXDH_VRING_DESC_F_NEXT : 0;
+ start_dp[idx].id = idx;
- flags |= vq->cached_flags;
- start_dp[idx].flags = flags;
- }
+ vq->vq_descx[idx].cookie = cookie;
+ uint16_t flags = cookie->next ? ZXDH_VRING_DESC_F_NEXT : 0;
+ flags |= vq->cached_flags;
+ start_dp[idx].flags = flags;
idx++;
if (idx >= vq->vq_nentries) {
@@ -456,7 +426,7 @@ zxdh_update_packet_stats(struct zxdh_virtnet_stats *stats, struct rte_mbuf *mbuf
}
static void
-zxdh_xmit_flush(struct zxdh_virtqueue *vq)
+zxdh_xmit_fast_flush(struct zxdh_virtqueue *vq)
{
uint16_t id = 0;
uint16_t curr_id = 0;
@@ -465,27 +435,39 @@ zxdh_xmit_flush(struct zxdh_virtqueue *vq)
struct zxdh_vring_packed_desc *desc = vq->vq_packed.ring.desc;
struct zxdh_vq_desc_extra *dxp = NULL;
uint16_t used_idx = vq->vq_used_cons_idx;
+ uint16_t budget = size;
/*
* The function desc_is_used performs a load-acquire operation
* or calls rte_io_rmb to ensure memory consistency. It waits
* for a used descriptor in the virtqueue.
*/
- while (desc_is_used(&desc[used_idx], vq)) {
+ while (budget > 0 && desc_is_used(&desc[used_idx], vq)) {
+ /*
+ * vq_nentries is validated as power-of-two in
+ * zxdh_queue_desc_pre_setup(), so mask the prefetch index to keep
+ * it inside desc[] when used_idx is near the end of the ring.
+ */
+ rte_prefetch0(&desc[(used_idx + NEXT_CACHELINE_OFF_16B) & (size - 1)]);
id = desc[used_idx].id;
+ if (unlikely(id >= size))
+ break;
do {
curr_id = used_idx;
dxp = &vq->vq_descx[used_idx];
- used_idx += dxp->ndescs;
- free_cnt += dxp->ndescs;
- if (used_idx >= size) {
- used_idx -= size;
- vq->used_wrap_counter ^= 1;
- }
if (dxp->cookie != NULL) {
- rte_pktmbuf_free(dxp->cookie);
+ rte_pktmbuf_free_seg(dxp->cookie);
dxp->cookie = NULL;
}
+ used_idx += 1;
+ free_cnt += 1;
+ budget -= 1;
+ if (unlikely(used_idx == size)) {
+ used_idx = 0;
+ vq->used_wrap_counter ^= 1;
+ }
+ if (unlikely(budget == 0))
+ break;
} while (curr_id != id);
}
vq->vq_used_cons_idx = used_idx;
@@ -499,13 +481,12 @@ zxdh_xmit_pkts_packed(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkt
struct zxdh_virtqueue *vq = txvq->vq;
uint16_t nb_tx = 0;
- zxdh_xmit_flush(vq);
+ zxdh_xmit_fast_flush(vq);
for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) {
struct rte_mbuf *txm = tx_pkts[nb_tx];
int32_t can_push = 0;
int32_t slots = 0;
- int32_t need = 0;
rte_prefetch0(txm);
/* optimize ring usage */
@@ -522,26 +503,15 @@ zxdh_xmit_pkts_packed(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkt
* default => number of segments + 1
**/
slots = txm->nb_segs + !can_push;
- need = slots - vq->vq_free_cnt;
- /* Positive value indicates it need free vring descriptors */
- if (unlikely(need > 0)) {
- zxdh_xmit_cleanup_inorder_packed(vq, need);
- need = slots - vq->vq_free_cnt;
- if (unlikely(need > 0)) {
- PMD_TX_LOG(ERR,
- " No enough %d free tx descriptors to transmit."
- "freecnt %d",
- need,
- vq->vq_free_cnt);
- break;
- }
- }
+
+ if (unlikely(slots > vq->vq_free_cnt))
+ break;
/* Enqueue Packet buffers */
if (can_push)
- zxdh_enqueue_xmit_packed_fast(txvq, txm);
+ zxdh_xmit_enqueue_push(txvq, txm);
else
- zxdh_enqueue_xmit_packed(txvq, txm, slots);
+ zxdh_xmit_enqueue_append(txvq, txm, slots);
zxdh_update_packet_stats(&txvq->stats, txm);
}
txvq->stats.packets += nb_tx;
--
2.27.0
[-- Attachment #1.1.2: Type: text/html , Size: 28751 bytes --]
next prev parent reply other threads:[~2026-08-19 9:58 UTC|newest]
Thread overview: 73+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-26 2:28 [PATCH v1] net/zxdh: optimize Rx/Tx path performance Junlong Wang
2026-03-26 3:27 ` Stephen Hemminger
2026-04-06 4:26 ` Stephen Hemminger
2026-04-23 1:18 ` [PATCH v2 0/3] " Junlong Wang
2026-04-23 1:18 ` [PATCH v2 1/3] net/zxdh: optimize queue structure to improve performance Junlong Wang
2026-04-23 18:57 ` Stephen Hemminger
2026-04-23 1:18 ` [PATCH v2 2/3] net/zxdh: optimize Rx recv pkts performance Junlong Wang
2026-04-23 18:54 ` Stephen Hemminger
2026-04-23 23:39 ` Stephen Hemminger
2026-04-23 1:18 ` [PATCH v2 3/3] net/zxdh: optimize Tx xmit " Junlong Wang
2026-04-23 19:23 ` [PATCH v2 0/3] net/zxdh: optimize Rx/Tx path performance Stephen Hemminger
2026-05-09 6:29 ` [PATCH v3 " Junlong Wang
2026-05-09 6:29 ` [PATCH v3 1/3] net/zxdh: optimize queue structure to improve performance Junlong Wang
2026-05-18 2:20 ` Stephen Hemminger
2026-05-09 6:29 ` [PATCH v3 2/3] net/zxdh: optimize Rx recv pkts performance Junlong Wang
2026-05-09 6:29 ` [PATCH v3 3/3] net/zxdh: optimize Tx xmit " Junlong Wang
2026-05-18 2:22 ` Stephen Hemminger
2026-06-06 6:32 ` [PATCH v4 0/4] net/zxdh: optimize Rx/Tx path performance Junlong Wang
2026-06-06 6:32 ` [PATCH v4 1/4] net/zxdh: optimize queue structure to improve performance Junlong Wang
2026-06-06 6:32 ` [PATCH v4 2/4] net/zxdh: optimize Rx recv pkts performance Junlong Wang
2026-06-06 6:32 ` [PATCH v4 3/4] net/zxdh: optimize Tx xmit " Junlong Wang
2026-06-06 6:32 ` [PATCH v4 4/4] net/zxdh: fix queue enable intr issues Junlong Wang
2026-06-07 18:00 ` [PATCH v4 0/4] net/zxdh: optimize Rx/Tx path performance Stephen Hemminger
2026-06-15 1:19 ` [PATCH v5 " Junlong Wang
2026-06-15 1:19 ` [PATCH v5 1/4] net/zxdh: fix queue enable intr issues Junlong Wang
2026-06-15 1:19 ` [PATCH v5 2/4] net/zxdh: optimize queue structure to improve performance Junlong Wang
2026-06-15 1:19 ` [PATCH v5 3/4] net/zxdh: optimize Rx recv pkts performance Junlong Wang
2026-06-15 1:19 ` [PATCH v5 4/4] net/zxdh: optimize Tx xmit " Junlong Wang
2026-06-15 18:38 ` Stephen Hemminger
2026-06-17 8:28 ` [PATCH v6 0/4] net/zxdh: optimize Rx/Tx path performance Junlong Wang
2026-06-17 8:28 ` [PATCH v6 1/4] net/zxdh: fix queue enable intr issues Junlong Wang
2026-06-17 8:28 ` [PATCH v6 2/4] net/zxdh: optimize queue structure to improve performance Junlong Wang
2026-06-17 8:28 ` [PATCH v6 3/4] net/zxdh: optimize Rx recv pkts performance Junlong Wang
2026-06-17 8:28 ` [PATCH v6 4/4] net/zxdh: optimize Tx xmit " Junlong Wang
2026-06-17 15:21 ` [PATCH v6 0/4] net/zxdh: optimize Rx/Tx path performance Stephen Hemminger
2026-06-23 6:09 ` [PATCH v7 " Junlong Wang
2026-06-23 6:09 ` [PATCH v7 1/4] net/zxdh: fix queue enable intr issues Junlong Wang
2026-06-23 6:09 ` [PATCH v7 2/4] net/zxdh: optimize queue structure to improve performance Junlong Wang
2026-06-23 6:09 ` [PATCH v7 3/4] net/zxdh: optimize Rx recv pkts performance Junlong Wang
2026-06-23 6:09 ` [PATCH v7 4/4] net/zxdh: optimize Tx xmit " Junlong Wang
2026-06-23 15:54 ` [PATCH v7 0/4] net/zxdh: optimize Rx/Tx path performance Stephen Hemminger
2026-06-25 12:03 ` [PATCH v8 " Junlong Wang
2026-06-25 12:03 ` [PATCH v8 1/4] net/zxdh: fix queue enable intr issues Junlong Wang
2026-06-25 12:03 ` [PATCH v8 2/4] net/zxdh: optimize queue structure to improve performance Junlong Wang
2026-06-25 12:03 ` [PATCH v8 3/4] net/zxdh: optimize Rx recv pkts performance Junlong Wang
2026-06-25 12:03 ` [PATCH v8 4/4] net/zxdh: optimize Tx xmit " Junlong Wang
2026-06-25 22:42 ` [PATCH v8 0/4] net/zxdh: optimize Rx/Tx path performance Stephen Hemminger
2026-06-26 3:10 ` [v8,0/4] " Junlong Wang
2026-07-03 8:17 ` Junlong Wang
2026-07-09 10:46 ` [PATCH v9 0/4] " Junlong Wang
2026-07-09 10:46 ` [PATCH v9 1/4] net/zxdh: fix queue enable intr issues Junlong Wang
2026-07-09 10:46 ` [PATCH v9 2/4] net/zxdh: optimize queue structure to improve performance Junlong Wang
2026-07-09 10:46 ` [PATCH v9 3/4] net/zxdh: optimize Rx recv pkts performance Junlong Wang
2026-07-09 10:46 ` [PATCH v9 4/4] net/zxdh: optimize Tx xmit " Junlong Wang
2026-07-26 16:39 ` [PATCH v9 0/4] net/zxdh: optimize Rx/Tx path performance Stephen Hemminger
2026-08-03 11:24 ` [PATCH v10 " Junlong Wang
2026-08-03 11:24 ` [PATCH v10 1/4] net/zxdh: fix queue enable intr issues Junlong Wang
2026-08-03 11:24 ` [PATCH v10 2/4] net/zxdh: optimize queue structure to improve performance Junlong Wang
2026-08-03 11:24 ` [PATCH v10 3/4] net/zxdh: optimize Rx recv pkts performance Junlong Wang
2026-08-03 11:24 ` [PATCH v10 4/4] net/zxdh: optimize Tx xmit " Junlong Wang
2026-08-04 16:33 ` [PATCH v10 0/4] net/zxdh: optimize Rx/Tx path performance Stephen Hemminger
2026-08-19 9:52 ` [PATCH v11 " Junlong Wang
2026-08-19 9:53 ` [PATCH v11 1/4] net/zxdh: fix queue enable intr issues Junlong Wang
2026-08-19 9:53 ` [PATCH v11 2/4] net/zxdh: optimize queue structure to improve performance Junlong Wang
2026-08-19 9:53 ` [PATCH v11 3/4] net/zxdh: optimize Rx recv pkts performance Junlong Wang
2026-08-19 9:53 ` Junlong Wang [this message]
2026-08-19 21:04 ` [PATCH v11 0/4] net/zxdh: optimize Rx/Tx path performance Stephen Hemminger
2026-08-25 12:00 ` [PATCH v12 " Junlong Wang
2026-08-25 12:00 ` [PATCH v12 1/4] net/zxdh: fix queue enable intr issues Junlong Wang
2026-08-25 12:00 ` [PATCH v12 2/4] net/zxdh: optimize queue structure to improve performance Junlong Wang
2026-08-25 12:00 ` [PATCH v12 3/4] net/zxdh: optimize Rx recv pkts performance Junlong Wang
2026-08-25 12:00 ` [PATCH v12 4/4] net/zxdh: optimize Tx xmit " Junlong Wang
2026-08-25 19:58 ` [PATCH v12 0/4] net/zxdh: optimize Rx/Tx path performance Stephen Hemminger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260819095304.3016940-5-wang.junlong1@zte.com.cn \
--to=wang.junlong1@zte.com.cn \
--cc=dev@dpdk.org \
--cc=stephen@networkplumber.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.