tcp: add tcpi_bytes_received to tcp_info
authorEric Dumazet <edumazet@google.com>
Tue, 28 Apr 2015 22:28:18 +0000 (15:28 -0700)
committerDanny Wood <danwood76@gmail.com>
Thu, 15 Jul 2021 09:45:36 +0000 (10:45 +0100)
This patch tracks total number of payload bytes received on a TCP socket.
This is the sum of all changes done to tp->rcv_nxt

RFC4898 named this : tcpEStatsAppHCThruOctetsReceived

This is a 64bit field, and can be fetched both from TCP_INFO
getsockopt() if one has a handle on a TCP socket, or from inet_diag
netlink facility (iproute2/ss patch will follow)

Note that tp->bytes_received was placed near tp->rcv_nxt for
best data locality and minimal performance impact.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Yuchung Cheng <ycheng@google.com>
Cc: Matt Mathis <mattmathis@google.com>
Cc: Eric Salo <salo@google.com>
Cc: Martin Lau <kafai@fb.com>
Cc: Chris Rapier <rapier@psc.edu>
Acked-by: Yuchung Cheng <ycheng@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Change-Id: Ieaf3d4c7d1bea0ac8906cc0702bc22c73314c889

include/linux/tcp.h
include/uapi/linux/tcp.h
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c

index 2f020e2f7e527ca63c594776c38ae4fd6f5b0b35..9e43ae2a972b38fab2a2fb3dbb001b96c876b6fe 100644 (file)
@@ -148,6 +148,10 @@ struct tcp_sock {
  *     read the code and the spec side by side (and laugh ...)
  *     See RFC793 and RFC1122. The RFC writes these in capitals.
  */
+       u64     bytes_received; /* RFC4898 tcpEStatsAppHCThruOctetsReceived
+                                * sum(delta(rcv_nxt)), or how many bytes
+                                * were acked.
+                                */
        u32     rcv_nxt;        /* What we want to receive next         */
        u32     copied_seq;     /* Head of yet unread data              */
        u32     rcv_wup;        /* rcv_nxt on last window update sent   */
index 6ff507835e4c3b588cbb4ee1225c70d1a1953353..2028627fd75ce44ff5efe5e2bf9d7ea95738ce08 100644 (file)
@@ -189,6 +189,7 @@ struct tcp_info {
        __u64   tcpi_pacing_rate;
        __u64   tcpi_max_pacing_rate;
        __u64   tcpi_bytes_acked; /* RFC4898 tcpEStatsAppHCThruOctetsAcked */
+       __u64   tcpi_bytes_received; /* RFC4898 tcpEStatsAppHCThruOctetsReceived */
 };
 
 /* for TCP_MD5SIG socket option */
index d6a8ccacab6103927e3a17d4bd357716d22ef9e0..42e4a00f4328b6d00473ab8bc9055f09430c7f4b 100644 (file)
@@ -2778,6 +2778,7 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
 
        spin_lock_bh(&sk->sk_lock.slock);
        info->tcpi_bytes_acked = tp->bytes_acked;
+       info->tcpi_bytes_received = tp->bytes_received;
        spin_unlock_bh(&sk->sk_lock.slock);
 }
 EXPORT_SYMBOL_GPL(tcp_get_info);
index eb19bd3bea94256c4973824da085fe877cbcd930..ac7d718c1ae7a6fa60dcdcfcc72c082fac7c090b 100644 (file)
@@ -3257,6 +3257,15 @@ static void tcp_snd_una_update(struct tcp_sock *tp, u32 ack)
        tp->snd_una = ack;
 }
 
+/* If we update tp->rcv_nxt, also update tp->bytes_received */
+static void tcp_rcv_nxt_update(struct tcp_sock *tp, u32 seq)
+{
+       u32 delta = seq - tp->rcv_nxt;
+
+       tp->bytes_received += delta;
+       tp->rcv_nxt = seq;
+}
+
 /* Update our send window.
  *
  * Window update algorithm, described in RFC793/RFC1122 (used in linux-2.2
@@ -4102,7 +4111,7 @@ static void tcp_ofo_queue(struct sock *sk)
 
                __skb_unlink(skb, &tp->out_of_order_queue);
                __skb_queue_tail(&sk->sk_receive_queue, skb);
-               tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+               tcp_rcv_nxt_update(tp, TCP_SKB_CB(skb)->end_seq);
                if (tcp_hdr(skb)->fin)
                        tcp_fin(sk);
        }
@@ -4304,7 +4313,7 @@ static int __must_check tcp_queue_rcv(struct sock *sk, struct sk_buff *skb, int
        __skb_pull(skb, hdrlen);
        eaten = (tail &&
                 tcp_try_coalesce(sk, tail, skb, fragstolen)) ? 1 : 0;
-       tcp_sk(sk)->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+       tcp_rcv_nxt_update(tcp_sk(sk), TCP_SKB_CB(skb)->end_seq);
        if (!eaten) {
                __skb_queue_tail(&sk->sk_receive_queue, skb);
                skb_set_owner_r(skb, sk);
@@ -4403,7 +4412,7 @@ queue_and_out:
 
                        eaten = tcp_queue_rcv(sk, skb, 0, &fragstolen);
                }
-               tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+               tcp_rcv_nxt_update(tp, TCP_SKB_CB(skb)->end_seq);
                if (skb->len)
                        tcp_event_data_recv(sk, skb);
                if (th->fin)
@@ -5257,7 +5266,7 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
                                        tcp_rcv_rtt_measure_ts(sk, skb);
 
                                        __skb_pull(skb, tcp_header_len);
-                                       tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+                                       tcp_rcv_nxt_update(tp, TCP_SKB_CB(skb)->end_seq);
                                        NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPHPHITSTOUSER);
                                }
                                if (copied_early)
index 3110456f3eeaa09ac1fa8b085918cdf58be017ae..64800d40a358976daaae6bb3fb15c8269c0399c6 100644 (file)
@@ -1467,6 +1467,7 @@ static int tcp_v4_conn_req_fastopen(struct sock *sk,
                __skb_queue_tail(&child->sk_receive_queue, skb);
                tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
                tp->syn_data_acked = 1;
+               tp->bytes_received = TCP_SKB_CB(skb)->end_seq - TCP_SKB_CB(skb)->seq - 1;
        }
        sk->sk_data_ready(sk);
        bh_unlock_sock(child);