Configure and send TX sending hardware timestamp from
 user space application to the socket layer,
 to provide to the TC ETC Qdisc, and pass it to
 the interface network driver.

 - New flag for the SO_TXTIME socket option.
 - New access auxiliary data header to pass the
   TX sending hardware timestamp.
 - Add the hardware timestamp to the socket cookie.
 - Copy the TX sending hardware timestamp to the socket cookie.

Signed-off-by: Erez Geva <erez.geva....@siemens.com>
---
 include/net/sock.h                | 2 ++
 include/uapi/asm-generic/socket.h | 3 +++
 include/uapi/linux/net_tstamp.h   | 3 ++-
 net/core/sock.c                   | 9 +++++++++
 4 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/include/net/sock.h b/include/net/sock.h
index a5c6ae78df77..dd5bfd42b4e2 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -859,6 +859,7 @@ enum sock_flags {
        SOCK_SELECT_ERR_QUEUE, /* Wake select on error queue */
        SOCK_RCU_FREE, /* wait rcu grace period in sk_destruct() */
        SOCK_TXTIME,
+       SOCK_HW_TXTIME,
        SOCK_XDP, /* XDP is attached */
        SOCK_TSTAMP_NEW, /* Indicates 64 bit timestamps always */
 };
@@ -1690,6 +1691,7 @@ void sk_send_sigurg(struct sock *sk);
 
 struct sockcm_cookie {
        u64 transmit_time;
+       u64 transmit_hw_time;
        u32 mark;
        u16 tsflags;
 };
diff --git a/include/uapi/asm-generic/socket.h 
b/include/uapi/asm-generic/socket.h
index 77f7c1638eb1..16265b00c25a 100644
--- a/include/uapi/asm-generic/socket.h
+++ b/include/uapi/asm-generic/socket.h
@@ -119,6 +119,9 @@
 
 #define SO_DETACH_REUSEPORT_BPF 68
 
+#define SO_HW_TXTIME           69
+#define SCM_HW_TXTIME          SO_HW_TXTIME
+
 #if !defined(__KERNEL__)
 
 #if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__))
diff --git a/include/uapi/linux/net_tstamp.h b/include/uapi/linux/net_tstamp.h
index 7ed0b3d1c00a..dd51c9a99b1f 100644
--- a/include/uapi/linux/net_tstamp.h
+++ b/include/uapi/linux/net_tstamp.h
@@ -162,8 +162,9 @@ struct scm_ts_pktinfo {
 enum txtime_flags {
        SOF_TXTIME_DEADLINE_MODE = (1 << 0),
        SOF_TXTIME_REPORT_ERRORS = (1 << 1),
+       SOF_TXTIME_USE_HW_TIMESTAMP = (1 << 2),
 
-       SOF_TXTIME_FLAGS_LAST = SOF_TXTIME_REPORT_ERRORS,
+       SOF_TXTIME_FLAGS_LAST = SOF_TXTIME_USE_HW_TIMESTAMP,
        SOF_TXTIME_FLAGS_MASK = (SOF_TXTIME_FLAGS_LAST - 1) |
                                 SOF_TXTIME_FLAGS_LAST
 };
diff --git a/net/core/sock.c b/net/core/sock.c
index 727ea1cc633c..317dce54321b 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1227,6 +1227,8 @@ int sock_setsockopt(struct socket *sock, int level, int 
optname,
                        break;
                }
                sock_valbool_flag(sk, SOCK_TXTIME, true);
+               sock_valbool_flag(sk, SOCK_HW_TXTIME,
+                                 sk_txtime.flags & 
SOF_TXTIME_USE_HW_TIMESTAMP);
                sk->sk_clockid = sk_txtime.clockid;
                sk->sk_txtime_deadline_mode =
                        !!(sk_txtime.flags & SOF_TXTIME_DEADLINE_MODE);
@@ -2378,6 +2380,13 @@ int __sock_cmsg_send(struct sock *sk, struct msghdr 
*msg, struct cmsghdr *cmsg,
                        return -EINVAL;
                sockc->transmit_time = get_unaligned((u64 *)CMSG_DATA(cmsg));
                break;
+       case SCM_HW_TXTIME:
+               if (!sock_flag(sk, SOCK_HW_TXTIME))
+                       return -EINVAL;
+               if (cmsg->cmsg_len != CMSG_LEN(sizeof(u64)))
+                       return -EINVAL;
+               sockc->transmit_hw_time = get_unaligned((u64 *)CMSG_DATA(cmsg));
+               break;
        /* SCM_RIGHTS and SCM_CREDENTIALS are semantically in SOL_UNIX. */
        case SCM_RIGHTS:
        case SCM_CREDENTIALS:
-- 
2.20.1

Reply via email to