|
@@ -4902,6 +4902,7 @@ end:
|
|
|
static void tcp_collapse_ofo_queue(struct sock *sk)
|
|
|
{
|
|
|
struct tcp_sock *tp = tcp_sk(sk);
|
|
|
+ u32 range_truesize, sum_tiny = 0;
|
|
|
struct sk_buff *skb, *head;
|
|
|
u32 start, end;
|
|
|
|
|
@@ -4913,6 +4914,7 @@ new_range:
|
|
|
}
|
|
|
start = TCP_SKB_CB(skb)->seq;
|
|
|
end = TCP_SKB_CB(skb)->end_seq;
|
|
|
+ range_truesize = skb->truesize;
|
|
|
|
|
|
for (head = skb;;) {
|
|
|
skb = skb_rb_next(skb);
|
|
@@ -4923,11 +4925,20 @@ new_range:
|
|
|
if (!skb ||
|
|
|
after(TCP_SKB_CB(skb)->seq, end) ||
|
|
|
before(TCP_SKB_CB(skb)->end_seq, start)) {
|
|
|
- tcp_collapse(sk, NULL, &tp->out_of_order_queue,
|
|
|
- head, skb, start, end);
|
|
|
+ /* Do not attempt collapsing tiny skbs */
|
|
|
+ if (range_truesize != head->truesize ||
|
|
|
+ end - start >= SKB_WITH_OVERHEAD(SK_MEM_QUANTUM)) {
|
|
|
+ tcp_collapse(sk, NULL, &tp->out_of_order_queue,
|
|
|
+ head, skb, start, end);
|
|
|
+ } else {
|
|
|
+ sum_tiny += range_truesize;
|
|
|
+ if (sum_tiny > sk->sk_rcvbuf >> 3)
|
|
|
+ return;
|
|
|
+ }
|
|
|
goto new_range;
|
|
|
}
|
|
|
|
|
|
+ range_truesize += skb->truesize;
|
|
|
if (unlikely(before(TCP_SKB_CB(skb)->seq, start)))
|
|
|
start = TCP_SKB_CB(skb)->seq;
|
|
|
if (after(TCP_SKB_CB(skb)->end_seq, end))
|