aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/tcp.c')
-rw-r--r--net/ipv4/tcp.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 8c5cd9efebbc..f1377f2a0472 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>
@@ -401,6 +402,7 @@ void tcp_init_sock(struct sock *sk)
401 tp->snd_ssthresh = TCP_INFINITE_SSTHRESH; 402 tp->snd_ssthresh = TCP_INFINITE_SSTHRESH;
402 tp->snd_cwnd_clamp = ~0; 403 tp->snd_cwnd_clamp = ~0;
403 tp->mss_cache = TCP_MSS_DEFAULT; 404 tp->mss_cache = TCP_MSS_DEFAULT;
405 u64_stats_init(&tp->syncp);
404 406
405 tp->reordering = sysctl_tcp_reordering; 407 tp->reordering = sysctl_tcp_reordering;
406 tcp_enable_early_retrans(tp); 408 tcp_enable_early_retrans(tp);
@@ -2592,11 +2594,12 @@ EXPORT_SYMBOL(compat_tcp_setsockopt);
2592#endif 2594#endif
2593 2595
2594/* Return information about state of tcp endpoint in API format. */ 2596/* Return information about state of tcp endpoint in API format. */
2595void tcp_get_info(const struct sock *sk, struct tcp_info *info) 2597void tcp_get_info(struct sock *sk, struct tcp_info *info)
2596{ 2598{
2597 const struct tcp_sock *tp = tcp_sk(sk); 2599 const struct tcp_sock *tp = tcp_sk(sk);
2598 const struct inet_connection_sock *icsk = inet_csk(sk); 2600 const struct inet_connection_sock *icsk = inet_csk(sk);
2599 u32 now = tcp_time_stamp; 2601 u32 now = tcp_time_stamp;
2602 unsigned int start;
2600 u32 rate; 2603 u32 rate;
2601 2604
2602 memset(info, 0, sizeof(*info)); 2605 memset(info, 0, sizeof(*info));
@@ -2663,6 +2666,12 @@ void tcp_get_info(const struct sock *sk, struct tcp_info *info)
2663 2666
2664 rate = READ_ONCE(sk->sk_max_pacing_rate); 2667 rate = READ_ONCE(sk->sk_max_pacing_rate);
2665 info->tcpi_max_pacing_rate = rate != ~0U ? rate : ~0ULL; 2668 info->tcpi_max_pacing_rate = rate != ~0U ? rate : ~0ULL;
2669
2670 do {
2671 start = u64_stats_fetch_begin_irq(&tp->syncp);
2672 info->tcpi_bytes_acked = tp->bytes_acked;
2673 info->tcpi_bytes_received = tp->bytes_received;
2674 } while (u64_stats_fetch_retry_irq(&tp->syncp, start));
2666} 2675}
2667EXPORT_SYMBOL_GPL(tcp_get_info); 2676EXPORT_SYMBOL_GPL(tcp_get_info);
2668 2677
@@ -2734,6 +2743,26 @@ static int do_tcp_getsockopt(struct sock *sk, int level,
2734 return -EFAULT; 2743 return -EFAULT;
2735 return 0; 2744 return 0;
2736 } 2745 }
2746 case TCP_CC_INFO: {
2747 const struct tcp_congestion_ops *ca_ops;
2748 union tcp_cc_info info;
2749 size_t sz = 0;
2750 int attr;
2751
2752 if (get_user(len, optlen))
2753 return -EFAULT;
2754
2755 ca_ops = icsk->icsk_ca_ops;
2756 if (ca_ops && ca_ops->get_info)
2757 sz = ca_ops->get_info(sk, ~0U, &attr, &info);
2758
2759 len = min_t(unsigned int, len, sz);
2760 if (put_user(len, optlen))
2761 return -EFAULT;
2762 if (copy_to_user(optval, &info, len))
2763 return -EFAULT;
2764 return 0;
2765 }
2737 case TCP_QUICKACK: 2766 case TCP_QUICKACK:
2738 val = !icsk->icsk_ack.pingpong; 2767 val = !icsk->icsk_ack.pingpong;
2739 break; 2768 break;