aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r--net/ipv4/tcp_input.c22
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);