diff options
-rw-r--r-- | include/net/dst.h | 12 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 31 |
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 */ | ||
132 | static 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 | |||
137 | static 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 | |||
131 | static inline u32 | 143 | static inline u32 |
132 | dst_allfrag(const struct dst_entry *dst) | 144 | dst_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); |