diff options
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r-- | net/ipv4/tcp_input.c | 47 |
1 files changed, 32 insertions, 15 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index fec8a7a4dbaf..378ca8a086a3 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -1851,19 +1851,22 @@ static inline u32 tcp_cwnd_min(const struct sock *sk) | |||
1851 | } | 1851 | } |
1852 | 1852 | ||
1853 | /* Decrease cwnd each second ack. */ | 1853 | /* Decrease cwnd each second ack. */ |
1854 | static void tcp_cwnd_down(struct sock *sk) | 1854 | static void tcp_cwnd_down(struct sock *sk, int flag) |
1855 | { | 1855 | { |
1856 | struct tcp_sock *tp = tcp_sk(sk); | 1856 | struct tcp_sock *tp = tcp_sk(sk); |
1857 | int decr = tp->snd_cwnd_cnt + 1; | 1857 | int decr = tp->snd_cwnd_cnt + 1; |
1858 | 1858 | ||
1859 | tp->snd_cwnd_cnt = decr&1; | 1859 | if ((flag&FLAG_FORWARD_PROGRESS) || |
1860 | decr >>= 1; | 1860 | (IsReno(tp) && !(flag&FLAG_NOT_DUP))) { |
1861 | tp->snd_cwnd_cnt = decr&1; | ||
1862 | decr >>= 1; | ||
1861 | 1863 | ||
1862 | if (decr && tp->snd_cwnd > tcp_cwnd_min(sk)) | 1864 | if (decr && tp->snd_cwnd > tcp_cwnd_min(sk)) |
1863 | tp->snd_cwnd -= decr; | 1865 | tp->snd_cwnd -= decr; |
1864 | 1866 | ||
1865 | tp->snd_cwnd = min(tp->snd_cwnd, tcp_packets_in_flight(tp)+1); | 1867 | tp->snd_cwnd = min(tp->snd_cwnd, tcp_packets_in_flight(tp)+1); |
1866 | tp->snd_cwnd_stamp = tcp_time_stamp; | 1868 | tp->snd_cwnd_stamp = tcp_time_stamp; |
1869 | } | ||
1867 | } | 1870 | } |
1868 | 1871 | ||
1869 | /* Nothing was retransmitted or returned timestamp is less | 1872 | /* Nothing was retransmitted or returned timestamp is less |
@@ -2060,7 +2063,7 @@ static void tcp_try_to_open(struct sock *sk, int flag) | |||
2060 | } | 2063 | } |
2061 | tcp_moderate_cwnd(tp); | 2064 | tcp_moderate_cwnd(tp); |
2062 | } else { | 2065 | } else { |
2063 | tcp_cwnd_down(sk); | 2066 | tcp_cwnd_down(sk, flag); |
2064 | } | 2067 | } |
2065 | } | 2068 | } |
2066 | 2069 | ||
@@ -2109,7 +2112,10 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una, | |||
2109 | { | 2112 | { |
2110 | struct inet_connection_sock *icsk = inet_csk(sk); | 2113 | struct inet_connection_sock *icsk = inet_csk(sk); |
2111 | struct tcp_sock *tp = tcp_sk(sk); | 2114 | struct tcp_sock *tp = tcp_sk(sk); |
2112 | int is_dupack = (tp->snd_una == prior_snd_una && !(flag&FLAG_NOT_DUP)); | 2115 | int is_dupack = (tp->snd_una == prior_snd_una && |
2116 | (!(flag&FLAG_NOT_DUP) || | ||
2117 | ((flag&FLAG_DATA_SACKED) && | ||
2118 | (tp->fackets_out > tp->reordering)))); | ||
2113 | 2119 | ||
2114 | /* Some technical things: | 2120 | /* Some technical things: |
2115 | * 1. Reno does not count dupacks (sacked_out) automatically. */ | 2121 | * 1. Reno does not count dupacks (sacked_out) automatically. */ |
@@ -2260,7 +2266,7 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una, | |||
2260 | 2266 | ||
2261 | if (is_dupack || tcp_head_timedout(sk)) | 2267 | if (is_dupack || tcp_head_timedout(sk)) |
2262 | tcp_update_scoreboard(sk); | 2268 | tcp_update_scoreboard(sk); |
2263 | tcp_cwnd_down(sk); | 2269 | tcp_cwnd_down(sk, flag); |
2264 | tcp_xmit_retransmit_queue(sk); | 2270 | tcp_xmit_retransmit_queue(sk); |
2265 | } | 2271 | } |
2266 | 2272 | ||
@@ -2490,12 +2496,23 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p) | |||
2490 | tcp_ack_update_rtt(sk, acked, seq_rtt); | 2496 | tcp_ack_update_rtt(sk, acked, seq_rtt); |
2491 | tcp_ack_packets_out(sk); | 2497 | tcp_ack_packets_out(sk); |
2492 | 2498 | ||
2493 | /* Is the ACK triggering packet unambiguous? */ | 2499 | if (ca_ops->pkts_acked) { |
2494 | if (acked & FLAG_RETRANS_DATA_ACKED) | 2500 | s32 rtt_us = -1; |
2495 | last_ackt = net_invalid_timestamp(); | 2501 | |
2502 | /* Is the ACK triggering packet unambiguous? */ | ||
2503 | if (!(acked & FLAG_RETRANS_DATA_ACKED)) { | ||
2504 | /* High resolution needed and available? */ | ||
2505 | if (ca_ops->flags & TCP_CONG_RTT_STAMP && | ||
2506 | !ktime_equal(last_ackt, | ||
2507 | net_invalid_timestamp())) | ||
2508 | rtt_us = ktime_us_delta(ktime_get_real(), | ||
2509 | last_ackt); | ||
2510 | else if (seq_rtt > 0) | ||
2511 | rtt_us = jiffies_to_usecs(seq_rtt); | ||
2512 | } | ||
2496 | 2513 | ||
2497 | if (ca_ops->pkts_acked) | 2514 | ca_ops->pkts_acked(sk, pkts_acked, rtt_us); |
2498 | ca_ops->pkts_acked(sk, pkts_acked, last_ackt); | 2515 | } |
2499 | } | 2516 | } |
2500 | 2517 | ||
2501 | #if FASTRETRANS_DEBUG > 0 | 2518 | #if FASTRETRANS_DEBUG > 0 |