tcp_collapse() detects skb to start collapsing from in the first loop. If the last skb has SYN or FIN, the condition is tested again after the loop. skb_frags_readable() is placed inside and outside of the loop as well. If we goto skip_this in both cases, we can remove the second tests and simply replace end_of_skbs with the inverted loop condition. Then, we do not need a test for tcp_collapse_one() too. Also, skb_frags_readable() should be tested after the fully overlapping check. Let's clean up the loop. Signed-off-by: Kuniyuki Iwashima --- net/ipv4/tcp_input.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index a2074a1af422..32e63d089db8 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5839,23 +5839,17 @@ tcp_collapse(struct sock *sk, struct sk_buff_head *list, struct rb_root *root, { struct sk_buff *skb = head, *n; struct sk_buff_head tmp; - bool end_of_skbs; /* First, check that queue is collapsible and find * the point where collapsing can be useful. */ restart: - for (end_of_skbs = true; skb != NULL && skb != tail; skb = n) { + for (; skb && skb != tail; skb = n) { n = tcp_skb_next(skb, list); - if (!skb_frags_readable(skb)) - goto skip_this; - /* No new bits? It is possible on ofo queue. */ if (!before(start, TCP_SKB_CB(skb)->end_seq)) { skb = tcp_collapse_one(sk, skb, list, root); - if (!skb) - break; goto restart; } @@ -5864,27 +5858,25 @@ tcp_collapse(struct sock *sk, struct sk_buff_head *list, struct rb_root *root, * - bloated or contains data before "start" or * overlaps to the next one and mptcp allow collapsing. */ - if (!(TCP_SKB_CB(skb)->tcp_flags & (TCPHDR_SYN | TCPHDR_FIN)) && - (tcp_win_from_space(sk, skb->truesize) > skb->len || - before(TCP_SKB_CB(skb)->seq, start))) { - end_of_skbs = false; + if (!skb_frags_readable(skb) || + TCP_SKB_CB(skb)->tcp_flags & (TCPHDR_SYN | TCPHDR_FIN)) + goto skip_this; + + if (tcp_win_from_space(sk, skb->truesize) > skb->len || + before(TCP_SKB_CB(skb)->seq, start)) break; - } if (n && n != tail && skb_frags_readable(n) && tcp_skb_can_collapse_rx(skb, n) && - TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(n)->seq) { - end_of_skbs = false; + TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(n)->seq) break; - } skip_this: /* Decided to skip this, advance start seq. */ start = TCP_SKB_CB(skb)->end_seq; } - if (end_of_skbs || - (TCP_SKB_CB(skb)->tcp_flags & (TCPHDR_SYN | TCPHDR_FIN)) || - !skb_frags_readable(skb)) + + if (!skb || skb == tail) return; __skb_queue_head_init(&tmp); -- 2.56.0.611.g1030f0b940-goog