diff options
author | Eric Dumazet <edumazet@google.com> | 2015-04-28 18:28:17 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-04-29 17:10:37 -0400 |
commit | 0df48c26d8418c5c9fba63fac15b660d70ca2f1c (patch) | |
tree | 3dbdd83937001fde41106b43cae4a3cd1a84bdd0 /net/ipv4 | |
parent | 2decb2682f80759f631c8332f9a2a34a02150a03 (diff) |
tcp: add tcpi_bytes_acked to tcp_info
This patch tracks total number of bytes acked for a TCP socket.
This is the sum of all changes done to tp->snd_una, and allows
for precise tracking of delivered data.
RFC4898 named this : tcpEStatsAppHCThruOctetsAcked
This is a 64bit field, and can be fetched both from TCP_INFO
getsockopt() if one has a handle on a TCP socket, or from inet_diag
netlink facility (iproute2/ss patch will follow)
Note that tp->bytes_acked was placed near tp->snd_una for
best data locality and minimal performance impact.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Acked-by: Yuchung Cheng <ycheng@google.com>
Cc: Matt Mathis <mattmathis@google.com>
Cc: Eric Salo <salo@google.com>
Cc: Martin Lau <kafai@fb.com>
Cc: Chris Rapier <rapier@psc.edu>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/tcp.c | 6 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 13 |
2 files changed, 16 insertions, 3 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 8c5cd9efebbc..4bf0e8ca7b5b 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -2592,7 +2592,7 @@ EXPORT_SYMBOL(compat_tcp_setsockopt); | |||
2592 | #endif | 2592 | #endif |
2593 | 2593 | ||
2594 | /* Return information about state of tcp endpoint in API format. */ | 2594 | /* Return information about state of tcp endpoint in API format. */ |
2595 | void tcp_get_info(const struct sock *sk, struct tcp_info *info) | 2595 | void tcp_get_info(struct sock *sk, struct tcp_info *info) |
2596 | { | 2596 | { |
2597 | const struct tcp_sock *tp = tcp_sk(sk); | 2597 | const struct tcp_sock *tp = tcp_sk(sk); |
2598 | const struct inet_connection_sock *icsk = inet_csk(sk); | 2598 | const struct inet_connection_sock *icsk = inet_csk(sk); |
@@ -2663,6 +2663,10 @@ void tcp_get_info(const struct sock *sk, struct tcp_info *info) | |||
2663 | 2663 | ||
2664 | rate = READ_ONCE(sk->sk_max_pacing_rate); | 2664 | rate = READ_ONCE(sk->sk_max_pacing_rate); |
2665 | info->tcpi_max_pacing_rate = rate != ~0U ? rate : ~0ULL; | 2665 | info->tcpi_max_pacing_rate = rate != ~0U ? rate : ~0ULL; |
2666 | |||
2667 | spin_lock_bh(&sk->sk_lock.slock); | ||
2668 | info->tcpi_bytes_acked = tp->bytes_acked; | ||
2669 | spin_unlock_bh(&sk->sk_lock.slock); | ||
2666 | } | 2670 | } |
2667 | EXPORT_SYMBOL_GPL(tcp_get_info); | 2671 | EXPORT_SYMBOL_GPL(tcp_get_info); |
2668 | 2672 | ||
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 3a4d9b34bed4..378d3f4d4dc3 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -3280,6 +3280,15 @@ static inline bool tcp_may_update_window(const struct tcp_sock *tp, | |||
3280 | (ack_seq == tp->snd_wl1 && nwin > tp->snd_wnd); | 3280 | (ack_seq == tp->snd_wl1 && nwin > tp->snd_wnd); |
3281 | } | 3281 | } |
3282 | 3282 | ||
3283 | /* If we update tp->snd_una, also update tp->bytes_acked */ | ||
3284 | static void tcp_snd_una_update(struct tcp_sock *tp, u32 ack) | ||
3285 | { | ||
3286 | u32 delta = ack - tp->snd_una; | ||
3287 | |||
3288 | tp->bytes_acked += delta; | ||
3289 | tp->snd_una = ack; | ||
3290 | } | ||
3291 | |||
3283 | /* Update our send window. | 3292 | /* Update our send window. |
3284 | * | 3293 | * |
3285 | * Window update algorithm, described in RFC793/RFC1122 (used in linux-2.2 | 3294 | * Window update algorithm, described in RFC793/RFC1122 (used in linux-2.2 |
@@ -3315,7 +3324,7 @@ static int tcp_ack_update_window(struct sock *sk, const struct sk_buff *skb, u32 | |||
3315 | } | 3324 | } |
3316 | } | 3325 | } |
3317 | 3326 | ||
3318 | tp->snd_una = ack; | 3327 | tcp_snd_una_update(tp, ack); |
3319 | 3328 | ||
3320 | return flag; | 3329 | return flag; |
3321 | } | 3330 | } |
@@ -3497,7 +3506,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) | |||
3497 | * Note, we use the fact that SND.UNA>=SND.WL2. | 3506 | * Note, we use the fact that SND.UNA>=SND.WL2. |
3498 | */ | 3507 | */ |
3499 | tcp_update_wl(tp, ack_seq); | 3508 | tcp_update_wl(tp, ack_seq); |
3500 | tp->snd_una = ack; | 3509 | tcp_snd_una_update(tp, ack); |
3501 | flag |= FLAG_WIN_UPDATE; | 3510 | flag |= FLAG_WIN_UPDATE; |
3502 | 3511 | ||
3503 | tcp_in_ack_event(sk, CA_ACK_WIN_UPDATE); | 3512 | tcp_in_ack_event(sk, CA_ACK_WIN_UPDATE); |