aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_metrics.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/tcp_metrics.c')
-rw-r--r--net/ipv4/tcp_metrics.c42
1 files changed, 17 insertions, 25 deletions
diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c
index f6a005c485a9..4a22f3e715df 100644
--- a/net/ipv4/tcp_metrics.c
+++ b/net/ipv4/tcp_metrics.c
@@ -443,7 +443,7 @@ void tcp_init_metrics(struct sock *sk)
443 struct dst_entry *dst = __sk_dst_get(sk); 443 struct dst_entry *dst = __sk_dst_get(sk);
444 struct tcp_sock *tp = tcp_sk(sk); 444 struct tcp_sock *tp = tcp_sk(sk);
445 struct tcp_metrics_block *tm; 445 struct tcp_metrics_block *tm;
446 u32 val; 446 u32 val, crtt = 0; /* cached RTT scaled by 8 */
447 447
448 if (dst == NULL) 448 if (dst == NULL)
449 goto reset; 449 goto reset;
@@ -478,15 +478,19 @@ void tcp_init_metrics(struct sock *sk)
478 tp->reordering = val; 478 tp->reordering = val;
479 } 479 }
480 480
481 val = tcp_metric_get(tm, TCP_METRIC_RTT); 481 crtt = tcp_metric_get_jiffies(tm, TCP_METRIC_RTT);
482 if (val == 0 || tp->srtt == 0) { 482 rcu_read_unlock();
483 rcu_read_unlock(); 483reset:
484 goto reset; 484 /* The initial RTT measurement from the SYN/SYN-ACK is not ideal
485 } 485 * to seed the RTO for later data packets because SYN packets are
486 /* Initial rtt is determined from SYN,SYN-ACK. 486 * small. Use the per-dst cached values to seed the RTO but keep
487 * The segment is small and rtt may appear much 487 * the RTT estimator variables intact (e.g., srtt, mdev, rttvar).
488 * less than real one. Use per-dst memory 488 * Later the RTO will be updated immediately upon obtaining the first
489 * to make it more realistic. 489 * data RTT sample (tcp_rtt_estimator()). Hence the cached RTT only
490 * influences the first RTO but not later RTT estimation.
491 *
492 * But if RTT is not available from the SYN (due to retransmits or
493 * syn cookies) or the cache, force a conservative 3secs timeout.
490 * 494 *
491 * A bit of theory. RTT is time passed after "normal" sized packet 495 * A bit of theory. RTT is time passed after "normal" sized packet
492 * is sent until it is ACKed. In normal circumstances sending small 496 * is sent until it is ACKed. In normal circumstances sending small
@@ -497,21 +501,9 @@ void tcp_init_metrics(struct sock *sk)
497 * to low value, and then abruptly stops to do it and starts to delay 501 * to low value, and then abruptly stops to do it and starts to delay
498 * ACKs, wait for troubles. 502 * ACKs, wait for troubles.
499 */ 503 */
500 val = msecs_to_jiffies(val); 504 if (crtt > tp->srtt) {
501 if (val > tp->srtt) { 505 inet_csk(sk)->icsk_rto = crtt + max(crtt >> 2, tcp_rto_min(sk));
502 tp->srtt = val; 506 } else if (tp->srtt == 0) {
503 tp->rtt_seq = tp->snd_nxt;
504 }
505 val = tcp_metric_get_jiffies(tm, TCP_METRIC_RTTVAR);
506 if (val > tp->mdev) {
507 tp->mdev = val;
508 tp->mdev_max = tp->rttvar = max(tp->mdev, tcp_rto_min(sk));
509 }
510 rcu_read_unlock();
511
512 tcp_set_rto(sk);
513reset:
514 if (tp->srtt == 0) {
515 /* RFC6298: 5.7 We've failed to get a valid RTT sample from 507 /* RFC6298: 5.7 We've failed to get a valid RTT sample from
516 * 3WHS. This is most likely due to retransmission, 508 * 3WHS. This is most likely due to retransmission,
517 * including spurious one. Reset the RTO back to 3secs 509 * including spurious one. Reset the RTO back to 3secs