Skip to contentSkip to conversation

tcp: add missing tcp_skb_can_collapse() test in tcp_shift_skb_data()

PATCH Applied Eric Dumazet 5 participants 5 messages Feb 1, 2022 – Feb 3, 2022

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 tcp: add missing tcp_skb_can_collapse() test in tcp_shift_skb_data()

From: Eric Dumazet <[email protected]>

tcp_shift_skb_data() might collapse three packets into a larger one.

P_A, P_B, P_C -> P_ABC

Historically, it used a single tcp_skb_can_collapse_to(P_A) call, because it was enough.

In commit 85712484110d ("tcp: coalesce/collapse must respect MPTCP extensions"), this call was replaced by a call to tcp_skb_can_collapse(P_A, P_B)

But the now needed test over P_C has been missed.

This probably broke MPTCP.

Then later, commit 9b65b17db723 ("net: avoid double accounting for pure zerocopy skbs") added an extra condition to tcp_skb_can_collapse(), but the missing call from tcp_shift_skb_data() is also breaking TCP zerocopy, because P_A and P_C might have different skb_zcopy_pure() status.

Fixes 85712484110d ("tcp: coalesce/collapse must respect MPTCP extensions")
Fixes 9b65b17db723 ("net: avoid double accounting for pure zerocopy skbs")
Cc Paolo Abeni <[email protected]>
Cc Mat Martineau <[email protected]>
Cc Talal Ahmad <[email protected]>
Cc Arjun Roy <[email protected]>
Cc Soheil Hassas Yeganeh <[email protected]>
Cc Willem de Bruijn <[email protected]>
---
 net/ipv4/tcp_input.c | 2 ++
 1 file changed, 2 insertions(+)
net/ipv4/tcp_input.c +2 -0
index dc49a3d551eb919baf5ad812ef21698c5c7b9679..bfe4112e000c09ba9d7d8b64392f52337b9053e9 100644
@@ -1660,6 +1660,8 @@ static struct sk_buff *tcp_shift_skb_data(struct sock *sk, struct sk_buff *skb,
 	    (mss != tcp_skb_seglen(skb)))
 		goto out;
 
+	if (!tcp_skb_can_collapse(prev, skb))
+		goto out;
 	len = skb->len;
 	pcount = tcp_skb_pcount(skb);
 	if (tcp_skb_shift(prev, skb, pcount, len))
Signature · 1 line
2.35.0.rc2.247.g8bbb082509-goog
Acked-by on v1 1/1
#1 lore raw
Quoted 22 lines · Eric Dumazet

From: Eric Dumazet <[email protected]>

tcp_shift_skb_data() might collapse three packets into a larger one.

P_A, P_B, P_C -> P_ABC

Historically, it used a single tcp_skb_can_collapse_to(P_A) call, because it was enough.

In commit 85712484110d ("tcp: coalesce/collapse must respect MPTCP extensions"), this call was replaced by a call to tcp_skb_can_collapse(P_A, P_B)

But the now needed test over P_C has been missed.

This probably broke MPTCP.

Then later, commit 9b65b17db723 ("net: avoid double accounting for pure zerocopy skbs") added an extra condition to tcp_skb_can_collapse(), but the missing call from tcp_shift_skb_data() is also breaking TCP zerocopy, because P_A and P_C might have different skb_zcopy_pure() status.

Quoted 9 lines
Fixes 85712484110d ("tcp: coalesce/collapse must respect MPTCP extensions")
Fixes 9b65b17db723 ("net: avoid double accounting for pure zerocopy skbs")
Cc Paolo Abeni <[email protected]>
Cc Mat Martineau <[email protected]>
Cc Talal Ahmad <[email protected]>
Cc Arjun Roy <[email protected]>
Cc Soheil Hassas Yeganeh <[email protected]>
Cc Willem de Bruijn <[email protected]>

I wish there were some packetdrill tests for MPTCP. Thank you for the fix!

Quoted 20 lines
---
 net/ipv4/tcp_input.c | 2 ++
 1 file changed, 2 insertions(+)
net/ipv4/tcp_input.c +2 -1
index dc49a3d551eb919baf5ad812ef21698c5c7b9679..bfe4112e000c09ba9d7d8b64392f52337b9053e9 100644
@@ -1660,6 +1660,8 @@ static struct sk_buff *tcp_shift_skb_data(struct sock *sk, struct sk_buff *skb,
            (mss != tcp_skb_seglen(skb)))
                goto out;
 
+       if (!tcp_skb_can_collapse(prev, skb))
+               goto out;
        len = skb->len;
        pcount = tcp_skb_pcount(skb);
        if (tcp_skb_shift(prev, skb, pcount, len))
--

2.35.0.rc2.247.g8bbb082509-goog

#2 lore raw
Quoted 33 lines · Soheil Hassas Yeganeh
Quoted 22 lines · Eric Dumazet

From: Eric Dumazet <[email protected]>

tcp_shift_skb_data() might collapse three packets into a larger one.

P_A, P_B, P_C -> P_ABC

Historically, it used a single tcp_skb_can_collapse_to(P_A) call, because it was enough.

