aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/dst.h12
-rw-r--r--net/ipv4/tcp_input.c31
2 files changed, 30 insertions, 13 deletions
diff --git a/include/net/dst.h b/include/net/dst.h
index 002500e631f5..c5c318a628f8 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -128,6 +128,18 @@ static inline u32 dst_mtu(const struct dst_entry *dst)
128 return mtu; 128 return mtu;
129} 129}
130 130
131/* RTT metrics are stored in milliseconds for user ABI, but used as jiffies */
132static inline unsigned long dst_metric_rtt(const struct dst_entry *dst, int metric)
133{
134 return msecs_to_jiffies(dst_metric(dst, metric));
135}
136
137static inline void set_dst_metric_rtt(struct dst_entry *dst, int metric,
138 unsigned long rtt)
139{
140 dst->metrics[metric-1] = jiffies_to_msecs(rtt);
141}
142
131static inline u32 143static inline u32
132dst_allfrag(const struct dst_entry *dst) 144dst_allfrag(const struct dst_entry *dst)
133{ 145{
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index fac49a6e1611..88810bc01370 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -602,7 +602,7 @@ static u32 tcp_rto_min(struct sock *sk)
602 u32 rto_min = TCP_RTO_MIN; 602 u32 rto_min = TCP_RTO_MIN;
603 603
604 if (dst && dst_metric_locked(dst, RTAX_RTO_MIN)) 604 if (dst && dst_metric_locked(dst, RTAX_RTO_MIN))
605 rto_min = dst_metric(dst, RTAX_RTO_MIN); 605 rto_min = dst_metric_rtt(dst, RTAX_RTO_MIN);
606 return rto_min; 606 return rto_min;
607} 607}
608 608
@@ -729,6 +729,7 @@ void tcp_update_metrics(struct sock *sk)
729 if (dst && (dst->flags & DST_HOST)) { 729 if (dst && (dst->flags & DST_HOST)) {
730 const struct inet_connection_sock *icsk = inet_csk(sk); 730 const struct inet_connection_sock *icsk = inet_csk(sk);
731 int m; 731 int m;
732 unsigned long rtt;
732 733
733 if (icsk->icsk_backoff || !tp->srtt) { 734 if (icsk->icsk_backoff || !tp->srtt) {
734 /* This session failed to estimate rtt. Why? 735 /* This session failed to estimate rtt. Why?
@@ -740,7 +741,8 @@ void tcp_update_metrics(struct sock *sk)
740 return; 741 return;
741 } 742 }
742 743
743 m = dst_metric(dst, RTAX_RTT) - tp->srtt; 744 rtt = dst_metric_rtt(dst, RTAX_RTT);
745 m = rtt - tp->srtt;
744 746
745 /* If newly calculated rtt larger than stored one, 747 /* If newly calculated rtt larger than stored one,
746 * store new one. Otherwise, use EWMA. Remember, 748 * store new one. Otherwise, use EWMA. Remember,
@@ -748,12 +750,13 @@ void tcp_update_metrics(struct sock *sk)
748 */ 750 */
749 if (!(dst_metric_locked(dst, RTAX_RTT))) { 751 if (!(dst_metric_locked(dst, RTAX_RTT))) {
750 if (m <= 0) 752 if (m <= 0)
751 dst->metrics[RTAX_RTT - 1] = tp->srtt; 753 set_dst_metric_rtt(dst, RTAX_RTT, tp->srtt);
752 else 754 else
753 dst->metrics[RTAX_RTT - 1] -= (m >> 3); 755 set_dst_metric_rtt(dst, RTAX_RTT, rtt - (m >> 3));
754 } 756 }
755 757
756 if (!(dst_metric_locked(dst, RTAX_RTTVAR))) { 758 if (!(dst_metric_locked(dst, RTAX_RTTVAR))) {
759 unsigned long var;
757 if (m < 0) 760 if (m < 0)
758 m = -m; 761 m = -m;
759 762
@@ -762,11 +765,13 @@ void tcp_update_metrics(struct sock *sk)
762 if (m < tp->mdev) 765 if (m < tp->mdev)
763 m = tp->mdev; 766 m = tp->mdev;
764 767
765 if (m >= dst_metric(dst, RTAX_RTTVAR)) 768 var = dst_metric_rtt(dst, RTAX_RTTVAR);
766 dst->metrics[RTAX_RTTVAR - 1] = m; 769 if (m >= var)
770 var = m;
767 else 771 else
768 dst->metrics[RTAX_RTTVAR-1] -= 772 var -= (var - m) >> 2;
769 (dst_metric(dst, RTAX_RTTVAR) - m)>>2; 773
774 set_dst_metric_rtt(dst, RTAX_RTTVAR, var);
770 } 775 }
771 776
772 if (tp->snd_ssthresh >= 0xFFFF) { 777 if (tp->snd_ssthresh >= 0xFFFF) {
@@ -897,7 +902,7 @@ static void tcp_init_metrics(struct sock *sk)
897 if (dst_metric(dst, RTAX_RTT) == 0) 902 if (dst_metric(dst, RTAX_RTT) == 0)
898 goto reset; 903 goto reset;
899 904
900 if (!tp->srtt && dst_metric(dst, RTAX_RTT) < (TCP_TIMEOUT_INIT << 3)) 905 if (!tp->srtt && dst_metric_rtt(dst, RTAX_RTT) < (TCP_TIMEOUT_INIT << 3))
901 goto reset; 906 goto reset;
902 907
903 /* Initial rtt is determined from SYN,SYN-ACK. 908 /* Initial rtt is determined from SYN,SYN-ACK.
@@ -914,12 +919,12 @@ static void tcp_init_metrics(struct sock *sk)
914 * to low value, and then abruptly stops to do it and starts to delay 919 * to low value, and then abruptly stops to do it and starts to delay
915 * ACKs, wait for troubles. 920 * ACKs, wait for troubles.
916 */ 921 */
917 if (dst_metric(dst, RTAX_RTT) > tp->srtt) { 922 if (dst_metric_rtt(dst, RTAX_RTT) > tp->srtt) {
918 tp->srtt = dst_metric(dst, RTAX_RTT); 923 tp->srtt = dst_metric_rtt(dst, RTAX_RTT);
919 tp->rtt_seq = tp->snd_nxt; 924 tp->rtt_seq = tp->snd_nxt;
920 } 925 }
921 if (dst_metric(dst, RTAX_RTTVAR) > tp->mdev) { 926 if (dst_metric_rtt(dst, RTAX_RTTVAR) > tp->mdev) {
922 tp->mdev = dst_metric(dst, RTAX_RTTVAR); 927 tp->mdev = dst_metric_rtt(dst, RTAX_RTTVAR);
923 tp->mdev_max = tp->rttvar = max(tp->mdev, tcp_rto_min(sk)); 928 tp->mdev_max = tp->rttvar = max(tp->mdev, tcp_rto_min(sk));
924 } 929 }
925 tcp_set_rto(sk); 930 tcp_set_rto(sk);