Skip to content

Commit 0f87230

Browse files
francisyyandavem330
authored andcommitted
tcp: instrument how long TCP is busy sending
This patch measures TCP busy time, which is defined as the period of time when sender has data (or FIN) to send. The time starts when data is buffered and stops when the write queue is flushed by ACKs or error events. Note the busy time does not include SYN time, unless data is included in SYN (i.e. Fast Open). It does include FIN time even if the FIN carries no payload. Excluding pure FIN is possible but would incur one additional test in the fast path, which may not be worth it. Signed-off-by: Francis Yan <francisyyan@gmail.com> Signed-off-by: Yuchung Cheng <ycheng@google.com> Signed-off-by: Soheil Hassas Yeganeh <soheil@google.com> Acked-by: Neal Cardwell <ncardwell@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 05b055e commit 0f87230

File tree

3 files changed

+24
-4
lines changed

3 files changed

+24
-4
lines changed

include/net/tcp.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1535,6 +1535,7 @@ static inline void tcp_write_queue_purge(struct sock *sk)
15351535
{
15361536
struct sk_buff *skb;
15371537

1538+
tcp_chrono_stop(sk, TCP_CHRONO_BUSY);
15381539
while ((skb = __skb_dequeue(&sk->sk_write_queue)) != NULL)
15391540
sk_wmem_free_skb(sk, skb);
15401541
sk_mem_reclaim(sk);
@@ -1593,8 +1594,10 @@ static inline void tcp_advance_send_head(struct sock *sk, const struct sk_buff *
15931594

15941595
static inline void tcp_check_send_head(struct sock *sk, struct sk_buff *skb_unlinked)
15951596
{
1596-
if (sk->sk_send_head == skb_unlinked)
1597+
if (sk->sk_send_head == skb_unlinked) {
15971598
sk->sk_send_head = NULL;
1599+
tcp_chrono_stop(sk, TCP_CHRONO_BUSY);
1600+
}
15981601
if (tcp_sk(sk)->highest_sack == skb_unlinked)
15991602
tcp_sk(sk)->highest_sack = NULL;
16001603
}
@@ -1616,6 +1619,7 @@ static inline void tcp_add_write_queue_tail(struct sock *sk, struct sk_buff *skb
16161619
/* Queue it, remembering where we must start sending. */
16171620
if (sk->sk_send_head == NULL) {
16181621
sk->sk_send_head = skb;
1622+
tcp_chrono_start(sk, TCP_CHRONO_BUSY);
16191623

16201624
if (tcp_sk(sk)->highest_sack == NULL)
16211625
tcp_sk(sk)->highest_sack = skb;

net/ipv4/tcp_input.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3178,6 +3178,9 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
31783178
tp->lost_skb_hint = NULL;
31793179
}
31803180

3181+
if (!skb)
3182+
tcp_chrono_stop(sk, TCP_CHRONO_BUSY);
3183+
31813184
if (likely(between(tp->snd_up, prior_snd_una, tp->snd_una)))
31823185
tp->snd_up = tp->snd_una;
31833186

net/ipv4/tcp_output.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2096,8 +2096,8 @@ void tcp_chrono_start(struct sock *sk, const enum tcp_chrono type)
20962096
struct tcp_sock *tp = tcp_sk(sk);
20972097

20982098
/* If there are multiple conditions worthy of tracking in a
2099-
* chronograph then the highest priority enum takes precedence over
2100-
* the other conditions. So that if something "more interesting"
2099+
* chronograph then the highest priority enum takes precedence
2100+
* over the other conditions. So that if something "more interesting"
21012101
* starts happening, stop the previous chrono and start a new one.
21022102
*/
21032103
if (type > tp->chrono_type)
@@ -2108,7 +2108,18 @@ void tcp_chrono_stop(struct sock *sk, const enum tcp_chrono type)
21082108
{
21092109
struct tcp_sock *tp = tcp_sk(sk);
21102110

2111-
tcp_chrono_set(tp, TCP_CHRONO_UNSPEC);
2111+
2112+
/* There are multiple conditions worthy of tracking in a
2113+
* chronograph, so that the highest priority enum takes
2114+
* precedence over the other conditions (see tcp_chrono_start).
2115+
* If a condition stops, we only stop chrono tracking if
2116+
* it's the "most interesting" or current chrono we are
2117+
* tracking and starts busy chrono if we have pending data.
2118+
*/
2119+
if (tcp_write_queue_empty(sk))
2120+
tcp_chrono_set(tp, TCP_CHRONO_UNSPEC);
2121+
else if (type == tp->chrono_type)
2122+
tcp_chrono_set(tp, TCP_CHRONO_BUSY);
21122123
}
21132124

21142125
/* This routine writes packets to the network. It advances the
@@ -3328,6 +3339,8 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn)
33283339
fo->copied = space;
33293340

33303341
tcp_connect_queue_skb(sk, syn_data);
3342+
if (syn_data->len)
3343+
tcp_chrono_start(sk, TCP_CHRONO_BUSY);
33313344

33323345
err = tcp_transmit_skb(sk, syn_data, 1, sk->sk_allocation);
33333346

0 commit comments

Comments
 (0)