diff options
Diffstat (limited to 'net/ipv4/tcp_timer.c')
-rw-r--r-- | net/ipv4/tcp_timer.c | 45 |
1 files changed, 42 insertions, 3 deletions
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 6df36ad55a38..fc04711e80c8 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c | |||
@@ -252,7 +252,8 @@ static void tcp_delack_timer(unsigned long data) | |||
252 | inet_csk(sk)->icsk_ack.blocked = 1; | 252 | inet_csk(sk)->icsk_ack.blocked = 1; |
253 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_DELAYEDACKLOCKED); | 253 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_DELAYEDACKLOCKED); |
254 | /* deleguate our work to tcp_release_cb() */ | 254 | /* deleguate our work to tcp_release_cb() */ |
255 | set_bit(TCP_WRITE_TIMER_DEFERRED, &tcp_sk(sk)->tsq_flags); | 255 | if (!test_and_set_bit(TCP_DELACK_TIMER_DEFERRED, &tcp_sk(sk)->tsq_flags)) |
256 | sock_hold(sk); | ||
256 | } | 257 | } |
257 | bh_unlock_sock(sk); | 258 | bh_unlock_sock(sk); |
258 | sock_put(sk); | 259 | sock_put(sk); |
@@ -304,6 +305,35 @@ static void tcp_probe_timer(struct sock *sk) | |||
304 | } | 305 | } |
305 | 306 | ||
306 | /* | 307 | /* |
308 | * Timer for Fast Open socket to retransmit SYNACK. Note that the | ||
309 | * sk here is the child socket, not the parent (listener) socket. | ||
310 | */ | ||
311 | static void tcp_fastopen_synack_timer(struct sock *sk) | ||
312 | { | ||
313 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
314 | int max_retries = icsk->icsk_syn_retries ? : | ||
315 | sysctl_tcp_synack_retries + 1; /* add one more retry for fastopen */ | ||
316 | struct request_sock *req; | ||
317 | |||
318 | req = tcp_sk(sk)->fastopen_rsk; | ||
319 | req->rsk_ops->syn_ack_timeout(sk, req); | ||
320 | |||
321 | if (req->retrans >= max_retries) { | ||
322 | tcp_write_err(sk); | ||
323 | return; | ||
324 | } | ||
325 | /* XXX (TFO) - Unlike regular SYN-ACK retransmit, we ignore error | ||
326 | * returned from rtx_syn_ack() to make it more persistent like | ||
327 | * regular retransmit because if the child socket has been accepted | ||
328 | * it's not good to give up too easily. | ||
329 | */ | ||
330 | req->rsk_ops->rtx_syn_ack(sk, req, NULL); | ||
331 | req->retrans++; | ||
332 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, | ||
333 | TCP_TIMEOUT_INIT << req->retrans, TCP_RTO_MAX); | ||
334 | } | ||
335 | |||
336 | /* | ||
307 | * The TCP retransmit timer. | 337 | * The TCP retransmit timer. |
308 | */ | 338 | */ |
309 | 339 | ||
@@ -316,7 +346,15 @@ void tcp_retransmit_timer(struct sock *sk) | |||
316 | tcp_resume_early_retransmit(sk); | 346 | tcp_resume_early_retransmit(sk); |
317 | return; | 347 | return; |
318 | } | 348 | } |
319 | 349 | if (tp->fastopen_rsk) { | |
350 | BUG_ON(sk->sk_state != TCP_SYN_RECV && | ||
351 | sk->sk_state != TCP_FIN_WAIT1); | ||
352 | tcp_fastopen_synack_timer(sk); | ||
353 | /* Before we receive ACK to our SYN-ACK don't retransmit | ||
354 | * anything else (e.g., data or FIN segments). | ||
355 | */ | ||
356 | return; | ||
357 | } | ||
320 | if (!tp->packets_out) | 358 | if (!tp->packets_out) |
321 | goto out; | 359 | goto out; |
322 | 360 | ||
@@ -481,7 +519,8 @@ static void tcp_write_timer(unsigned long data) | |||
481 | tcp_write_timer_handler(sk); | 519 | tcp_write_timer_handler(sk); |
482 | } else { | 520 | } else { |
483 | /* deleguate our work to tcp_release_cb() */ | 521 | /* deleguate our work to tcp_release_cb() */ |
484 | set_bit(TCP_WRITE_TIMER_DEFERRED, &tcp_sk(sk)->tsq_flags); | 522 | if (!test_and_set_bit(TCP_WRITE_TIMER_DEFERRED, &tcp_sk(sk)->tsq_flags)) |
523 | sock_hold(sk); | ||
485 | } | 524 | } |
486 | bh_unlock_sock(sk); | 525 | bh_unlock_sock(sk); |
487 | sock_put(sk); | 526 | sock_put(sk); |