Skip to content

Commit eb8329e

Browse files
yuchungchengdavem330
authored andcommitted
tcp: export data delivery rate
This commit export two new fields in struct tcp_info: tcpi_delivery_rate: The most recent goodput, as measured by tcp_rate_gen(). If the socket is limited by the sending application (e.g., no data to send), it reports the highest measurement instead of the most recent. The unit is bytes per second (like other rate fields in tcp_info). tcpi_delivery_rate_app_limited: A boolean indicating if the goodput was measured when the socket's throughput was limited by the sending application. This delivery rate information can be useful for applications that want to know the current throughput the TCP connection is seeing, e.g. adaptive bitrate video streaming. It can also be very useful for debugging or troubleshooting. Signed-off-by: Van Jacobson <[email protected]> Signed-off-by: Neal Cardwell <[email protected]> Signed-off-by: Yuchung Cheng <[email protected]> Signed-off-by: Nandita Dukkipati <[email protected]> Signed-off-by: Eric Dumazet <[email protected]> Signed-off-by: Soheil Hassas Yeganeh <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d7722e8 commit eb8329e

File tree

4 files changed

+28
-3
lines changed

4 files changed

+28
-3
lines changed

include/linux/tcp.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,8 @@ struct tcp_sock {
213213
u8 reord; /* reordering detected */
214214
} rack;
215215
u16 advmss; /* Advertised MSS */
216-
u8 unused;
216+
u8 rate_app_limited:1, /* rate_{delivered,interval_us} limited? */
217+
unused:7;
217218
u8 nonagle : 4,/* Disable Nagle algorithm? */
218219
thin_lto : 1,/* Use linear timeouts for thin streams */
219220
thin_dupack : 1,/* Fast retransmit on first dupack */
@@ -271,6 +272,8 @@ struct tcp_sock {
271272
u32 app_limited; /* limited until "delivered" reaches this val */
272273
struct skb_mstamp first_tx_mstamp; /* start of window send phase */
273274
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 */
274277

275278
u32 rcv_wnd; /* Current receiver window */
276279
u32 write_seq; /* Tail(+1) of data held in tcp send buffer */

include/uapi/linux/tcp.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ struct tcp_info {
167167
__u8 tcpi_backoff;
168168
__u8 tcpi_options;
169169
__u8 tcpi_snd_wscale : 4, tcpi_rcv_wscale : 4;
170+
__u8 tcpi_delivery_rate_app_limited:1;
170171

171172
__u32 tcpi_rto;
172173
__u32 tcpi_ato;
@@ -211,6 +212,8 @@ struct tcp_info {
211212
__u32 tcpi_min_rtt;
212213
__u32 tcpi_data_segs_in; /* RFC4898 tcpEStatsDataSegsIn */
213214
__u32 tcpi_data_segs_out; /* RFC4898 tcpEStatsDataSegsOut */
215+
216+
__u64 tcpi_delivery_rate;
214217
};
215218

216219
/* for TCP_MD5SIG socket option */

net/ipv4/tcp.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2712,7 +2712,7 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
27122712
{
27132713
const struct tcp_sock *tp = tcp_sk(sk); /* iff sk_type == SOCK_STREAM */
27142714
const struct inet_connection_sock *icsk = inet_csk(sk);
2715-
u32 now = tcp_time_stamp;
2715+
u32 now = tcp_time_stamp, intv;
27162716
unsigned int start;
27172717
int notsent_bytes;
27182718
u64 rate64;
@@ -2802,6 +2802,15 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
28022802
info->tcpi_min_rtt = tcp_min_rtt(tp);
28032803
info->tcpi_data_segs_in = tp->data_segs_in;
28042804
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+
}
28052814
}
28062815
EXPORT_SYMBOL_GPL(tcp_get_info);
28072816

net/ipv4/tcp_rate.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,12 +149,22 @@ void tcp_rate_gen(struct sock *sk, u32 delivered, u32 lost,
149149
* for connections suffer heavy or prolonged losses.
150150
*/
151151
if (unlikely(rs->interval_us < tcp_min_rtt(tp))) {
152-
rs->interval_us = -1;
153152
if (!rs->is_retrans)
154153
pr_debug("tcp rate: %ld %d %u %u %u\n",
155154
rs->interval_us, rs->delivered,
156155
inet_csk(sk)->icsk_ca_state,
157156
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;
158168
}
159169
}
160170

0 commit comments

Comments
 (0)