06/11/2026 09:07, Andrey Mokrushin:
> rte_gro_reassemble_burst() decrements nb_after_gro only for packets that
> are merged while being inserted into the reassembly tables. When the
> tables are flushed at the end of the burst, gro_udp4_tbl_timeout_flush()
> and gro_vxlan_udp4_tbl_timeout_flush() call gro_udp4_merge_items(), which
> merges fragments that became adjacent only after an intermediate fragment
> arrived. Such merges are not reflected in nb_after_gro, but they are
> accounted for in the local index i, which after the flush holds the
> actual number of packets written to pkts[].
>
> The function returns nb_after_gro regardless. When a flush-time merge
> happens, the caller is told there are more packets than were actually
> produced: the surplus pkts[] entries point to mbufs that are already
> chained into an earlier packet. Freeing the returned burst then frees
> those mbufs twice and corrupts the mempool, and the surplus entry, whose
> headers have been stripped by the merge, is handed back to the caller as
> a standalone packet built from fragment payload.
>
> Return the actual packet count i instead. In the path where the flush
> block is skipped, i equals nb_pkts, which also equals nb_after_gro, so
> the non-merging case is unchanged.
>
> Fixes: 74080d7dcf31 ("gro: support IPv6 for TCP")
> Cc: [email protected]
>
> Signed-off-by: Andrey Mokrushin <[email protected]>
Applied, thanks.