diff options
-rw-r--r-- | include/linux/tcp.h | 13 | ||||
-rw-r--r-- | include/uapi/linux/tcp.h | 10 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 46 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 4 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 2 | ||||
-rw-r--r-- | net/ipv4/tcp_recovery.c | 2 |
6 files changed, 69 insertions, 8 deletions
diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 58a8d7d71354..263e37271afd 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h | |||
@@ -181,10 +181,16 @@ struct tcp_sock { | |||
181 | u32 data_segs_out; /* RFC4898 tcpEStatsPerfDataSegsOut | 181 | u32 data_segs_out; /* RFC4898 tcpEStatsPerfDataSegsOut |
182 | * total number of data segments sent. | 182 | * total number of data segments sent. |
183 | */ | 183 | */ |
184 | u64 bytes_sent; /* RFC4898 tcpEStatsPerfHCDataOctetsOut | ||
185 | * total number of data bytes sent. | ||
186 | */ | ||
184 | u64 bytes_acked; /* RFC4898 tcpEStatsAppHCThruOctetsAcked | 187 | u64 bytes_acked; /* RFC4898 tcpEStatsAppHCThruOctetsAcked |
185 | * sum(delta(snd_una)), or how many bytes | 188 | * sum(delta(snd_una)), or how many bytes |
186 | * were acked. | 189 | * were acked. |
187 | */ | 190 | */ |
191 | u32 dsack_dups; /* RFC4898 tcpEStatsStackDSACKDups | ||
192 | * total number of DSACK blocks received | ||
193 | */ | ||
188 | u32 snd_una; /* First byte we want an ack for */ | 194 | u32 snd_una; /* First byte we want an ack for */ |
189 | u32 snd_sml; /* Last byte of the most recently transmitted small packet */ | 195 | u32 snd_sml; /* Last byte of the most recently transmitted small packet */ |
190 | u32 rcv_tstamp; /* timestamp of last received ACK (for keepalives) */ | 196 | u32 rcv_tstamp; /* timestamp of last received ACK (for keepalives) */ |
@@ -214,8 +220,7 @@ struct tcp_sock { | |||
214 | #define TCP_RACK_RECOVERY_THRESH 16 | 220 | #define TCP_RACK_RECOVERY_THRESH 16 |
215 | u8 reo_wnd_persist:5, /* No. of recovery since last adj */ | 221 | u8 reo_wnd_persist:5, /* No. of recovery since last adj */ |
216 | dsack_seen:1, /* Whether DSACK seen after last adj */ | 222 | dsack_seen:1, /* Whether DSACK seen after last adj */ |
217 | advanced:1, /* mstamp advanced since last lost marking */ | 223 | advanced:1; /* mstamp advanced since last lost marking */ |
218 | reord:1; /* reordering detected */ | ||
219 | } rack; | 224 | } rack; |
220 | u16 advmss; /* Advertised MSS */ | 225 | u16 advmss; /* Advertised MSS */ |
221 | u8 compressed_ack; | 226 | u8 compressed_ack; |
@@ -261,6 +266,7 @@ struct tcp_sock { | |||
261 | u8 ecn_flags; /* ECN status bits. */ | 266 | u8 ecn_flags; /* ECN status bits. */ |
262 | u8 keepalive_probes; /* num of allowed keep alive probes */ | 267 | u8 keepalive_probes; /* num of allowed keep alive probes */ |
263 | u32 reordering; /* Packet reordering metric. */ | 268 | u32 reordering; /* Packet reordering metric. */ |
269 | u32 reord_seen; /* number of data packet reordering events */ | ||
264 | u32 snd_up; /* Urgent pointer */ | 270 | u32 snd_up; /* Urgent pointer */ |
265 | 271 | ||
266 | /* | 272 | /* |
@@ -330,6 +336,9 @@ struct tcp_sock { | |||
330 | * the first SYN. */ | 336 | * the first SYN. */ |
331 | u32 undo_marker; /* snd_una upon a new recovery episode. */ | 337 | u32 undo_marker; /* snd_una upon a new recovery episode. */ |
332 | int undo_retrans; /* number of undoable retransmissions. */ | 338 | int undo_retrans; /* number of undoable retransmissions. */ |
339 | u64 bytes_retrans; /* RFC4898 tcpEStatsPerfOctetsRetrans | ||
340 | * Total data bytes retransmitted | ||
341 | */ | ||
333 | u32 total_retrans; /* Total retransmits for entire connection */ | 342 | u32 total_retrans; /* Total retransmits for entire connection */ |
334 | 343 | ||
335 | u32 urg_seq; /* Seq of received urgent pointer */ | 344 | u32 urg_seq; /* Seq of received urgent pointer */ |
diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h index e3f6ed8a7064..e02d31986ff9 100644 --- a/include/uapi/linux/tcp.h +++ b/include/uapi/linux/tcp.h | |||
@@ -235,6 +235,11 @@ struct tcp_info { | |||
235 | 235 | ||
236 | __u32 tcpi_delivered; | 236 | __u32 tcpi_delivered; |
237 | __u32 tcpi_delivered_ce; | 237 | __u32 tcpi_delivered_ce; |
238 | |||
239 | __u64 tcpi_bytes_sent; /* RFC4898 tcpEStatsPerfHCDataOctetsOut */ | ||
240 | __u64 tcpi_bytes_retrans; /* RFC4898 tcpEStatsPerfOctetsRetrans */ | ||
241 | __u32 tcpi_dsack_dups; /* RFC4898 tcpEStatsStackDSACKDups */ | ||
242 | __u32 tcpi_reord_seen; /* reordering events seen */ | ||
238 | }; | 243 | }; |
239 | 244 | ||
240 | /* netlink attributes types for SCM_TIMESTAMPING_OPT_STATS */ | 245 | /* netlink attributes types for SCM_TIMESTAMPING_OPT_STATS */ |
@@ -257,7 +262,10 @@ enum { | |||
257 | TCP_NLA_SND_SSTHRESH, /* Slow start size threshold */ | 262 | TCP_NLA_SND_SSTHRESH, /* Slow start size threshold */ |
258 | TCP_NLA_DELIVERED, /* Data pkts delivered incl. out-of-order */ | 263 | TCP_NLA_DELIVERED, /* Data pkts delivered incl. out-of-order */ |
259 | TCP_NLA_DELIVERED_CE, /* Like above but only ones w/ CE marks */ | 264 | TCP_NLA_DELIVERED_CE, /* Like above but only ones w/ CE marks */ |
260 | 265 | TCP_NLA_BYTES_SENT, /* Data bytes sent including retransmission */ | |
266 | TCP_NLA_BYTES_RETRANS, /* Data bytes retransmitted */ | ||
267 | TCP_NLA_DSACK_DUPS, /* DSACK blocks received */ | ||
268 | TCP_NLA_REORD_SEEN, /* reordering events seen */ | ||
261 | }; | 269 | }; |
262 | 270 | ||
263 | /* for TCP_MD5SIG socket option */ | 271 | /* for TCP_MD5SIG socket option */ |
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 | } |
3206 | EXPORT_SYMBOL_GPL(tcp_get_info); | 3214 | EXPORT_SYMBOL_GPL(tcp_get_info); |
3207 | 3215 | ||
3216 | static 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 | |||
3208 | struct sk_buff *tcp_get_timestamping_opt_stats(const struct sock *sk) | 3243 | struct 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 | */ |