aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv4/tcp_output.c75
1 files changed, 38 insertions, 37 deletions
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 2f24ecc37067..9f44be633ef6 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -2034,53 +2034,54 @@ void tcp_xmit_retransmit_queue(struct sock *sk)
2034 struct sk_buff *skb; 2034 struct sk_buff *skb;
2035 int mib_idx; 2035 int mib_idx;
2036 2036
2037 if (!tp->lost_out)
2038 tp->retransmit_high = tp->snd_una;
2039
2037 if (tp->retransmit_skb_hint) 2040 if (tp->retransmit_skb_hint)
2038 skb = tp->retransmit_skb_hint; 2041 skb = tp->retransmit_skb_hint;
2039 else 2042 else
2040 skb = tcp_write_queue_head(sk); 2043 skb = tcp_write_queue_head(sk);
2041 2044
2042 /* First pass: retransmit lost packets. */ 2045 /* First pass: retransmit lost packets. */
2043 if (tp->lost_out) { 2046 tcp_for_write_queue_from(skb, sk) {
2044 tcp_for_write_queue_from(skb, sk) { 2047 __u8 sacked = TCP_SKB_CB(skb)->sacked;
2045 __u8 sacked = TCP_SKB_CB(skb)->sacked;
2046 2048
2047 if (skb == tcp_send_head(sk)) 2049 if (skb == tcp_send_head(sk))
2048 break; 2050 break;
2049 /* we could do better than to assign each time */ 2051 /* we could do better than to assign each time */
2050 tp->retransmit_skb_hint = skb; 2052 tp->retransmit_skb_hint = skb;
2051 2053
2052 /* Assume this retransmit will generate 2054 /* Assume this retransmit will generate
2053 * only one packet for congestion window 2055 * only one packet for congestion window
2054 * calculation purposes. This works because 2056 * calculation purposes. This works because
2055 * tcp_retransmit_skb() will chop up the 2057 * tcp_retransmit_skb() will chop up the
2056 * packet to be MSS sized and all the 2058 * packet to be MSS sized and all the
2057 * packet counting works out. 2059 * packet counting works out.
2058 */ 2060 */
2059 if (tcp_packets_in_flight(tp) >= tp->snd_cwnd) 2061 if (tcp_packets_in_flight(tp) >= tp->snd_cwnd)
2060 return; 2062 return;
2061 if (!before(TCP_SKB_CB(skb)->seq, tp->retransmit_high)) 2063 if (!before(TCP_SKB_CB(skb)->seq, tp->retransmit_high))
2062 break; 2064 break;
2063 if (sacked & (TCPCB_SACKED_ACKED|TCPCB_SACKED_RETRANS)) 2065 if (sacked & (TCPCB_SACKED_ACKED|TCPCB_SACKED_RETRANS))
2064 continue; 2066 continue;
2065 2067
2066 if (!(sacked & TCPCB_LOST)) 2068 if (!(sacked & TCPCB_LOST))
2067 continue; 2069 continue;
2068 2070
2069 if (tcp_retransmit_skb(sk, skb)) { 2071 if (tcp_retransmit_skb(sk, skb)) {
2070 tp->retransmit_skb_hint = NULL; 2072 tp->retransmit_skb_hint = NULL;
2071 return; 2073 return;
2072 }
2073 if (icsk->icsk_ca_state != TCP_CA_Loss)
2074 mib_idx = LINUX_MIB_TCPFASTRETRANS;
2075 else
2076 mib_idx = LINUX_MIB_TCPSLOWSTARTRETRANS;
2077 NET_INC_STATS_BH(sock_net(sk), mib_idx);
2078
2079 if (skb == tcp_write_queue_head(sk))
2080 inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
2081 inet_csk(sk)->icsk_rto,
2082 TCP_RTO_MAX);
2083 } 2074 }
2075 if (icsk->icsk_ca_state != TCP_CA_Loss)
2076 mib_idx = LINUX_MIB_TCPFASTRETRANS;
2077 else
2078 mib_idx = LINUX_MIB_TCPSLOWSTARTRETRANS;
2079 NET_INC_STATS_BH(sock_net(sk), mib_idx);
2080
2081 if (skb == tcp_write_queue_head(sk))
2082 inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
2083 inet_csk(sk)->icsk_rto,
2084 TCP_RTO_MAX);
2084 } 2085 }
2085 2086
2086 /* OK, demanded retransmission is finished. */ 2087 /* OK, demanded retransmission is finished. */