diff mbox

[net-next,2/7] net-timestamp: MSG_TSTAMP one-shot tx timestamps

Message ID 1403624632-17327-3-git-send-email-willemb@google.com
State Changes Requested, archived
Delegated to: David Miller
Headers show

Commit Message

Willem de Bruijn June 24, 2014, 3:43 p.m. UTC
The kernel support datagram tx timestamping through socket option
SO_TIMESTAMPING. This patch add send() flag MSG_TSTAMP to allow
selectively requesting a timestamp for a single packet.

MSG_TSTAMP does not depend on SO_TIMESTAMPING. Enabling both
concurrently is redundant, but safe.

This patch adds support for IPv4 and IPv6 UDP sendmsg().

The feature maintains semantics of the socket option: with IP
fragmentation, only the first fragment is timestamped. This
should not happen, but can be forced, e.g., by disabling PMTU
on UDP.

Signed-off-by: Willem de Bruijn <willemb@google.com>
---
 include/linux/skbuff.h | 10 ++++++++++
 include/linux/socket.h |  1 +
 include/net/sock.h     |  5 +++--
 net/ipv4/udp.c         |  1 +
 net/ipv6/ip6_output.c  |  4 +++-
 net/socket.c           |  3 ++-
 6 files changed, 20 insertions(+), 4 deletions(-)

Comments

Richard Cochran June 25, 2014, 5:01 a.m. UTC | #1
On Tue, Jun 24, 2014 at 11:43:47AM -0400, Willem de Bruijn wrote:
> The kernel support datagram tx timestamping through socket option
> SO_TIMESTAMPING. This patch add send() flag MSG_TSTAMP to allow
> selectively requesting a timestamp for a single packet.

This is a nice idea. I wonder whether the drivers will react
correctly, need to think about it.

> MSG_TSTAMP does not depend on SO_TIMESTAMPING. Enabling both
> concurrently is redundant, but safe.
> 
> This patch adds support for IPv4 and IPv6 UDP sendmsg().

What about raw?

Thanks,
Richard

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Willem de Bruijn June 25, 2014, 9:20 p.m. UTC | #2
On Wed, Jun 25, 2014 at 1:01 AM, Richard Cochran
<richardcochran@gmail.com> wrote:
> On Tue, Jun 24, 2014 at 11:43:47AM -0400, Willem de Bruijn wrote:
>> The kernel support datagram tx timestamping through socket option
>> SO_TIMESTAMPING. This patch add send() flag MSG_TSTAMP to allow
>> selectively requesting a timestamp for a single packet.
>
> This is a nice idea. I wonder whether the drivers will react
> correctly, need to think about it.
>
>> MSG_TSTAMP does not depend on SO_TIMESTAMPING. Enabling both
>> concurrently is redundant, but safe.
>>
>> This patch adds support for IPv4 and IPv6 UDP sendmsg().
>
> What about raw?

I saw that bug/feature request earlier this month, too. I can add that
as future work to this patch set. It seems like a straightforward
extension.

>
> Thanks,
> Richard
>
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index ec89301..bec3ded 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -2736,6 +2736,16 @@  static inline void skb_tx_timestamp(struct sk_buff *skb)
 	sw_tx_timestamp(skb);
 }
 
+static inline u8 skbflags_tx_tstamp(int flags)
+{
+	u8 tx_flags = 0;
+
+	if (unlikely(flags & MSG_TSTAMP))
+		tx_flags |= SKBTX_SW_TSTAMP;
+
+	return tx_flags;
+}
+
 /**
  * skb_complete_wifi_ack - deliver skb with wifi status
  *
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 8e98297..ce4101e 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -253,6 +253,7 @@  struct ucred {
 #define MSG_MORE	0x8000	/* Sender will send more */
 #define MSG_WAITFORONE	0x10000	/* recvmmsg(): block until 1+ packets avail */
 #define MSG_SENDPAGE_NOTLAST 0x20000 /* sendpage() internal : not the last page */
+#define MSG_TSTAMP	0x100000
 #define MSG_EOF         MSG_FIN
 
 #define MSG_FASTOPEN	0x20000000	/* Send data in TCP SYN */
diff --git a/include/net/sock.h b/include/net/sock.h
index 07b7fcd..32cd1be 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -2138,14 +2138,15 @@  sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
 	 * - receive time stamping in software requested (SOCK_RCVTSTAMP
 	 *   or SOCK_TIMESTAMPING_RX_SOFTWARE)
 	 * - software time stamp available and wanted
-	 *   (SOCK_TIMESTAMPING_SOFTWARE)
+	 *   (SOCK_TIMESTAMPING_SOFTWARE || SKBTX_SW_TSTAMP)
 	 * - hardware time stamps available and wanted
 	 *   (SOCK_TIMESTAMPING_SYS_HARDWARE or
 	 *   SOCK_TIMESTAMPING_RAW_HARDWARE)
 	 */
 	if (sock_flag(sk, SOCK_RCVTSTAMP) ||
 	    sock_flag(sk, SOCK_TIMESTAMPING_RX_SOFTWARE) ||
-	    (kt.tv64 && sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE)) ||
+	    (kt.tv64 && (sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE) ||
+	     skb_shinfo(skb)->tx_flags & SKBTX_SW_TSTAMP)) ||
 	    (hwtstamps->hwtstamp.tv64 &&
 	     sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE)) ||
 	    (hwtstamps->syststamp.tv64 &&
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index d92f94b..9127aab 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -967,6 +967,7 @@  int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 	ipc.oif = sk->sk_bound_dev_if;
 
 	sock_tx_timestamp(sk, &ipc.tx_flags);
+	ipc.tx_flags |= skbflags_tx_tstamp(msg->msg_flags);
 
 	if (msg->msg_controllen) {
 		err = ip_cmsg_send(sock_net(sk), msg, &ipc,
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index cb9df0e..7306c5d 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1270,8 +1270,10 @@  emsgsize:
 	}
 
 	/* For UDP, check if TX timestamp is enabled */
-	if (sk->sk_type == SOCK_DGRAM)
+	if (sk->sk_type == SOCK_DGRAM) {
 		sock_tx_timestamp(sk, &tx_flags);
+		tx_flags |= skbflags_tx_tstamp(flags);
+	}
 
 	/*
 	 * Let's try using as much space as possible.
diff --git a/net/socket.c b/net/socket.c
index c001746..18ab44a 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -723,7 +723,8 @@  void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
 	}
 
 	memset(&tss, 0, sizeof(tss));
-	if (sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE) &&
+	if ((sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE) ||
+	     skb_shinfo(skb)->tx_flags & SKBTX_SW_TSTAMP) &&
 	    ktime_to_timespec_cond(skb->tstamp, &tss.ts_sw)) {
 		empty = 0;
 		tss.ts_type = SCM_TSTAMP_SND;