diff options
| author | Paolo Abeni <pabeni@redhat.com> | 2025-11-21 18:02:11 +0100 |
|---|---|---|
| committer | Jakub Kicinski <kuba@kernel.org> | 2025-11-24 19:49:42 -0800 |
| commit | 9db5b3cec4ec1c0cd3239689f5c8653d691a1754 (patch) | |
| tree | 6b0b6b0d2cb8c8ad78c48bcad8b214ac3b1a02a6 /net/mptcp/protocol.h | |
| parent | 0eeb372deebce6c25b9afc09e35d6c75a744299a (diff) | |
mptcp: borrow forward memory from subflow
In the MPTCP receive path, we release the subflow allocated fwd
memory just to allocate it again shortly after for the msk.
That could increases the failures chances, especially when we will
add backlog processing, with other actions could consume the just
released memory before the msk socket has a chance to do the
rcv allocation.
Replace the skb_orphan() call with an open-coded variant that
explicitly borrows, the fwd memory from the subflow socket instead
of releasing it.
The borrowed memory does not have PAGE_SIZE granularity; rounding to
the page size will make the fwd allocated memory higher than what is
strictly required and could make the incoming subflow fwd mem
consistently negative. Instead, keep track of the accumulated frag and
borrow the full page at subflow close time.
This allow removing the last drop in the TCP to MPTCP transition and
the associated, now unused, MIB.
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20251121-net-next-mptcp-memcg-backlog-imp-v1-12-1f34b6c1e0b1@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'net/mptcp/protocol.h')
| -rw-r--r-- | net/mptcp/protocol.h | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index d30806b287d2..5e2749d92a49 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -547,6 +547,7 @@ struct mptcp_subflow_context { bool scheduled; bool pm_listener; /* a listener managed by the kernel PM? */ bool fully_established; /* path validated */ + u32 lent_mem_frag; u32 remote_nonce; u64 thmac; u32 local_nonce; @@ -646,6 +647,33 @@ mptcp_send_active_reset_reason(struct sock *sk) tcp_send_active_reset(sk, GFP_ATOMIC, reason); } +/* Made the fwd mem carried by the given skb available to the msk, + * To be paired with a previous mptcp_subflow_lend_fwdmem() before freeing + * the skb or setting the skb ownership. + */ +static inline void mptcp_borrow_fwdmem(struct sock *sk, struct sk_buff *skb) +{ + struct sock *ssk = skb->sk; + + /* The subflow just lend the skb fwd memory, and we know that the skb + * is only accounted on the incoming subflow rcvbuf. + */ + DEBUG_NET_WARN_ON_ONCE(skb->destructor); + skb->sk = NULL; + sk_forward_alloc_add(sk, skb->truesize); + atomic_sub(skb->truesize, &ssk->sk_rmem_alloc); +} + +static inline void +mptcp_subflow_lend_fwdmem(struct mptcp_subflow_context *subflow, + struct sk_buff *skb) +{ + int frag = (subflow->lent_mem_frag + skb->truesize) & (PAGE_SIZE - 1); + + skb->destructor = NULL; + subflow->lent_mem_frag = frag; +} + static inline u64 mptcp_subflow_get_map_offset(const struct mptcp_subflow_context *subflow) { |
