diff options
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r-- | net/ipv4/tcp_input.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 5573202f0861..7d0958785bfb 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -2138,7 +2138,9 @@ static void tcp_mark_head_lost(struct sock *sk, int packets) | |||
2138 | { | 2138 | { |
2139 | struct tcp_sock *tp = tcp_sk(sk); | 2139 | struct tcp_sock *tp = tcp_sk(sk); |
2140 | struct sk_buff *skb; | 2140 | struct sk_buff *skb; |
2141 | int cnt; | 2141 | int cnt, oldcnt; |
2142 | int err; | ||
2143 | unsigned int mss; | ||
2142 | 2144 | ||
2143 | BUG_TRAP(packets <= tp->packets_out); | 2145 | BUG_TRAP(packets <= tp->packets_out); |
2144 | if (tp->lost_skb_hint) { | 2146 | if (tp->lost_skb_hint) { |
@@ -2157,13 +2159,25 @@ static void tcp_mark_head_lost(struct sock *sk, int packets) | |||
2157 | tp->lost_skb_hint = skb; | 2159 | tp->lost_skb_hint = skb; |
2158 | tp->lost_cnt_hint = cnt; | 2160 | tp->lost_cnt_hint = cnt; |
2159 | 2161 | ||
2162 | if (after(TCP_SKB_CB(skb)->end_seq, tp->high_seq)) | ||
2163 | break; | ||
2164 | |||
2165 | oldcnt = cnt; | ||
2160 | if (tcp_is_fack(tp) || tcp_is_reno(tp) || | 2166 | if (tcp_is_fack(tp) || tcp_is_reno(tp) || |
2161 | (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)) | 2167 | (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)) |
2162 | cnt += tcp_skb_pcount(skb); | 2168 | cnt += tcp_skb_pcount(skb); |
2163 | 2169 | ||
2164 | if ((cnt > packets) || | 2170 | if (cnt > packets) { |
2165 | after(TCP_SKB_CB(skb)->end_seq, tp->high_seq)) | 2171 | if (tcp_is_sack(tp) || (oldcnt >= packets)) |
2166 | break; | 2172 | break; |
2173 | |||
2174 | mss = skb_shinfo(skb)->gso_size; | ||
2175 | err = tcp_fragment(sk, skb, (packets - oldcnt) * mss, mss); | ||
2176 | if (err < 0) | ||
2177 | break; | ||
2178 | cnt = packets; | ||
2179 | } | ||
2180 | |||
2167 | if (!(TCP_SKB_CB(skb)->sacked & (TCPCB_SACKED_ACKED|TCPCB_LOST))) { | 2181 | if (!(TCP_SKB_CB(skb)->sacked & (TCPCB_SACKED_ACKED|TCPCB_LOST))) { |
2168 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; | 2182 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; |
2169 | tp->lost_out += tcp_skb_pcount(skb); | 2183 | tp->lost_out += tcp_skb_pcount(skb); |