diff options
Diffstat (limited to 'net/ipv4/tcp_timer.c')
-rw-r--r-- | net/ipv4/tcp_timer.c | 26 |
1 files changed, 11 insertions, 15 deletions
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index c4a35ba7f8ed..c0feeeef962a 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c | |||
@@ -139,21 +139,17 @@ static void tcp_mtu_probing(struct inet_connection_sock *icsk, struct sock *sk) | |||
139 | * @timeout: A custom timeout value. | 139 | * @timeout: A custom timeout value. |
140 | * If set to 0 the default timeout is calculated and used. | 140 | * If set to 0 the default timeout is calculated and used. |
141 | * Using TCP_RTO_MIN and the number of unsuccessful retransmits. | 141 | * Using TCP_RTO_MIN and the number of unsuccessful retransmits. |
142 | * @syn_set: true if the SYN Bit was set. | ||
143 | * | 142 | * |
144 | * The default "timeout" value this function can calculate and use | 143 | * The default "timeout" value this function can calculate and use |
145 | * is equivalent to the timeout of a TCP Connection | 144 | * is equivalent to the timeout of a TCP Connection |
146 | * after "boundary" unsuccessful, exponentially backed-off | 145 | * after "boundary" unsuccessful, exponentially backed-off |
147 | * retransmissions with an initial RTO of TCP_RTO_MIN or TCP_TIMEOUT_INIT if | 146 | * retransmissions with an initial RTO of TCP_RTO_MIN. |
148 | * syn_set flag is set. | ||
149 | * | ||
150 | */ | 147 | */ |
151 | static bool retransmits_timed_out(struct sock *sk, | 148 | static bool retransmits_timed_out(struct sock *sk, |
152 | unsigned int boundary, | 149 | unsigned int boundary, |
153 | unsigned int timeout, | 150 | unsigned int timeout) |
154 | bool syn_set) | ||
155 | { | 151 | { |
156 | unsigned int rto_base = syn_set ? TCP_TIMEOUT_INIT : TCP_RTO_MIN; | 152 | const unsigned int rto_base = TCP_RTO_MIN; |
157 | unsigned int linear_backoff_thresh, start_ts; | 153 | unsigned int linear_backoff_thresh, start_ts; |
158 | 154 | ||
159 | if (!inet_csk(sk)->icsk_retransmits) | 155 | if (!inet_csk(sk)->icsk_retransmits) |
@@ -181,8 +177,8 @@ static int tcp_write_timeout(struct sock *sk) | |||
181 | struct inet_connection_sock *icsk = inet_csk(sk); | 177 | struct inet_connection_sock *icsk = inet_csk(sk); |
182 | struct tcp_sock *tp = tcp_sk(sk); | 178 | struct tcp_sock *tp = tcp_sk(sk); |
183 | struct net *net = sock_net(sk); | 179 | struct net *net = sock_net(sk); |
180 | bool expired, do_reset; | ||
184 | int retry_until; | 181 | int retry_until; |
185 | bool do_reset, syn_set = false; | ||
186 | 182 | ||
187 | if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) { | 183 | if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) { |
188 | if (icsk->icsk_retransmits) { | 184 | if (icsk->icsk_retransmits) { |
@@ -196,9 +192,9 @@ static int tcp_write_timeout(struct sock *sk) | |||
196 | sk_rethink_txhash(sk); | 192 | sk_rethink_txhash(sk); |
197 | } | 193 | } |
198 | retry_until = icsk->icsk_syn_retries ? : net->ipv4.sysctl_tcp_syn_retries; | 194 | retry_until = icsk->icsk_syn_retries ? : net->ipv4.sysctl_tcp_syn_retries; |
199 | syn_set = true; | 195 | expired = icsk->icsk_retransmits >= retry_until; |
200 | } else { | 196 | } else { |
201 | if (retransmits_timed_out(sk, net->ipv4.sysctl_tcp_retries1, 0, 0)) { | 197 | if (retransmits_timed_out(sk, net->ipv4.sysctl_tcp_retries1, 0)) { |
202 | /* Some middle-boxes may black-hole Fast Open _after_ | 198 | /* Some middle-boxes may black-hole Fast Open _after_ |
203 | * the handshake. Therefore we conservatively disable | 199 | * the handshake. Therefore we conservatively disable |
204 | * Fast Open on this path on recurring timeouts after | 200 | * Fast Open on this path on recurring timeouts after |
@@ -224,15 +220,15 @@ static int tcp_write_timeout(struct sock *sk) | |||
224 | 220 | ||
225 | retry_until = tcp_orphan_retries(sk, alive); | 221 | retry_until = tcp_orphan_retries(sk, alive); |
226 | do_reset = alive || | 222 | do_reset = alive || |
227 | !retransmits_timed_out(sk, retry_until, 0, 0); | 223 | !retransmits_timed_out(sk, retry_until, 0); |
228 | 224 | ||
229 | if (tcp_out_of_resources(sk, do_reset)) | 225 | if (tcp_out_of_resources(sk, do_reset)) |
230 | return 1; | 226 | return 1; |
231 | } | 227 | } |
228 | expired = retransmits_timed_out(sk, retry_until, | ||
229 | icsk->icsk_user_timeout); | ||
232 | } | 230 | } |
233 | 231 | if (expired) { | |
234 | if (retransmits_timed_out(sk, retry_until, | ||
235 | syn_set ? 0 : icsk->icsk_user_timeout, syn_set)) { | ||
236 | /* Has it gone just too far? */ | 232 | /* Has it gone just too far? */ |
237 | tcp_write_err(sk); | 233 | tcp_write_err(sk); |
238 | return 1; | 234 | return 1; |
@@ -540,7 +536,7 @@ out_reset_timer: | |||
540 | icsk->icsk_rto = min(icsk->icsk_rto << 1, TCP_RTO_MAX); | 536 | icsk->icsk_rto = min(icsk->icsk_rto << 1, TCP_RTO_MAX); |
541 | } | 537 | } |
542 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto, TCP_RTO_MAX); | 538 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto, TCP_RTO_MAX); |
543 | if (retransmits_timed_out(sk, net->ipv4.sysctl_tcp_retries1 + 1, 0, 0)) | 539 | if (retransmits_timed_out(sk, net->ipv4.sysctl_tcp_retries1 + 1, 0)) |
544 | __sk_dst_reset(sk); | 540 | __sk_dst_reset(sk); |
545 | 541 | ||
546 | out:; | 542 | out:; |