Skip to content

Commit 9718475

Browse files
deepa-hubdavem330
authored andcommitted
socket: Add SO_TIMESTAMPING_NEW
Add SO_TIMESTAMPING_NEW variant of socket timestamp options. This is the y2038 safe versions of the SO_TIMESTAMPING_OLD for all architectures. Signed-off-by: Deepa Dinamani <[email protected]> Acked-by: Willem de Bruijn <[email protected]> Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Signed-off-by: David S. Miller <[email protected]>
1 parent 887feae commit 9718475

File tree

12 files changed

+88
-30
lines changed

12 files changed

+88
-30
lines changed

arch/alpha/include/uapi/asm/socket.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,19 +117,20 @@
117117

118118
#define SO_TIMESTAMP_NEW 63
119119
#define SO_TIMESTAMPNS_NEW 64
120+
#define SO_TIMESTAMPING_NEW 65
120121

121122
#if !defined(__KERNEL__)
122123

123124
#if __BITS_PER_LONG == 64
124125
#define SO_TIMESTAMP SO_TIMESTAMP_OLD
125126
#define SO_TIMESTAMPNS SO_TIMESTAMPNS_OLD
127+
#define SO_TIMESTAMPING SO_TIMESTAMPING_OLD
126128
#else
127129
#define SO_TIMESTAMP (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMP_OLD : SO_TIMESTAMP_NEW)
128130
#define SO_TIMESTAMPNS (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPNS_OLD : SO_TIMESTAMPNS_NEW)
131+
#define SO_TIMESTAMPING (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPING_OLD : SO_TIMESTAMPING_NEW)
129132
#endif
130133

131-
#define SO_TIMESTAMPING SO_TIMESTAMPING_OLD
132-
133134
#define SCM_TIMESTAMP SO_TIMESTAMP
134135
#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
135136
#define SCM_TIMESTAMPING SO_TIMESTAMPING

arch/mips/include/uapi/asm/socket.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,19 +128,20 @@
128128

129129
#define SO_TIMESTAMP_NEW 63
130130
#define SO_TIMESTAMPNS_NEW 64
131+
#define SO_TIMESTAMPING_NEW 65
131132

132133
#if !defined(__KERNEL__)
133134

134135
#if __BITS_PER_LONG == 64
135136
#define SO_TIMESTAMP SO_TIMESTAMP_OLD
136137
#define SO_TIMESTAMPNS SO_TIMESTAMPNS_OLD
138+
#define SO_TIMESTAMPING SO_TIMESTAMPING_OLD
137139
#else
138140
#define SO_TIMESTAMP (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMP_OLD : SO_TIMESTAMP_NEW)
139141
#define SO_TIMESTAMPNS (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPNS_OLD : SO_TIMESTAMPNS_NEW)
142+
#define SO_TIMESTAMPING (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPING_OLD : SO_TIMESTAMPING_NEW)
140143
#endif
141144

142-
#define SO_TIMESTAMPING SO_TIMESTAMPING_OLD
143-
144145
#define SCM_TIMESTAMP SO_TIMESTAMP
145146
#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
146147
#define SCM_TIMESTAMPING SO_TIMESTAMPING

arch/parisc/include/uapi/asm/socket.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,19 +109,20 @@
109109

110110
#define SO_TIMESTAMP_NEW 0x4038
111111
#define SO_TIMESTAMPNS_NEW 0x4039
112+
#define SO_TIMESTAMPING_NEW 0x403A
112113

113114
#if !defined(__KERNEL__)
114115

115116
#if __BITS_PER_LONG == 64
116117
#define SO_TIMESTAMP SO_TIMESTAMP_OLD
117118
#define SO_TIMESTAMPNS SO_TIMESTAMPNS_OLD
119+
#define SO_TIMESTAMPING SO_TIMESTAMPING_OLD
118120
#else
119121
#define SO_TIMESTAMP (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMP_OLD : SO_TIMESTAMP_NEW)
120122
#define SO_TIMESTAMPNS (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPNS_OLD : SO_TIMESTAMPNS_NEW)
123+
#define SO_TIMESTAMPING (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPING_OLD : SO_TIMESTAMPING_NEW)
121124
#endif
122125

123-
#define SO_TIMESTAMPING SO_TIMESTAMPING_OLD
124-
125126
#define SCM_TIMESTAMP SO_TIMESTAMP
126127
#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
127128
#define SCM_TIMESTAMPING SO_TIMESTAMPING

arch/sparc/include/uapi/asm/socket.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,19 +110,20 @@
110110

111111
#define SO_TIMESTAMP_NEW 0x0041
112112
#define SO_TIMESTAMPNS_NEW 0x0042
113+
#define SO_TIMESTAMPING_NEW 0x0043
113114

114115
#if !defined(__KERNEL__)
115116

