aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYuchung Cheng <ycheng@google.com>2018-04-18 02:18:49 -0400
committerDavid S. Miller <davem@davemloft.net>2018-04-19 13:05:16 -0400
commitfeb5f2ec646483fb66f9ad7218b1aad2a93a2a5c (patch)
treecc1b3d9495eeab4743e7086ff22a926854d79823
parente21db6f69a95b846ff04e31fe0a86004cbd000d7 (diff)
tcp: export packets delivery info
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>
-rw-r--r--include/uapi/linux/snmp.h2
-rw-r--r--include/uapi/linux/tcp.h5
-rw-r--r--net/ipv4/proc.c2
-rw-r--r--net/ipv4/tcp.c7
-rw-r--r--net/ipv4/tcp_input.c6
5 files changed, 20 insertions, 2 deletions
diff --git a/include/uapi/linux/snmp.h b/include/uapi/linux/snmp.h
index 33a70ece462f..d02e859301ff 100644
--- a/include/uapi/linux/snmp.h
+++ b/include/uapi/linux/snmp.h
@@ -276,6 +276,8 @@ enum
276 LINUX_MIB_TCPKEEPALIVE, /* TCPKeepAlive */ 276 LINUX_MIB_TCPKEEPALIVE, /* TCPKeepAlive */
277 LINUX_MIB_TCPMTUPFAIL, /* TCPMTUPFail */ 277 LINUX_MIB_TCPMTUPFAIL, /* TCPMTUPFail */
278 LINUX_MIB_TCPMTUPSUCCESS, /* TCPMTUPSuccess */ 278 LINUX_MIB_TCPMTUPSUCCESS, /* TCPMTUPSuccess */
279 LINUX_MIB_TCPDELIVERED, /* TCPDelivered */
280 LINUX_MIB_TCPDELIVEREDCE, /* TCPDeliveredCE */
279 __LINUX_MIB_MAX 281 __LINUX_MIB_MAX
280}; 282};
281 283
diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h
index 560374c978f9..379b08700a54 100644
--- a/include/uapi/linux/tcp.h
+++ b/include/uapi/linux/tcp.h
@@ -224,6 +224,9 @@ struct tcp_info {
224 __u64 tcpi_busy_time; /* Time (usec) busy sending data */ 224 __u64 tcpi_busy_time; /* Time (usec) busy sending data */
225 __u64 tcpi_rwnd_limited; /* Time (usec) limited by receive window */ 225 __u64 tcpi_rwnd_limited; /* Time (usec) limited by receive window */
226 __u64 tcpi_sndbuf_limited; /* Time (usec) limited by send buffer */ 226 __u64 tcpi_sndbuf_limited; /* Time (usec) limited by send buffer */
227
228 __u32 tcpi_delivered;
229 __u32 tcpi_delivered_ce;
227}; 230};
228 231
229/* netlink attributes types for SCM_TIMESTAMPING_OPT_STATS */ 232/* netlink attributes types for SCM_TIMESTAMPING_OPT_STATS */
@@ -244,6 +247,8 @@ enum {
244 TCP_NLA_SNDQ_SIZE, /* Data (bytes) pending in send queue */ 247 TCP_NLA_SNDQ_SIZE, /* Data (bytes) pending in send queue */
245 TCP_NLA_CA_STATE, /* ca_state of socket */ 248 TCP_NLA_CA_STATE, /* ca_state of socket */
246 TCP_NLA_SND_SSTHRESH, /* Slow start size threshold */ 249 TCP_NLA_SND_SSTHRESH, /* Slow start size threshold */
250 TCP_NLA_DELIVERED, /* Data pkts delivered incl. out-of-order */
251 TCP_NLA_DELIVERED_CE, /* Like above but only ones w/ CE marks */
247 252
248}; 253};
249 254
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index a058de677e94..261b71d0ccc5 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -296,6 +296,8 @@ static const struct snmp_mib snmp4_net_list[] = {
296 SNMP_MIB_ITEM("TCPKeepAlive", LINUX_MIB_TCPKEEPALIVE), 296 SNMP_MIB_ITEM("TCPKeepAlive", LINUX_MIB_TCPKEEPALIVE),
297 SNMP_MIB_ITEM("TCPMTUPFail", LINUX_MIB_TCPMTUPFAIL), 297 SNMP_MIB_ITEM("TCPMTUPFail", LINUX_MIB_TCPMTUPFAIL),
298 SNMP_MIB_ITEM("TCPMTUPSuccess", LINUX_MIB_TCPMTUPSUCCESS), 298 SNMP_MIB_ITEM("TCPMTUPSuccess", LINUX_MIB_TCPMTUPSUCCESS),
299 SNMP_MIB_ITEM("TCPDelivered", LINUX_MIB_TCPDELIVERED),
300 SNMP_MIB_ITEM("TCPDeliveredCE", LINUX_MIB_TCPDELIVEREDCE),
299 SNMP_MIB_SENTINEL 301 SNMP_MIB_SENTINEL
300}; 302};
301 303
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 5a5ce6da4792..4022073b0aee 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -3167,6 +3167,8 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
3167 rate64 = tcp_compute_delivery_rate(tp); 3167 rate64 = tcp_compute_delivery_rate(tp);
3168 if (rate64) 3168 if (rate64)
3169 info->tcpi_delivery_rate = rate64; 3169 info->tcpi_delivery_rate = rate64;
3170 info->tcpi_delivered = tp->delivered;
3171 info->tcpi_delivered_ce = tp->delivered_ce;
3170 unlock_sock_fast(sk, slow); 3172 unlock_sock_fast(sk, slow);
3171} 3173}
3172EXPORT_SYMBOL_GPL(tcp_get_info); 3174EXPORT_SYMBOL_GPL(tcp_get_info);
@@ -3180,7 +3182,7 @@ struct sk_buff *tcp_get_timestamping_opt_stats(const struct sock *sk)
3180 u32 rate; 3182 u32 rate;
3181 3183
3182 stats = alloc_skb(7 * nla_total_size_64bit(sizeof(u64)) + 3184 stats = alloc_skb(7 * nla_total_size_64bit(sizeof(u64)) +
3183 5 * nla_total_size(sizeof(u32)) + 3185 7 * nla_total_size(sizeof(u32)) +
3184 3 * nla_total_size(sizeof(u8)), GFP_ATOMIC); 3186 3 * nla_total_size(sizeof(u8)), GFP_ATOMIC);
3185 if (!stats) 3187 if (!stats)
3186 return NULL; 3188 return NULL;
@@ -3211,9 +3213,12 @@ struct sk_buff *tcp_get_timestamping_opt_stats(const struct sock *sk)
3211 nla_put_u8(stats, TCP_NLA_RECUR_RETRANS, inet_csk(sk)->icsk_retransmits); 3213 nla_put_u8(stats, TCP_NLA_RECUR_RETRANS, inet_csk(sk)->icsk_retransmits);
3212 nla_put_u8(stats, TCP_NLA_DELIVERY_RATE_APP_LMT, !!tp->rate_app_limited); 3214 nla_put_u8(stats, TCP_NLA_DELIVERY_RATE_APP_LMT, !!tp->rate_app_limited);
3213 nla_put_u32(stats, TCP_NLA_SND_SSTHRESH, tp->snd_ssthresh); 3215 nla_put_u32(stats, TCP_NLA_SND_SSTHRESH, tp->snd_ssthresh);
3216 nla_put_u32(stats, TCP_NLA_DELIVERED, tp->delivered);
3217 nla_put_u32(stats, TCP_NLA_DELIVERED_CE, tp->delivered_ce);
3214 3218
3215 nla_put_u32(stats, TCP_NLA_SNDQ_SIZE, tp->write_seq - tp->snd_una); 3219 nla_put_u32(stats, TCP_NLA_SNDQ_SIZE, tp->write_seq - tp->snd_una);
3216 nla_put_u8(stats, TCP_NLA_CA_STATE, inet_csk(sk)->icsk_ca_state); 3220 nla_put_u8(stats, TCP_NLA_CA_STATE, inet_csk(sk)->icsk_ca_state);
3221
3217 return stats; 3222 return stats;
3218} 3223}
3219 3224
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index b3bff9c20606..0396fb919b5d 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -3499,12 +3499,16 @@ static void tcp_xmit_recovery(struct sock *sk, int rexmit)
3499/* Returns the number of packets newly acked or sacked by the current ACK */ 3499/* Returns the number of packets newly acked or sacked by the current ACK */
3500static u32 tcp_newly_delivered(struct sock *sk, u32 prior_delivered, int flag) 3500static u32 tcp_newly_delivered(struct sock *sk, u32 prior_delivered, int flag)
3501{ 3501{
3502 const struct net *net = sock_net(sk);
3502 struct tcp_sock *tp = tcp_sk(sk); 3503 struct tcp_sock *tp = tcp_sk(sk);
3503 u32 delivered; 3504 u32 delivered;
3504 3505
3505 delivered = tp->delivered - prior_delivered; 3506 delivered = tp->delivered - prior_delivered;
3506 if (flag & FLAG_ECE) 3507 NET_ADD_STATS(net, LINUX_MIB_TCPDELIVERED, delivered);
3508 if (flag & FLAG_ECE) {
3507 tp->delivered_ce += delivered; 3509 tp->delivered_ce += delivered;
3510 NET_ADD_STATS(net, LINUX_MIB_TCPDELIVEREDCE, delivered);
3511 }
3508 return delivered; 3512 return delivered;
3509} 3513}
3510 3514