RE: [PATCH net v2] igc: return XSK frame copies on XDP_TX failure

From: Loktionov, Aleksandr

Date: Wed Oct 28 2026 - 14:48:56 EST




> -----Original Message-----
> From: Paul Moses <p@xxxxxxx>
> Sent: Wednesday, October 28, 2026 9:50 AM
> To: intel-wired-lan@xxxxxxxxxxxxxxxx
> Cc: netdev@xxxxxxxxxxxxxxx; Nguyen, Anthony L
> <anthony.l.nguyen@xxxxxxxxx>; Kitszel, Przemyslaw
> <przemyslaw.kitszel@xxxxxxxxx>; andrew+netdev@xxxxxxx;
> davem@xxxxxxxxxxxxx; edumazet@xxxxxxxxxx; kuba@xxxxxxxxxx;
> pabeni@xxxxxxxxxx; ast@xxxxxxxxxx; daniel@xxxxxxxxxxxxx;
> hawk@xxxxxxxxxx; john.fastabend@xxxxxxxxx; sdf@xxxxxxxxxxx; Fijalkowski,
> Maciej <maciej.fijalkowski@xxxxxxxxx>; andre.guedes@xxxxxxxxx;
> jithu.joseph@xxxxxxxxx; vedang.patel@xxxxxxxxx; linux-
> kernel@xxxxxxxxxxxxxxx; bpf@xxxxxxxxxxxxxxx; stable@xxxxxxxxxxxxxxx
> Subject: [PATCH net v2] igc: return XSK frame copies on XDP_TX failure
>
> Converting an XSK buffer to an XDP frame allocates a page and returns
> the original buffer to its pool. If the TX ring is full or DMA mapping
> fails, igc_xdp_xmit_back() returns an error without freeing the copy.
> The RX cleaner cannot release it, so the page leaks.
>
> Return the copied frame on TX failure. Use the RX memory type so native
> frames remain RX-owned on failure.
>
> Fixes: fc9df2a0b520 ("igc: Enable RX via AF_XDP zero-copy")
> Cc: stable@xxxxxxxxxxxxxxx
> Signed-off-by: Paul Moses <p@xxxxxxx>
> Reviewed-by: Maciej Fijalkowski <maciej.fijalkowski@xxxxxxxxx>
> ---
> v1..v2
> - Sort declarations
> - Update the description to match the initialization order
>
> v1: https://lore.kernel.org/all/20261023141317.3904442-1-p@xxxxxxx/
>
> v1 testing:
> Tested on Intel I225-V with baseline and patched kernels. Physical
> pause-frame backpressure caused 46 leaked copies on the baseline.
> With the fix, all 72 rejected copies were returned once and freed, and
> all 192 copies were accounted for.
>
> drivers/net/ethernet/intel/igc/igc_main.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/drivers/net/ethernet/intel/igc/igc_main.c
> b/drivers/net/ethernet/intel/igc/igc_main.c
> index 1fb5f3cbe..d10dfbdb1 100644
> --- a/drivers/net/ethernet/intel/igc/igc_main.c
> +++ b/drivers/net/ethernet/intel/igc/igc_main.c
> @@ -2488,6 +2488,7 @@ struct igc_ring *igc_get_tx_ring(struct
> igc_adapter *adapter, int cpu) static int igc_xdp_xmit_back(struct
> igc_adapter *adapter, struct xdp_buff *xdp) {
> struct xdp_frame *xdpf = xdp_convert_buff_to_frame(xdp);
> + enum xdp_mem_type mem_type = xdp->rxq->mem.type;
> int cpu = smp_processor_id();
> struct netdev_queue *nq;
> struct igc_ring *ring;
> @@ -2504,6 +2505,10 @@ static int igc_xdp_xmit_back(struct igc_adapter
> *adapter, struct xdp_buff *xdp)
> txq_trans_cond_update(nq);
> res = igc_xdp_init_tx_descriptor(ring, xdpf);
> __netif_tx_unlock(nq);
> +
> + if (res && mem_type == MEM_TYPE_XSK_BUFF_POOL)
> + xdp_return_frame(xdpf);
> +
> return res;
> }
>
> --
> 2.56.GIT
>

Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@xxxxxxxxx>