Commit 88b6b7f7b216 for kernel

commit 88b6b7f7b216108a09887b074395fa7b751880b1
Author: Larysa Zaremba <larysa.zaremba@intel.com>
Date:   Thu Mar 5 12:12:42 2026 +0100

    xdp: use modulo operation to calculate XDP frag tailroom

    The current formula for calculating XDP tailroom in mbuf packets works only
    if each frag has its own page (if rxq->frag_size is PAGE_SIZE), this
    defeats the purpose of the parameter overall and without any indication
    leads to negative calculated tailroom on at least half of frags, if shared
    pages are used.

    There are not many drivers that set rxq->frag_size. Among them:
    * i40e and enetc always split page uniformly between frags, use shared
      pages
    * ice uses page_pool frags via libeth, those are power-of-2 and uniformly
      distributed across page
    * idpf has variable frag_size with XDP on, so current API is not applicable
    * mlx5, mtk and mvneta use PAGE_SIZE or 0 as frag_size for page_pool

    As for AF_XDP ZC, only ice, i40e and idpf declare frag_size for it. Modulo
    operation yields good results for aligned chunks, they are all power-of-2,
    between 2K and PAGE_SIZE. Formula without modulo fails when chunk_size is
    2K. Buffers in unaligned mode are not distributed uniformly, so modulo
    operation would not work.

    To accommodate unaligned buffers, we could define frag_size as
    data + tailroom, and hence do not subtract offset when calculating
    tailroom, but this would necessitate more changes in the drivers.

    Define rxq->frag_size as an even portion of a page that fully belongs to a
    single frag. When calculating tailroom, locate the data start within such
    portion by performing a modulo operation on page offset.

    Fixes: bf25146a5595 ("bpf: add frags support to the bpf_xdp_adjust_tail() API")
    Acked-by: Jakub Kicinski <kuba@kernel.org>
    Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
    Signed-off-by: Larysa Zaremba <larysa.zaremba@intel.com>
    Link: https://patch.msgid.link/20260305111253.2317394-2-larysa.zaremba@intel.com
    Signed-off-by: Jakub Kicinski <kuba@kernel.org>

diff --git a/net/core/filter.c b/net/core/filter.c
index 0d5d5a17acb2..d6fafb3633b0 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -4155,7 +4155,8 @@ static int bpf_xdp_frags_increase_tail(struct xdp_buff *xdp, int offset)
 	if (!rxq->frag_size || rxq->frag_size > xdp->frame_sz)
 		return -EOPNOTSUPP;

-	tailroom = rxq->frag_size - skb_frag_size(frag) - skb_frag_off(frag);
+	tailroom = rxq->frag_size - skb_frag_size(frag) -
+		   skb_frag_off(frag) % rxq->frag_size;
 	if (unlikely(offset > tailroom))
 		return -EINVAL;