diff options
Diffstat (limited to 'net/ipv4/tcp_timer.c')
-rw-r--r-- | net/ipv4/tcp_timer.c | 79 |
1 files changed, 43 insertions, 36 deletions
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 655dd8d7f064..968fda198376 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c | |||
@@ -22,8 +22,6 @@ | |||
22 | #include <linux/gfp.h> | 22 | #include <linux/gfp.h> |
23 | #include <net/tcp.h> | 23 | #include <net/tcp.h> |
24 | 24 | ||
25 | int sysctl_tcp_thin_linear_timeouts __read_mostly; | ||
26 | |||
27 | /** | 25 | /** |
28 | * tcp_write_err() - close socket and save error info | 26 | * tcp_write_err() - close socket and save error info |
29 | * @sk: The socket the error has appeared on. | 27 | * @sk: The socket the error has appeared on. |
@@ -109,26 +107,23 @@ static int tcp_orphan_retries(struct sock *sk, bool alive) | |||
109 | 107 | ||
110 | static void tcp_mtu_probing(struct inet_connection_sock *icsk, struct sock *sk) | 108 | static void tcp_mtu_probing(struct inet_connection_sock *icsk, struct sock *sk) |
111 | { | 109 | { |
112 | struct net *net = sock_net(sk); | 110 | const struct net *net = sock_net(sk); |
111 | int mss; | ||
113 | 112 | ||
114 | /* Black hole detection */ | 113 | /* Black hole detection */ |
115 | if (net->ipv4.sysctl_tcp_mtu_probing) { | 114 | if (!net->ipv4.sysctl_tcp_mtu_probing) |
116 | if (!icsk->icsk_mtup.enabled) { | 115 | return; |
117 | icsk->icsk_mtup.enabled = 1; | 116 | |
118 | icsk->icsk_mtup.probe_timestamp = tcp_jiffies32; | 117 | if (!icsk->icsk_mtup.enabled) { |
119 | tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); | 118 | icsk->icsk_mtup.enabled = 1; |
120 | } else { | 119 | icsk->icsk_mtup.probe_timestamp = tcp_jiffies32; |
121 | struct net *net = sock_net(sk); | 120 | } else { |
122 | struct tcp_sock *tp = tcp_sk(sk); | 121 | mss = tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_low) >> 1; |
123 | int mss; | 122 | mss = min(net->ipv4.sysctl_tcp_base_mss, mss); |
124 | 123 | mss = max(mss, 68 - tcp_sk(sk)->tcp_header_len); | |
125 | mss = tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_low) >> 1; | 124 | icsk->icsk_mtup.search_low = tcp_mss_to_mtu(sk, mss); |
126 | mss = min(net->ipv4.sysctl_tcp_base_mss, mss); | ||
127 | mss = max(mss, 68 - tp->tcp_header_len); | ||
128 | icsk->icsk_mtup.search_low = tcp_mss_to_mtu(sk, mss); | ||
129 | tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); | ||
130 | } | ||
131 | } | 125 | } |
126 | tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); | ||
132 | } | 127 | } |
133 | 128 | ||
134 | 129 | ||
@@ -156,8 +151,13 @@ static bool retransmits_timed_out(struct sock *sk, | |||
156 | return false; | 151 | return false; |
157 | 152 | ||
158 | start_ts = tcp_sk(sk)->retrans_stamp; | 153 | start_ts = tcp_sk(sk)->retrans_stamp; |
159 | if (unlikely(!start_ts)) | 154 | if (unlikely(!start_ts)) { |
160 | start_ts = tcp_skb_timestamp(tcp_write_queue_head(sk)); | 155 | struct sk_buff *head = tcp_rtx_queue_head(sk); |
156 | |||
157 | if (!head) | ||
158 | return false; | ||
159 | start_ts = tcp_skb_timestamp(head); | ||
160 | } | ||
161 | 161 | ||
162 | if (likely(timeout == 0)) { | 162 | if (likely(timeout == 0)) { |
163 | linear_backoff_thresh = ilog2(TCP_RTO_MAX/rto_base); | 163 | linear_backoff_thresh = ilog2(TCP_RTO_MAX/rto_base); |
@@ -264,6 +264,7 @@ void tcp_delack_timer_handler(struct sock *sk) | |||
264 | icsk->icsk_ack.pingpong = 0; | 264 | icsk->icsk_ack.pingpong = 0; |
265 | icsk->icsk_ack.ato = TCP_ATO_MIN; | 265 | icsk->icsk_ack.ato = TCP_ATO_MIN; |
266 | } | 266 | } |
267 | tcp_mstamp_refresh(tcp_sk(sk)); | ||
267 | tcp_send_ack(sk); | 268 | tcp_send_ack(sk); |
268 | __NET_INC_STATS(sock_net(sk), LINUX_MIB_DELAYEDACKS); | 269 | __NET_INC_STATS(sock_net(sk), LINUX_MIB_DELAYEDACKS); |
269 | } | 270 | } |
@@ -283,15 +284,17 @@ out: | |||
283 | * | 284 | * |
284 | * Returns: Nothing (void) | 285 | * Returns: Nothing (void) |
285 | */ | 286 | */ |
286 | static void tcp_delack_timer(unsigned long data) | 287 | static void tcp_delack_timer(struct timer_list *t) |
287 | { | 288 | { |
288 | struct sock *sk = (struct sock *)data; | 289 | struct inet_connection_sock *icsk = |
290 | from_timer(icsk, t, icsk_delack_timer); | ||
291 | struct sock *sk = &icsk->icsk_inet.sk; | ||
289 | 292 | ||
290 | bh_lock_sock(sk); | 293 | bh_lock_sock(sk); |
291 | if (!sock_owned_by_user(sk)) { | 294 | if (!sock_owned_by_user(sk)) { |
292 | tcp_delack_timer_handler(sk); | 295 | tcp_delack_timer_handler(sk); |
293 | } else { | 296 | } else { |
294 | inet_csk(sk)->icsk_ack.blocked = 1; | 297 | icsk->icsk_ack.blocked = 1; |
295 | __NET_INC_STATS(sock_net(sk), LINUX_MIB_DELAYEDACKLOCKED); | 298 | __NET_INC_STATS(sock_net(sk), LINUX_MIB_DELAYEDACKLOCKED); |
296 | /* deleguate our work to tcp_release_cb() */ | 299 | /* deleguate our work to tcp_release_cb() */ |
297 | if (!test_and_set_bit(TCP_DELACK_TIMER_DEFERRED, &sk->sk_tsq_flags)) | 300 | if (!test_and_set_bit(TCP_DELACK_TIMER_DEFERRED, &sk->sk_tsq_flags)) |
@@ -304,11 +307,12 @@ static void tcp_delack_timer(unsigned long data) | |||
304 | static void tcp_probe_timer(struct sock *sk) | 307 | static void tcp_probe_timer(struct sock *sk) |
305 | { | 308 | { |
306 | struct inet_connection_sock *icsk = inet_csk(sk); | 309 | struct inet_connection_sock *icsk = inet_csk(sk); |
310 | struct sk_buff *skb = tcp_send_head(sk); | ||
307 | struct tcp_sock *tp = tcp_sk(sk); | 311 | struct tcp_sock *tp = tcp_sk(sk); |
308 | int max_probes; | 312 | int max_probes; |
309 | u32 start_ts; | 313 | u32 start_ts; |
310 | 314 | ||
311 | if (tp->packets_out || !tcp_send_head(sk)) { | 315 | if (tp->packets_out || !skb) { |
312 | icsk->icsk_probes_out = 0; | 316 | icsk->icsk_probes_out = 0; |
313 | return; | 317 | return; |
314 | } | 318 | } |
@@ -321,9 +325,9 @@ static void tcp_probe_timer(struct sock *sk) | |||
321 | * corresponding system limit. We also implement similar policy when | 325 | * corresponding system limit. We also implement similar policy when |
322 | * we use RTO to probe window in tcp_retransmit_timer(). | 326 | * we use RTO to probe window in tcp_retransmit_timer(). |
323 | */ | 327 | */ |
324 | start_ts = tcp_skb_timestamp(tcp_send_head(sk)); | 328 | start_ts = tcp_skb_timestamp(skb); |
325 | if (!start_ts) | 329 | if (!start_ts) |
326 | tcp_send_head(sk)->skb_mstamp = tp->tcp_mstamp; | 330 | skb->skb_mstamp = tp->tcp_mstamp; |
327 | else if (icsk->icsk_user_timeout && | 331 | else if (icsk->icsk_user_timeout && |
328 | (s32)(tcp_time_stamp(tp) - start_ts) > | 332 | (s32)(tcp_time_stamp(tp) - start_ts) > |
329 | jiffies_to_msecs(icsk->icsk_user_timeout)) | 333 | jiffies_to_msecs(icsk->icsk_user_timeout)) |
@@ -408,7 +412,7 @@ void tcp_retransmit_timer(struct sock *sk) | |||
408 | if (!tp->packets_out) | 412 | if (!tp->packets_out) |
409 | goto out; | 413 | goto out; |
410 | 414 | ||
411 | WARN_ON(tcp_write_queue_empty(sk)); | 415 | WARN_ON(tcp_rtx_queue_empty(sk)); |
412 | 416 | ||
413 | tp->tlp_high_seq = 0; | 417 | tp->tlp_high_seq = 0; |
414 | 418 | ||
@@ -441,7 +445,7 @@ void tcp_retransmit_timer(struct sock *sk) | |||
441 | goto out; | 445 | goto out; |
442 | } | 446 | } |
443 | tcp_enter_loss(sk); | 447 | tcp_enter_loss(sk); |
444 | tcp_retransmit_skb(sk, tcp_write_queue_head(sk), 1); | 448 | tcp_retransmit_skb(sk, tcp_rtx_queue_head(sk), 1); |
445 | __sk_dst_reset(sk); | 449 | __sk_dst_reset(sk); |
446 | goto out_reset_timer; | 450 | goto out_reset_timer; |
447 | } | 451 | } |
@@ -473,7 +477,7 @@ void tcp_retransmit_timer(struct sock *sk) | |||
473 | 477 | ||
474 | tcp_enter_loss(sk); | 478 | tcp_enter_loss(sk); |
475 | 479 | ||
476 | if (tcp_retransmit_skb(sk, tcp_write_queue_head(sk), 1) > 0) { | 480 | if (tcp_retransmit_skb(sk, tcp_rtx_queue_head(sk), 1) > 0) { |
477 | /* Retransmission failed because of local congestion, | 481 | /* Retransmission failed because of local congestion, |
478 | * do not backoff. | 482 | * do not backoff. |
479 | */ | 483 | */ |
@@ -514,7 +518,7 @@ out_reset_timer: | |||
514 | * linear-timeout retransmissions into a black hole | 518 | * linear-timeout retransmissions into a black hole |
515 | */ | 519 | */ |
516 | if (sk->sk_state == TCP_ESTABLISHED && | 520 | if (sk->sk_state == TCP_ESTABLISHED && |
517 | (tp->thin_lto || sysctl_tcp_thin_linear_timeouts) && | 521 | (tp->thin_lto || net->ipv4.sysctl_tcp_thin_linear_timeouts) && |
518 | tcp_stream_is_thin(tp) && | 522 | tcp_stream_is_thin(tp) && |
519 | icsk->icsk_retransmits <= TCP_THIN_LINEAR_RETRIES) { | 523 | icsk->icsk_retransmits <= TCP_THIN_LINEAR_RETRIES) { |
520 | icsk->icsk_backoff = 0; | 524 | icsk->icsk_backoff = 0; |
@@ -570,9 +574,11 @@ out: | |||
570 | sk_mem_reclaim(sk); | 574 | sk_mem_reclaim(sk); |
571 | } | 575 | } |
572 | 576 | ||
573 | static void tcp_write_timer(unsigned long data) | 577 | static void tcp_write_timer(struct timer_list *t) |
574 | { | 578 | { |
575 | struct sock *sk = (struct sock *)data; | 579 | struct inet_connection_sock *icsk = |
580 | from_timer(icsk, t, icsk_retransmit_timer); | ||
581 | struct sock *sk = &icsk->icsk_inet.sk; | ||
576 | 582 | ||
577 | bh_lock_sock(sk); | 583 | bh_lock_sock(sk); |
578 | if (!sock_owned_by_user(sk)) { | 584 | if (!sock_owned_by_user(sk)) { |
@@ -607,9 +613,9 @@ void tcp_set_keepalive(struct sock *sk, int val) | |||
607 | EXPORT_SYMBOL_GPL(tcp_set_keepalive); | 613 | EXPORT_SYMBOL_GPL(tcp_set_keepalive); |
608 | 614 | ||
609 | 615 | ||
610 | static void tcp_keepalive_timer (unsigned long data) | 616 | static void tcp_keepalive_timer (struct timer_list *t) |
611 | { | 617 | { |
612 | struct sock *sk = (struct sock *) data; | 618 | struct sock *sk = from_timer(sk, t, sk_timer); |
613 | struct inet_connection_sock *icsk = inet_csk(sk); | 619 | struct inet_connection_sock *icsk = inet_csk(sk); |
614 | struct tcp_sock *tp = tcp_sk(sk); | 620 | struct tcp_sock *tp = tcp_sk(sk); |
615 | u32 elapsed; | 621 | u32 elapsed; |
@@ -627,6 +633,7 @@ static void tcp_keepalive_timer (unsigned long data) | |||
627 | goto out; | 633 | goto out; |
628 | } | 634 | } |
629 | 635 | ||
636 | tcp_mstamp_refresh(tp); | ||
630 | if (sk->sk_state == TCP_FIN_WAIT2 && sock_flag(sk, SOCK_DEAD)) { | 637 | if (sk->sk_state == TCP_FIN_WAIT2 && sock_flag(sk, SOCK_DEAD)) { |
631 | if (tp->linger2 >= 0) { | 638 | if (tp->linger2 >= 0) { |
632 | const int tmo = tcp_fin_time(sk) - TCP_TIMEWAIT_LEN; | 639 | const int tmo = tcp_fin_time(sk) - TCP_TIMEWAIT_LEN; |
@@ -647,7 +654,7 @@ static void tcp_keepalive_timer (unsigned long data) | |||
647 | elapsed = keepalive_time_when(tp); | 654 | elapsed = keepalive_time_when(tp); |
648 | 655 | ||
649 | /* It is alive without keepalive 8) */ | 656 | /* It is alive without keepalive 8) */ |
650 | if (tp->packets_out || tcp_send_head(sk)) | 657 | if (tp->packets_out || !tcp_write_queue_empty(sk)) |
651 | goto resched; | 658 | goto resched; |
652 | 659 | ||
653 | elapsed = keepalive_time_elapsed(tp); | 660 | elapsed = keepalive_time_elapsed(tp); |