[PATCH v11 08/19] net/pcap: cleanup transmit buffer handling

Stephen Hemminger
2026-01-30T17:35:46Z

The transmit loops should handle the possible failure
of rte_pktmbuf_read(). If a pcap_sendpacket fails, then
the packet with error should be freed.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
drivers/net/pcap/pcap_ethdev.c | 50 ++++++++++++++--------------------
1 file changed, 21 insertions(+), 29 deletions(-)

diff --git a/drivers/net/pcap/pcap_ethdev.c b/drivers/net/pcap/pcap_ethdev.c
index 1a186142d3..394fd0b6b2 100644
--- a/drivers/net/pcap/pcap_ethdev.c
+++ b/drivers/net/pcap/pcap_ethdev.c
@@ -389,7 +389,6 @@ static uint16_t
eth_pcap_tx_dumper(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
{
unsigned int i;
- struct rte_mbuf *mbuf;
struct pmd_process_private *pp;
struct pcap_tx_queue *dumper_q = queue;
uint16_t num_tx = 0;
@@ -397,7 +396,6 @@ eth_pcap_tx_dumper(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
struct pcap_pkthdr header;
pcap_dumper_t *dumper;
unsigned char *temp_data;
- size_t len, caplen;

pp = rte_eth_devices[dumper_q->port_id].process_private;
dumper = pp->tx_dumper[dumper_q->queue_id];
@@ -409,21 +407,22 @@ eth_pcap_tx_dumper(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
/* writes the nb_pkts packets to the previously opened pcap file
* dumper */
for (i = 0; i < nb_pkts; i++) {
- mbuf = bufs[i];
+ struct rte_mbuf *mbuf = bufs[i];
+ uint32_t len, caplen;
+ const uint8_t *data;
+
len = caplen = rte_pktmbuf_pkt_len(mbuf);

calculate_timestamp(&header.ts);
header.len = len;
header.caplen = caplen;
- /* 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.
- */
- pcap_dump((u_char *)dumper, &header,
- rte_pktmbuf_read(mbuf, 0, caplen, temp_data));

- num_tx++;
- tx_bytes += caplen;
+ data = rte_pktmbuf_read(mbuf, 0, caplen, temp_data);
+ if (likely(data != NULL)) {
+ pcap_dump((u_char *)dumper, &header, data);
+ num_tx++;
+ tx_bytes += caplen;
+ }
}
rte_pktmbuf_free_bulk(bufs, nb_pkts);

@@ -458,7 +457,7 @@ eth_tx_drop(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
tx_queue->tx_stat.pkts += nb_pkts;
tx_queue->tx_stat.bytes += tx_bytes;

- return i;
+ return nb_pkts;
}

/*
@@ -468,15 +467,12 @@ static uint16_t
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;
struct pcap_tx_queue *tx_queue = queue;
uint16_t num_tx = 0;
uint32_t tx_bytes = 0;
pcap_t *pcap;
unsigned char *temp_data;
- size_t len;

pp = rte_eth_devices[tx_queue->port_id].process_private;
pcap = pp->tx_pcap[tx_queue->queue_id];
@@ -486,19 +482,15 @@ eth_pcap_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
return 0;

for (i = 0; i < nb_pkts; i++) {
- mbuf = bufs[i];
- len = rte_pktmbuf_pkt_len(mbuf);
-
- /* 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))
- break;
- num_tx++;
- tx_bytes += len;
+ struct rte_mbuf *mbuf = bufs[i];
+ uint32_t len = rte_pktmbuf_pkt_len(mbuf);
+ const uint8_t *data;
+
+ data = rte_pktmbuf_read(mbuf, 0, len, temp_data);
+ if (likely(data != NULL && pcap_sendpacket(pcap, data, len) == 0)) {
+ num_tx++;
+ tx_bytes += len;
+ }
}

rte_pktmbuf_free_bulk(bufs, nb_pkts);
@@ -507,7 +499,7 @@ eth_pcap_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
tx_queue->tx_stat.bytes += tx_bytes;
tx_queue->tx_stat.err_pkts += i - num_tx;

- return i;
+ return nb_pkts;
}

/*
--
2.51.0