diff options
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/tcp.c | 11 | ||||
-rw-r--r-- | net/ipv4/tcp_rate.c | 12 |
2 files changed, 21 insertions, 2 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 2250f891f931..f253e5019d22 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -2712,7 +2712,7 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info) | |||
2712 | { | 2712 | { |
2713 | const struct tcp_sock *tp = tcp_sk(sk); /* iff sk_type == SOCK_STREAM */ | 2713 | const struct tcp_sock *tp = tcp_sk(sk); /* iff sk_type == SOCK_STREAM */ |
2714 | const struct inet_connection_sock *icsk = inet_csk(sk); | 2714 | const struct inet_connection_sock *icsk = inet_csk(sk); |
2715 | u32 now = tcp_time_stamp; | 2715 | u32 now = tcp_time_stamp, intv; |
2716 | unsigned int start; | 2716 | unsigned int start; |
2717 | int notsent_bytes; | 2717 | int notsent_bytes; |
2718 | u64 rate64; | 2718 | u64 rate64; |
@@ -2802,6 +2802,15 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info) | |||
2802 | info->tcpi_min_rtt = tcp_min_rtt(tp); | 2802 | info->tcpi_min_rtt = tcp_min_rtt(tp); |
2803 | info->tcpi_data_segs_in = tp->data_segs_in; | 2803 | info->tcpi_data_segs_in = tp->data_segs_in; |
2804 | info->tcpi_data_segs_out = tp->data_segs_out; | 2804 | info->tcpi_data_segs_out = tp->data_segs_out; |
2805 | |||
2806 | info->tcpi_delivery_rate_app_limited = tp->rate_app_limited ? 1 : 0; | ||
2807 | rate = READ_ONCE(tp->rate_delivered); | ||
2808 | intv = READ_ONCE(tp->rate_interval_us); | ||
2809 | if (rate && intv) { | ||
2810 | rate64 = (u64)rate * tp->mss_cache * USEC_PER_SEC; | ||
2811 | do_div(rate64, intv); | ||
2812 | put_unaligned(rate64, &info->tcpi_delivery_rate); | ||
2813 | } | ||
2805 | } | 2814 | } |
2806 | EXPORT_SYMBOL_GPL(tcp_get_info); | 2815 | EXPORT_SYMBOL_GPL(tcp_get_info); |
2807 | 2816 | ||
diff --git a/net/ipv4/tcp_rate.c b/net/ipv4/tcp_rate.c index 52ff84be59ab..9be1581a5a08 100644 --- a/net/ipv4/tcp_rate.c +++ b/net/ipv4/tcp_rate.c | |||
@@ -149,12 +149,22 @@ void tcp_rate_gen(struct sock *sk, u32 delivered, u32 lost, | |||
149 | * for connections suffer heavy or prolonged losses. | 149 | * for connections suffer heavy or prolonged losses. |
150 | */ | 150 | */ |
151 | if (unlikely(rs->interval_us < tcp_min_rtt(tp))) { | 151 | if (unlikely(rs->interval_us < tcp_min_rtt(tp))) { |
152 | rs->interval_us = -1; | ||
153 | if (!rs->is_retrans) | 152 | if (!rs->is_retrans) |
154 | pr_debug("tcp rate: %ld %d %u %u %u\n", | 153 | pr_debug("tcp rate: %ld %d %u %u %u\n", |
155 | rs->interval_us, rs->delivered, | 154 | rs->interval_us, rs->delivered, |
156 | inet_csk(sk)->icsk_ca_state, | 155 | inet_csk(sk)->icsk_ca_state, |
157 | tp->rx_opt.sack_ok, tcp_min_rtt(tp)); | 156 | tp->rx_opt.sack_ok, tcp_min_rtt(tp)); |
157 | rs->interval_us = -1; | ||
158 | return; | ||
159 | } | ||
160 | |||
161 | /* Record the last non-app-limited or the highest app-limited bw */ | ||
162 | if (!rs->is_app_limited || | ||
163 | ((u64)rs->delivered * tp->rate_interval_us >= | ||
164 | (u64)tp->rate_delivered * rs->interval_us)) { | ||
165 | tp->rate_delivered = rs->delivered; | ||
166 | tp->rate_interval_us = rs->interval_us; | ||
167 | tp->rate_app_limited = rs->is_app_limited; | ||
158 | } | 168 | } |
159 | } | 169 | } |
160 | 170 | ||