116117
#if __BITS_PER_LONG == 64
117118
#define SO_TIMESTAMP SO_TIMESTAMP_OLD
118119
#define SO_TIMESTAMPNS SO_TIMESTAMPNS_OLD
120+
#define SO_TIMESTAMPING SO_TIMESTAMPING_OLD
119121
#else
120122
#define SO_TIMESTAMP (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMP_OLD : SO_TIMESTAMP_NEW)
121123
#define SO_TIMESTAMPNS (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPNS_OLD : SO_TIMESTAMPNS_NEW)
124+
#define SO_TIMESTAMPING (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPING_OLD : SO_TIMESTAMPING_NEW)
122125
#endif
123126

124-
#define SO_TIMESTAMPING SO_TIMESTAMPING_OLD
125-
126127
#define SCM_TIMESTAMP SO_TIMESTAMP
127128
#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
128129
#define SCM_TIMESTAMPING SO_TIMESTAMPING

include/linux/socket.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,9 +349,17 @@ struct ucred {
349349
extern int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr);
350350
extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
351351

352+
struct timespec64;
352353
struct __kernel_timespec;
353354
struct old_timespec32;
354355

356+
struct scm_timestamping_internal {
357+
struct timespec64 ts[3];
358+
};
359+
360+
extern void put_cmsg_scm_timestamping64(struct msghdr *msg, struct scm_timestamping_internal *tss);
361+
extern void put_cmsg_scm_timestamping(struct msghdr *msg, struct scm_timestamping_internal *tss);
362+
355363
/* The __sys_...msg variants allow MSG_CMSG_COMPAT iff
356364
* forbid_cmsg_compat==false
357365
*/

include/uapi/asm-generic/socket.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,20 +112,21 @@
112112

113113
#define SO_TIMESTAMP_NEW 63
114114
#define SO_TIMESTAMPNS_NEW 64
115+
#define SO_TIMESTAMPING_NEW 65
115116

116117
#if !defined(__KERNEL__)
117118

118119
#if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__))
119120
/* on 64-bit and x32, avoid the ?: operator */
120121
#define SO_TIMESTAMP SO_TIMESTAMP_OLD
121122
#define SO_TIMESTAMPNS SO_TIMESTAMPNS_OLD
123+
#define SO_TIMESTAMPING SO_TIMESTAMPING_OLD
122124
#else
123125
#define SO_TIMESTAMP (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMP_OLD : SO_TIMESTAMP_NEW)
124126
#define SO_TIMESTAMPNS (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPNS_OLD : SO_TIMESTAMPNS_NEW)
127+
#define SO_TIMESTAMPING (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPING_OLD : SO_TIMESTAMPING_NEW)
125128
#endif
126129

127-
#define SO_TIMESTAMPING SO_TIMESTAMPING_OLD
128-
129130
#define SCM_TIMESTAMP SO_TIMESTAMP
130131
#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
131132
#define SCM_TIMESTAMPING SO_TIMESTAMPING

include/uapi/linux/errqueue.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ struct scm_timestamping {
4141
struct timespec ts[3];
4242
};
4343

