diff options
-rw-r--r-- | include/linux/tcp.h | 4 | ||||
-rw-r--r-- | include/net/tcp.h | 2 | ||||
-rw-r--r-- | include/uapi/linux/tcp.h | 1 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 6 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 13 |
5 files changed, 22 insertions, 4 deletions
diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 0caa3a2d4106..0f73b43171da 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h | |||
@@ -150,6 +150,10 @@ struct tcp_sock { | |||
150 | u32 rcv_wup; /* rcv_nxt on last window update sent */ | 150 | u32 rcv_wup; /* rcv_nxt on last window update sent */ |
151 | u32 snd_nxt; /* Next sequence we send */ | 151 | u32 snd_nxt; /* Next sequence we send */ |
152 | 152 | ||
153 | u64 bytes_acked; /* RFC4898 tcpEStatsAppHCThruOctetsAcked | ||
154 | * sum(delta(snd_una)), or how many bytes | ||
155 | * were acked. | ||
156 | */ | ||
153 | u32 snd_una; /* First byte we want an ack for */ | 157 | u32 snd_una; /* First byte we want an ack for */ |
154 | u32 snd_sml; /* Last byte of the most recently transmitted small packet */ | 158 | u32 snd_sml; /* Last byte of the most recently transmitted small packet */ |
155 | u32 rcv_tstamp; /* timestamp of last received ACK (for keepalives) */ | 159 | u32 rcv_tstamp; /* timestamp of last received ACK (for keepalives) */ |
diff --git a/include/net/tcp.h b/include/net/tcp.h index 051dc5c2802d..dd7b4ea6a10c 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -576,7 +576,7 @@ static inline int tcp_bound_to_half_wnd(struct tcp_sock *tp, int pktsize) | |||
576 | } | 576 | } |
577 | 577 | ||
578 | /* tcp.c */ | 578 | /* tcp.c */ |
579 | void tcp_get_info(const struct sock *, struct tcp_info *); | 579 | void tcp_get_info(struct sock *, struct tcp_info *); |
580 | 580 | ||
581 | /* Read 'sendfile()'-style from a TCP socket */ | 581 | /* Read 'sendfile()'-style from a TCP socket */ |
582 | typedef int (*sk_read_actor_t)(read_descriptor_t *, struct sk_buff *, | 582 | typedef int (*sk_read_actor_t)(read_descriptor_t *, struct sk_buff *, |
diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h index 3b9718328d8b..6666e98a0af9 100644 --- a/include/uapi/linux/tcp.h +++ b/include/uapi/linux/tcp.h | |||
@@ -189,6 +189,7 @@ struct tcp_info { | |||
189 | 189 | ||
190 | __u64 tcpi_pacing_rate; | 190 | __u64 tcpi_pacing_rate; |
191 | __u64 tcpi_max_pacing_rate; | 191 | __u64 tcpi_max_pacing_rate; |
192 | __u64 tcpi_bytes_acked; /* RFC4898 tcpEStatsAppHCThruOctetsAcked */ | ||
192 | }; | 193 | }; |
193 | 194 | ||
194 | /* for TCP_MD5SIG socket option */ | 195 | /* for TCP_MD5SIG socket option */ |
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); |