On Mon, Nov 28, 2016 at 2:07 AM, Yuchung Cheng <ycheng@xxxxxxxxxx> wrote: > From: Francis Yan <francisyyan@xxxxxxxxx> > > This patch exports the sender chronograph stats via the socket > SO_TIMESTAMPING channel. Currently we can instrument how long a > particular application unit of data was queued in TCP by tracking > SOF_TIMESTAMPING_TX_SOFTWARE and SOF_TIMESTAMPING_TX_SCHED. Having Seems a new linux-next failure leads back to here ; I did not run a full bisect, since the variable seems confined to this commit: net/socket.c:701: error: 'SCM_TIMESTAMPING_OPT_STATS' undeclared (first use in this function) http://kisskb.ellerman.id.au/kisskb/buildresult/12875981/ Paul. -- > these sender chronograph stats exported simultaneously along with > these timestamps allow further breaking down the various sender > limitation. For example, a video server can tell if a particular > chunk of video on a connection takes a long time to deliver because > TCP was experiencing small receive window. It is not possible to > tell before this patch without packet traces. > > To prepare these stats, the user needs to set > SOF_TIMESTAMPING_OPT_STATS and SOF_TIMESTAMPING_OPT_TSONLY flags > while requesting other SOF_TIMESTAMPING TX timestamps. When the > timestamps are available in the error queue, the stats are returned > in a separate control message of type SCM_TIMESTAMPING_OPT_STATS, > in a list of TLVs (struct nlattr) of types: TCP_NLA_BUSY_TIME, > TCP_NLA_RWND_LIMITED, TCP_NLA_SNDBUF_LIMITED. Unit is microsecond. > > Signed-off-by: Francis Yan <francisyyan@xxxxxxxxx> > Signed-off-by: Yuchung Cheng <ycheng@xxxxxxxxxx> > Signed-off-by: Soheil Hassas Yeganeh <soheil@xxxxxxxxxx> > --- > ChangeLog since v1: > - fix build break if CONFIG_INET is not defined > > Documentation/networking/timestamping.txt | 10 ++++++++++ > arch/alpha/include/uapi/asm/socket.h | 2 ++ > arch/frv/include/uapi/asm/socket.h | 2 ++ > arch/ia64/include/uapi/asm/socket.h | 2 ++ > arch/m32r/include/uapi/asm/socket.h | 2 ++ > arch/mips/include/uapi/asm/socket.h | 2 ++ > arch/mn10300/include/uapi/asm/socket.h | 2 ++ > arch/parisc/include/uapi/asm/socket.h | 2 ++ > arch/powerpc/include/uapi/asm/socket.h | 2 ++ > arch/s390/include/uapi/asm/socket.h | 2 ++ > arch/sparc/include/uapi/asm/socket.h | 2 ++ > arch/xtensa/include/uapi/asm/socket.h | 2 ++ > include/linux/tcp.h | 2 ++ > include/uapi/asm-generic/socket.h | 2 ++ > include/uapi/linux/net_tstamp.h | 3 ++- > include/uapi/linux/tcp.h | 8 ++++++++ > net/core/skbuff.c | 14 +++++++++++--- > net/core/sock.c | 7 +++++++ > net/ipv4/tcp.c | 20 ++++++++++++++++++++ > net/socket.c | 7 ++++++- > 20 files changed, 90 insertions(+), 5 deletions(-) > > diff --git a/Documentation/networking/timestamping.txt b/Documentation/networking/timestamping.txt > index 671cccf..96f5069 100644 > --- a/Documentation/networking/timestamping.txt > +++ b/Documentation/networking/timestamping.txt > @@ -182,6 +182,16 @@ SOF_TIMESTAMPING_OPT_TSONLY: > the timestamp even if sysctl net.core.tstamp_allow_data is 0. > This option disables SOF_TIMESTAMPING_OPT_CMSG. > > +SOF_TIMESTAMPING_OPT_STATS: > + > + Optional stats that are obtained along with the transmit timestamps. > + It must be used together with SOF_TIMESTAMPING_OPT_TSONLY. When the > + transmit timestamp is available, the stats are available in a > + separate control message of type SCM_TIMESTAMPING_OPT_STATS, as a > + list of TLVs (struct nlattr) of types. These stats allow the > + application to associate various transport layer stats with > + the transmit timestamps, such as how long a certain block of > + data was limited by peer's receiver window. > > New applications are encouraged to pass SOF_TIMESTAMPING_OPT_ID to > disambiguate 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 9e46d6e..afc901b 100644 > --- a/arch/alpha/include/uapi/asm/socket.h > +++ b/arch/alpha/include/uapi/asm/socket.h > @@ -97,4 +97,6 @@ > > #define SO_CNX_ADVICE 53 > > +#define SCM_TIMESTAMPING_OPT_STATS 54 > + > #endif /* _UAPI_ASM_SOCKET_H */ > diff --git a/arch/frv/include/uapi/asm/socket.h b/arch/frv/include/uapi/asm/socket.h > index afbc98f0..81e0353 100644 > --- a/arch/frv/include/uapi/asm/socket.h > +++ b/arch/frv/include/uapi/asm/socket.h > @@ -90,5 +90,7 @@ > > #define SO_CNX_ADVICE 53 > > +#define SCM_TIMESTAMPING_OPT_STATS 54 > + > #endif /* _ASM_SOCKET_H */ > > diff --git a/arch/ia64/include/uapi/asm/socket.h b/arch/ia64/include/uapi/asm/socket.h > index 0018fad..57feb0c 100644 > --- a/arch/ia64/include/uapi/asm/socket.h > +++ b/arch/ia64/include/uapi/asm/socket.h > @@ -99,4 +99,6 @@ > > #define SO_CNX_ADVICE 53 > > +#define SCM_TIMESTAMPING_OPT_STATS 54 > + > #endif /* _ASM_IA64_SOCKET_H */ > diff --git a/arch/m32r/include/uapi/asm/socket.h b/arch/m32r/include/uapi/asm/socket.h > index 5fe42fc..5853f8e9 100644 > --- a/arch/m32r/include/uapi/asm/socket.h > +++ b/arch/m32r/include/uapi/asm/socket.h > @@ -90,4 +90,6 @@ > > #define SO_CNX_ADVICE 53 > > +#define SCM_TIMESTAMPING_OPT_STATS 54 > + > #endif /* _ASM_M32R_SOCKET_H */ > diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h > index 2027240a..566ecdc 100644 > --- a/arch/mips/include/uapi/asm/socket.h > +++ b/arch/mips/include/uapi/asm/socket.h > @@ -108,4 +108,6 @@ > > #define SO_CNX_ADVICE 53 > > +#define SCM_TIMESTAMPING_OPT_STATS 54 > + > #endif /* _UAPI_ASM_SOCKET_H */ > diff --git a/arch/mn10300/include/uapi/asm/socket.h b/arch/mn10300/include/uapi/asm/socket.h > index 5129f23..0e12527 100644 > --- a/arch/mn10300/include/uapi/asm/socket.h > +++ b/arch/mn10300/include/uapi/asm/socket.h > @@ -90,4 +90,6 @@ > > #define SO_CNX_ADVICE 53 > > +#define SCM_TIMESTAMPING_OPT_STATS 54 > + > #endif /* _ASM_SOCKET_H */ > diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h > index 9c935d7..7a109b7 100644 > --- a/arch/parisc/include/uapi/asm/socket.h > +++ b/arch/parisc/include/uapi/asm/socket.h > @@ -89,4 +89,6 @@ > > #define SO_CNX_ADVICE 0x402E > > +#define SCM_TIMESTAMPING_OPT_STATS 0x402F > + > #endif /* _UAPI_ASM_SOCKET_H */ > diff --git a/arch/powerpc/include/uapi/asm/socket.h b/arch/powerpc/include/uapi/asm/socket.h > index 1672e33..44583a5 100644 > --- a/arch/powerpc/include/uapi/asm/socket.h > +++ b/arch/powerpc/include/uapi/asm/socket.h > @@ -97,4 +97,6 @@ > > #define SO_CNX_ADVICE 53 > > +#define SCM_TIMESTAMPING_OPT_STATS 54 > + > #endif /* _ASM_POWERPC_SOCKET_H */ > diff --git a/arch/s390/include/uapi/asm/socket.h b/arch/s390/include/uapi/asm/socket.h > index 41b51c2..b24a64c 100644 > --- a/arch/s390/include/uapi/asm/socket.h > +++ b/arch/s390/include/uapi/asm/socket.h > @@ -96,4 +96,6 @@ > > #define SO_CNX_ADVICE 53 > > +#define SCM_TIMESTAMPING_OPT_STATS 54 > + > #endif /* _ASM_SOCKET_H */ > diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h > index 31aede3..a25dc32 100644 > --- a/arch/sparc/include/uapi/asm/socket.h > +++ b/arch/sparc/include/uapi/asm/socket.h > @@ -86,6 +86,8 @@ > > #define SO_CNX_ADVICE 0x0037 > > +#define SCM_TIMESTAMPING_OPT_STATS 0x0038 > + > /* Security levels - as per NRL IPv6 - don't actually do anything */ > #define SO_SECURITY_AUTHENTICATION 0x5001 > #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 81435d9..9fdbe1f 100644 > --- a/arch/xtensa/include/uapi/asm/socket.h > +++ b/arch/xtensa/include/uapi/asm/socket.h > @@ -101,4 +101,6 @@ > > #define SO_CNX_ADVICE 53 > > +#define SCM_TIMESTAMPING_OPT_STATS 54 > + > #endif /* _XTENSA_SOCKET_H */ > diff --git a/include/linux/tcp.h b/include/linux/tcp.h > index d5d3bd8..00e0ee8 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) > tp->saved_syn = NULL; > } > > +struct sk_buff *tcp_get_timestamping_opt_stats(const struct sock *sk); > + > #endif /* _LINUX_TCP_H */ > diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h > index 67d632f..2c748dd 100644 > --- a/include/uapi/asm-generic/socket.h > +++ b/include/uapi/asm-generic/socket.h > @@ -92,4 +92,6 @@ > > #define SO_CNX_ADVICE 53 > > +#define SCM_TIMESTAMPING_OPT_STATS 54 > + > #endif /* __ASM_GENERIC_SOCKET_H */ > diff --git a/include/uapi/linux/net_tstamp.h b/include/uapi/linux/net_tstamp.h > index 264e515..464dcca 100644 > --- a/include/uapi/linux/net_tstamp.h > +++ b/include/uapi/linux/net_tstamp.h > @@ -25,8 +25,9 @@ enum { > SOF_TIMESTAMPING_TX_ACK = (1<<9), > SOF_TIMESTAMPING_OPT_CMSG = (1<<10), > SOF_TIMESTAMPING_OPT_TSONLY = (1<<11), > + SOF_TIMESTAMPING_OPT_STATS = (1<<12), > > - SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_OPT_TSONLY, > + SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_OPT_STATS, > SOF_TIMESTAMPING_MASK = (SOF_TIMESTAMPING_LAST - 1) | > SOF_TIMESTAMPING_LAST > }; > diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h > index 2863b66..c53de26 100644 > --- a/include/uapi/linux/tcp.h > +++ b/include/uapi/linux/tcp.h > @@ -220,6 +220,14 @@ struct tcp_info { > __u64 tcpi_sndbuf_limited; /* Time (usec) limited by send buffer */ > }; > > +/* netlink attributes types for SCM_TIMESTAMPING_OPT_STATS */ > +enum { > + TCP_NLA_PAD, > + TCP_NLA_BUSY, /* Time (usec) busy sending data */ > + TCP_NLA_RWND_LIMITED, /* Time (usec) limited by receive window */ > + TCP_NLA_SNDBUF_LIMITED, /* Time (usec) limited by send buffer */ > +}; > + > /* for TCP_MD5SIG socket option */ > #define TCP_MD5SIG_MAXKEYLEN 80 > > diff --git a/net/core/skbuff.c b/net/core/skbuff.c > index d1d1a5a..ea6fa95 100644 > --- a/net/core/skbuff.c > +++ b/net/core/skbuff.c > @@ -3839,10 +3839,18 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb, > if (!skb_may_tx_timestamp(sk, tsonly)) > return; > > - if (tsonly) > - skb = alloc_skb(0, GFP_ATOMIC); > - else > + if (tsonly) { > +#ifdef CONFIG_INET > + if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS) && > + sk->sk_protocol == IPPROTO_TCP && > + sk->sk_type == SOCK_STREAM) > + skb = tcp_get_timestamping_opt_stats(sk); > + else > +#endif > + skb = alloc_skb(0, GFP_ATOMIC); > + } else { > skb = skb_clone(orig_skb, GFP_ATOMIC); > + } > if (!skb) > return; > > diff --git a/net/core/sock.c b/net/core/sock.c > index 14e6145..d8c7f8c 100644 > --- a/net/core/sock.c > +++ b/net/core/sock.c > @@ -854,6 +854,13 @@ int sock_setsockopt(struct socket *sock, int level, int optname, > sk->sk_tskey = 0; > } > } > + > + if (val & SOF_TIMESTAMPING_OPT_STATS && > + !(val & SOF_TIMESTAMPING_OPT_TSONLY)) { > + ret = -EINVAL; > + break; > + } > + > sk->sk_tsflags = val; > if (val & SOF_TIMESTAMPING_RX_SOFTWARE) > sock_enable_timestamp(sk, > diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c > index cdde20f..1149b48 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) > } > EXPORT_SYMBOL_GPL(tcp_get_info); > > +struct sk_buff *tcp_get_timestamping_opt_stats(const struct sock *sk) > +{ > + const struct tcp_sock *tp = tcp_sk(sk); > + struct sk_buff *stats; > + struct tcp_info info; > + > + stats = alloc_skb(3 * nla_total_size_64bit(sizeof(u64)), GFP_ATOMIC); > + if (!stats) > + return NULL; > + > + tcp_get_info_chrono_stats(tp, &info); > + nla_put_u64_64bit(stats, TCP_NLA_BUSY, > + info.tcpi_busy_time, TCP_NLA_PAD); > + nla_put_u64_64bit(stats, TCP_NLA_RWND_LIMITED, > + info.tcpi_rwnd_limited, TCP_NLA_PAD); > + nla_put_u64_64bit(stats, TCP_NLA_SNDBUF_LIMITED, > + info.tcpi_sndbuf_limited, TCP_NLA_PAD); > + return stats; > +} > + > static int do_tcp_getsockopt(struct sock *sk, int level, > int optname, char __user *optval, int __user *optlen) > { > diff --git a/net/socket.c b/net/socket.c > index e2584c5..e631894 100644 > --- a/net/socket.c > +++ b/net/socket.c > @@ -693,9 +693,14 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, > (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) && > ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2)) > empty = 0; > - if (!empty) > + if (!empty) { > put_cmsg(msg, SOL_SOCKET, > SCM_TIMESTAMPING, sizeof(tss), &tss); > + > + if (skb->len && (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS)) > + put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_OPT_STATS, > + skb->len, skb->data); > + } > } > EXPORT_SYMBOL_GPL(__sock_recv_timestamp); > > -- > 2.8.0.rc3.226.g39d4020 > -- To unsubscribe from this list: send the line "unsubscribe linux-next" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html