diff options
author | Yuchung Cheng <ycheng@google.com> | 2012-04-30 06:00:18 +0000 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-05-12 09:32:19 -0700 |
commit | 28a3d46497af5da64dd88110bf03d99cf181d5f9 (patch) | |
tree | 5c84ac7763af530a1f9798564539b27763927a5e | |
parent | ac931e2df86c0f7e69df21001832ad63ffe3d1c9 (diff) | |
download | lwn-28a3d46497af5da64dd88110bf03d99cf181d5f9.tar.gz lwn-28a3d46497af5da64dd88110bf03d99cf181d5f9.zip |
tcp: fix infinite cwnd in tcp_complete_cwr()
[ Upstream commit 1cebce36d660c83bd1353e41f3e66abd4686f215 ]
When the cwnd reduction is done, ssthresh may be infinite
if TCP enters CWR via ECN or F-RTO. If cwnd is not undone, i.e.,
undo_marker is set, tcp_complete_cwr() falsely set cwnd to the
infinite ssthresh value. The correct operation is to keep cwnd
intact because it has been updated in ECN or F-RTO.
Signed-off-by: Yuchung Cheng <ycheng@google.com>
Acked-by: Neal Cardwell <ncardwell@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | net/ipv4/tcp_input.c | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 1c30511e9c32..210f474b4fe3 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2866,11 +2866,14 @@ static inline void tcp_complete_cwr(struct sock *sk) /* Do not moderate cwnd if it's already undone in cwr or recovery. */ if (tp->undo_marker) { - if (inet_csk(sk)->icsk_ca_state == TCP_CA_CWR) + if (inet_csk(sk)->icsk_ca_state == TCP_CA_CWR) { tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh); - else /* PRR */ + tp->snd_cwnd_stamp = tcp_time_stamp; + } else if (tp->snd_ssthresh < TCP_INFINITE_SSTHRESH) { + /* PRR algorithm. */ tp->snd_cwnd = tp->snd_ssthresh; - tp->snd_cwnd_stamp = tcp_time_stamp; + tp->snd_cwnd_stamp = tcp_time_stamp; + } } tcp_ca_event(sk, CA_EVENT_COMPLETE_CWR); } |