aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-08-01 12:56:11 -0400
committerDavid S. Miller <davem@davemloft.net>2018-08-01 12:56:11 -0400
commitfab9593df10691b02da99b5ce9ed6930c020eedc (patch)
tree5debcce08aca141b24d1a5c9875d73cae07f3394 /net
parent53dd9652b5f530da2739298025c8324b6a4d0f21 (diff)
parent7ec65372ca534217b53fd208500cf7aac223a383 (diff)
Merge branch 'tcp-add-4-new-stats'
Wei Wang says: ==================== tcp: add 4 new stats This patch series adds 3 RFC4898 stats: 1. tcpEStatsPerfHCDataOctetsOut 2. tcpEStatsPerfOctetsRetrans 3. tcpEStatsStackDSACKDups and an addtional stat to record the number of data packet reordering events seen: 4. tcp_reord_seen Together with the existing stats, application can use them to measure the retransmission rate in bytes, exclude spurious retransmissions reflected by DSACK, and keep track of the reordering events on live connections. In particular the networks with different MTUs make bytes-based loss stats more useful. Google servers have been using these stats for many years to instrument transport and network performance. Note: The first patch is a refactor to add a helper to calculate opt_stats size in order to make later changes cleaner. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/tcp.c46
-rw-r--r--net/ipv4/tcp_input.c4
-rw-r--r--net/ipv4/tcp_output.c2
-rw-r--r--net/ipv4/tcp_recovery.c2
4 files changed, 49 insertions, 5 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index f3bfb9f29520..31fa1c080f28 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2594,6 +2594,10 @@ int tcp_disconnect(struct sock *sk, int flags)
2594 sk->sk_rx_dst = NULL; 2594 sk->sk_rx_dst = NULL;
2595 tcp_saved_syn_free(tp); 2595 tcp_saved_syn_free(tp);
2596 tp->compressed_ack = 0; 2596 tp->compressed_ack = 0;
2597 tp->bytes_sent = 0;
2598 tp->bytes_retrans = 0;
2599 tp->dsack_dups = 0;
2600 tp->reord_seen = 0;
2597 2601
2598 /* Clean up fastopen related fields */ 2602 /* Clean up fastopen related fields */
2599 tcp_free_fastopen_req(tp); 2603 tcp_free_fastopen_req(tp);
@@ -3201,10 +3205,41 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
3201 info->tcpi_delivery_rate = rate64; 3205 info->tcpi_delivery_rate = rate64;
3202 info->tcpi_delivered = tp->delivered; 3206 info->tcpi_delivered = tp->delivered;
3203 info->tcpi_delivered_ce = tp->delivered_ce; 3207 info->tcpi_delivered_ce = tp->delivered_ce;
3208 info->tcpi_bytes_sent = tp->bytes_sent;
3209 info->tcpi_bytes_retrans = tp->bytes_retrans;
3210 info->tcpi_dsack_dups = tp->dsack_dups;
3211 info->tcpi_reord_seen = tp->reord_seen;
3204 unlock_sock_fast(sk, slow); 3212 unlock_sock_fast(sk, slow);
3205} 3213}
3206EXPORT_SYMBOL_GPL(tcp_get_info); 3214EXPORT_SYMBOL_GPL(tcp_get_info);
3207 3215
3216static size_t tcp_opt_stats_get_size(void)
3217{
3218 return
3219 nla_total_size_64bit(sizeof(u64)) + /* TCP_NLA_BUSY */
3220 nla_total_size_64bit(sizeof(u64)) + /* TCP_NLA_RWND_LIMITED */
3221 nla_total_size_64bit(sizeof(u64)) + /* TCP_NLA_SNDBUF_LIMITED */
3222 nla_total_size_64bit(sizeof(u64)) + /* TCP_NLA_DATA_SEGS_OUT */
3223 nla_total_size_64bit(sizeof(u64)) + /* TCP_NLA_TOTAL_RETRANS */
3224 nla_total_size_64bit(sizeof(u64)) + /* TCP_NLA_PACING_RATE */
3225 nla_total_size_64bit(sizeof(u64)) + /* TCP_NLA_DELIVERY_RATE */
3226 nla_total_size(sizeof(u32)) + /* TCP_NLA_SND_CWND */
3227 nla_total_size(sizeof(u32)) + /* TCP_NLA_REORDERING */
3228 nla_total_size(sizeof(u32)) + /* TCP_NLA_MIN_RTT */
3229 nla_total_size(sizeof(u8)) + /* TCP_NLA_RECUR_RETRANS */
3230 nla_total_size(sizeof(u8)) + /* TCP_NLA_DELIVERY_RATE_APP_LMT */
3231 nla_total_size(sizeof(u32)) + /* TCP_NLA_SNDQ_SIZE */
3232 nla_total_size(sizeof(u8)) + /* TCP_NLA_CA_STATE */
3233 nla_total_size(sizeof(u32)) + /* TCP_NLA_SND_SSTHRESH */
3234 nla_total_size(sizeof(u32)) + /* TCP_NLA_DELIVERED */
3235 nla_total_size(sizeof(u32)) + /* TCP_NLA_DELIVERED_CE */
3236 nla_total_size_64bit(sizeof(u64)) + /* TCP_NLA_BYTES_SENT */
3237 nla_total_size_64bit(sizeof(u64)) + /* TCP_NLA_BYTES_RETRANS */
3238 nla_total_size(sizeof(u32)) + /* TCP_NLA_DSACK_DUPS */
3239 nla_total_size(sizeof(u32)) + /* TCP_NLA_REORD_SEEN */
3240 0;
3241}
3242
3208struct sk_buff *tcp_get_timestamping_opt_stats(const struct sock *sk) 3243struct sk_buff *tcp_get_timestamping_opt_stats(const struct sock *sk)
3209{ 3244{
3210 const struct tcp_sock *tp = tcp_sk(sk); 3245 const struct tcp_sock *tp = tcp_sk(sk);
@@ -3213,9 +3248,7 @@ struct sk_buff *tcp_get_timestamping_opt_stats(const struct sock *sk)
3213 u64 rate64; 3248 u64 rate64;
3214 u32 rate; 3249 u32 rate;
3215 3250
3216 stats = alloc_skb(7 * nla_total_size_64bit(sizeof(u64)) + 3251 stats = alloc_skb(tcp_opt_stats_get_size(), GFP_ATOMIC);
3217 7 * nla_total_size(sizeof(u32)) +
3218 3 * nla_total_size(sizeof(u8)), GFP_ATOMIC);
3219 if (!stats) 3252 if (!stats)
3220 return NULL; 3253 return NULL;
3221 3254
@@ -3251,6 +3284,13 @@ struct sk_buff *tcp_get_timestamping_opt_stats(const struct sock *sk)
3251 nla_put_u32(stats, TCP_NLA_SNDQ_SIZE, tp->write_seq - tp->snd_una); 3284 nla_put_u32(stats, TCP_NLA_SNDQ_SIZE, tp->write_seq - tp->snd_una);
3252 nla_put_u8(stats, TCP_NLA_CA_STATE, inet_csk(sk)->icsk_ca_state); 3285 nla_put_u8(stats, TCP_NLA_CA_STATE, inet_csk(sk)->icsk_ca_state);
3253 3286
3287 nla_put_u64_64bit(stats, TCP_NLA_BYTES_SENT, tp->bytes_sent,
3288 TCP_NLA_PAD);
3289 nla_put_u64_64bit(stats, TCP_NLA_BYTES_RETRANS, tp->bytes_retrans,
3290 TCP_NLA_PAD);
3291 nla_put_u32(stats, TCP_NLA_DSACK_DUPS, tp->dsack_dups);
3292 nla_put_u32(stats, TCP_NLA_REORD_SEEN, tp->reord_seen);
3293
3254 return stats; 3294 return stats;
3255} 3295}
3256 3296
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index d51fa358b2b1..3d6156f07a8d 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -874,6 +874,7 @@ static void tcp_dsack_seen(struct tcp_sock *tp)
874{ 874{
875 tp->rx_opt.sack_ok |= TCP_DSACK_SEEN; 875 tp->rx_opt.sack_ok |= TCP_DSACK_SEEN;
876 tp->rack.dsack_seen = 1; 876 tp->rack.dsack_seen = 1;
877 tp->dsack_dups++;
877} 878}
878 879
879/* It's reordering when higher sequence was delivered (i.e. sacked) before 880/* It's reordering when higher sequence was delivered (i.e. sacked) before
@@ -905,8 +906,8 @@ static void tcp_check_sack_reordering(struct sock *sk, const u32 low_seq,
905 sock_net(sk)->ipv4.sysctl_tcp_max_reordering); 906 sock_net(sk)->ipv4.sysctl_tcp_max_reordering);
906 } 907 }
907 908
908 tp->rack.reord = 1;
909 /* This exciting event is worth to be remembered. 8) */ 909 /* This exciting event is worth to be remembered. 8) */
910 tp->reord_seen++;
910 NET_INC_STATS(sock_net(sk), 911 NET_INC_STATS(sock_net(sk),
911 ts ? LINUX_MIB_TCPTSREORDER : LINUX_MIB_TCPSACKREORDER); 912 ts ? LINUX_MIB_TCPTSREORDER : LINUX_MIB_TCPSACKREORDER);
912} 913}
@@ -1870,6 +1871,7 @@ static void tcp_check_reno_reordering(struct sock *sk, const int addend)
1870 1871
1871 tp->reordering = min_t(u32, tp->packets_out + addend, 1872 tp->reordering = min_t(u32, tp->packets_out + addend,
1872 sock_net(sk)->ipv4.sysctl_tcp_max_reordering); 1873 sock_net(sk)->ipv4.sysctl_tcp_max_reordering);
1874 tp->reord_seen++;
1873 NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPRENOREORDER); 1875 NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPRENOREORDER);
1874} 1876}
1875 1877
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 490df62f26d4..50cabf7656f3 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -1136,6 +1136,7 @@ static int __tcp_transmit_skb(struct sock *sk, struct sk_buff *skb,
1136 if (skb->len != tcp_header_size) { 1136 if (skb->len != tcp_header_size) {
1137 tcp_event_data_sent(tp, sk); 1137 tcp_event_data_sent(tp, sk);
1138 tp->data_segs_out += tcp_skb_pcount(skb); 1138 tp->data_segs_out += tcp_skb_pcount(skb);
1139 tp->bytes_sent += skb->len - tcp_header_size;
1139 tcp_internal_pacing(sk, skb); 1140 tcp_internal_pacing(sk, skb);
1140 } 1141 }
1141 1142
@@ -2870,6 +2871,7 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs)
2870 if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN) 2871 if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN)
2871 __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPSYNRETRANS); 2872 __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPSYNRETRANS);
2872 tp->total_retrans += segs; 2873 tp->total_retrans += segs;
2874 tp->bytes_retrans += skb->len;
2873 2875
2874 /* make sure skb->data is aligned on arches that require it 2876 /* make sure skb->data is aligned on arches that require it
2875 * and check if ack-trimming & collapsing extended the headroom 2877 * and check if ack-trimming & collapsing extended the headroom
diff --git a/net/ipv4/tcp_recovery.c b/net/ipv4/tcp_recovery.c
index 71593e4400ab..c81aadff769b 100644
--- a/net/ipv4/tcp_recovery.c
+++ b/net/ipv4/tcp_recovery.c
@@ -25,7 +25,7 @@ static u32 tcp_rack_reo_wnd(const struct sock *sk)
25{ 25{
26 struct tcp_sock *tp = tcp_sk(sk); 26 struct tcp_sock *tp = tcp_sk(sk);
27 27
28 if (!tp->rack.reord) { 28 if (!tp->reord_seen) {
29 /* If reordering has not been observed, be aggressive during 29 /* If reordering has not been observed, be aggressive during
30 * the recovery or starting the recovery by DUPACK threshold. 30 * the recovery or starting the recovery by DUPACK threshold.
31 */ 31 */