44+
struct scm_timestamping64 {
45+
struct __kernel_timespec ts[3];
46+
};
47+
4448
/* The type of scm_timestamping, passed in sock_extended_err ee_info.
4549
* This defines the type of ts[0]. For SCM_TSTAMP_SND only, if ts[0]
4650
* is zero, then this is a hardware timestamp and recorded in ts[2].

net/core/scm.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <linux/pid.h>
3030
#include <linux/nsproxy.h>
3131
#include <linux/slab.h>
32+
#include <linux/errqueue.h>
3233

3334
#include <linux/uaccess.h>
3435

@@ -252,6 +253,32 @@ int put_cmsg(struct msghdr * msg, int level, int type, int len, void *data)
252253
}
253254
EXPORT_SYMBOL(put_cmsg);
254255

256+
void put_cmsg_scm_timestamping64(struct msghdr *msg, struct scm_timestamping_internal *tss_internal)
257+
{
258+
struct scm_timestamping64 tss;
259+
int i;
260+
261+
for (i = 0; i < ARRAY_SIZE(tss.ts); i++) {
262+
tss.ts[i].tv_sec = tss_internal->ts[i].tv_sec;
263+
tss.ts[i].tv_nsec = tss_internal->ts[i].tv_nsec;
264+
}
265+
266+
put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPING_NEW, sizeof(tss), &tss);
267+
}
268+
EXPORT_SYMBOL(put_cmsg_scm_timestamping64);
269+
270+
void put_cmsg_scm_timestamping(struct msghdr *msg, struct scm_timestamping_internal *tss_internal)
271+
{
272+
struct scm_timestamping tss;
273+
int i;
274+
275+
for (i = 0; i < ARRAY_SIZE(tss.ts); i++)
276+
tss.ts[i] = timespec64_to_timespec(tss_internal->ts[i]);
277+
278+
put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPING_OLD, sizeof(tss), &tss);
279+
}
280+
EXPORT_SYMBOL(put_cmsg_scm_timestamping);
281+
255282
void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm)
256283
{
257284
struct cmsghdr __user *cm

net/core/sock.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -890,6 +890,8 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
890890
}
891891
break;
892892

893+
case SO_TIMESTAMPING_NEW:
894+
sock_set_flag(sk, SOCK_TSTAMP_NEW);
893895
case SO_TIMESTAMPING_OLD:
894896
if (val & ~SOF_TIMESTAMPING_MASK) {
895897
ret = -EINVAL;
@@ -921,9 +923,13 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
921923
if (val & SOF_TIMESTAMPING_RX_SOFTWARE)
922924
sock_enable_timestamp(sk,
923925
SOCK_TIMESTAMPING_RX_SOFTWARE);
924-
else
926+
else {
927+
if (optname == SO_TIMESTAMPING_NEW)
928+
sock_reset_flag(sk, SOCK_TSTAMP_NEW);
929+
925930
sock_disable_timestamp(sk,
926931
(1UL << SOCK_TIMESTAMPING_RX_SOFTWARE));
932+
}
927933
break;
928934

929935
case SO_RCVLOWAT:

net/ipv4/tcp.c

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1844,22 +1844,22 @@ static int tcp_zerocopy_receive(struct sock *sk,
18441844
#endif
18451845

18461846
static void tcp_update_recv_tstamps(struct sk_buff *skb,
1847-
struct scm_timestamping *tss)
1847+
struct scm_timestamping_internal *tss)
18481848
{
18491849
if (skb->tstamp)
1850-
tss->ts[0] = ktime_to_timespec(skb->tstamp);
1850+
tss->ts[0] = ktime_to_timespec64(skb->tstamp);
18511851
else
1852-
tss->ts[0] = (struct timespec) {0};
1852+
tss->ts[0] = (struct timespec64) {0};
18531853

18541854
if (skb_hwtstamps(skb)->hwtstamp)
1855-
tss->ts[2] = ktime_to_timespec(skb_hwtstamps(skb)->hwtstamp);
1855+
tss->ts[2] = ktime_to_timespec64(skb_hwtstamps(skb)->hwtstamp);
18561856
else
1857-
tss->ts[2] = (struct timespec) {0};
1857+
tss->ts[2] = (struct timespec64) {0};
18581858
}
18591859

18601860
/* Similar to __sock_recv_timestamp, but does not require an skb */
18611861
static void tcp_recv_timestamp(struct msghdr *msg, const struct sock *sk,
1862-
struct scm_timestamping *tss)
1862+
struct scm_timestamping_internal *tss)
18631863
{
18641864
int new_tstamp = sock_flag(sk, SOCK_TSTAMP_NEW);
18651865
bool has_timestamping = false;
@@ -1873,8 +1873,10 @@ static void tcp_recv_timestamp(struct msghdr *msg, const struct sock *sk,
18731873
put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_NEW,
18741874
sizeof(kts), &kts);
18751875
} else {
1876+
struct timespec ts_old = timespec64_to_timespec(tss->ts[0]);
1877+
18761878
put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_OLD,
1877-
sizeof(tss->ts[0]), &tss->ts[0]);
1879+
sizeof(ts_old), &ts_old);
18781880
}
18791881
} else {
18801882
if (new_tstamp) {
@@ -1898,20 +1900,22 @@ static void tcp_recv_timestamp(struct msghdr *msg, const struct sock *sk,
18981900
if (sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE)
18991901
has_timestamping = true;
19001902
else
1901-
tss->ts[0] = (struct timespec) {0};
1903+
tss->ts[0] = (struct timespec64) {0};
19021904
}
19031905

19041906
if (tss->ts[2].tv_sec || tss->ts[2].tv_nsec) {
19051907
if (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE)
19061908
has_timestamping = true;
19071909
else
1908-
tss->ts[2] = (struct timespec) {0};
1910+
tss->ts[2] = (struct timespec64) {0};
19091911
}
19101912

19111913
if (has_timestamping) {
1912-
tss->ts[1] = (struct timespec) {0};
1913-
put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPING_OLD,
1914-
sizeof(*tss), tss);
1914+
tss->ts[1] = (struct timespec64) {0};
1915+
if (sock_flag(sk, SOCK_TSTAMP_NEW))
1916+
put_cmsg_scm_timestamping64(msg, tss);
1917+
else
1918+
put_cmsg_scm_timestamping(msg, tss);
19151919
}
19161920
}
19171921

@@ -1952,7 +1956,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
19521956
long timeo;
19531957
struct sk_buff *skb, *last;
19541958
u32 urg_hole = 0;
1955-
struct scm_timestamping tss;
1959+
struct scm_timestamping_internal tss;
19561960
bool has_tss = false;
19571961
bool has_cmsg;
19581962

0 commit comments

Comments
 (0)