tcp: add earliest departure time to SCM_TIMESTAMPING_OPT_STATS
authorYousuk Seung <ysseung@google.com>
Thu, 30 Jul 2020 22:44:40 +0000 (15:44 -0700)
committerDavid S. Miller <davem@davemloft.net>
Sat, 1 Aug 2020 00:00:44 +0000 (17:00 -0700)
This change adds TCP_NLA_EDT to SCM_TIMESTAMPING_OPT_STATS that reports
the earliest departure time(EDT) of the timestamped skb. By tracking EDT
values of the skb from different timestamps, we can observe when and how
much the value changed. This allows to measure the precise delay
injected on the sender host e.g. by a bpf-base throttler.

Signed-off-by: Yousuk Seung <ysseung@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Acked-by: Neal Cardwell <ncardwell@google.com>
Acked-by: Soheil Hassas Yeganeh <soheil@google.com>
Acked-by: Yuchung Cheng <ycheng@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/tcp.h
include/uapi/linux/tcp.h
net/core/skbuff.c
net/ipv4/tcp.c

index 527d668a52758de820bd82b99d312c8eb7c6b07d..14b62d7df94232c72b13bfe08d9b6660a2454d02 100644 (file)
@@ -484,7 +484,8 @@ static inline void tcp_saved_syn_free(struct tcp_sock *tp)
        tp->saved_syn = NULL;
 }
 
-struct sk_buff *tcp_get_timestamping_opt_stats(const struct sock *sk);
+struct sk_buff *tcp_get_timestamping_opt_stats(const struct sock *sk,
+                                              const struct sk_buff *orig_skb);
 
 static inline u16 tcp_mss_clamp(const struct tcp_sock *tp, u16 mss)
 {
index f2acb2566333479ad981a45da8c4e24931dce571..cfcb10b7548382fc295e4d0fd4d03c81522b6475 100644 (file)
@@ -313,6 +313,7 @@ enum {
        TCP_NLA_SRTT,           /* smoothed RTT in usecs */
        TCP_NLA_TIMEOUT_REHASH, /* Timeout-triggered rehash attempts */
        TCP_NLA_BYTES_NOTSENT,  /* Bytes in write queue not yet sent */
+       TCP_NLA_EDT,            /* Earliest departure time (CLOCK_MONOTONIC) */
 };
 
 /* for TCP_MD5SIG socket option */
index b8afefe6f6b697fae630bfe784a81e531a011c47..4e2edfbe0e1936900d4269ef610483fb7d4f3d99 100644 (file)
@@ -4692,7 +4692,7 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb,
                if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS) &&
                    sk->sk_protocol == IPPROTO_TCP &&
                    sk->sk_type == SOCK_STREAM) {
-                       skb = tcp_get_timestamping_opt_stats(sk);
+                       skb = tcp_get_timestamping_opt_stats(sk, orig_skb);
                        opt_stats = true;
                } else
 #endif
index 4afec552f211b95603b1a5ada158e04ceee1c4ab..c06d2bfd2ec46160f23b7869912dbd79e5dcd0dd 100644 (file)
@@ -3501,10 +3501,12 @@ static size_t tcp_opt_stats_get_size(void)
                nla_total_size(sizeof(u32)) + /* TCP_NLA_SRTT */
                nla_total_size(sizeof(u16)) + /* TCP_NLA_TIMEOUT_REHASH */
                nla_total_size(sizeof(u32)) + /* TCP_NLA_BYTES_NOTSENT */
+               nla_total_size_64bit(sizeof(u64)) + /* TCP_NLA_EDT */
                0;
 }
 
-struct sk_buff *tcp_get_timestamping_opt_stats(const struct sock *sk)
+struct sk_buff *tcp_get_timestamping_opt_stats(const struct sock *sk,
+                                              const struct sk_buff *orig_skb)
 {
        const struct tcp_sock *tp = tcp_sk(sk);
        struct sk_buff *stats;
@@ -3558,6 +3560,8 @@ struct sk_buff *tcp_get_timestamping_opt_stats(const struct sock *sk)
        nla_put_u16(stats, TCP_NLA_TIMEOUT_REHASH, tp->timeout_rehash);
        nla_put_u32(stats, TCP_NLA_BYTES_NOTSENT,
                    max_t(int, 0, tp->write_seq - tp->snd_nxt));
+       nla_put_u64_64bit(stats, TCP_NLA_EDT, orig_skb->skb_mstamp_ns,
+                         TCP_NLA_PAD);
 
        return stats;
 }