Commit 92f37fd2ee805aa77925c1e64fd56088b46094fc

Authored by Eric Dumazet
Committed by David S. Miller
1 parent c7a3c5da35

[NET]: Adding SO_TIMESTAMPNS / SCM_TIMESTAMPNS support

Now that network timestamps use ktime_t infrastructure, we can add a new
SOL_SOCKET sockopt  SO_TIMESTAMPNS.

This command is similar to SO_TIMESTAMP, but permits transmission of
a 'timespec struct' instead of a 'timeval struct' control message.
(nanosecond resolution instead of microsecond)

Control message is labelled SCM_TIMESTAMPNS instead of SCM_TIMESTAMP

A socket cannot mix SO_TIMESTAMP and SO_TIMESTAMPNS : the two modes are
mutually exclusive.

sock_recv_timestamp() became too big to be fully inlined so I added a
__sock_recv_timestamp() helper function.

Signed-off-by: Eric Dumazet <dada1@cosmosbay.com>
CC: linux-arch@vger.kernel.org
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 25 changed files with 101 additions and 13 deletions Side-by-side Diff

include/asm-alpha/socket.h
... ... @@ -52,6 +52,8 @@
52 52  
53 53 #define SO_PEERSEC 30
54 54 #define SO_PASSSEC 34
  55 +#define SO_TIMESTAMPNS 35
  56 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
55 57  
56 58 /* Security levels - as per NRL IPv6 - don't actually do anything */
57 59 #define SO_SECURITY_AUTHENTICATION 19
include/asm-arm/socket.h
... ... @@ -49,6 +49,8 @@
49 49  
50 50 #define SO_PEERSEC 31
51 51 #define SO_PASSSEC 34
  52 +#define SO_TIMESTAMPNS 35
  53 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
52 54  
53 55 #endif /* _ASM_SOCKET_H */
include/asm-arm26/socket.h
... ... @@ -49,6 +49,8 @@
49 49  
50 50 #define SO_PEERSEC 31
51 51 #define SO_PASSSEC 34
  52 +#define SO_TIMESTAMPNS 35
  53 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
52 54  
53 55 #endif /* _ASM_SOCKET_H */
include/asm-avr32/socket.h
... ... @@ -49,6 +49,8 @@
49 49  
50 50 #define SO_PEERSEC 31
51 51 #define SO_PASSSEC 34
  52 +#define SO_TIMESTAMPNS 35
  53 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
52 54  
53 55 #endif /* __ASM_AVR32_SOCKET_H */
include/asm-cris/socket.h
... ... @@ -51,6 +51,8 @@
51 51  
52 52 #define SO_PEERSEC 31
53 53 #define SO_PASSSEC 34
  54 +#define SO_TIMESTAMPNS 35
  55 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
54 56  
55 57 #endif /* _ASM_SOCKET_H */
include/asm-frv/socket.h
... ... @@ -49,6 +49,8 @@
49 49  
50 50 #define SO_PEERSEC 31
51 51 #define SO_PASSSEC 34
  52 +#define SO_TIMESTAMPNS 35
  53 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
52 54  
53 55 #endif /* _ASM_SOCKET_H */
include/asm-h8300/socket.h
... ... @@ -49,6 +49,8 @@
49 49  
50 50 #define SO_PEERSEC 31
51 51 #define SO_PASSSEC 34
  52 +#define SO_TIMESTAMPNS 35
  53 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
52 54  
53 55 #endif /* _ASM_SOCKET_H */
include/asm-i386/socket.h
... ... @@ -49,6 +49,8 @@
49 49  
50 50 #define SO_PEERSEC 31
51 51 #define SO_PASSSEC 34
  52 +#define SO_TIMESTAMPNS 35
  53 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
52 54  
53 55 #endif /* _ASM_SOCKET_H */
include/asm-ia64/socket.h
... ... @@ -58,6 +58,8 @@
58 58  
59 59 #define SO_PEERSEC 31
60 60 #define SO_PASSSEC 34
  61 +#define SO_TIMESTAMPNS 35
  62 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
61 63  
62 64 #endif /* _ASM_IA64_SOCKET_H */
include/asm-m32r/socket.h
... ... @@ -49,6 +49,8 @@
49 49  
50 50 #define SO_PEERSEC 31
51 51 #define SO_PASSSEC 34
  52 +#define SO_TIMESTAMPNS 35
  53 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
52 54  
53 55 #endif /* _ASM_M32R_SOCKET_H */
include/asm-m68k/socket.h
... ... @@ -49,6 +49,8 @@
49 49  
50 50 #define SO_PEERSEC 31
51 51 #define SO_PASSSEC 34
  52 +#define SO_TIMESTAMPNS 35
  53 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
