Commit 3a6cbdf2 authored by Eric Dumazet's avatar Eric Dumazet Committed by Khalid Elmously

tcp: add tcp_ooo_try_coalesce() helper

BugLink: https://bugs.launchpad.net/bugs/1801893

[ Upstream commit 58152ecb ]

In case skb in out_or_order_queue is the result of
multiple skbs coalescing, we would like to get a proper gso_segs
counter tracking, so that future tcp_drop() can report an accurate
number.

I chose to not implement this tracking for skbs in receive queue,
since they are not dropped, unless socket is disconnected.
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Acked-by: default avatarSoheil Hassas Yeganeh <soheil@google.com>
Acked-by: default avatarYuchung Cheng <ycheng@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarMao Wenan <maowenan@huawei.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarJuerg Haefliger <juergh@canonical.com>
Signed-off-by: default avatarKhalid Elmously <khalid.elmously@canonical.com>
parent e6419993
...@@ -4293,6 +4293,23 @@ static bool tcp_try_coalesce(struct sock *sk, ...@@ -4293,6 +4293,23 @@ static bool tcp_try_coalesce(struct sock *sk,
return true; return true;
} }
static bool tcp_ooo_try_coalesce(struct sock *sk,
struct sk_buff *to,
struct sk_buff *from,
bool *fragstolen)
{
bool res = tcp_try_coalesce(sk, to, from, fragstolen);
/* In case tcp_drop() is called later, update to->gso_segs */
if (res) {
u32 gso_segs = max_t(u16, 1, skb_shinfo(to)->gso_segs) +
max_t(u16, 1, skb_shinfo(from)->gso_segs);
skb_shinfo(to)->gso_segs = min_t(u32, gso_segs, 0xFFFF);
}
return res;
}
static void tcp_drop(struct sock *sk, struct sk_buff *skb) static void tcp_drop(struct sock *sk, struct sk_buff *skb)
{ {
sk_drops_add(sk, skb); sk_drops_add(sk, skb);
...@@ -4419,7 +4436,8 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) ...@@ -4419,7 +4436,8 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb)
/* In the typical case, we are adding an skb to the end of the list. /* In the typical case, we are adding an skb to the end of the list.
* Use of ooo_last_skb avoids the O(Log(N)) rbtree lookup. * Use of ooo_last_skb avoids the O(Log(N)) rbtree lookup.
*/ */
if (tcp_try_coalesce(sk, tp->ooo_last_skb, skb, &fragstolen)) { if (tcp_ooo_try_coalesce(sk, tp->ooo_last_skb,
skb, &fragstolen)) {
coalesce_done: coalesce_done:
tcp_grow_window(sk, skb); tcp_grow_window(sk, skb);
kfree_skb_partial(skb, fragstolen); kfree_skb_partial(skb, fragstolen);
...@@ -4464,7 +4482,8 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) ...@@ -4464,7 +4482,8 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb)
tcp_drop(sk, skb1); tcp_drop(sk, skb1);
goto merge_right; goto merge_right;
} }
} else if (tcp_try_coalesce(sk, skb1, skb, &fragstolen)) { } else if (tcp_ooo_try_coalesce(sk, skb1,
skb, &fragstolen)) {
goto coalesce_done; goto coalesce_done;
} }
p = &parent->rb_right; p = &parent->rb_right;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment