sock: accept SO_TIMESTAMPING flags in socket cmsg
authorSoheil Hassas Yeganeh <soheil@google.com>
Sun, 3 Apr 2016 03:08:09 +0000 (23:08 -0400)
committerDavid S. Miller <davem@davemloft.net>
Mon, 4 Apr 2016 19:50:30 +0000 (15:50 -0400)
Accept SO_TIMESTAMPING in control messages of the SOL_SOCKET level
as a basis to accept timestamping requests per write.

This implementation only accepts TX recording flags (i.e.,
SOF_TIMESTAMPING_TX_HARDWARE, SOF_TIMESTAMPING_TX_SOFTWARE,
SOF_TIMESTAMPING_TX_SCHED, and SOF_TIMESTAMPING_TX_ACK) in
control messages. Users need to set reporting flags (e.g.,
SOF_TIMESTAMPING_OPT_ID) per socket via socket options.

This commit adds a tsflags field in sockcm_cookie which is
set in __sock_cmsg_send. It only override the SOF_TIMESTAMPING_TX_*
bits in sockcm_cookie.tsflags allowing the control message
to override the recording behavior per write, yet maintaining
the value of other flags.

This patch implements validating the control message and setting
tsflags in struct sockcm_cookie. Next commits in this series will
actually implement timestamping per write for different protocols.

Signed-off-by: Soheil Hassas Yeganeh <soheil@google.com>
Acked-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/sock.h
include/uapi/linux/net_tstamp.h
net/core/sock.c

index 03772d4b06e6f0c1e2a58866a1f0973db2fe17f5..af012da5e608d14c3b1a490cad4d81e70b9f6677 100644 (file)
@@ -1418,6 +1418,7 @@ void sk_send_sigurg(struct sock *sk);
 
 struct sockcm_cookie {
        u32 mark;
+       u16 tsflags;
 };
 
 int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg,
index 6d1abea9746ea7b7d1128a0c1fd1a3ad5f45b96d..264e515de16f6ede07c962344ae0ac92f641d161 100644 (file)
@@ -31,6 +31,16 @@ enum {
                                 SOF_TIMESTAMPING_LAST
 };
 
+/*
+ * SO_TIMESTAMPING flags are either for recording a packet timestamp or for
+ * reporting the timestamp to user space.
+ * Recording flags can be set both via socket options and control messages.
+ */
+#define SOF_TIMESTAMPING_TX_RECORD_MASK        (SOF_TIMESTAMPING_TX_HARDWARE | \
+                                        SOF_TIMESTAMPING_TX_SOFTWARE | \
+                                        SOF_TIMESTAMPING_TX_SCHED | \
+                                        SOF_TIMESTAMPING_TX_ACK)
+
 /**
  * struct hwtstamp_config - %SIOCGHWTSTAMP and %SIOCSHWTSTAMP parameter
  *
index 0a64fe20ce5a903ba697e163752ff3a127c31662..315f5e57fffede023974e02d7cc7df943fb26703 100644 (file)
@@ -1870,6 +1870,8 @@ EXPORT_SYMBOL(sock_alloc_send_skb);
 int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg,
                     struct sockcm_cookie *sockc)
 {
+       u32 tsflags;
+
        switch (cmsg->cmsg_type) {
        case SO_MARK:
                if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
@@ -1878,6 +1880,17 @@ int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg,
                        return -EINVAL;
                sockc->mark = *(u32 *)CMSG_DATA(cmsg);
                break;
+       case SO_TIMESTAMPING:
+               if (cmsg->cmsg_len != CMSG_LEN(sizeof(u32)))
+                       return -EINVAL;
+
+               tsflags = *(u32 *)CMSG_DATA(cmsg);
+               if (tsflags & ~SOF_TIMESTAMPING_TX_RECORD_MASK)
+                       return -EINVAL;
+
+               sockc->tsflags &= ~SOF_TIMESTAMPING_TX_RECORD_MASK;
+               sockc->tsflags |= tsflags;
+               break;
        default:
                return -EINVAL;
        }