socket: Add SO_TIMESTAMP[NS]_NEW
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> Acked-by: Willem de Bruijn <willemb@google.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 Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
98bb03c865
Коммит
887feae36a
|
@ -3,6 +3,7 @@
|
||||||
#define _UAPI_ASM_SOCKET_H
|
#define _UAPI_ASM_SOCKET_H
|
||||||
|
|
||||||
#include <asm/sockios.h>
|
#include <asm/sockios.h>
|
||||||
|
#include <asm/bitsperlong.h>
|
||||||
|
|
||||||
/* For setsockopt(2) */
|
/* For setsockopt(2) */
|
||||||
/*
|
/*
|
||||||
|
@ -114,10 +115,19 @@
|
||||||
#define SO_TIMESTAMPNS_OLD 35
|
#define SO_TIMESTAMPNS_OLD 35
|
||||||
#define SO_TIMESTAMPING_OLD 37
|
#define SO_TIMESTAMPING_OLD 37
|
||||||
|
|
||||||
|
#define SO_TIMESTAMP_NEW 63
|
||||||
|
#define SO_TIMESTAMPNS_NEW 64
|
||||||
|
|
||||||
#if !defined(__KERNEL__)
|
#if !defined(__KERNEL__)
|
||||||
|
|
||||||
#define SO_TIMESTAMP SO_TIMESTAMP_OLD
|
#if __BITS_PER_LONG == 64
|
||||||
#define SO_TIMESTAMPNS SO_TIMESTAMPNS_OLD
|
#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 SO_TIMESTAMPING SO_TIMESTAMPING_OLD
|
||||||
|
|
||||||
#define SCM_TIMESTAMP SO_TIMESTAMP
|
#define SCM_TIMESTAMP SO_TIMESTAMP
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#define _UAPI_ASM_SOCKET_H
|
#define _UAPI_ASM_SOCKET_H
|
||||||
|
|
||||||
#include <asm/sockios.h>
|
#include <asm/sockios.h>
|
||||||
|
#include <asm/bitsperlong.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For setsockopt(2)
|
* For setsockopt(2)
|
||||||
|
@ -125,10 +126,19 @@
|
||||||
#define SO_TIMESTAMPNS_OLD 35
|
#define SO_TIMESTAMPNS_OLD 35
|
||||||
#define SO_TIMESTAMPING_OLD 37
|
#define SO_TIMESTAMPING_OLD 37
|
||||||
|
|
||||||
|
#define SO_TIMESTAMP_NEW 63
|
||||||
|
#define SO_TIMESTAMPNS_NEW 64
|
||||||
|
|
||||||
#if !defined(__KERNEL__)
|
#if !defined(__KERNEL__)
|
||||||
|
|
||||||
#define SO_TIMESTAMP SO_TIMESTAMP_OLD
|
#if __BITS_PER_LONG == 64
|
||||||
#define SO_TIMESTAMPNS SO_TIMESTAMPNS_OLD
|
#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 SO_TIMESTAMPING SO_TIMESTAMPING_OLD
|
||||||
|
|
||||||
#define SCM_TIMESTAMP SO_TIMESTAMP
|
#define SCM_TIMESTAMP SO_TIMESTAMP
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#define _UAPI_ASM_SOCKET_H
|
#define _UAPI_ASM_SOCKET_H
|
||||||
|
|
||||||
#include <asm/sockios.h>
|
#include <asm/sockios.h>
|
||||||
|
#include <asm/bitsperlong.h>
|
||||||
|
|
||||||
/* For setsockopt(2) */
|
/* For setsockopt(2) */
|
||||||
#define SOL_SOCKET 0xffff
|
#define SOL_SOCKET 0xffff
|
||||||
|
@ -106,10 +107,19 @@
|
||||||
#define SO_TIMESTAMPNS_OLD 0x4013
|
#define SO_TIMESTAMPNS_OLD 0x4013
|
||||||
#define SO_TIMESTAMPING_OLD 0x4020
|
#define SO_TIMESTAMPING_OLD 0x4020
|
||||||
|
|
||||||
|
#define SO_TIMESTAMP_NEW 0x4038
|
||||||
|
#define SO_TIMESTAMPNS_NEW 0x4039
|
||||||
|
|
||||||
#if !defined(__KERNEL__)
|
#if !defined(__KERNEL__)
|
||||||
|
|
||||||
#define SO_TIMESTAMP SO_TIMESTAMP_OLD
|
#if __BITS_PER_LONG == 64
|
||||||
#define SO_TIMESTAMPNS SO_TIMESTAMPNS_OLD
|
#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 SO_TIMESTAMPING SO_TIMESTAMPING_OLD
|
||||||
|
|
||||||
#define SCM_TIMESTAMP SO_TIMESTAMP
|
#define SCM_TIMESTAMP SO_TIMESTAMP
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#define _ASM_SOCKET_H
|
#define _ASM_SOCKET_H
|
||||||
|
|
||||||
#include <asm/sockios.h>
|
#include <asm/sockios.h>
|
||||||
|
#include <asm/bitsperlong.h>
|
||||||
|
|
||||||
/* For setsockopt(2) */
|
/* For setsockopt(2) */
|
||||||
#define SOL_SOCKET 0xffff
|
#define SOL_SOCKET 0xffff
|
||||||
|
@ -107,10 +108,19 @@
|
||||||
#define SO_TIMESTAMPNS_OLD 0x0021
|
#define SO_TIMESTAMPNS_OLD 0x0021
|
||||||
#define SO_TIMESTAMPING_OLD 0x0023
|
#define SO_TIMESTAMPING_OLD 0x0023
|
||||||
|
|
||||||
|
#define SO_TIMESTAMP_NEW 0x0041
|
||||||
|
#define SO_TIMESTAMPNS_NEW 0x0042
|
||||||
|
|
||||||
#if !defined(__KERNEL__)
|
#if !defined(__KERNEL__)
|
||||||
|
|
||||||
#define SO_TIMESTAMP SO_TIMESTAMP_OLD
|
#if __BITS_PER_LONG == 64
|
||||||
#define SO_TIMESTAMPNS SO_TIMESTAMPNS_OLD
|
#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 SO_TIMESTAMPING SO_TIMESTAMPING_OLD
|
||||||
|
|
||||||
#define SCM_TIMESTAMP SO_TIMESTAMP
|
#define SCM_TIMESTAMP SO_TIMESTAMP
|
||||||
|
|
|
@ -3498,12 +3498,30 @@ static inline void skb_get_timestamp(const struct sk_buff *skb,
|
||||||
*stamp = ns_to_kernel_old_timeval(skb->tstamp);
|
*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,
|
static inline void skb_get_timestampns(const struct sk_buff *skb,
|
||||||
struct timespec *stamp)
|
struct timespec *stamp)
|
||||||
{
|
{
|
||||||
*stamp = ktime_to_timespec(skb->tstamp);
|
*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)
|
static inline void __net_timestamp(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
skb->tstamp = ktime_get_real();
|
skb->tstamp = ktime_get_real();
|
||||||
|
|
|
@ -805,6 +805,7 @@ enum sock_flags {
|
||||||
SOCK_RCU_FREE, /* wait rcu grace period in sk_destruct() */
|
SOCK_RCU_FREE, /* wait rcu grace period in sk_destruct() */
|
||||||
SOCK_TXTIME,
|
SOCK_TXTIME,
|
||||||
SOCK_XDP, /* XDP is attached */
|
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))
|
#define SK_FLAGS_TIMESTAMP ((1UL << SOCK_TIMESTAMP) | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE))
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#define __ASM_GENERIC_SOCKET_H
|
#define __ASM_GENERIC_SOCKET_H
|
||||||
|
|
||||||
#include <asm/sockios.h>
|
#include <asm/sockios.h>
|
||||||
|
#include <asm/bitsperlong.h>
|
||||||
|
|
||||||
/* For setsockopt(2) */
|
/* For setsockopt(2) */
|
||||||
#define SOL_SOCKET 1
|
#define SOL_SOCKET 1
|
||||||
|
@ -109,10 +110,20 @@
|
||||||
#define SO_TIMESTAMPNS_OLD 35
|
#define SO_TIMESTAMPNS_OLD 35
|
||||||
#define SO_TIMESTAMPING_OLD 37
|
#define SO_TIMESTAMPING_OLD 37
|
||||||
|
|
||||||
|
#define SO_TIMESTAMP_NEW 63
|
||||||
|
#define SO_TIMESTAMPNS_NEW 64
|
||||||
|
|
||||||
#if !defined(__KERNEL__)
|
#if !defined(__KERNEL__)
|
||||||
|
|
||||||
#define SO_TIMESTAMP SO_TIMESTAMP_OLD
|
#if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__))
|
||||||
#define SO_TIMESTAMPNS SO_TIMESTAMPNS_OLD
|
/* 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 SO_TIMESTAMPING SO_TIMESTAMPING_OLD
|
||||||
|
|
||||||
#define SCM_TIMESTAMP SO_TIMESTAMP
|
#define SCM_TIMESTAMP SO_TIMESTAMP
|
||||||
|
|
|
@ -868,9 +868,16 @@ set_rcvbuf:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SO_TIMESTAMP_OLD:
|
case SO_TIMESTAMP_OLD:
|
||||||
|
case SO_TIMESTAMP_NEW:
|
||||||
case SO_TIMESTAMPNS_OLD:
|
case SO_TIMESTAMPNS_OLD:
|
||||||
|
case SO_TIMESTAMPNS_NEW:
|
||||||
if (valbool) {
|
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);
|
sock_reset_flag(sk, SOCK_RCVTSTAMPNS);
|
||||||
else
|
else
|
||||||
sock_set_flag(sk, SOCK_RCVTSTAMPNS);
|
sock_set_flag(sk, SOCK_RCVTSTAMPNS);
|
||||||
|
@ -879,6 +886,7 @@ set_rcvbuf:
|
||||||
} else {
|
} else {
|
||||||
sock_reset_flag(sk, SOCK_RCVTSTAMP);
|
sock_reset_flag(sk, SOCK_RCVTSTAMP);
|
||||||
sock_reset_flag(sk, SOCK_RCVTSTAMPNS);
|
sock_reset_flag(sk, SOCK_RCVTSTAMPNS);
|
||||||
|
sock_reset_flag(sk, SOCK_TSTAMP_NEW);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1245,11 +1253,20 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
|
||||||
|
|
||||||
case SO_TIMESTAMP_OLD:
|
case SO_TIMESTAMP_OLD:
|
||||||
v.val = sock_flag(sk, SOCK_RCVTSTAMP) &&
|
v.val = sock_flag(sk, SOCK_RCVTSTAMP) &&
|
||||||
|
!sock_flag(sk, SOCK_TSTAMP_NEW) &&
|
||||||
!sock_flag(sk, SOCK_RCVTSTAMPNS);
|
!sock_flag(sk, SOCK_RCVTSTAMPNS);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SO_TIMESTAMPNS_OLD:
|
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;
|
break;
|
||||||
|
|
||||||
case SO_TIMESTAMPING_OLD:
|
case SO_TIMESTAMPING_OLD:
|
||||||
|
|
|
@ -1861,20 +1861,37 @@ static void tcp_update_recv_tstamps(struct sk_buff *skb,
|
||||||
static void tcp_recv_timestamp(struct msghdr *msg, const struct sock *sk,
|
static void tcp_recv_timestamp(struct msghdr *msg, const struct sock *sk,
|
||||||
struct scm_timestamping *tss)
|
struct scm_timestamping *tss)
|
||||||
{
|
{
|
||||||
struct __kernel_old_timeval tv;
|
int new_tstamp = sock_flag(sk, SOCK_TSTAMP_NEW);
|
||||||
bool has_timestamping = false;
|
bool has_timestamping = false;
|
||||||
|
|
||||||
if (tss->ts[0].tv_sec || tss->ts[0].tv_nsec) {
|
if (tss->ts[0].tv_sec || tss->ts[0].tv_nsec) {
|
||||||
if (sock_flag(sk, SOCK_RCVTSTAMP)) {
|
if (sock_flag(sk, SOCK_RCVTSTAMP)) {
|
||||||
if (sock_flag(sk, SOCK_RCVTSTAMPNS)) {
|
if (sock_flag(sk, SOCK_RCVTSTAMPNS)) {
|
||||||
put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_OLD,
|
if (new_tstamp) {
|
||||||
sizeof(tss->ts[0]), &tss->ts[0]);
|
struct __kernel_timespec kts = {tss->ts[0].tv_sec, tss->ts[0].tv_nsec};
|
||||||
} else {
|
|
||||||
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,
|
put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_NEW,
|
||||||
sizeof(tv), &tv);
|
sizeof(kts), &kts);
|
||||||
|
} else {
|
||||||
|
put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_OLD,
|
||||||
|
sizeof(tss->ts[0]), &tss->ts[0]);
|
||||||
|
}
|
||||||
|
} 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
static int rds_enable_recvtstamp(struct sock *sk, char __user *optval,
|
||||||
int optlen)
|
int optlen, int optname)
|
||||||
{
|
{
|
||||||
int val, valbool;
|
int val, valbool;
|
||||||
|
|
||||||
|
@ -360,6 +360,9 @@ static int rds_enable_recvtstamp(struct sock *sk, char __user *optval,
|
||||||
|
|
||||||
valbool = val ? 1 : 0;
|
valbool = val ? 1 : 0;
|
||||||
|
|
||||||
|
if (optname == SO_TIMESTAMP_NEW)
|
||||||
|
sock_set_flag(sk, SOCK_TSTAMP_NEW);
|
||||||
|
|
||||||
if (valbool)
|
if (valbool)
|
||||||
sock_set_flag(sk, SOCK_RCVTSTAMP);
|
sock_set_flag(sk, SOCK_RCVTSTAMP);
|
||||||
else
|
else
|
||||||
|
@ -431,8 +434,9 @@ static int rds_setsockopt(struct socket *sock, int level, int optname,
|
||||||
release_sock(sock->sk);
|
release_sock(sock->sk);
|
||||||
break;
|
break;
|
||||||
case SO_TIMESTAMP_OLD:
|
case SO_TIMESTAMP_OLD:
|
||||||
|
case SO_TIMESTAMP_NEW:
|
||||||
lock_sock(sock->sk);
|
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);
|
release_sock(sock->sk);
|
||||||
break;
|
break;
|
||||||
case SO_RDS_MSG_RXPATH_LATENCY:
|
case SO_RDS_MSG_RXPATH_LATENCY:
|
||||||
|
|
|
@ -550,8 +550,20 @@ static int rds_cmsg_recv(struct rds_incoming *inc, struct msghdr *msg,
|
||||||
if ((inc->i_rx_tstamp != 0) &&
|
if ((inc->i_rx_tstamp != 0) &&
|
||||||
sock_flag(rds_rs_to_sk(rs), SOCK_RCVTSTAMP)) {
|
sock_flag(rds_rs_to_sk(rs), SOCK_RCVTSTAMP)) {
|
||||||
struct __kernel_old_timeval tv = ns_to_kernel_old_timeval(inc->i_rx_tstamp);
|
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)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
35
net/socket.c
35
net/socket.c
|
@ -705,6 +705,7 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
|
||||||
struct sk_buff *skb)
|
struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
|
int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
|
||||||
|
int new_tstamp = sock_flag(sk, SOCK_TSTAMP_NEW);
|
||||||
struct scm_timestamping tss;
|
struct scm_timestamping tss;
|
||||||
int empty = 1, false_tstamp = 0;
|
int empty = 1, false_tstamp = 0;
|
||||||
struct skb_shared_hwtstamps *shhwtstamps =
|
struct skb_shared_hwtstamps *shhwtstamps =
|
||||||
|
@ -719,15 +720,33 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
|
||||||
|
|
||||||
if (need_software_tstamp) {
|
if (need_software_tstamp) {
|
||||||
if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
|
if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
|
||||||
struct __kernel_old_timeval tv;
|
if (new_tstamp) {
|
||||||
skb_get_timestamp(skb, &tv);
|
struct __kernel_sock_timeval tv;
|
||||||
put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_OLD,
|
|
||||||
sizeof(tv), &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 {
|
} else {
|
||||||
struct timespec ts;
|
if (new_tstamp) {
|
||||||
skb_get_timestampns(skb, &ts);
|
struct __kernel_timespec ts;
|
||||||
put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_OLD,
|
|
||||||
sizeof(ts), &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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче