diff options
Diffstat (limited to 'net/ipv4/tcp_output.c')
-rw-r--r-- | net/ipv4/tcp_output.c | 22 |
1 files changed, 11 insertions, 11 deletions
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index f57b5aa51b59..19105b46a304 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -2514,7 +2514,7 @@ void tcp_skb_collapse_tstamp(struct sk_buff *skb, | |||
2514 | } | 2514 | } |
2515 | 2515 | ||
2516 | /* Collapses two adjacent SKB's during retransmission. */ | 2516 | /* Collapses two adjacent SKB's during retransmission. */ |
2517 | static void tcp_collapse_retrans(struct sock *sk, struct sk_buff *skb) | 2517 | static bool tcp_collapse_retrans(struct sock *sk, struct sk_buff *skb) |
2518 | { | 2518 | { |
2519 | struct tcp_sock *tp = tcp_sk(sk); | 2519 | struct tcp_sock *tp = tcp_sk(sk); |
2520 | struct sk_buff *next_skb = tcp_write_queue_next(sk, skb); | 2520 | struct sk_buff *next_skb = tcp_write_queue_next(sk, skb); |
@@ -2525,14 +2525,17 @@ static void tcp_collapse_retrans(struct sock *sk, struct sk_buff *skb) | |||
2525 | 2525 | ||
2526 | BUG_ON(tcp_skb_pcount(skb) != 1 || tcp_skb_pcount(next_skb) != 1); | 2526 | BUG_ON(tcp_skb_pcount(skb) != 1 || tcp_skb_pcount(next_skb) != 1); |
2527 | 2527 | ||
2528 | if (next_skb_size) { | ||
2529 | if (next_skb_size <= skb_availroom(skb)) | ||
2530 | skb_copy_bits(next_skb, 0, skb_put(skb, next_skb_size), | ||
2531 | next_skb_size); | ||
2532 | else if (!skb_shift(skb, next_skb, next_skb_size)) | ||
2533 | return false; | ||
2534 | } | ||
2528 | tcp_highest_sack_combine(sk, next_skb, skb); | 2535 | tcp_highest_sack_combine(sk, next_skb, skb); |
2529 | 2536 | ||
2530 | tcp_unlink_write_queue(next_skb, sk); | 2537 | tcp_unlink_write_queue(next_skb, sk); |
2531 | 2538 | ||
2532 | if (next_skb_size) | ||
2533 | skb_copy_bits(next_skb, 0, skb_put(skb, next_skb_size), | ||
2534 | next_skb_size); | ||
2535 | |||
2536 | if (next_skb->ip_summed == CHECKSUM_PARTIAL) | 2539 | if (next_skb->ip_summed == CHECKSUM_PARTIAL) |
2537 | skb->ip_summed = CHECKSUM_PARTIAL; | 2540 | skb->ip_summed = CHECKSUM_PARTIAL; |
2538 | 2541 | ||
@@ -2561,6 +2564,7 @@ static void tcp_collapse_retrans(struct sock *sk, struct sk_buff *skb) | |||
2561 | tcp_skb_collapse_tstamp(skb, next_skb); | 2564 | tcp_skb_collapse_tstamp(skb, next_skb); |
2562 | 2565 | ||
2563 | sk_wmem_free_skb(sk, next_skb); | 2566 | sk_wmem_free_skb(sk, next_skb); |
2567 | return true; | ||
2564 | } | 2568 | } |
2565 | 2569 | ||
2566 | /* Check if coalescing SKBs is legal. */ | 2570 | /* Check if coalescing SKBs is legal. */ |
@@ -2610,16 +2614,12 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *to, | |||
2610 | 2614 | ||
2611 | if (space < 0) | 2615 | if (space < 0) |
2612 | break; | 2616 | break; |
2613 | /* Punt if not enough space exists in the first SKB for | ||
2614 | * the data in the second | ||
2615 | */ | ||
2616 | if (skb->len > skb_availroom(to)) | ||
2617 | break; | ||
2618 | 2617 | ||
2619 | if (after(TCP_SKB_CB(skb)->end_seq, tcp_wnd_end(tp))) | 2618 | if (after(TCP_SKB_CB(skb)->end_seq, tcp_wnd_end(tp))) |
2620 | break; | 2619 | break; |
2621 | 2620 | ||
2622 | tcp_collapse_retrans(sk, to); | 2621 | if (!tcp_collapse_retrans(sk, to)) |
2622 | break; | ||
2623 | } | 2623 | } |
2624 | } | 2624 | } |
2625 | 2625 | ||