In commit 85712484110d ("tcp: coalesce/collapse must respect MPTCP extensions"), this call was replaced by a call to tcp_skb_can_collapse(P_A, P_B)

But the now needed test over P_C has been missed.

This probably broke MPTCP.

Then later, commit 9b65b17db723 ("net: avoid double accounting for pure zerocopy skbs") added an extra condition to tcp_skb_can_collapse(), but the missing call from tcp_shift_skb_data() is also breaking TCP zerocopy, because P_A and P_C might have different skb_zcopy_pure() status.

Quoted 9 lines
Fixes 85712484110d ("tcp: coalesce/collapse must respect MPTCP extensions")
Fixes 9b65b17db723 ("net: avoid double accounting for pure zerocopy skbs")
Cc Paolo Abeni <[email protected]>
Cc Mat Martineau <[email protected]>
Cc Talal Ahmad <[email protected]>
Cc Arjun Roy <[email protected]>
Cc Soheil Hassas Yeganeh <[email protected]>
Cc Willem de Bruijn <[email protected]>
Quoted 4 lines

I wish there were some packetdrill tests for MPTCP. Thank you for the fix!

Soheil -

I have good news, there are packetdrill tests for MPTCP:

https://github.com/multipath-tcp/packetdrill

This is still in a fork. I think Davide has talked to Neal about upstreaming the MPTCP changes before but there may be some code that needs refactoring before that could happen.

Quoted 12 lines
Quoted 12 lines
---
 net/ipv4/tcp_input.c | 2 ++
 1 file changed, 2 insertions(+)
net/ipv4/tcp_input.c +0 -0
index dc49a3d551eb919baf5ad812ef21698c5c7b9679..bfe4112e000c09ba9d7d8b64392f52337b9053e9 100644
@@ -1660,6 +1660,8 @@ static struct sk_buff *tcp_shift_skb_data(struct sock *sk, struct sk_buff *skb,
            (mss != tcp_skb_seglen(skb)))
                goto out;
 
Quoted 9 lines
Quoted 8 lines
net/ipv4/tcp_input.c +2 -1
+       if (!tcp_skb_can_collapse(prev, skb))
+               goto out;
        len = skb->len;
        pcount = tcp_skb_pcount(skb);
        if (tcp_skb_shift(prev, skb, pcount, len))
--

2.35.0.rc2.247.g8bbb082509-goog

--
Mat Martineau
Intel

maintainer Acked-by
#3 lore raw
Quoted 13 lines · Mat Martineau
Quoted 11 lines · Soheil Hassas Yeganeh
Quoted 10 lines · Eric Dumazet

From: Eric Dumazet <[email protected]>

tcp_shift_skb_data() might collapse three packets into a larger one.

P_A, P_B, P_C -> P_ABC

Historically, it used a single tcp_skb_can_collapse_to(P_A) call, because it was enough.

Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

In commit 85712484110d ("tcp: coalesce/collapse must respect MPTCP extensions"), this call was replaced by a call to tcp_skb_can_collapse(P_A, P_B)

But the now needed test over P_C has been missed.

This probably broke MPTCP.

Indeed it looks like it could cause MPTCP data stream corruption, in case of multiple substreams, if we hit this code-path. Thanks for catching and fixing it!

Quoted 15 lines
Quoted 15 lines
Quoted 14 lines

Then later, commit 9b65b17db723 ("net: avoid double accounting for pure zerocopy skbs") added an extra condition to tcp_skb_can_collapse(), but the missing call from tcp_shift_skb_data() is also breaking TCP zerocopy, because P_A and P_C might have different skb_zcopy_pure() status.

Fixes 85712484110d ("tcp: coalesce/collapse must respect MPTCP extensions")
Fixes 9b65b17db723 ("net: avoid double accounting for pure zerocopy skbs")
Cc Paolo Abeni <[email protected]>
Cc Mat Martineau <[email protected]>
Cc Talal Ahmad <[email protected]>
Cc Arjun Roy <[email protected]>
Cc Soheil Hassas Yeganeh <[email protected]>
Cc Willem de Bruijn <[email protected]>
Quoted 1 line
Quoted 1 line
Quoted 2 lines
Quoted 2 lines

I wish there were some packetdrill tests for MPTCP. Thank you for the fix!

Do you have by chance a drill for the zero-copy case? it may help creating the MPTCP one, too.

Thanks!

Paolo

#4 lore raw
In reply to Eric Dumazet
This patch was applied to netdev/net.git (master) by Jakub Kicinski <[email protected]>:

Hello:

This patch was applied to netdev/net.git (master)
by Jakub Kicinski <[email protected]>:

Quoted 10 lines · On Tue, 1 Feb 2022 10:46:40 -0800 you wrote:

From: Eric Dumazet <[email protected]>

tcp_shift_skb_data() might collapse three packets into a larger one.

P_A, P_B, P_C -> P_ABC

Historically, it used a single tcp_skb_can_collapse_to(P_A) call, because it was enough.

[...]

Here is the summary with links:
- [net] tcp: add missing tcp_skb_can_collapse() test in tcp_shift_skb_data()

    https://git.kernel.org/netdev/net/c/b67985be4009

You are awesome, thank you!

Signature · 2 lines
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html