Skip to content

Commit

Permalink
tcp: add tcp_ooo_try_coalesce() helper
Browse files Browse the repository at this point in the history
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: Eric Dumazet <[email protected]>
Acked-by: Soheil Hassas Yeganeh <[email protected]>
Acked-by: Yuchung Cheng <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Eric Dumazet authored and davem330 committed Jul 23, 2018
1 parent 8541b21 commit 58152ec
Showing 1 changed file with 21 additions and 4 deletions.
25 changes: 21 additions & 4 deletions net/ipv4/tcp_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -4358,6 +4358,23 @@ static bool tcp_try_coalesce(struct sock *sk,
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)
{
sk_drops_add(sk, skb);
Expand Down Expand Up @@ -4481,8 +4498,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.
* 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:
tcp_grow_window(sk, skb);
kfree_skb_partial(skb, fragstolen);
Expand Down Expand Up @@ -4532,8 +4549,8 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb)
tcp_drop(sk, skb1);
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;
}
p = &parent->rb_right;
Expand Down

0 comments on commit 58152ec

Please sign in to comment.