diff options
-rw-r--r-- | include/linux/tcp.h | 2 | ||||
-rw-r--r-- | include/net/tcp.h | 2 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 34 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 25 |
4 files changed, 30 insertions, 33 deletions
diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 2e2557388e36..d7637c4b2840 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h | |||
@@ -358,7 +358,7 @@ struct tcp_sock { | |||
358 | */ | 358 | */ |
359 | 359 | ||
360 | int lost_cnt_hint; | 360 | int lost_cnt_hint; |
361 | int retransmit_cnt_hint; | 361 | u32 retransmit_high; /* L-bits may be on up to this seqno */ |
362 | 362 | ||
363 | u32 lost_retrans_low; /* Sent seq after any rxmit (lowest) */ | 363 | u32 lost_retrans_low; /* Sent seq after any rxmit (lowest) */ |
364 | 364 | ||
diff --git a/include/net/tcp.h b/include/net/tcp.h index b71676326950..d0e90c50722b 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -472,6 +472,8 @@ extern void tcp_send_delayed_ack(struct sock *sk); | |||
472 | 472 | ||
473 | /* tcp_input.c */ | 473 | /* tcp_input.c */ |
474 | extern void tcp_cwnd_application_limited(struct sock *sk); | 474 | extern void tcp_cwnd_application_limited(struct sock *sk); |
475 | extern void tcp_skb_mark_lost_uncond_verify(struct tcp_sock *tp, | ||
476 | struct sk_buff *skb); | ||
475 | 477 | ||
476 | /* tcp_timer.c */ | 478 | /* tcp_timer.c */ |
477 | extern void tcp_init_xmit_timers(struct sock *); | 479 | extern void tcp_init_xmit_timers(struct sock *); |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 12512336dbd8..d271cc825005 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -979,17 +979,17 @@ static void tcp_update_reordering(struct sock *sk, const int metric, | |||
979 | } | 979 | } |
980 | } | 980 | } |
981 | 981 | ||
982 | /* RFC: This is from the original, I doubt that this is necessary at all: | 982 | /* This must be called before lost_out is incremented */ |
983 | * clear xmit_retrans hint if seq of this skb is beyond hint. How could we | ||
984 | * retransmitted past LOST markings in the first place? I'm not fully sure | ||
985 | * about undo and end of connection cases, which can cause R without L? | ||
986 | */ | ||
987 | static void tcp_verify_retransmit_hint(struct tcp_sock *tp, struct sk_buff *skb) | 983 | static void tcp_verify_retransmit_hint(struct tcp_sock *tp, struct sk_buff *skb) |
988 | { | 984 | { |
989 | if ((tp->retransmit_skb_hint != NULL) && | 985 | if ((tp->retransmit_skb_hint == NULL) || |
990 | before(TCP_SKB_CB(skb)->seq, | 986 | before(TCP_SKB_CB(skb)->seq, |
991 | TCP_SKB_CB(tp->retransmit_skb_hint)->seq)) | 987 | TCP_SKB_CB(tp->retransmit_skb_hint)->seq)) |
992 | tp->retransmit_skb_hint = NULL; | 988 | tp->retransmit_skb_hint = skb; |
989 | |||
990 | if (!tp->lost_out || | ||
991 | after(TCP_SKB_CB(skb)->end_seq, tp->retransmit_high)) | ||
992 | tp->retransmit_high = TCP_SKB_CB(skb)->end_seq; | ||
993 | } | 993 | } |
994 | 994 | ||
995 | static void tcp_skb_mark_lost(struct tcp_sock *tp, struct sk_buff *skb) | 995 | static void tcp_skb_mark_lost(struct tcp_sock *tp, struct sk_buff *skb) |
@@ -1002,6 +1002,16 @@ static void tcp_skb_mark_lost(struct tcp_sock *tp, struct sk_buff *skb) | |||
1002 | } | 1002 | } |
1003 | } | 1003 | } |
1004 | 1004 | ||
1005 | void tcp_skb_mark_lost_uncond_verify(struct tcp_sock *tp, struct sk_buff *skb) | ||
1006 | { | ||
1007 | tcp_verify_retransmit_hint(tp, skb); | ||
1008 | |||
1009 | if (!(TCP_SKB_CB(skb)->sacked & (TCPCB_LOST|TCPCB_SACKED_ACKED))) { | ||
1010 | tp->lost_out += tcp_skb_pcount(skb); | ||
1011 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; | ||
1012 | } | ||
1013 | } | ||
1014 | |||
1005 | /* This procedure tags the retransmission queue when SACKs arrive. | 1015 | /* This procedure tags the retransmission queue when SACKs arrive. |
1006 | * | 1016 | * |
1007 | * We have three tag bits: SACKED(S), RETRANS(R) and LOST(L). | 1017 | * We have three tag bits: SACKED(S), RETRANS(R) and LOST(L). |
@@ -1178,13 +1188,7 @@ static void tcp_mark_lost_retrans(struct sock *sk) | |||
1178 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS; | 1188 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS; |
1179 | tp->retrans_out -= tcp_skb_pcount(skb); | 1189 | tp->retrans_out -= tcp_skb_pcount(skb); |
1180 | 1190 | ||
1181 | /* clear lost hint */ | 1191 | tcp_skb_mark_lost_uncond_verify(tp, skb); |
1182 | tp->retransmit_skb_hint = NULL; | ||
1183 | |||
1184 | if (!(TCP_SKB_CB(skb)->sacked & (TCPCB_LOST|TCPCB_SACKED_ACKED))) { | ||
1185 | tp->lost_out += tcp_skb_pcount(skb); | ||
1186 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; | ||
1187 | } | ||
1188 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPLOSTRETRANSMIT); | 1192 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPLOSTRETRANSMIT); |
1189 | } else { | 1193 | } else { |
1190 | if (before(ack_seq, new_low_seq)) | 1194 | if (before(ack_seq, new_low_seq)) |
@@ -1890,6 +1894,7 @@ static void tcp_enter_frto_loss(struct sock *sk, int allowed_segments, int flag) | |||
1890 | if (!(TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)) { | 1894 | if (!(TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)) { |
1891 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; | 1895 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; |
1892 | tp->lost_out += tcp_skb_pcount(skb); | 1896 | tp->lost_out += tcp_skb_pcount(skb); |
1897 | tp->retransmit_high = TCP_SKB_CB(skb)->end_seq; | ||
1893 | } | 1898 | } |
1894 | } | 1899 | } |
1895 | tcp_verify_left_out(tp); | 1900 | tcp_verify_left_out(tp); |
@@ -1974,6 +1979,7 @@ void tcp_enter_loss(struct sock *sk, int how) | |||
1974 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_ACKED; | 1979 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_ACKED; |
1975 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; | 1980 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; |
1976 | tp->lost_out += tcp_skb_pcount(skb); | 1981 | tp->lost_out += tcp_skb_pcount(skb); |
1982 | tp->retransmit_high = TCP_SKB_CB(skb)->end_seq; | ||
1977 | } | 1983 | } |
1978 | } | 1984 | } |
1979 | tcp_verify_left_out(tp); | 1985 | tcp_verify_left_out(tp); |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 11490958a096..cfae61b40c44 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -1838,7 +1838,7 @@ void tcp_simple_retransmit(struct sock *sk) | |||
1838 | struct tcp_sock *tp = tcp_sk(sk); | 1838 | struct tcp_sock *tp = tcp_sk(sk); |
1839 | struct sk_buff *skb; | 1839 | struct sk_buff *skb; |
1840 | unsigned int mss = tcp_current_mss(sk, 0); | 1840 | unsigned int mss = tcp_current_mss(sk, 0); |
1841 | int lost = 0; | 1841 | u32 prior_lost = tp->lost_out; |
1842 | 1842 | ||
1843 | tcp_for_write_queue(skb, sk) { | 1843 | tcp_for_write_queue(skb, sk) { |
1844 | if (skb == tcp_send_head(sk)) | 1844 | if (skb == tcp_send_head(sk)) |
@@ -1849,17 +1849,13 @@ void tcp_simple_retransmit(struct sock *sk) | |||
1849 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS; | 1849 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS; |
1850 | tp->retrans_out -= tcp_skb_pcount(skb); | 1850 | tp->retrans_out -= tcp_skb_pcount(skb); |
1851 | } | 1851 | } |
1852 | if (!(TCP_SKB_CB(skb)->sacked & TCPCB_LOST)) { | 1852 | tcp_skb_mark_lost_uncond_verify(tp, skb); |
1853 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; | ||
1854 | tp->lost_out += tcp_skb_pcount(skb); | ||
1855 | lost = 1; | ||
1856 | } | ||
1857 | } | 1853 | } |
1858 | } | 1854 | } |
1859 | 1855 | ||
1860 | tcp_clear_all_retrans_hints(tp); | 1856 | tcp_clear_all_retrans_hints(tp); |
1861 | 1857 | ||
1862 | if (!lost) | 1858 | if (prior_lost == tp->lost_out) |
1863 | return; | 1859 | return; |
1864 | 1860 | ||
1865 | if (tcp_is_reno(tp)) | 1861 | if (tcp_is_reno(tp)) |
@@ -2009,15 +2005,11 @@ void tcp_xmit_retransmit_queue(struct sock *sk) | |||
2009 | const struct inet_connection_sock *icsk = inet_csk(sk); | 2005 | const struct inet_connection_sock *icsk = inet_csk(sk); |
2010 | struct tcp_sock *tp = tcp_sk(sk); | 2006 | struct tcp_sock *tp = tcp_sk(sk); |
2011 | struct sk_buff *skb; | 2007 | struct sk_buff *skb; |
2012 | int packet_cnt; | ||
2013 | 2008 | ||
2014 | if (tp->retransmit_skb_hint) { | 2009 | if (tp->retransmit_skb_hint) |
2015 | skb = tp->retransmit_skb_hint; | 2010 | skb = tp->retransmit_skb_hint; |
2016 | packet_cnt = tp->retransmit_cnt_hint; | 2011 | else |
2017 | } else { | ||
2018 | skb = tcp_write_queue_head(sk); | 2012 | skb = tcp_write_queue_head(sk); |
2019 | packet_cnt = 0; | ||
2020 | } | ||
2021 | 2013 | ||
2022 | /* First pass: retransmit lost packets. */ | 2014 | /* First pass: retransmit lost packets. */ |
2023 | if (tp->lost_out) { | 2015 | if (tp->lost_out) { |
@@ -2028,7 +2020,6 @@ void tcp_xmit_retransmit_queue(struct sock *sk) | |||
2028 | break; | 2020 | break; |
2029 | /* we could do better than to assign each time */ | 2021 | /* we could do better than to assign each time */ |
2030 | tp->retransmit_skb_hint = skb; | 2022 | tp->retransmit_skb_hint = skb; |
2031 | tp->retransmit_cnt_hint = packet_cnt; | ||
2032 | 2023 | ||
2033 | /* Assume this retransmit will generate | 2024 | /* Assume this retransmit will generate |
2034 | * only one packet for congestion window | 2025 | * only one packet for congestion window |
@@ -2039,6 +2030,8 @@ void tcp_xmit_retransmit_queue(struct sock *sk) | |||
2039 | */ | 2030 | */ |
2040 | if (tcp_packets_in_flight(tp) >= tp->snd_cwnd) | 2031 | if (tcp_packets_in_flight(tp) >= tp->snd_cwnd) |
2041 | return; | 2032 | return; |
2033 | if (!before(TCP_SKB_CB(skb)->seq, tp->retransmit_high)) | ||
2034 | break; | ||
2042 | 2035 | ||
2043 | if (sacked & TCPCB_LOST) { | 2036 | if (sacked & TCPCB_LOST) { |
2044 | if (!(sacked & (TCPCB_SACKED_ACKED|TCPCB_SACKED_RETRANS))) { | 2037 | if (!(sacked & (TCPCB_SACKED_ACKED|TCPCB_SACKED_RETRANS))) { |
@@ -2059,10 +2052,6 @@ void tcp_xmit_retransmit_queue(struct sock *sk) | |||
2059 | inet_csk(sk)->icsk_rto, | 2052 | inet_csk(sk)->icsk_rto, |
2060 | TCP_RTO_MAX); | 2053 | TCP_RTO_MAX); |
2061 | } | 2054 | } |
2062 | |||
2063 | packet_cnt += tcp_skb_pcount(skb); | ||
2064 | if (packet_cnt >= tp->lost_out) | ||
2065 | break; | ||
2066 | } | 2055 | } |
2067 | } | 2056 | } |
2068 | } | 2057 | } |