lkml.org 
[lkml]   [2019]   [Jan]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v3 6/8] socket: Add SO_TIMESTAMP[NS]_NEW
    Date
    Add SO_TIMESTAMP_NEW and SO_TIMESTAMPNS_NEW variants of
    socket timestamp options.
    These are the y2038 safe versions of the SO_TIMESTAMP_OLD
    and SO_TIMESTAMPNS_OLD for all architectures.

    Note that the format of scm_timestamping.ts[0] is not changed
    in this patch.

    Signed-off-by: Deepa Dinamani <deepa.kernel@gmail.com>
    Cc: jejb@parisc-linux.org
    Cc: ralf@linux-mips.org
    Cc: rth@twiddle.net
    Cc: linux-alpha@vger.kernel.org
    Cc: linux-mips@linux-mips.org
    Cc: linux-parisc@vger.kernel.org
    Cc: linux-rdma@vger.kernel.org
    Cc: netdev@vger.kernel.org
    Cc: sparclinux@vger.kernel.org
    ---
    arch/alpha/include/uapi/asm/socket.h | 15 ++++++++++--
    arch/mips/include/uapi/asm/socket.h | 14 +++++++++--
    arch/parisc/include/uapi/asm/socket.h | 14 +++++++++--
    arch/sparc/include/uapi/asm/socket.h | 14 +++++++++--
    include/linux/skbuff.h | 18 ++++++++++++++
    include/net/sock.h | 1 +
    include/uapi/asm-generic/socket.h | 15 ++++++++++--
    net/core/sock.c | 21 ++++++++++++++--
    net/ipv4/tcp.c | 35 +++++++++++++++++++++------
    net/rds/af_rds.c | 8 ++++--
    net/rds/recv.c | 16 ++++++++++--
    net/socket.c | 35 +++++++++++++++++++++------
    12 files changed, 174 insertions(+), 32 deletions(-)

    diff --git a/arch/alpha/include/uapi/asm/socket.h b/arch/alpha/include/uapi/asm/socket.h
    index 00e45c80e574..352e3dc0b3d9 100644
    --- a/arch/alpha/include/uapi/asm/socket.h
    +++ b/arch/alpha/include/uapi/asm/socket.h
    @@ -3,6 +3,7 @@
    #define _UAPI_ASM_SOCKET_H

    #include <asm/sockios.h>
    +#include <asm/bitsperlong.h>

    /* For setsockopt(2) */
    /*
    @@ -110,12 +111,22 @@

    #define SO_TIMESTAMP_OLD 29
    #define SO_TIMESTAMPNS_OLD 35
    +
    #define SO_TIMESTAMPING_OLD 37

    +#define SO_TIMESTAMP_NEW 62
    +#define SO_TIMESTAMPNS_NEW 63
    +
    #if !defined(__KERNEL__)

    -#define SO_TIMESTAMP SO_TIMESTAMP_OLD
    -#define SO_TIMESTAMPNS SO_TIMESTAMPNS_OLD
    +#if __BITS_PER_LONG == 64
    +#define SO_TIMESTAMP SO_TIMESTAMP_OLD
    +#define SO_TIMESTAMPNS SO_TIMESTAMPNS_OLD
    +#else
    +#define SO_TIMESTAMP (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMP_OLD : SO_TIMESTAMP_NEW)
    +#define SO_TIMESTAMPNS (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPNS_OLD : SO_TIMESTAMPNS_NEW)
    +#endif
    +
    #define SO_TIMESTAMPING SO_TIMESTAMPING_OLD

    #define SCM_TIMESTAMP SO_TIMESTAMP
    diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h
    index b9553f770346..d1752e3f1248 100644
    --- a/arch/mips/include/uapi/asm/socket.h
    +++ b/arch/mips/include/uapi/asm/socket.h
    @@ -11,6 +11,7 @@
    #define _UAPI_ASM_SOCKET_H

    #include <asm/sockios.h>
    +#include <asm/bitsperlong.h>

    /*
    * For setsockopt(2)
    @@ -123,10 +124,19 @@
    #define SO_TIMESTAMPNS_OLD 35
    #define SO_TIMESTAMPING_OLD 37

    +#define SO_TIMESTAMP_NEW 62
    +#define SO_TIMESTAMPNS_NEW 63
    +
    #if !defined(__KERNEL__)

    -#define SO_TIMESTAMP SO_TIMESTAMP_OLD
    -#define SO_TIMESTAMPNS SO_TIMESTAMPNS_OLD
    +#if __BITS_PER_LONG == 64
    +#define SO_TIMESTAMP SO_TIMESTAMP_OLD
    +#define SO_TIMESTAMPNS SO_TIMESTAMPNS_OLD
    +#else
    +#define SO_TIMESTAMP (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMP_OLD : SO_TIMESTAMP_NEW)
    +#define SO_TIMESTAMPNS (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPNS_OLD : SO_TIMESTAMPNS_NEW)
    +#endif
    +
    #define SO_TIMESTAMPING SO_TIMESTAMPING_OLD

    #define SCM_TIMESTAMP SO_TIMESTAMP
    diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h
    index 37cdfe64bb27..0a45b668abd1 100644
    --- a/arch/parisc/include/uapi/asm/socket.h
    +++ b/arch/parisc/include/uapi/asm/socket.h
    @@ -3,6 +3,7 @@
    #define _UAPI_ASM_SOCKET_H

    #include <asm/sockios.h>
    +#include <asm/bitsperlong.h>

    /* For setsockopt(2) */
    #define SOL_SOCKET 0xffff
    @@ -104,10 +105,19 @@
    #define SO_TIMESTAMPNS_OLD 0x4013
    #define SO_TIMESTAMPING_OLD 0x4020

    +#define SO_TIMESTAMP_NEW 0x4037
    +#define SO_TIMESTAMPNS_NEW 0x4038
    +
    #if !defined(__KERNEL__)

    -#define SO_TIMESTAMP SO_TIMESTAMP_OLD
    -#define SO_TIMESTAMPNS SO_TIMESTAMPNS_OLD
    +#if __BITS_PER_LONG == 64
    +#define SO_TIMESTAMP SO_TIMESTAMP_OLD
    +#define SO_TIMESTAMPNS SO_TIMESTAMPNS_OLD
    +#else
    +#define SO_TIMESTAMP (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMP_OLD : SO_TIMESTAMP_NEW)
    +#define SO_TIMESTAMPNS (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPNS_OLD : SO_TIMESTAMPNS_NEW)
    +#endif
    +
    #define SO_TIMESTAMPING SO_TIMESTAMPING_OLD

    #define SCM_TIMESTAMP SO_TIMESTAMP
    diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h
    index ca573641fc6c..dc8527cae5a7 100644
    --- a/arch/sparc/include/uapi/asm/socket.h
    +++ b/arch/sparc/include/uapi/asm/socket.h
    @@ -3,6 +3,7 @@
    #define _ASM_SOCKET_H

    #include <asm/sockios.h>
    +#include <asm/bitsperlong.h>

    /* For setsockopt(2) */
    #define SOL_SOCKET 0xffff
    @@ -105,10 +106,19 @@
    #define SO_TIMESTAMPNS_OLD 0x0021
    #define SO_TIMESTAMPING_OLD 0x0023

    +#define SO_TIMESTAMP_NEW 0x0040
    +#define SO_TIMESTAMPNS_NEW 0x0041
    +
    #if !defined(__KERNEL__)

    -#define SO_TIMESTAMP SO_TIMESTAMP_OLD
    -#define SO_TIMESTAMPNS SO_TIMESTAMPNS_OLD
    +#if __BITS_PER_LONG == 64
    +#define SO_TIMESTAMP SO_TIMESTAMP_OLD
    +#define SO_TIMESTAMPNS SO_TIMESTAMPNS_OLD
    +#else
    +#define SO_TIMESTAMP (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMP_OLD : SO_TIMESTAMP_NEW)
    +#define SO_TIMESTAMPNS (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPNS_OLD : SO_TIMESTAMPNS_NEW)
    +#endif
    +
    #define SO_TIMESTAMPING SO_TIMESTAMPING_OLD

    #define SCM_TIMESTAMP SO_TIMESTAMP
    diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
    index 85f6226d106f..31c45d4f3896 100644
    --- a/include/linux/skbuff.h
    +++ b/include/linux/skbuff.h
    @@ -3492,12 +3492,30 @@ static inline void skb_get_timestamp(const struct sk_buff *skb,
    *stamp = ns_to_kernel_old_timeval(skb->tstamp);
    }

    +static inline void skb_get_new_timestamp(const struct sk_buff *skb,
    + struct __kernel_sock_timeval *stamp)
    +{
    + struct timespec64 ts = ktime_to_timespec64(skb->tstamp);
    +
    + stamp->tv_sec = ts.tv_sec;
    + stamp->tv_usec = ts.tv_nsec / 1000;
    +}
    +
    static inline void skb_get_timestampns(const struct sk_buff *skb,
    struct timespec *stamp)
    {
    *stamp = ktime_to_timespec(skb->tstamp);
    }

    +static inline void skb_get_new_timestampns(const struct sk_buff *skb,
    + struct __kernel_timespec *stamp)
    +{
    + struct timespec64 ts = ktime_to_timespec64(skb->tstamp);
    +
    + stamp->tv_sec = ts.tv_sec;
    + stamp->tv_nsec = ts.tv_nsec;
    +}
    +
    static inline void __net_timestamp(struct sk_buff *skb)
    {
    skb->tstamp = ktime_get_real();
    diff --git a/include/net/sock.h b/include/net/sock.h
    index 2b229f7be8eb..6679f3c120b0 100644
    --- a/include/net/sock.h
    +++ b/include/net/sock.h
    @@ -805,6 +805,7 @@ enum sock_flags {
    SOCK_RCU_FREE, /* wait rcu grace period in sk_destruct() */
    SOCK_TXTIME,
    SOCK_XDP, /* XDP is attached */
    + SOCK_TSTAMP_NEW, /* Indicates 64 bit timestamps always */
    };

    #define SK_FLAGS_TIMESTAMP ((1UL << SOCK_TIMESTAMP) | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE))
    diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h
    index dc704e41203d..0b0fae6b57a9 100644
    --- a/include/uapi/asm-generic/socket.h
    +++ b/include/uapi/asm-generic/socket.h
    @@ -3,6 +3,7 @@
    #define __ASM_GENERIC_SOCKET_H

    #include <asm/sockios.h>
    +#include <asm/bitsperlong.h>

    /* For setsockopt(2) */
    #define SOL_SOCKET 1
    @@ -107,10 +108,20 @@
    #define SO_TIMESTAMPNS_OLD 35
    #define SO_TIMESTAMPING_OLD 37

    +#define SO_TIMESTAMP_NEW 62
    +#define SO_TIMESTAMPNS_NEW 63
    +
    #if !defined(__KERNEL__)

    -#define SO_TIMESTAMP SO_TIMESTAMP_OLD
    -#define SO_TIMESTAMPNS SO_TIMESTAMPNS_OLD
    +#if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__))
    +/* on 64-bit and x32, avoid the ?: operator */
    +#define SO_TIMESTAMP SO_TIMESTAMP_OLD
    +#define SO_TIMESTAMPNS SO_TIMESTAMPNS_OLD
    +#else
    +#define SO_TIMESTAMP (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMP_OLD : SO_TIMESTAMP_NEW)
    +#define SO_TIMESTAMPNS (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPNS_OLD : SO_TIMESTAMPNS_NEW)
    +#endif
    +
    #define SO_TIMESTAMPING SO_TIMESTAMPING_OLD

    #define SCM_TIMESTAMP SO_TIMESTAMP
    diff --git a/net/core/sock.c b/net/core/sock.c
    index 492a8407130a..35c7cd9b2793 100644
    --- a/net/core/sock.c
    +++ b/net/core/sock.c
    @@ -816,9 +816,16 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
    break;

    case SO_TIMESTAMP_OLD:
    + case SO_TIMESTAMP_NEW:
    case SO_TIMESTAMPNS_OLD:
    + case SO_TIMESTAMPNS_NEW:
    if (valbool) {
    - if (optname == SO_TIMESTAMP_OLD)
    + if (optname == SO_TIMESTAMP_NEW || optname == SO_TIMESTAMPNS_NEW)
    + sock_set_flag(sk, SOCK_TSTAMP_NEW);
    + else
    + sock_reset_flag(sk, SOCK_TSTAMP_NEW);
    +
    + if (optname == SO_TIMESTAMP_OLD || optname == SO_TIMESTAMP_NEW)
    sock_reset_flag(sk, SOCK_RCVTSTAMPNS);
    else
    sock_set_flag(sk, SOCK_RCVTSTAMPNS);
    @@ -827,6 +834,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
    } else {
    sock_reset_flag(sk, SOCK_RCVTSTAMP);
    sock_reset_flag(sk, SOCK_RCVTSTAMPNS);
    + sock_reset_flag(sk, SOCK_TSTAMP_NEW);
    }
    break;

    @@ -1188,11 +1196,20 @@ int sock_getsockopt(struct socket *sock, int level, int optname,

    case SO_TIMESTAMP_OLD:
    v.val = sock_flag(sk, SOCK_RCVTSTAMP) &&
    + !sock_flag(sk, SOCK_TSTAMP_NEW) &&
    !sock_flag(sk, SOCK_RCVTSTAMPNS);
    break;

    case SO_TIMESTAMPNS_OLD:
    - v.val = sock_flag(sk, SOCK_RCVTSTAMPNS);
    + v.val = sock_flag(sk, SOCK_RCVTSTAMPNS) && !sock_flag(sk, SOCK_TSTAMP_NEW);
    + break;
    +
    + case SO_TIMESTAMP_NEW:
    + v.val = sock_flag(sk, SOCK_RCVTSTAMP) && sock_flag(sk, SOCK_TSTAMP_NEW);
    + break;
    +
    + case SO_TIMESTAMPNS_NEW:
    + v.val = sock_flag(sk, SOCK_RCVTSTAMPNS) && sock_flag(sk, SOCK_TSTAMP_NEW);
    break;

    case SO_TIMESTAMPING_OLD:
    diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
    index e6e2ea0ac0f4..44fe307af09c 100644
    --- a/net/ipv4/tcp.c
    +++ b/net/ipv4/tcp.c
    @@ -1864,20 +1864,39 @@ static void tcp_update_recv_tstamps(struct sk_buff *skb,
    static void tcp_recv_timestamp(struct msghdr *msg, const struct sock *sk,
    struct scm_timestamping *tss)
    {
    - struct __kernel_old_timeval tv;
    bool has_timestamping = false;
    + int new_tstamp = sock_flag(sk, SOCK_TSTAMP_NEW);

    if (tss->ts[0].tv_sec || tss->ts[0].tv_nsec) {
    if (sock_flag(sk, SOCK_RCVTSTAMP)) {
    if (sock_flag(sk, SOCK_RCVTSTAMPNS)) {
    - put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_OLD,
    - sizeof(tss->ts[0]), &tss->ts[0]);
    - } else {
    - tv.tv_sec = tss->ts[0].tv_sec;
    - tv.tv_usec = tss->ts[0].tv_nsec / 1000;
    + if (new_tstamp) {
    + struct __kernel_timespec kts = {tss->ts[0].tv_sec, tss->ts[0].tv_nsec};
    +
    + put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_NEW,
    + sizeof(kts), &kts);
    + } else {
    + struct timespec ts_old = tss->ts[0];

    - put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_OLD,
    - sizeof(tv), &tv);
    + put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_OLD,
    + sizeof(ts_old), &ts_old);
    + }
    + } else {
    + if (new_tstamp) {
    + struct __kernel_sock_timeval stv;
    +
    + stv.tv_sec = tss->ts[0].tv_sec;
    + stv.tv_usec = tss->ts[0].tv_nsec / 1000;
    + put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_NEW,
    + sizeof(stv), &stv);
    + } else {
    + struct __kernel_old_timeval tv;
    +
    + tv.tv_sec = tss->ts[0].tv_sec;
    + tv.tv_usec = tss->ts[0].tv_nsec / 1000;
    + put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_OLD,
    + sizeof(tv), &tv);
    + }
    }
    }

    diff --git a/net/rds/af_rds.c b/net/rds/af_rds.c
    index eeb4639adbe5..65571a6273c3 100644
    --- a/net/rds/af_rds.c
    +++ b/net/rds/af_rds.c
    @@ -348,7 +348,7 @@ static int rds_set_transport(struct rds_sock *rs, char __user *optval,
    }

    static int rds_enable_recvtstamp(struct sock *sk, char __user *optval,
    - int optlen)
    + int optlen, int optname)
    {
    int val, valbool;

    @@ -360,6 +360,9 @@ static int rds_enable_recvtstamp(struct sock *sk, char __user *optval,

    valbool = val ? 1 : 0;

    + if (optname == SO_TIMESTAMP_NEW)
    + sock_set_flag(sk, SOCK_TSTAMP_NEW);
    +
    if (valbool)
    sock_set_flag(sk, SOCK_RCVTSTAMP);
    else
    @@ -431,8 +434,9 @@ static int rds_setsockopt(struct socket *sock, int level, int optname,
    release_sock(sock->sk);
    break;
    case SO_TIMESTAMP_OLD:
    + case SO_TIMESTAMP_NEW:
    lock_sock(sock->sk);
    - ret = rds_enable_recvtstamp(sock->sk, optval, optlen);
    + ret = rds_enable_recvtstamp(sock->sk, optval, optlen, optname);
    release_sock(sock->sk);
    break;
    case SO_RDS_MSG_RXPATH_LATENCY:
    diff --git a/net/rds/recv.c b/net/rds/recv.c
    index 435bf2320cd3..6bb6b16ca270 100644
    --- a/net/rds/recv.c
    +++ b/net/rds/recv.c
    @@ -550,8 +550,20 @@ static int rds_cmsg_recv(struct rds_incoming *inc, struct msghdr *msg,
    if ((inc->i_rx_tstamp != 0) &&
    sock_flag(rds_rs_to_sk(rs), SOCK_RCVTSTAMP)) {
    struct __kernel_old_timeval tv = ns_to_kernel_old_timeval(inc->i_rx_tstamp);
    - ret = put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_OLD,
    - sizeof(tv), &tv);
    +
    + if (!sock_flag(rds_rs_to_sk(rs), SOCK_TSTAMP_NEW)) {
    + ret = put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_OLD,
    + sizeof(tv), &tv);
    + } else {
    + struct __kernel_sock_timeval sk_tv;
    +
    + sk_tv.tv_sec = tv.tv_sec;
    + sk_tv.tv_usec = tv.tv_usec;
    +
    + ret = put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_NEW,
    + sizeof(sk_tv), &sk_tv);
    + }
    +
    if (ret)
    goto out;
    }
    diff --git a/net/socket.c b/net/socket.c
    index 9cc281cdb9d9..1de96abd78d3 100644
    --- a/net/socket.c
    +++ b/net/socket.c
    @@ -705,6 +705,7 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
    struct sk_buff *skb)
    {
    int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
    + int new_tstamp = sock_flag(sk, SOCK_TSTAMP_NEW);
    struct scm_timestamping tss;
    int empty = 1, false_tstamp = 0;
    struct skb_shared_hwtstamps *shhwtstamps =
    @@ -719,15 +720,33 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,

    if (need_software_tstamp) {
    if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
    - struct __kernel_old_timeval tv;
    - skb_get_timestamp(skb, &tv);
    - put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_OLD,
    - sizeof(tv), &tv);
    + if (new_tstamp) {
    + struct __kernel_sock_timeval tv;
    +
    + skb_get_new_timestamp(skb, &tv);
    + put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_NEW,
    + sizeof(tv), &tv);
    + } else {
    + struct __kernel_old_timeval tv;
    +
    + skb_get_timestamp(skb, &tv);
    + put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_OLD,
    + sizeof(tv), &tv);
    + }
    } else {
    - struct timespec ts;
    - skb_get_timestampns(skb, &ts);
    - put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_OLD,
    - sizeof(ts), &ts);
    + if (new_tstamp) {
    + struct __kernel_timespec ts;
    +
    + skb_get_new_timestampns(skb, &ts);
    + put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_NEW,
    + sizeof(ts), &ts);
    + } else {
    + struct timespec ts;
    +
    + skb_get_timestampns(skb, &ts);
    + put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_OLD,
    + sizeof(ts), &ts);
    + }
    }
    }

    --
    2.17.1
    \
     
     \ /
      Last update: 2019-01-08 04:28    [W:3.300 / U:0.412 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site