From patchwork Wed Apr 12 14:17:33 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Miroslav Lichvar X-Patchwork-Id: 750037 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3w35c90knFz9sNJ for ; Thu, 13 Apr 2017 00:18:01 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753411AbdDLOR7 (ORCPT ); Wed, 12 Apr 2017 10:17:59 -0400 Received: from mx1.redhat.com ([209.132.183.28]:46742 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753239AbdDLORx (ORCPT ); Wed, 12 Apr 2017 10:17:53 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 97F732DC342; Wed, 12 Apr 2017 14:17:47 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 97F732DC342 Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=mlichvar@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 97F732DC342 Received: from holly.brq.redhat.com. (holly.brq.redhat.com [10.34.24.121]) by smtp.corp.redhat.com (Postfix) with ESMTP id AD3047B8D8; Wed, 12 Apr 2017 14:17:45 +0000 (UTC) From: Miroslav Lichvar To: netdev@vger.kernel.org Cc: Richard Cochran , Willem de Bruijn , Soheil Hassas Yeganeh , "Keller, Jacob E" , Denny Page , Jiri Benc Subject: [RFC PATCH 3/7] net: add option to get information about timestamped packets Date: Wed, 12 Apr 2017 16:17:33 +0200 Message-Id: <20170412141737.5881-4-mlichvar@redhat.com> In-Reply-To: <20170412141737.5881-1-mlichvar@redhat.com> References: <20170412141737.5881-1-mlichvar@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Wed, 12 Apr 2017 14:17:47 +0000 (UTC) Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Extend the skb_shared_hwtstamps structure with the index of the real interface which received or transmitted the packet and the length of the packet at layer 2. Add a SOF_TIMESTAMPING_OPT_PKTINFO flag to the SO_TIMESTAMPING option to allow applications to get this information as struct scm_ts_pktinfo in SCM_TIMESTAMPING_PKTINFO control message. The index is mainly useful with bonding, bridges and other virtual interfaces, where IP_PKTINFO doesn't provide the index of the real interface. Applications may need it to determine which PHC made the timestamp. With the L2 length it is possible to transpose preamble timestamps to trailer timestamps, which are used in the NTP protocol. Instead of adding a new check to a common path that might slow down processing of received packets without hardware timestamps, the new fields are expected to be set by the drivers together with the hardware timestamp using the skb_hw_timestamp() function. CC: Richard Cochran CC: Willem de Bruijn Signed-off-by: Miroslav Lichvar --- Documentation/networking/timestamping.txt | 8 ++++++++ include/linux/skbuff.h | 22 ++++++++++++++++++++++ include/uapi/asm-generic/socket.h | 2 ++ include/uapi/linux/errqueue.h | 8 ++++++++ include/uapi/linux/net_tstamp.h | 3 ++- net/core/skbuff.c | 12 +++++++++--- net/socket.c | 11 ++++++++++- 7 files changed, 61 insertions(+), 5 deletions(-) diff --git a/Documentation/networking/timestamping.txt b/Documentation/networking/timestamping.txt index 96f5069..ed04aaa 100644 --- a/Documentation/networking/timestamping.txt +++ b/Documentation/networking/timestamping.txt @@ -193,6 +193,14 @@ SOF_TIMESTAMPING_OPT_STATS: the transmit timestamps, such as how long a certain block of data was limited by peer's receiver window. +SOF_TIMESTAMPING_OPT_PKTINFO: + + Optional information about timestamped packets. It includes the + index of the real interface which received or transmitted the + packet and its length at layer 2. If the device driver provides + this information, it will be attached in struct scm_ts_pktinfo as + a separate control message of type SCM_TIMESTAMPING_PKTINFO. + New applications are encouraged to pass SOF_TIMESTAMPING_OPT_ID to disambiguate timestamps and SOF_TIMESTAMPING_OPT_TSONLY to operate regardless of the setting of sysctl net.core.tstamp_allow_data. diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 741d75c..e91685a 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -349,6 +349,8 @@ static inline void skb_frag_size_sub(skb_frag_t *frag, int delta) * struct skb_shared_hwtstamps - hardware time stamps * @hwtstamp: hardware time stamp transformed into duration * since arbitrary point in time + * @if_index: index of the interface which timestamped the packet + * @pkt_length: length of the packet * * Software time stamps generated by ktime_get_real() are stored in * skb->tstamp. @@ -361,6 +363,8 @@ static inline void skb_frag_size_sub(skb_frag_t *frag, int delta) */ struct skb_shared_hwtstamps { ktime_t hwtstamp; + int if_index; + int pkt_length; }; /* Definitions for tx_flags in struct skb_shared_info */ @@ -3322,6 +3326,24 @@ static inline void skb_tx_timestamp(struct sk_buff *skb) } /** + * skb_hw_timestamp - set hardware timestamp with packet information + * + * @skb: A socket buffer. + * @hwtstamp: The hardware timestamp. + * @if_index: The index of the interface which timestamped the packet. + * @pkt_len: The length of the packet. + */ +static inline void skb_hw_timestamp(struct sk_buff *skb, ktime_t hwtstamp, + int if_index, int pkt_length) +{ + struct skb_shared_hwtstamps *hwtstamps = skb_hwtstamps(skb); + + hwtstamps->hwtstamp = hwtstamp; + hwtstamps->if_index = if_index; + hwtstamps->pkt_length = pkt_length; +} + +/** * skb_complete_wifi_ack - deliver skb with wifi status * * @skb: the original outgoing packet diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h index 2b48856..a5f6e81 100644 --- a/include/uapi/asm-generic/socket.h +++ b/include/uapi/asm-generic/socket.h @@ -100,4 +100,6 @@ #define SO_COOKIE 57 +#define SCM_TIMESTAMPING_PKTINFO 58 + #endif /* __ASM_GENERIC_SOCKET_H */ diff --git a/include/uapi/linux/errqueue.h b/include/uapi/linux/errqueue.h index 07bdce1..66d752f 100644 --- a/include/uapi/linux/errqueue.h +++ b/include/uapi/linux/errqueue.h @@ -43,4 +43,12 @@ enum { SCM_TSTAMP_ACK, /* data acknowledged by peer */ }; +/** + * struct scm_ts_pktinfo - information about HW-timestamped packets + */ +struct scm_ts_pktinfo { + int if_index; + int pkt_length; +}; + #endif /* _UAPI_LINUX_ERRQUEUE_H */ diff --git a/include/uapi/linux/net_tstamp.h b/include/uapi/linux/net_tstamp.h index 0749fb1..8397ecd 100644 --- a/include/uapi/linux/net_tstamp.h +++ b/include/uapi/linux/net_tstamp.h @@ -26,8 +26,9 @@ enum { SOF_TIMESTAMPING_OPT_CMSG = (1<<10), SOF_TIMESTAMPING_OPT_TSONLY = (1<<11), SOF_TIMESTAMPING_OPT_STATS = (1<<12), + SOF_TIMESTAMPING_OPT_PKTINFO = (1<<13), - SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_OPT_STATS, + SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_OPT_PKTINFO, SOF_TIMESTAMPING_MASK = (SOF_TIMESTAMPING_LAST - 1) | SOF_TIMESTAMPING_LAST }; diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 9f78109..7ca251f 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3888,10 +3888,16 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb, skb_shinfo(skb)->tskey = skb_shinfo(orig_skb)->tskey; } - if (hwtstamps) - *skb_hwtstamps(skb) = *hwtstamps; - else + if (hwtstamps) { + skb_hwtstamps(skb)->hwtstamp = hwtstamps->hwtstamp; + if (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) { + skb_hwtstamps(skb)->if_index = orig_skb->dev->ifindex; + skb_hwtstamps(skb)->pkt_length = orig_skb->mac_len + + orig_skb->len; + } + } else { skb->tstamp = ktime_get_real(); + } __skb_complete_tx_timestamp(skb, sk, tstype, opt_stats); } diff --git a/net/socket.c b/net/socket.c index eea9970..f272019 100644 --- a/net/socket.c +++ b/net/socket.c @@ -670,6 +670,7 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, { int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP); struct scm_timestamping tss; + struct scm_ts_pktinfo ts_pktinfo; int empty = 1; struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb); @@ -699,8 +700,16 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, empty = 0; if (shhwtstamps && (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) && - ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2)) + ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2)) { + if (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_PKTINFO && + shhwtstamps->if_index) { + ts_pktinfo.if_index = shhwtstamps->if_index; + ts_pktinfo.pkt_length = shhwtstamps->pkt_length; + put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_PKTINFO, + sizeof(ts_pktinfo), &ts_pktinfo); + } empty = 0; + } if (!empty) { put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING, sizeof(tss), &tss);