forked from mirrors/linux
		
	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:
		
							parent
							
								
									98bb03c865
								
							
						
					
					
						commit
						887feae36a
					
				
					 12 changed files with 171 additions and 32 deletions
				
			
		|  | @ -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 @@ int sock_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 		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 @@ int sock_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 		} 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); | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Deepa Dinamani
						Deepa Dinamani