diff options
-rw-r--r-- | include/linux/tcp.h | 5 | ||||
-rw-r--r-- | include/uapi/linux/tcp.h | 3 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 11 | ||||
-rw-r--r-- | net/ipv4/tcp_rate.c | 12 |
4 files changed, 28 insertions, 3 deletions
diff --git a/include/linux/tcp.h b/include/linux/tcp.h index fdcd00ffcb66..a17ae7b85218 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h | |||
@@ -213,7 +213,8 @@ struct tcp_sock { | |||
213 | u8 reord; /* reordering detected */ | 213 | u8 reord; /* reordering detected */ |
214 | } rack; | 214 | } rack; |
215 | u16 advmss; /* Advertised MSS */ | 215 | u16 advmss; /* Advertised MSS */ |
216 | u8 unused; | 216 | u8 rate_app_limited:1, /* rate_{delivered,interval_us} limited? */ |
217 | unused:7; | ||
217 | u8 nonagle : 4,/* Disable Nagle algorithm? */ | 218 | u8 nonagle : 4,/* Disable Nagle algorithm? */ |
218 | thin_lto : 1,/* Use linear timeouts for thin streams */ | 219 | thin_lto : 1,/* Use linear timeouts for thin streams */ |
219 | thin_dupack : 1,/* Fast retransmit on first dupack */ | 220 | thin_dupack : 1,/* Fast retransmit on first dupack */ |
@@ -271,6 +272,8 @@ struct tcp_sock { | |||
271 | u32 app_limited; /* limited until "delivered" reaches this val */ | 272 | u32 app_limited; /* limited until "delivered" reaches this val */ |
272 | struct skb_mstamp first_tx_mstamp; /* start of window send phase */ | 273 | struct skb_mstamp first_tx_mstamp; /* start of window send phase */ |
273 | struct skb_mstamp delivered_mstamp; /* time we reached "delivered" */ | 274 | struct skb_mstamp delivered_mstamp; /* time we reached "delivered" */ |
275 | u32 rate_delivered; /* saved rate sample: packets delivered */ | ||
276 | u32 rate_interval_us; /* saved rate sample: time elapsed */ | ||
274 | 277 | ||
275 | u32 rcv_wnd; /* Current receiver window */ | 278 | u32 rcv_wnd; /* Current receiver window */ |
276 | u32 write_seq; /* Tail(+1) of data held in tcp send buffer */ | 279 | u32 write_seq; /* Tail(+1) of data held in tcp send buffer */ |
diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h index 482898fc433a..73ac0db487f8 100644 --- a/include/uapi/linux/tcp.h +++ b/include/uapi/linux/tcp.h | |||
@@ -167,6 +167,7 @@ struct tcp_info { | |||
167 | __u8 tcpi_backoff; | 167 | __u8 tcpi_backoff; |
168 | __u8 tcpi_options; | 168 | __u8 tcpi_options; |
169 | __u8 tcpi_snd_wscale : 4, tcpi_rcv_wscale : 4; | 169 | __u8 tcpi_snd_wscale : 4, tcpi_rcv_wscale : 4; |
170 | __u8 tcpi_delivery_rate_app_limited:1; | ||
170 | 171 | ||
171 | __u32 tcpi_rto; | 172 | __u32 tcpi_rto; |
172 | __u32 tcpi_ato; | 173 | __u32 tcpi_ato; |
@@ -211,6 +212,8 @@ struct tcp_info { | |||
211 | __u32 tcpi_min_rtt; | 212 | __u32 tcpi_min_rtt; |
212 | __u32 tcpi_data_segs_in; /* RFC4898 tcpEStatsDataSegsIn */ | 213 | __u32 tcpi_data_segs_in; /* RFC4898 tcpEStatsDataSegsIn */ |
213 | __u32 tcpi_data_segs_out; /* RFC4898 tcpEStatsDataSegsOut */ | 214 | __u32 tcpi_data_segs_out; /* RFC4898 tcpEStatsDataSegsOut */ |
215 | |||
216 | __u64 tcpi_delivery_rate; | ||
214 | }; | 217 | }; |
215 | 218 | ||
216 | /* for TCP_MD5SIG socket option */ | 219 | /* for TCP_MD5SIG socket option */ |
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 | ||