patch 'net/pcap: fix error accounting and backpressure on Tx' has been queued to stable release 25.11.3
Kevin Traynor
ktraynor at redhat.com
Thu Jul 30 14:26:22 CEST 2026
Hi,
FYI, your patch has been queued to stable release 25.11.3
Note it hasn't been pushed to http://dpdk.org/browse/dpdk-stable yet.
It will be pushed if I get no objections before 08/04/26. So please
shout if anyone has objections.
Also note that after the patch there's a diff of the upstream commit vs the
patch applied to the branch. This will indicate if there was any rebasing
needed to apply to the stable branch. If there were code changes for rebasing
(ie: not only metadata diffs), please double check that the rebase was
correctly done.
Queued patches are on a temporary branch at:
https://github.com/kevintraynor/dpdk-stable
This queued commit can be viewed at:
https://github.com/kevintraynor/dpdk-stable/commit/d1622805b8bf8c4595934f325f973180cdd925ea
Thanks.
Kevin
---
>From d1622805b8bf8c4595934f325f973180cdd925ea Mon Sep 17 00:00:00 2001
From: Stephen Hemminger <stephen at networkplumber.org>
Date: Sun, 19 Apr 2026 09:09:42 -0700
Subject: [PATCH] net/pcap: fix error accounting and backpressure on Tx
[ upstream commit cf91cce204ea0fd9289d91e58d1b7c6ece385d56 ]
Correct two problems in eth_pcap_tx():
Oversized multi-segment packets that exceed the bounce buffer are
dropped but were not counted as errors. Add err_pkts accounting
for these drops.
When pcap_sendpacket() fails due to kernel socket backpressure,
the remaining unsent packets were counted as TX errors. Since
backpressure is transient (EAGAIN/EBUSY/EINTR), break the loop
and return the number of packets attempted so the caller retains
ownership of the unsent mbufs per tx_burst semantics.
Fixes: fbbbf553f268 ("net/pcap: fix concurrent multiseg Tx")
Signed-off-by: Stephen Hemminger <stephen at networkplumber.org>
---
drivers/net/pcap/pcap_ethdev.c | 35 +++++++++++++++++++++-------------
1 file changed, 22 insertions(+), 13 deletions(-)
diff --git a/drivers/net/pcap/pcap_ethdev.c b/drivers/net/pcap/pcap_ethdev.c
index c3d58e2752..37e847c5c5 100644
--- a/drivers/net/pcap/pcap_ethdev.c
+++ b/drivers/net/pcap/pcap_ethdev.c
@@ -457,5 +457,15 @@ eth_tx_drop(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
/*
- * Callback to handle sending packets through a real NIC.
+ * Send a burst of packets to a pcap device.
+ *
+ * On Linux, pcap_sendpacket() calls send() on a blocking PF_PACKET
+ * socket with default kernel buffer sizes and no TX ring (PACKET_TX_RING).
+ * The send() call only blocks when the kernel socket send buffer is full,
+ * providing limited backpressure.
+ *
+ * On error, pcap_sendpacket() returns non-zero and the loop breaks,
+ * leaving remaining packets unsent.
+ *
+ * Bottom line: backpressure is not an error.
*/
static uint16_t
@@ -463,5 +473,4 @@ eth_pcap_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
{
unsigned int i;
- int ret;
struct rte_mbuf *mbuf;
struct pmd_process_private *pp;
@@ -471,5 +480,4 @@ eth_pcap_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
pcap_t *pcap;
unsigned char temp_data[RTE_ETH_PCAP_SNAPLEN];
- size_t len;
pp = rte_eth_devices[tx_queue->port_id].process_private;
@@ -481,22 +489,24 @@ eth_pcap_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
for (i = 0; i < nb_pkts; i++) {
mbuf = bufs[i];
- len = rte_pktmbuf_pkt_len(mbuf);
+ uint32_t len = rte_pktmbuf_pkt_len(mbuf);
+ const uint8_t *data;
if (unlikely(!rte_pktmbuf_is_contiguous(mbuf) &&
len > sizeof(temp_data))) {
PMD_LOG(ERR,
- "Dropping multi segment PCAP packet. Size (%zd) > max size (%zd).",
+ "Dropping multi segment PCAP packet. Size (%u) > max size (%zd).",
len, sizeof(temp_data));
+ tx_queue->tx_stat.err_pkts++;
rte_pktmbuf_free(mbuf);
continue;
}
- /* rte_pktmbuf_read() returns a pointer to the data directly
- * in the mbuf (when the mbuf is contiguous) or, otherwise,
- * a pointer to temp_data after copying into it.
- */
- ret = pcap_sendpacket(pcap,
- rte_pktmbuf_read(mbuf, 0, len, temp_data), len);
- if (unlikely(ret != 0))
+ data = rte_pktmbuf_read(mbuf, 0, len, temp_data);
+ RTE_ASSERT(data != NULL);
+
+ if (unlikely(pcap_sendpacket(pcap, data, len) != 0)) {
+ /* Assume failure is backpressure */
+ PMD_LOG(ERR, "pcap_sendpacket() failed: %s", pcap_geterr(pcap));
break;
+ }
num_tx++;
tx_bytes += len;
@@ -506,5 +516,4 @@ eth_pcap_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
tx_queue->tx_stat.pkts += num_tx;
tx_queue->tx_stat.bytes += tx_bytes;
- tx_queue->tx_stat.err_pkts += i - num_tx;
return i;
--
2.55.0
---
Diff of the applied patch vs upstream commit (please double-check if non-empty:
---
--- - 2026-07-30 13:22:52.274290846 +0100
+++ 0001-net-pcap-fix-error-accounting-and-backpressure-on-Tx.patch 2026-07-30 13:22:52.231386056 +0100
@@ -1 +1 @@
-From cf91cce204ea0fd9289d91e58d1b7c6ece385d56 Mon Sep 17 00:00:00 2001
+From d1622805b8bf8c4595934f325f973180cdd925ea Mon Sep 17 00:00:00 2001
@@ -5,0 +6,2 @@
+[ upstream commit cf91cce204ea0fd9289d91e58d1b7c6ece385d56 ]
+
@@ -19 +20,0 @@
-Cc: stable at dpdk.org
@@ -23,2 +24,2 @@
- drivers/net/pcap/pcap_ethdev.c | 34 ++++++++++++++++++++++------------
- 1 file changed, 22 insertions(+), 12 deletions(-)
+ drivers/net/pcap/pcap_ethdev.c | 35 +++++++++++++++++++++-------------
+ 1 file changed, 22 insertions(+), 13 deletions(-)
@@ -27 +28 @@
-index 02d5cb591f..ca08b8e342 100644
+index c3d58e2752..37e847c5c5 100644
@@ -30 +31 @@
-@@ -463,5 +463,15 @@ eth_tx_drop(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
+@@ -457,5 +457,15 @@ eth_tx_drop(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
@@ -47 +48,13 @@
-@@ -485,24 +495,25 @@ eth_pcap_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
+@@ -463,5 +473,4 @@ eth_pcap_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
+ {
+ unsigned int i;
+- int ret;
+ struct rte_mbuf *mbuf;
+ struct pmd_process_private *pp;
+@@ -471,5 +480,4 @@ eth_pcap_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
+ pcap_t *pcap;
+ unsigned char temp_data[RTE_ETH_PCAP_SNAPLEN];
+- size_t len;
+
+ pp = rte_eth_devices[tx_queue->port_id].process_private;
+@@ -481,22 +489,24 @@ eth_pcap_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
@@ -49,3 +62,2 @@
- struct rte_mbuf *mbuf = bufs[i];
-- size_t len = rte_pktmbuf_pkt_len(mbuf);
-- int ret;
+ mbuf = bufs[i];
+- len = rte_pktmbuf_pkt_len(mbuf);
@@ -54 +65,0 @@
-
@@ -56 +67 @@
- len > RTE_ETH_PCAP_SNAPSHOT_LEN)) {
+ len > sizeof(temp_data))) {
@@ -58,3 +69,3 @@
-- "Dropping multi segment PCAP packet. Size (%zd) > max size (%u).",
-+ "Dropping multi segment PCAP packet. Size (%u) > max size (%u).",
- len, RTE_ETH_PCAP_SNAPSHOT_LEN);
+- "Dropping multi segment PCAP packet. Size (%zd) > max size (%zd).",
++ "Dropping multi segment PCAP packet. Size (%u) > max size (%zd).",
+ len, sizeof(temp_data));
@@ -83 +94 @@
-@@ -512,5 +523,4 @@ eth_pcap_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
+@@ -506,5 +516,4 @@ eth_pcap_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
More information about the stable
mailing list