tcp: Add TCP_INFO counter for packets received out-of-order
authorThomas Higdon <tph@fb.com>
Fri, 13 Sep 2019 23:23:34 +0000 (23:23 +0000)
committerDavid S. Miller <davem@davemloft.net>
Mon, 16 Sep 2019 14:26:11 +0000 (16:26 +0200)
For receive-heavy cases on the server-side, we want to track the
connection quality for individual client IPs. This counter, similar to
the existing system-wide TCPOFOQueue counter in /proc/net/netstat,
tracks out-of-order packet reception. By providing this counter in
TCP_INFO, it will allow understanding to what degree receive-heavy
sockets are experiencing out-of-order delivery and packet drops
indicating congestion.

Please note that this is similar to the counter in NetBSD TCP_INFO, and
has the same name.

Also note that we avoid increasing the size of the tcp_sock struct by
taking advantage of a hole.

Signed-off-by: Thomas Higdon <tph@fb.com>
Acked-by: Neal Cardwell <ncardwell@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/tcp.h
include/uapi/linux/tcp.h
net/ipv4/tcp.c
net/ipv4/tcp_input.c

index f3a85a7fb4b1b527667ee387e187d46701e19443..99617e528ea2906b234cadc1fb3d79d0efd46331 100644 (file)
@@ -354,6 +354,8 @@ struct tcp_sock {
 #define BPF_SOCK_OPS_TEST_FLAG(TP, ARG) 0
 #endif
 
+       u32 rcv_ooopack; /* Received out-of-order packets, for tcpinfo */
+
 /* Receiver side RTT estimation */
        u32 rcv_rtt_last_tsecr;
        struct {
index b3564f85a762fa52b26dcb1c0380e2cee61c7685..20237987ccc825592a7a76ff19b72aa839f88c50 100644 (file)
@@ -270,6 +270,8 @@ struct tcp_info {
        __u64   tcpi_bytes_retrans;  /* RFC4898 tcpEStatsPerfOctetsRetrans */
        __u32   tcpi_dsack_dups;     /* RFC4898 tcpEStatsStackDSACKDups */
        __u32   tcpi_reord_seen;     /* reordering events seen */
+
+       __u32   tcpi_rcv_ooopack;    /* Out-of-order packets received */
 };
 
 /* netlink attributes types for SCM_TIMESTAMPING_OPT_STATS */
index 94df48bcecc25814d92905d81f3c395c8ee970ad..4cf58208270e7253dc427a60d2ec92149f33ff9c 100644 (file)
@@ -2653,6 +2653,7 @@ int tcp_disconnect(struct sock *sk, int flags)
        tp->rx_opt.saw_tstamp = 0;
        tp->rx_opt.dsack = 0;
        tp->rx_opt.num_sacks = 0;
+       tp->rcv_ooopack = 0;
 
 
        /* Clean up fastopen related fields */
@@ -3295,6 +3296,7 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
        info->tcpi_bytes_retrans = tp->bytes_retrans;
        info->tcpi_dsack_dups = tp->dsack_dups;
        info->tcpi_reord_seen = tp->reord_seen;
+       info->tcpi_rcv_ooopack = tp->rcv_ooopack;
        unlock_sock_fast(sk, slow);
 }
 EXPORT_SYMBOL_GPL(tcp_get_info);
index 7e94223fdb2b41311b7c9940763435bb3a26d68b..3578357abe30e92f818e5b9acf3317be1d997af5 100644 (file)
@@ -4555,6 +4555,7 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb)
        tp->pred_flags = 0;
        inet_csk_schedule_ack(sk);
 
+       tp->rcv_ooopack += max_t(u16, 1, skb_shinfo(skb)->gso_segs);
        NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPOFOQUEUE);
        seq = TCP_SKB_CB(skb)->seq;
        end_seq = TCP_SKB_CB(skb)->end_seq;