52 54  
53 55 #endif /* _ASM_SOCKET_H */
include/asm-mips/socket.h
... ... @@ -70,6 +70,8 @@
70 70 #define SO_SNDBUFFORCE 31
71 71 #define SO_RCVBUFFORCE 33
72 72 #define SO_PASSSEC 34
  73 +#define SO_TIMESTAMPNS 35
  74 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
73 75  
74 76 #ifdef __KERNEL__
75 77  
include/asm-parisc/socket.h
... ... @@ -33,6 +33,8 @@
33 33 #define SO_PEERCRED 0x4011
34 34 #define SO_TIMESTAMP 0x4012
35 35 #define SCM_TIMESTAMP SO_TIMESTAMP
  36 +#define SO_TIMESTAMPNS 0x4013
  37 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
36 38  
37 39 /* Security levels - as per NRL IPv6 - don't actually do anything */
38 40 #define SO_SECURITY_AUTHENTICATION 0x4016
include/asm-powerpc/socket.h
... ... @@ -56,6 +56,8 @@
56 56  
57 57 #define SO_PEERSEC 31
58 58 #define SO_PASSSEC 34
  59 +#define SO_TIMESTAMPNS 35
  60 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
59 61  
60 62 #endif /* _ASM_POWERPC_SOCKET_H */
include/asm-s390/socket.h
... ... @@ -57,6 +57,8 @@
57 57  
58 58 #define SO_PEERSEC 31
59 59 #define SO_PASSSEC 34
  60 +#define SO_TIMESTAMPNS 35
  61 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
60 62  
61 63 #endif /* _ASM_SOCKET_H */
include/asm-sh/socket.h
... ... @@ -49,6 +49,8 @@
49 49  
50 50 #define SO_PEERSEC 31
51 51 #define SO_PASSSEC 34
  52 +#define SO_TIMESTAMPNS 35
  53 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
52 54  
53 55 #endif /* __ASM_SH_SOCKET_H */
include/asm-sparc/socket.h
... ... @@ -49,6 +49,8 @@
49 49  
50 50 #define SO_PEERSEC 0x001e
51 51 #define SO_PASSSEC 0x001f
  52 +#define SO_TIMESTAMPNS 0x0021
  53 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
52 54  
53 55 /* Security levels - as per NRL IPv6 - don't actually do anything */
54 56 #define SO_SECURITY_AUTHENTICATION 0x5001
include/asm-sparc64/socket.h
... ... @@ -49,6 +49,8 @@
49 49  
50 50 #define SO_PEERSEC 0x001e
51 51 #define SO_PASSSEC 0x001f
  52 +#define SO_TIMESTAMPNS 0x0021
  53 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
52 54  
53 55 /* Security levels - as per NRL IPv6 - don't actually do anything */
54 56 #define SO_SECURITY_AUTHENTICATION 0x5001
include/asm-v850/socket.h
... ... @@ -49,6 +49,8 @@
49 49  
50 50 #define SO_PEERSEC 31
51 51 #define SO_PASSSEC 34
  52 +#define SO_TIMESTAMPNS 35
  53 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
52 54  
53 55 #endif /* __V850_SOCKET_H__ */
include/asm-x86_64/socket.h
... ... @@ -49,6 +49,8 @@
49 49  
50 50 #define SO_PEERSEC 31
51 51 #define SO_PASSSEC 34
  52 +#define SO_TIMESTAMPNS 35
  53 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
52 54  
53 55 #endif /* _ASM_SOCKET_H */
include/asm-xtensa/socket.h
... ... @@ -60,6 +60,8 @@
60 60 #define SO_ACCEPTCONN 30
61 61 #define SO_PEERSEC 31
62 62 #define SO_PASSSEC 34
  63 +#define SO_TIMESTAMPNS 35
  64 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
63 65  
64 66 #endif /* _XTENSA_SOCKET_H */
... ... @@ -390,6 +390,7 @@
390 390 SOCK_USE_WRITE_QUEUE, /* whether to call sk->sk_write_space in sock_wfree */
391 391 SOCK_DBG, /* %SO_DEBUG setting */
392 392 SOCK_RCVTSTAMP, /* %SO_TIMESTAMP setting */
  393 + SOCK_RCVTSTAMPNS, /* %SO_TIMESTAMPNS setting */
393 394 SOCK_LOCALROUTE, /* route locally only, %SO_DONTROUTE setting */
394 395 SOCK_QUEUE_SHRUNK, /* write queue has been shrunk recently */
395 396 };
396 397  
... ... @@ -1283,21 +1284,17 @@
1283 1284 return timeo == MAX_SCHEDULE_TIMEOUT ? -ERESTARTSYS : -EINTR;
1284 1285 }
1285 1286  
  1287 +extern void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
  1288 + struct sk_buff *skb);
  1289 +
