diff options
Diffstat (limited to 'net/ipv4/tcp.c')
-rw-r--r-- | net/ipv4/tcp.c | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 8c5cd9efebbc..46efa03d2b11 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -252,6 +252,7 @@ | |||
252 | #include <linux/types.h> | 252 | #include <linux/types.h> |
253 | #include <linux/fcntl.h> | 253 | #include <linux/fcntl.h> |
254 | #include <linux/poll.h> | 254 | #include <linux/poll.h> |
255 | #include <linux/inet_diag.h> | ||
255 | #include <linux/init.h> | 256 | #include <linux/init.h> |
256 | #include <linux/fs.h> | 257 | #include <linux/fs.h> |
257 | #include <linux/skbuff.h> | 258 | #include <linux/skbuff.h> |
@@ -2592,7 +2593,7 @@ EXPORT_SYMBOL(compat_tcp_setsockopt); | |||
2592 | #endif | 2593 | #endif |
2593 | 2594 | ||
2594 | /* Return information about state of tcp endpoint in API format. */ | 2595 | /* Return information about state of tcp endpoint in API format. */ |
2595 | void tcp_get_info(const struct sock *sk, struct tcp_info *info) | 2596 | void tcp_get_info(struct sock *sk, struct tcp_info *info) |
2596 | { | 2597 | { |
2597 | const struct tcp_sock *tp = tcp_sk(sk); | 2598 | const struct tcp_sock *tp = tcp_sk(sk); |
2598 | const struct inet_connection_sock *icsk = inet_csk(sk); | 2599 | const struct inet_connection_sock *icsk = inet_csk(sk); |
@@ -2663,6 +2664,11 @@ void tcp_get_info(const struct sock *sk, struct tcp_info *info) | |||
2663 | 2664 | ||
2664 | rate = READ_ONCE(sk->sk_max_pacing_rate); | 2665 | rate = READ_ONCE(sk->sk_max_pacing_rate); |
2665 | info->tcpi_max_pacing_rate = rate != ~0U ? rate : ~0ULL; | 2666 | info->tcpi_max_pacing_rate = rate != ~0U ? rate : ~0ULL; |
2667 | |||
2668 | spin_lock_bh(&sk->sk_lock.slock); | ||
2669 | info->tcpi_bytes_acked = tp->bytes_acked; | ||
2670 | info->tcpi_bytes_received = tp->bytes_received; | ||
2671 | spin_unlock_bh(&sk->sk_lock.slock); | ||
2666 | } | 2672 | } |
2667 | EXPORT_SYMBOL_GPL(tcp_get_info); | 2673 | EXPORT_SYMBOL_GPL(tcp_get_info); |
2668 | 2674 | ||
@@ -2734,6 +2740,26 @@ static int do_tcp_getsockopt(struct sock *sk, int level, | |||
2734 | return -EFAULT; | 2740 | return -EFAULT; |
2735 | return 0; | 2741 | return 0; |
2736 | } | 2742 | } |
2743 | case TCP_CC_INFO: { | ||
2744 | const struct tcp_congestion_ops *ca_ops; | ||
2745 | union tcp_cc_info info; | ||
2746 | size_t sz = 0; | ||
2747 | int attr; | ||
2748 | |||
2749 | if (get_user(len, optlen)) | ||
2750 | return -EFAULT; | ||
2751 | |||
2752 | ca_ops = icsk->icsk_ca_ops; | ||
2753 | if (ca_ops && ca_ops->get_info) | ||
2754 | sz = ca_ops->get_info(sk, ~0U, &attr, &info); | ||
2755 | |||
2756 | len = min_t(unsigned int, len, sz); | ||
2757 | if (put_user(len, optlen)) | ||
2758 | return -EFAULT; | ||
2759 | if (copy_to_user(optval, &info, len)) | ||
2760 | return -EFAULT; | ||
2761 | return 0; | ||
2762 | } | ||
2737 | case TCP_QUICKACK: | 2763 | case TCP_QUICKACK: |
2738 | val = !icsk->icsk_ack.pingpong; | 2764 | val = !icsk->icsk_ack.pingpong; |
2739 | break; | 2765 | break; |