]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
tcp: export packets delivery info
authorYuchung Cheng <ycheng@google.com>
Wed, 18 Apr 2018 06:18:49 +0000 (23:18 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 19 Apr 2018 17:05:16 +0000 (13:05 -0400)
Export data delivered and delivered with CE marks to
1) SNMP TCPDelivered and TCPDeliveredCE
2) getsockopt(TCP_INFO)
3) Timestamping API SOF_TIMESTAMPING_OPT_STATS

Note that for SCM_TSTAMP_ACK, the delivery info in
SOF_TIMESTAMPING_OPT_STATS is reported before the info
was fully updated on the ACK.

These stats help application monitor TCP delivery and ECN status
on per host, per connection, even per message level.

Signed-off-by: Yuchung Cheng <ycheng@google.com>
Reviewed-by: Neal Cardwell <ncardwell@google.com>
Reviewed-by: Soheil Hassas Yeganeh <soheil@google.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/uapi/linux/snmp.h
include/uapi/linux/tcp.h
net/ipv4/proc.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c

index 33a70ece462f00ee2be8c78c552b4471ddce9fcb..d02e859301ff499dd72a1c0e1b56bed10a9397a6 100644 (file)
@@ -276,6 +276,8 @@ enum
        LINUX_MIB_TCPKEEPALIVE,                 /* TCPKeepAlive */
        LINUX_MIB_TCPMTUPFAIL,                  /* TCPMTUPFail */
        LINUX_MIB_TCPMTUPSUCCESS,               /* TCPMTUPSuccess */
+       LINUX_MIB_TCPDELIVERED,                 /* TCPDelivered */
+       LINUX_MIB_TCPDELIVEREDCE,               /* TCPDeliveredCE */
        __LINUX_MIB_MAX
 };
 
index 560374c978f90b6b0269a5c68a82355b2547463f..379b08700a542d49bbce9b4b49b17879d00b69bb 100644 (file)
@@ -224,6 +224,9 @@ struct tcp_info {
        __u64   tcpi_busy_time;      /* Time (usec) busy sending data */
        __u64   tcpi_rwnd_limited;   /* Time (usec) limited by receive window */
        __u64   tcpi_sndbuf_limited; /* Time (usec) limited by send buffer */
+
+       __u32   tcpi_delivered;
+       __u32   tcpi_delivered_ce;
 };
 
 /* netlink attributes types for SCM_TIMESTAMPING_OPT_STATS */
@@ -244,6 +247,8 @@ enum {
        TCP_NLA_SNDQ_SIZE,      /* Data (bytes) pending in send queue */
        TCP_NLA_CA_STATE,       /* ca_state of socket */
        TCP_NLA_SND_SSTHRESH,   /* Slow start size threshold */
+       TCP_NLA_DELIVERED,      /* Data pkts delivered incl. out-of-order */
+       TCP_NLA_DELIVERED_CE,   /* Like above but only ones w/ CE marks */
 
 };
 
index a058de677e947846eb93020e0788148827c8f3cd..261b71d0ccc5c17c6032bf67eb8f842006766e64 100644 (file)
@@ -296,6 +296,8 @@ static const struct snmp_mib snmp4_net_list[] = {
        SNMP_MIB_ITEM("TCPKeepAlive", LINUX_MIB_TCPKEEPALIVE),
        SNMP_MIB_ITEM("TCPMTUPFail", LINUX_MIB_TCPMTUPFAIL),
        SNMP_MIB_ITEM("TCPMTUPSuccess", LINUX_MIB_TCPMTUPSUCCESS),
+       SNMP_MIB_ITEM("TCPDelivered", LINUX_MIB_TCPDELIVERED),
+       SNMP_MIB_ITEM("TCPDeliveredCE", LINUX_MIB_TCPDELIVEREDCE),
        SNMP_MIB_SENTINEL
 };
 
index 5a5ce6da4792b8ce0e90e2a82ff3969b2a0ddde6..4022073b0aeea9d07af0fa825b640a00512908a3 100644 (file)
@@ -3167,6 +3167,8 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
        rate64 = tcp_compute_delivery_rate(tp);
        if (rate64)
                info->tcpi_delivery_rate = rate64;
+       info->tcpi_delivered = tp->delivered;
+       info->tcpi_delivered_ce = tp->delivered_ce;
        unlock_sock_fast(sk, slow);
 }
 EXPORT_SYMBOL_GPL(tcp_get_info);
@@ -3180,7 +3182,7 @@ struct sk_buff *tcp_get_timestamping_opt_stats(const struct sock *sk)
        u32 rate;
 
        stats = alloc_skb(7 * nla_total_size_64bit(sizeof(u64)) +
-                         5 * nla_total_size(sizeof(u32)) +
+                         7 * nla_total_size(sizeof(u32)) +
                          3 * nla_total_size(sizeof(u8)), GFP_ATOMIC);
        if (!stats)
                return NULL;
@@ -3211,9 +3213,12 @@ struct sk_buff *tcp_get_timestamping_opt_stats(const struct sock *sk)
        nla_put_u8(stats, TCP_NLA_RECUR_RETRANS, inet_csk(sk)->icsk_retransmits);
        nla_put_u8(stats, TCP_NLA_DELIVERY_RATE_APP_LMT, !!tp->rate_app_limited);
        nla_put_u32(stats, TCP_NLA_SND_SSTHRESH, tp->snd_ssthresh);
+       nla_put_u32(stats, TCP_NLA_DELIVERED, tp->delivered);
+       nla_put_u32(stats, TCP_NLA_DELIVERED_CE, tp->delivered_ce);
 
        nla_put_u32(stats, TCP_NLA_SNDQ_SIZE, tp->write_seq - tp->snd_una);
        nla_put_u8(stats, TCP_NLA_CA_STATE, inet_csk(sk)->icsk_ca_state);
+
        return stats;
 }
 
index b3bff9c206061e0b77f026106c527b7f743f9b1d..0396fb919b5d5c00b9e5cea95a14a8c45bdb4f76 100644 (file)
@@ -3499,12 +3499,16 @@ static void tcp_xmit_recovery(struct sock *sk, int rexmit)
 /* Returns the number of packets newly acked or sacked by the current ACK */
 static u32 tcp_newly_delivered(struct sock *sk, u32 prior_delivered, int flag)
 {
+       const struct net *net = sock_net(sk);
        struct tcp_sock *tp = tcp_sk(sk);
        u32 delivered;
 
        delivered = tp->delivered - prior_delivered;
-       if (flag & FLAG_ECE)
+       NET_ADD_STATS(net, LINUX_MIB_TCPDELIVERED, delivered);
+       if (flag & FLAG_ECE) {
                tp->delivered_ce += delivered;
+               NET_ADD_STATS(net, LINUX_MIB_TCPDELIVEREDCE, delivered);
+       }
        return delivered;
 }