1286 1290 static __inline__ void
1287 1291 sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
1288 1292 {
1289 1293 ktime_t kt = skb->tstamp;
1290 1294  
1291   - if (sock_flag(sk, SOCK_RCVTSTAMP)) {
1292   - struct timeval tv;
1293   - /* Race occurred between timestamp enabling and packet
1294   - receiving. Fill in the current time for now. */
1295   - if (kt.tv64 == 0)
1296   - kt = ktime_get_real();
1297   - skb->tstamp = kt;
1298   - tv = ktime_to_timeval(kt);
1299   - put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP, sizeof(tv), &tv);
1300   - } else
  1295 + if (sock_flag(sk, SOCK_RCVTSTAMP))
  1296 + __sock_recv_timestamp(msg, sk, skb);
  1297 + else
1301 1298 sk->sk_stamp = kt;
1302 1299 }
1303 1300  
... ... @@ -215,6 +215,7 @@
215 215 int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *data)
216 216 {
217 217 struct compat_timeval ctv;
  218 + struct compat_timespec cts;
218 219 struct compat_cmsghdr __user *cm = (struct compat_cmsghdr __user *) kmsg->msg_control;
219 220 struct compat_cmsghdr cmhdr;
220 221 int cmlen;
... ... @@ -229,7 +230,14 @@
229 230 ctv.tv_sec = tv->tv_sec;
230 231 ctv.tv_usec = tv->tv_usec;
231 232 data = &ctv;
232   - len = sizeof(struct compat_timeval);
  233 + len = sizeof(ctv);
  234 + }
  235 + if (level == SOL_SOCKET && type == SO_TIMESTAMPNS) {
  236 + struct timespec *ts = (struct timespec *)data;
  237 + cts.tv_sec = ts->tv_sec;
  238 + cts.tv_nsec = ts->tv_nsec;
  239 + data = &cts;
  240 + len = sizeof(cts);
233 241 }
234 242  
235 243 cmlen = CMSG_COMPAT_LEN(len);
... ... @@ -521,11 +521,18 @@
521 521 break;
522 522  
523 523 case SO_TIMESTAMP:
  524 + case SO_TIMESTAMPNS:
524 525 if (valbool) {
  526 + if (optname == SO_TIMESTAMP)
  527 + sock_reset_flag(sk, SOCK_RCVTSTAMPNS);
  528 + else
  529 + sock_set_flag(sk, SOCK_RCVTSTAMPNS);
525 530 sock_set_flag(sk, SOCK_RCVTSTAMP);
526 531 sock_enable_timestamp(sk);
527   - } else
  532 + } else {
528 533 sock_reset_flag(sk, SOCK_RCVTSTAMP);
  534 + sock_reset_flag(sk, SOCK_RCVTSTAMPNS);
  535 + }
529 536 break;
530 537  
531 538 case SO_RCVLOWAT:
... ... @@ -715,7 +722,12 @@
715 722 break;
716 723  
717 724 case SO_TIMESTAMP:
718   - v.val = sock_flag(sk, SOCK_RCVTSTAMP);
  725 + v.val = sock_flag(sk, SOCK_RCVTSTAMP) &&
  726 + !sock_flag(sk, SOCK_RCVTSTAMPNS);
  727 + break;
  728 +
  729 + case SO_TIMESTAMPNS:
  730 + v.val = sock_flag(sk, SOCK_RCVTSTAMPNS);
719 731 break;
720 732  
721 733 case SO_RCVTIMEO:
... ... @@ -585,6 +585,35 @@
585 585 return result;
586 586 }
587 587  
  588 +/*
  589 + * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
  590 + */
  591 +void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
  592 + struct sk_buff *skb)
  593 +{
  594 + ktime_t kt = skb->tstamp;
  595 +
  596 + if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
  597 + struct timeval tv;
  598 + /* Race occurred between timestamp enabling and packet
  599 + receiving. Fill in the current time for now. */
  600 + if (kt.tv64 == 0)
  601 + kt = ktime_get_real();
  602 + skb->tstamp = kt;
  603 + tv = ktime_to_timeval(kt);
  604 + put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, sizeof(tv), &tv);
  605 + } else {
  606 + struct timespec ts;
  607 + /* Race occurred between timestamp enabling and packet
  608 + receiving. Fill in the current time for now. */
  609 + if (kt.tv64 == 0)
  610 + kt = ktime_get_real();
  611 + skb->tstamp = kt;
  612 + ts = ktime_to_timespec(kt);
  613 + put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, sizeof(ts), &ts);
  614 + }
  615 +}
  616 +
588 617 static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock,
589 618 struct msghdr *msg, size_t size, int flags)
590 619 {