summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/networking/timestamping.txt10
-rw-r--r--arch/alpha/include/uapi/asm/socket.h2
-rw-r--r--arch/frv/include/uapi/asm/socket.h2
-rw-r--r--arch/ia64/include/uapi/asm/socket.h2
-rw-r--r--arch/m32r/include/uapi/asm/socket.h2
-rw-r--r--arch/mips/include/uapi/asm/socket.h2
-rw-r--r--arch/mn10300/include/uapi/asm/socket.h2
-rw-r--r--arch/parisc/include/uapi/asm/socket.h2
-rw-r--r--arch/powerpc/include/uapi/asm/socket.h2
-rw-r--r--arch/s390/include/uapi/asm/socket.h2
-rw-r--r--arch/sparc/include/uapi/asm/socket.h2
-rw-r--r--arch/xtensa/include/uapi/asm/socket.h2
-rw-r--r--include/linux/tcp.h2
-rw-r--r--include/uapi/asm-generic/socket.h2
-rw-r--r--include/uapi/linux/net_tstamp.h3
-rw-r--r--include/uapi/linux/tcp.h8
-rw-r--r--net/core/skbuff.c14
-rw-r--r--net/core/sock.c7
-rw-r--r--net/ipv4/tcp.c20
-rw-r--r--net/socket.c7
20 files changed, 90 insertions, 5 deletions
diff --git a/Documentation/networking/timestamping.txt b/Documentation/networking/timestamping.txt
index 671cccf0dcd2..96f50694a748 100644
--- a/Documentation/networking/timestamping.txt
+++ b/Documentation/networking/timestamping.txt
@@ -182,6 +182,16 @@ SOF_TIMESTAMPING_OPT_TSONLY:
182 the timestamp even if sysctl net.core.tstamp_allow_data is 0. 182 the timestamp even if sysctl net.core.tstamp_allow_data is 0.
183 This option disables SOF_TIMESTAMPING_OPT_CMSG. 183 This option disables SOF_TIMESTAMPING_OPT_CMSG.
184 184
185SOF_TIMESTAMPING_OPT_STATS:
186
187 Optional stats that are obtained along with the transmit timestamps.
188 It must be used together with SOF_TIMESTAMPING_OPT_TSONLY. When the
189 transmit timestamp is available, the stats are available in a
190 separate control message of type SCM_TIMESTAMPING_OPT_STATS, as a
191 list of TLVs (struct nlattr) of types. These stats allow the
192 application to associate various transport layer stats with
193 the transmit timestamps, such as how long a certain block of
194 data was limited by peer's receiver window.
185 195
186New applications are encouraged to pass SOF_TIMESTAMPING_OPT_ID to 196New applications are encouraged to pass SOF_TIMESTAMPING_OPT_ID to
187disambiguate timestamps and SOF_TIMESTAMPING_OPT_TSONLY to operate 197disambiguate timestamps and SOF_TIMESTAMPING_OPT_TSONLY to operate
diff --git a/arch/alpha/include/uapi/asm/socket.h b/arch/alpha/include/uapi/asm/socket.h
index 9e46d6e656d9..afc901b7a6f6 100644
--- a/arch/alpha/include/uapi/asm/socket.h
+++ b/arch/alpha/include/uapi/asm/socket.h
@@ -97,4 +97,6 @@
97 97
98#define SO_CNX_ADVICE 53 98#define SO_CNX_ADVICE 53
99 99
100#define SCM_TIMESTAMPING_OPT_STATS 54
101
100#endif /* _UAPI_ASM_SOCKET_H */ 102#endif /* _UAPI_ASM_SOCKET_H */
diff --git a/arch/frv/include/uapi/asm/socket.h b/arch/frv/include/uapi/asm/socket.h
index afbc98f02d27..81e03530ed39 100644
--- a/arch/frv/include/uapi/asm/socket.h
+++ b/arch/frv/include/uapi/asm/socket.h
@@ -90,5 +90,7 @@
90 90
91#define SO_CNX_ADVICE 53 91#define SO_CNX_ADVICE 53
92 92
93#define SCM_TIMESTAMPING_OPT_STATS 54
94
93#endif /* _ASM_SOCKET_H */ 95#endif /* _ASM_SOCKET_H */
94 96
diff --git a/arch/ia64/include/uapi/asm/socket.h b/arch/ia64/include/uapi/asm/socket.h
index 0018fad9039f..57feb0c1f7d7 100644
--- a/arch/ia64/include/uapi/asm/socket.h
+++ b/arch/ia64/include/uapi/asm/socket.h
@@ -99,4 +99,6 @@
99 99
100#define SO_CNX_ADVICE 53 100#define SO_CNX_ADVICE 53
101 101
102#define SCM_TIMESTAMPING_OPT_STATS 54
103
102#endif /* _ASM_IA64_SOCKET_H */ 104#endif /* _ASM_IA64_SOCKET_H */
diff --git a/arch/m32r/include/uapi/asm/socket.h b/arch/m32r/include/uapi/asm/socket.h
index 5fe42fc7b6c5..5853f8e92c20 100644
--- a/arch/m32r/include/uapi/asm/socket.h
+++ b/arch/m32r/include/uapi/asm/socket.h
@@ -90,4 +90,6 @@
90 90
91#define SO_CNX_ADVICE 53 91#define SO_CNX_ADVICE 53
92 92
93#define SCM_TIMESTAMPING_OPT_STATS 54
94
93#endif /* _ASM_M32R_SOCKET_H */ 95#endif /* _ASM_M32R_SOCKET_H */
diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h
index 2027240aafbb..566ecdcb5b4b 100644
--- a/arch/mips/include/uapi/asm/socket.h
+++ b/arch/mips/include/uapi/asm/socket.h
@@ -108,4 +108,6 @@
108 108
109#define SO_CNX_ADVICE 53 109#define SO_CNX_ADVICE 53
110 110
111#define SCM_TIMESTAMPING_OPT_STATS 54
112
111#endif /* _UAPI_ASM_SOCKET_H */ 113#endif /* _UAPI_ASM_SOCKET_H */
diff --git a/arch/mn10300/include/uapi/asm/socket.h b/arch/mn10300/include/uapi/asm/socket.h
index 5129f23a9ee1..0e12527c4b0e 100644
--- a/arch/mn10300/include/uapi/asm/socket.h
+++ b/arch/mn10300/include/uapi/asm/socket.h
@@ -90,4 +90,6 @@
90 90
91#define SO_CNX_ADVICE 53 91#define SO_CNX_ADVICE 53
92 92
93#define SCM_TIMESTAMPING_OPT_STATS 54
94
93#endif /* _ASM_SOCKET_H */ 95#endif /* _ASM_SOCKET_H */
diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h
index 9c935d717df9..7a109b73ddf7 100644
--- a/arch/parisc/include/uapi/asm/socket.h
+++ b/arch/parisc/include/uapi/asm/socket.h
@@ -89,4 +89,6 @@
89 89
90#define SO_CNX_ADVICE 0x402E 90#define SO_CNX_ADVICE 0x402E
91 91
92#define SCM_TIMESTAMPING_OPT_STATS 0x402F
93
92#endif /* _UAPI_ASM_SOCKET_H */ 94#endif /* _UAPI_ASM_SOCKET_H */
diff --git a/arch/powerpc/include/uapi/asm/socket.h b/arch/powerpc/include/uapi/asm/socket.h
index 1672e3398270..44583a52f882 100644
--- a/arch/powerpc/include/uapi/asm/socket.h
+++ b/arch/powerpc/include/uapi/asm/socket.h
@@ -97,4 +97,6 @@
97 97
98#define SO_CNX_ADVICE 53 98#define SO_CNX_ADVICE 53
99 99
100#define SCM_TIMESTAMPING_OPT_STATS 54
101
100#endif /* _ASM_POWERPC_SOCKET_H */ 102#endif /* _ASM_POWERPC_SOCKET_H */
diff --git a/arch/s390/include/uapi/asm/socket.h b/arch/s390/include/uapi/asm/socket.h
index 41b51c2f4f1b..b24a64cbfeb1 100644
--- a/arch/s390/include/uapi/asm/socket.h
+++ b/arch/s390/include/uapi/asm/socket.h
@@ -96,4 +96,6 @@
96 96
97#define SO_CNX_ADVICE 53 97#define SO_CNX_ADVICE 53
98 98
99#define SCM_TIMESTAMPING_OPT_STATS 54
100
99#endif /* _ASM_SOCKET_H */ 101#endif /* _ASM_SOCKET_H */
diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h
index 31aede3af088..a25dc32f5d6a 100644
--- a/arch/sparc/include/uapi/asm/socket.h
+++ b/arch/sparc/include/uapi/asm/socket.h
@@ -86,6 +86,8 @@
86 86
87#define SO_CNX_ADVICE 0x0037 87#define SO_CNX_ADVICE 0x0037
88 88
89#define SCM_TIMESTAMPING_OPT_STATS 0x0038
90
89/* Security levels - as per NRL IPv6 - don't actually do anything */ 91/* Security levels - as per NRL IPv6 - don't actually do anything */
90#define SO_SECURITY_AUTHENTICATION 0x5001 92#define SO_SECURITY_AUTHENTICATION 0x5001
91#define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002 93#define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002
diff --git a/arch/xtensa/include/uapi/asm/socket.h b/arch/xtensa/include/uapi/asm/socket.h
index 81435d995e11..9fdbe1fe0473 100644
--- a/arch/xtensa/include/uapi/asm/socket.h
+++ b/arch/xtensa/include/uapi/asm/socket.h
@@ -101,4 +101,6 @@
101 101
102#define SO_CNX_ADVICE 53 102#define SO_CNX_ADVICE 53
103 103
104#define SCM_TIMESTAMPING_OPT_STATS 54
105
104#endif /* _XTENSA_SOCKET_H */ 106#endif /* _XTENSA_SOCKET_H */
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index d5d3bd814338..00e0ee8f001f 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -428,4 +428,6 @@ static inline void tcp_saved_syn_free(struct tcp_sock *tp)
428 tp->saved_syn = NULL; 428 tp->saved_syn = NULL;
429} 429}
430 430
431struct sk_buff *tcp_get_timestamping_opt_stats(const struct sock *sk);
432
431#endif /* _LINUX_TCP_H */ 433#endif /* _LINUX_TCP_H */
diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h
index 67d632f1743d..2c748ddad5f8 100644
--- a/include/uapi/asm-generic/socket.h
+++ b/include/uapi/asm-generic/socket.h
@@ -92,4 +92,6 @@
92 92
93#define SO_CNX_ADVICE 53 93#define SO_CNX_ADVICE 53
94 94
95#define SCM_TIMESTAMPING_OPT_STATS 54
96
95#endif /* __ASM_GENERIC_SOCKET_H */ 97#endif /* __ASM_GENERIC_SOCKET_H */
diff --git a/include/uapi/linux/net_tstamp.h b/include/uapi/linux/net_tstamp.h
index 264e515de16f..464dcca5ed68 100644
--- a/include/uapi/linux/net_tstamp.h
+++ b/include/uapi/linux/net_tstamp.h
@@ -25,8 +25,9 @@ enum {
25 SOF_TIMESTAMPING_TX_ACK = (1<<9), 25 SOF_TIMESTAMPING_TX_ACK = (1<<9),
26 SOF_TIMESTAMPING_OPT_CMSG = (1<<10), 26 SOF_TIMESTAMPING_OPT_CMSG = (1<<10),
27 SOF_TIMESTAMPING_OPT_TSONLY = (1<<11), 27 SOF_TIMESTAMPING_OPT_TSONLY = (1<<11),
28 SOF_TIMESTAMPING_OPT_STATS = (1<<12),
28 29
29 SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_OPT_TSONLY, 30 SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_OPT_STATS,
30 SOF_TIMESTAMPING_MASK = (SOF_TIMESTAMPING_LAST - 1) | 31 SOF_TIMESTAMPING_MASK = (SOF_TIMESTAMPING_LAST - 1) |
31 SOF_TIMESTAMPING_LAST 32 SOF_TIMESTAMPING_LAST
32}; 33};
diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h
index 2863b661d6e1..c53de2691cec 100644
--- a/include/uapi/linux/tcp.h
+++ b/include/uapi/linux/tcp.h
@@ -220,6 +220,14 @@ struct tcp_info {
220 __u64 tcpi_sndbuf_limited; /* Time (usec) limited by send buffer */ 220 __u64 tcpi_sndbuf_limited; /* Time (usec) limited by send buffer */
221}; 221};
222 222
223/* netlink attributes types for SCM_TIMESTAMPING_OPT_STATS */
224enum {
225 TCP_NLA_PAD,
226 TCP_NLA_BUSY, /* Time (usec) busy sending data */
227 TCP_NLA_RWND_LIMITED, /* Time (usec) limited by receive window */
228 TCP_NLA_SNDBUF_LIMITED, /* Time (usec) limited by send buffer */
229};
230
223/* for TCP_MD5SIG socket option */ 231/* for TCP_MD5SIG socket option */
224#define TCP_MD5SIG_MAXKEYLEN 80 232#define TCP_MD5SIG_MAXKEYLEN 80
225 233
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index d1d1a5a5ad24..ea6fa954c7a0 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -3839,10 +3839,18 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb,
3839 if (!skb_may_tx_timestamp(sk, tsonly)) 3839 if (!skb_may_tx_timestamp(sk, tsonly))
3840 return; 3840 return;
3841 3841
3842 if (tsonly) 3842 if (tsonly) {
3843 skb = alloc_skb(0, GFP_ATOMIC); 3843#ifdef CONFIG_INET
3844 else 3844 if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS) &&
3845 sk->sk_protocol == IPPROTO_TCP &&
3846 sk->sk_type == SOCK_STREAM)
3847 skb = tcp_get_timestamping_opt_stats(sk);
3848 else
3849#endif
3850 skb = alloc_skb(0, GFP_ATOMIC);
3851 } else {
3845 skb = skb_clone(orig_skb, GFP_ATOMIC); 3852 skb = skb_clone(orig_skb, GFP_ATOMIC);
3853 }
3846 if (!skb) 3854 if (!skb)
3847 return; 3855 return;
3848 3856
diff --git a/net/core/sock.c b/net/core/sock.c
index 14e6145be33b..d8c7f8c877ca 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -854,6 +854,13 @@ set_rcvbuf:
854 sk->sk_tskey = 0; 854 sk->sk_tskey = 0;
855 } 855 }
856 } 856 }
857
858 if (val & SOF_TIMESTAMPING_OPT_STATS &&
859 !(val & SOF_TIMESTAMPING_OPT_TSONLY)) {
860 ret = -EINVAL;
861 break;
862 }
863
857 sk->sk_tsflags = val; 864 sk->sk_tsflags = val;
858 if (val & SOF_TIMESTAMPING_RX_SOFTWARE) 865 if (val & SOF_TIMESTAMPING_RX_SOFTWARE)
859 sock_enable_timestamp(sk, 866 sock_enable_timestamp(sk,
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index cdde20f49999..1149b48700a1 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2841,6 +2841,26 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
2841} 2841}
2842EXPORT_SYMBOL_GPL(tcp_get_info); 2842EXPORT_SYMBOL_GPL(tcp_get_info);
2843 2843
2844struct sk_buff *tcp_get_timestamping_opt_stats(const struct sock *sk)
2845{
2846 const struct tcp_sock *tp = tcp_sk(sk);
2847 struct sk_buff *stats;
2848 struct tcp_info info;
2849
2850 stats = alloc_skb(3 * nla_total_size_64bit(sizeof(u64)), GFP_ATOMIC);
2851 if (!stats)
2852 return NULL;
2853
2854 tcp_get_info_chrono_stats(tp, &info);
2855 nla_put_u64_64bit(stats, TCP_NLA_BUSY,
2856 info.tcpi_busy_time, TCP_NLA_PAD);
2857 nla_put_u64_64bit(stats, TCP_NLA_RWND_LIMITED,
2858 info.tcpi_rwnd_limited, TCP_NLA_PAD);
2859 nla_put_u64_64bit(stats, TCP_NLA_SNDBUF_LIMITED,
2860 info.tcpi_sndbuf_limited, TCP_NLA_PAD);
2861 return stats;
2862}
2863
2844static int do_tcp_getsockopt(struct sock *sk, int level, 2864static int do_tcp_getsockopt(struct sock *sk, int level,
2845 int optname, char __user *optval, int __user *optlen) 2865 int optname, char __user *optval, int __user *optlen)
2846{ 2866{
diff --git a/net/socket.c b/net/socket.c
index e2584c51aa1f..e6318943ad07 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -693,9 +693,14 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
693 (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) && 693 (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
694 ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2)) 694 ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2))
695 empty = 0; 695 empty = 0;
696 if (!empty) 696 if (!empty) {
697 put_cmsg(msg, SOL_SOCKET, 697 put_cmsg(msg, SOL_SOCKET,
698 SCM_TIMESTAMPING, sizeof(tss), &tss); 698 SCM_TIMESTAMPING, sizeof(tss), &tss);
699
700 if (skb->len && (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS))
701 put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_OPT_STATS,
702 skb->len, skb->data);
703 }
699} 704}
700EXPORT_SYMBOL_GPL(__sock_recv_timestamp); 705EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
701 706