Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Eric Dumazet and committed by
David S. Miller
92f37fd2 c7a3c5da

+101 -13
+2
include/asm-alpha/socket.h
··· 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
+2
include/asm-arm/socket.h
··· 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 */
+2
include/asm-arm26/socket.h
··· 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 */
+2
include/asm-avr32/socket.h
··· 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 */
+2
include/asm-cris/socket.h
··· 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 */ 56 58
+2
include/asm-frv/socket.h
··· 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 */ 54 56
+2
include/asm-h8300/socket.h
··· 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 */
+2
include/asm-i386/socket.h
··· 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 */
+2
include/asm-ia64/socket.h
··· 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 */
+2
include/asm-m32r/socket.h
··· 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 */
+2
include/asm-m68k/socket.h
··· 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 */
+2
include/asm-mips/socket.h
··· 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
+2
include/asm-parisc/socket.h
··· 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
+2
include/asm-powerpc/socket.h
··· 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 */
+2
include/asm-s390/socket.h
··· 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 */
+2
include/asm-sh/socket.h
··· 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 */
+2
include/asm-sparc/socket.h
··· 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
+2
include/asm-sparc64/socket.h
··· 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
+2
include/asm-v850/socket.h
··· 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__ */
+2
include/asm-x86_64/socket.h
··· 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 */
+2
include/asm-xtensa/socket.h
··· 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 */
+7 -10
include/net/sock.h
··· 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 }; ··· 1284 1283 return timeo == MAX_SCHEDULE_TIMEOUT ? -ERESTARTSYS : -EINTR; 1285 1284 } 1286 1285 1286 + extern void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, 1287 + struct sk_buff *skb); 1288 + 1287 1289 static __inline__ void 1288 1290 sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb) 1289 1291 { 1290 1292 ktime_t kt = skb->tstamp; 1291 1293 1292 - if (sock_flag(sk, SOCK_RCVTSTAMP)) { 1293 - struct timeval tv; 1294 - /* Race occurred between timestamp enabling and packet 1295 - receiving. Fill in the current time for now. */ 1296 - if (kt.tv64 == 0) 1297 - kt = ktime_get_real(); 1298 - skb->tstamp = kt; 1299 - tv = ktime_to_timeval(kt); 1300 - put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP, sizeof(tv), &tv); 1301 - } else 1294 + if (sock_flag(sk, SOCK_RCVTSTAMP)) 1295 + __sock_recv_timestamp(msg, sk, skb); 1296 + else 1302 1297 sk->sk_stamp = kt; 1303 1298 } 1304 1299
+9 -1
net/compat.c
··· 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; ··· 230 229 ctv.tv_sec = tv->tv_sec; 231 230 ctv.tv_usec = tv->tv_usec; 232 231 data = &ctv; 233 - len = sizeof(struct compat_timeval); 232 + len = sizeof(ctv); 233 + } 234 + if (level == SOL_SOCKET && type == SO_TIMESTAMPNS) { 235 + struct timespec *ts = (struct timespec *)data; 236 + cts.tv_sec = ts->tv_sec; 237 + cts.tv_nsec = ts->tv_nsec; 238 + data = &cts; 239 + len = sizeof(cts); 234 240 } 235 241 236 242 cmlen = CMSG_COMPAT_LEN(len);
+14 -2
net/core/sock.c
··· 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: ··· 722 715 break; 723 716 724 717 case SO_TIMESTAMP: 725 - v.val = sock_flag(sk, SOCK_RCVTSTAMP); 718 + v.val = sock_flag(sk, SOCK_RCVTSTAMP) && 719 + !sock_flag(sk, SOCK_RCVTSTAMPNS); 720 + break; 721 + 722 + case SO_TIMESTAMPNS: 723 + v.val = sock_flag(sk, SOCK_RCVTSTAMPNS); 726 724 break; 727 725 728 726 case SO_RCVTIMEO:
+29
net/socket.c
··· 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 {