Merge branch 'net-prepare-skb-extensions-for-reuse-across-scrubs'

Jakub Sitnicki says:

====================
net: Prepare skb extensions for reuse across scrubs

Following Florian's suggestion from the discussion in [1].

The skb extension allocator retains the extension's offset after the
extension is deleted. This, in theory, allows skb_ext_add() to reuse the
existing storage instead of appending another copy when an extension is
added again.  However, it also means that we can't rely on the offset as an
indicator that the extension is present.

Make the extension cleanup safe, even when the offset is already allocated
and set, by making the individual extension put helpers idempotent, so that
they can be called multiple times.

This is preparatory work to support skb extension chunk area reuse after
skb scrubbing, which would be needed to persist BPF metadata skb extension
across scrubs [2].

[1] https://lore.kernel.org/ao9UV9S7rUkyQ8jv@strlen.de
[2] https://lore.kernel.org/64365932-c765-472e-bf6c-b07c9ee25eaf@kernel.org
====================

Link: https://patch.msgid.link/20260831-skb-ext-prep-work-v1-0-ecc2a8542fd9@cloudflare.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2026-09-01 17:11:28 -07:00
commit 0a1071aa32

View File

@ -7236,16 +7236,23 @@ static void skb_ext_put_sp(struct sec_path *sp)
{
unsigned int i;
if (!sp->len)
return;
for (i = 0; i < sp->len; i++)
xfrm_state_put(sp->xvec[i]);
sp->len = 0;
}
#endif
#ifdef CONFIG_MCTP_FLOWS
static void skb_ext_put_mctp(struct mctp_flow *flow)
{
if (flow->key)
mctp_key_unref(flow->key);
if (!flow->key)
return;
mctp_key_unref(flow->key);
flow->key = NULL;
}
#endif
@ -7257,15 +7264,20 @@ void __skb_ext_del(struct sk_buff *skb, enum skb_ext_id id)
if (skb->active_extensions == 0) {
skb->extensions = NULL;
__skb_ext_put(ext);
#ifdef CONFIG_XFRM
} else if (id == SKB_EXT_SEC_PATH &&
refcount_read(&ext->refcnt) == 1) {
struct sec_path *sp = skb_ext_get_ptr(ext, SKB_EXT_SEC_PATH);
skb_ext_put_sp(sp);
sp->len = 0;
#endif
return;
}
if (refcount_read(&ext->refcnt) > 1)
return;
#ifdef CONFIG_XFRM
if (id == SKB_EXT_SEC_PATH)
skb_ext_put_sp(skb_ext_get_ptr(ext, SKB_EXT_SEC_PATH));
#endif
#ifdef CONFIG_MCTP_FLOWS
if (id == SKB_EXT_MCTP)
skb_ext_put_mctp(skb_ext_get_ptr(ext, SKB_EXT_MCTP));
#endif
}
EXPORT_SYMBOL(__skb_ext_del);