|SUCCESS| [v3] net/idpf: fix multi-segment mbuf leak in split Tx

dpdklab at iol.unh.edu dpdklab at iol.unh.edu
Wed Apr 22 15:09:11 CEST 2026


Test-Label: ai-code-review
Test-Status: SUCCESS
https://dpdk.org/patch/163228

_AI Code Review_

=== Patch Review: series.patch (via Claude) ===
Review date: 2026-04-22

This patch addresses a resource leak in the split queue TX path for
multi-segment mbufs, where only the EOP mbuf was freed on RS completion,
leaking preceding segments.

commit 8c6098afa075 ("common/idpf: add Rx/Tx data path")
Author: Shaiq Wani <shaiq.wani at intel.com>

net/idpf: fix multi-segment mbuf leak in split Tx

RS completion only frees the EOP entry's mbuf, leaking preceding
segments of multi-segment packets. Add a first_id field to the Tx
entry struct, record the first sw_id at the EOP entry during submit,
and walk forward from first to EOP to free all segments on completion.

> diff --git a/drivers/net/intel/common/tx.h b/drivers/net/intel/common/tx.h
> index 283bd58d5d..53e61c0b62 100644
> --- a/drivers/net/intel/common/tx.h
> +++ b/drivers/net/intel/common/tx.h
> @@ -121,6 +121,7 @@ struct ci_tx_queue;
>  struct ci_tx_entry {
>  	struct rte_mbuf *mbuf; /* mbuf associated with TX desc, if any. */
>  	uint16_t next_id; /* Index of next descriptor in ring. */
> +	uint16_t first_id; /* Split-queue: first sw_id of packet at EOP entry. */
>  };

[ ... ]

> diff --git a/drivers/net/intel/idpf/idpf_common_rxtx.c b/drivers/net/intel/idpf/idpf_common_rxtx.c
> index f73716e57c..c56ba86f1e 100644
> --- a/drivers/net/intel/idpf/idpf_common_rxtx.c
> +++ b/drivers/net/intel/idpf/idpf_common_rxtx.c

[ ... ]

> @@ -979,6 +991,8 @@ idpf_dp_splitq_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
>  				tx_id = 0;
>  		}
>  
> +		uint16_t first_sw_id = sw_id;
> +

Per the DPDK coding style guide, local variable declarations must be
placed at the beginning of the block, before any statements. Can this
declaration of first_sw_id be moved to the top of idpf_dp_splitq_xmit_pkts()
or the start of the enclosing block?

>  		do {
>  			txd = &txr[tx_id];
>  			txn = &sw_ring[txe->next_id];
> @@ -1002,6 +1016,9 @@ idpf_dp_splitq_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
>  		/* fill the last descriptor with End of Packet (EOP) bit */
>  		txd->qw1.cmd_dtype |= IDPF_TXD_FLEX_FLOW_CMD_EOP;
>  
> +		/* Record first sw_id at EOP so completion can walk forward. */
> +		sw_ring[txd->qw1.compl_tag].first_id = first_sw_id;
> +

In idpf_dp_splitq_xmit_pkts(), is the value of txd->qw1.compl_tag
guaranteed to be valid before first_id is assigned? Does the do-while loop
above set compl_tag for all descriptors, or only for the final one?

>  		txq->nb_tx_free = (uint16_t)(txq->nb_tx_free - nb_used);
>  		txq->rs_compl_count += nb_used;


More information about the test-report mailing list