diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/tcp_timer.c | 24 |
1 files changed, 14 insertions, 10 deletions
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index c35b469e851c..74c54b30600f 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c | |||
@@ -135,13 +135,16 @@ static void tcp_mtu_probing(struct inet_connection_sock *icsk, struct sock *sk) | |||
135 | 135 | ||
136 | /* This function calculates a "timeout" which is equivalent to the timeout of a | 136 | /* This function calculates a "timeout" which is equivalent to the timeout of a |
137 | * TCP connection after "boundary" unsuccessful, exponentially backed-off | 137 | * TCP connection after "boundary" unsuccessful, exponentially backed-off |
138 | * retransmissions with an initial RTO of TCP_RTO_MIN. | 138 | * retransmissions with an initial RTO of TCP_RTO_MIN or TCP_TIMEOUT_INIT if |
139 | * syn_set flag is set. | ||
139 | */ | 140 | */ |
140 | static bool retransmits_timed_out(struct sock *sk, | 141 | static bool retransmits_timed_out(struct sock *sk, |
141 | unsigned int boundary) | 142 | unsigned int boundary, |
143 | bool syn_set) | ||
142 | { | 144 | { |
143 | unsigned int timeout, linear_backoff_thresh; | 145 | unsigned int timeout, linear_backoff_thresh; |
144 | unsigned int start_ts; | 146 | unsigned int start_ts; |
147 | unsigned int rto_base = syn_set ? TCP_TIMEOUT_INIT : TCP_RTO_MIN; | ||
145 | 148 | ||
146 | if (!inet_csk(sk)->icsk_retransmits) | 149 | if (!inet_csk(sk)->icsk_retransmits) |
147 | return false; | 150 | return false; |
@@ -151,12 +154,12 @@ static bool retransmits_timed_out(struct sock *sk, | |||
151 | else | 154 | else |
152 | start_ts = tcp_sk(sk)->retrans_stamp; | 155 | start_ts = tcp_sk(sk)->retrans_stamp; |
153 | 156 | ||
154 | linear_backoff_thresh = ilog2(TCP_RTO_MAX/TCP_RTO_MIN); | 157 | linear_backoff_thresh = ilog2(TCP_RTO_MAX/rto_base); |
155 | 158 | ||
156 | if (boundary <= linear_backoff_thresh) | 159 | if (boundary <= linear_backoff_thresh) |
157 | timeout = ((2 << boundary) - 1) * TCP_RTO_MIN; | 160 | timeout = ((2 << boundary) - 1) * rto_base; |
158 | else | 161 | else |
159 | timeout = ((2 << linear_backoff_thresh) - 1) * TCP_RTO_MIN + | 162 | timeout = ((2 << linear_backoff_thresh) - 1) * rto_base + |
160 | (boundary - linear_backoff_thresh) * TCP_RTO_MAX; | 163 | (boundary - linear_backoff_thresh) * TCP_RTO_MAX; |
161 | 164 | ||
162 | return (tcp_time_stamp - start_ts) >= timeout; | 165 | return (tcp_time_stamp - start_ts) >= timeout; |
@@ -167,14 +170,15 @@ static int tcp_write_timeout(struct sock *sk) | |||
167 | { | 170 | { |
168 | struct inet_connection_sock *icsk = inet_csk(sk); | 171 | struct inet_connection_sock *icsk = inet_csk(sk); |
169 | int retry_until; | 172 | int retry_until; |
170 | bool do_reset; | 173 | bool do_reset, syn_set = 0; |
171 | 174 | ||
172 | if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) { | 175 | if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) { |
173 | if (icsk->icsk_retransmits) | 176 | if (icsk->icsk_retransmits) |
174 | dst_negative_advice(sk); | 177 | dst_negative_advice(sk); |
175 | retry_until = icsk->icsk_syn_retries ? : sysctl_tcp_syn_retries; | 178 | retry_until = icsk->icsk_syn_retries ? : sysctl_tcp_syn_retries; |
179 | syn_set = 1; | ||
176 | } else { | 180 | } else { |
177 | if (retransmits_timed_out(sk, sysctl_tcp_retries1)) { | 181 | if (retransmits_timed_out(sk, sysctl_tcp_retries1, 0)) { |
178 | /* Black hole detection */ | 182 | /* Black hole detection */ |
179 | tcp_mtu_probing(icsk, sk); | 183 | tcp_mtu_probing(icsk, sk); |
180 | 184 | ||
@@ -187,14 +191,14 @@ static int tcp_write_timeout(struct sock *sk) | |||
187 | 191 | ||
188 | retry_until = tcp_orphan_retries(sk, alive); | 192 | retry_until = tcp_orphan_retries(sk, alive); |
189 | do_reset = alive || | 193 | do_reset = alive || |
190 | !retransmits_timed_out(sk, retry_until); | 194 | !retransmits_timed_out(sk, retry_until, 0); |
191 | 195 | ||
192 | if (tcp_out_of_resources(sk, do_reset)) | 196 | if (tcp_out_of_resources(sk, do_reset)) |
193 | return 1; | 197 | return 1; |
194 | } | 198 | } |
195 | } | 199 | } |
196 | 200 | ||
197 | if (retransmits_timed_out(sk, retry_until)) { | 201 | if (retransmits_timed_out(sk, retry_until, syn_set)) { |
198 | /* Has it gone just too far? */ | 202 | /* Has it gone just too far? */ |
199 | tcp_write_err(sk); | 203 | tcp_write_err(sk); |
200 | return 1; | 204 | return 1; |
@@ -436,7 +440,7 @@ out_reset_timer: | |||
436 | icsk->icsk_rto = min(icsk->icsk_rto << 1, TCP_RTO_MAX); | 440 | icsk->icsk_rto = min(icsk->icsk_rto << 1, TCP_RTO_MAX); |
437 | } | 441 | } |
438 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto, TCP_RTO_MAX); | 442 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto, TCP_RTO_MAX); |
439 | if (retransmits_timed_out(sk, sysctl_tcp_retries1 + 1)) | 443 | if (retransmits_timed_out(sk, sysctl_tcp_retries1 + 1, 0)) |
440 | __sk_dst_reset(sk); | 444 | __sk_dst_reset(sk); |
441 | 445 | ||
442 | out:; | 446 | out:; |