Subject: Re: CLOCK_MONOTONIC datagram timestamps by the kernel

From: Eric Dumazet <[email-masked]>
Date: Fri, 02 Mar 2007 01:56:41 +0100

Stephen Hemminger a écrit :
> Another value since if someone turns on SO_TIMESTAMP they want usec (timeval)
> and SO_TIMESTAMPNS would be for nanosecond values. Trying to set both
> flags would be not allowed.
> 
> - original -
> 
>      If the SO_TIMESTAMP option is enabled on a SOCK_DGRAM socket, the
>      recvmsg(2) call will return a timestamp corresponding to when the data-
>      gram was received.  The msg_control field in the msghdr structure points
>      to a buffer that contains a cmsghdr structure followed by a struct
>      timeval.  The cmsghdr fields have the following values:
> 
>      cmsg_len = sizeof(struct timeval)
>      cmsg_level = SOL_SOCKET
>      cmsg_type = SCM_TIMESTAMP
> 
> - add -
>      If the SO_TIMESTAMPNS option is enabled on a SOCK_DGRAM socket,
> ...
>      cmsg_len = sizeof(struct timespec)
>      cmsg_level = SOL_SOCKET
>      cmsg_type = SCM_TIMESTAMPNS

I got it now, thank you :)

Here is the second version of the patch.

[NET] : introduce nanosecond time infrastructure for packet timestamping

It appears some machines are *really* fast and that micro second resolution is
a limiting factor.

This patch converts sk_buff timestamp to use new nanosecond infra (added in
2.6.21), and introduces a new ioctl SIOCGSTAMPNS to let applications access
nanosecond resolution (ie a timespec instead of timeval)

SO_TIMESTAMPNS is also introduced so that a recvmsg() on SOCK_DGRAM socket may 
  transfer a struct timespec (cmsg_type = SCM_TIMESTAMPNS). SO_TIMESTAMP and 
SO_TIMESTAMPNS are mutually exclusive.

Signed-off-by: Eric Dumazet <[email-masked]>

  fs/compat_ioctl.c                       |   17 +++++++++
  include/asm-alpha/socket.h              |    2 +
  include/asm-alpha/sockios.h             |    1
  include/asm-arm/socket.h                |    2 +
  include/asm-arm26/socket.h              |    2 +
  include/asm-arm26/sockios.h             |    3 +
  include/asm-avr32/socket.h              |    2 +
  include/asm-avr32/sockios.h             |    3 +
  include/asm-cris/sockios.h              |    3 +
  include/asm-frv/socket.h                |    2 +
  include/asm-frv/sockios.h               |    3 +
  include/asm-h8300/socket.h              |    2 +
  include/asm-h8300/sockios.h             |    3 +
  include/asm-i386/socket.h               |    2 +
  include/asm-i386/sockios.h              |    3 +
  include/asm-ia64/socket.h               |    2 +
  include/asm-ia64/sockios.h              |    3 +
  include/asm-m32r/socket.h               |    2 +
  include/asm-m32r/sockios.h              |    3 +
  include/asm-m68k/socket.h               |    2 +
  include/asm-m68k/sockios.h              |    3 +
  include/asm-mips/socket.h               |    2 +
  include/asm-mips/sockios.h              |    3 +
  include/asm-parisc/socket.h             |    2 +
  include/asm-parisc/sockios.h            |    3 +
  include/asm-powerpc/socket.h            |    2 +
  include/asm-powerpc/sockios.h           |    3 +
  include/asm-s390/socket.h               |    2 -
  include/asm-s390/sockios.h              |    3 +
  include/asm-sh/socket.h                 |    2 -
  include/asm-sh/sockios.h                |    1
  include/asm-sh64/sockios.h              |    1
  include/asm-sparc/socket.h              |    2 +
  include/asm-sparc/sockios.h             |    3 +
  include/asm-sparc64/socket.h            |    2 +
  include/asm-sparc64/sockios.h           |    3 +
  include/asm-v850/socket.h               |    2 +
  include/asm-v850/sockios.h              |    3 +
  include/asm-x86_64/socket.h             |    2 +
  include/asm-x86_64/sockios.h            |    3 +
  include/asm-xtensa/socket.h             |    2 +
  include/asm-xtensa/sockios.h            |    3 +
  include/linux/skbuff.h                  |   38 ++++++++++++++++------
  include/net/compat.h                    |    1
  include/net/sock.h                      |   31 ++++++++++++-----
  net/appletalk/ddp.c                     |    3 +
  net/atm/ioctl.c                         |    3 +
  net/ax25/af_ax25.c                      |    4 ++
  net/bridge/netfilter/ebt_ulog.c         |    7 ++--
  net/compat.c                            |   33 +++++++++++++++++--
  net/core/dev.c                          |    8 ++--
  net/core/sock.c                         |   36 +++++++++++++++++++-
  net/econet/af_econet.c                  |    5 ++
  net/ipv4/af_inet.c                      |    3 +
  net/ipv4/ip_fragment.c                  |    6 +--
  net/ipv4/netfilter/ip_queue.c           |    2 -
  net/ipv4/netfilter/ipt_ULOG.c           |    2 -
  net/ipv6/af_inet6.c                     |    3 +
  net/ipv6/netfilter/ip6_queue.c          |    2 -
  net/ipv6/netfilter/nf_conntrack_reasm.c |    6 +--
  net/ipv6/reassembly.c                   |    6 +--
  net/ipx/af_ipx.c                        |    2 -
  net/netfilter/nfnetlink_log.c           |    2 -
  net/netfilter/nfnetlink_queue.c         |    2 -
  net/netrom/af_netrom.c                  |    5 ++
  net/packet/af_packet.c                  |    4 +-
  net/rose/af_rose.c                      |    2 +
  net/sunrpc/svcsock.c                    |    9 ++---
  net/wanrouter/af_wanpipe.c              |    3 +
  net/x25/af_x25.c                        |   12 ++++++
  70 files changed, 280 insertions(+), 74 deletions(-)

--- linux-2.6.21-rc2/include/linux/skbuff.h	2007-02-28 20:54:35.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/linux/skbuff.h	2007-03-01 23:53:23.000000000 +0100
@@ -156,9 +156,13 @@ struct skb_shared_info {
 #define SKB_DATAREF_SHIFT 16
 #define SKB_DATAREF_MASK ((1 << SKB_DATAREF_SHIFT) - 1)
 
-struct skb_timeval {
+/*
+ * We use a special timespec like structure, because ABI constraints 
+ * make 'struct timespec' being 16 bytes on 64bit platforms.
+ */
+struct skb_timespec {
 	u32	off_sec;
-	u32	off_usec;
+	u32	off_nsec;
 };

@@ -233,7 +237,7 @@ struct sk_buff {
 	struct sk_buff		*prev;
 
 	struct sock		*sk;
-	struct skb_timeval	tstamp;
+	struct skb_timespec	tstamp;
 	struct net_device	*dev;
 	struct net_device	*input_dev;
 
@@ -1350,6 +1354,20 @@ extern void skb_init(void);
 extern void skb_add_mtu(int mtu);
 
 /**
+ *	skb_get_timestampns - get timestamp from a skb
+ *	@skb: skb to get stamp from
+ *	@stampns: pointer to struct timespec to store stamp in
+ *
+ *	Timestamps are stored in the skb as offsets to a base timestamp.
+ *	This function converts the offset back to a struct timespec and stores
+ *	it in stamp.
+ */
+static inline void skb_get_timestampns(const struct sk_buff *skb, struct timespec *stampns)
+{
+	stampns->tv_sec  = skb->tstamp.off_sec;
+	stampns->tv_nsec = skb->tstamp.off_nsec;
+}
+/**
  *	skb_get_timestamp - get timestamp from a skb
  *	@skb: skb to get stamp from
  *	@stamp: pointer to struct timeval to store stamp in
@@ -1361,22 +1379,22 @@ extern void skb_add_mtu(int mtu);
 static inline void skb_get_timestamp(const struct sk_buff *skb, struct timeval *stamp)
 {
 	stamp->tv_sec  = skb->tstamp.off_sec;
-	stamp->tv_usec = skb->tstamp.off_usec;
+	stamp->tv_usec = skb->tstamp.off_nsec / NSEC_PER_USEC;
 }
 
 /**
- * 	skb_set_timestamp - set timestamp of a skb
+ * 	skb_set_timestampns - set timestamp of a skb
  *	@skb: skb to set stamp of
- *	@stamp: pointer to struct timeval to get stamp from
+ *	@stamp: pointer to struct timespec to get stamp from
  *
  *	Timestamps are stored in the skb as offsets to a base timestamp.
- *	This function converts a struct timeval to an offset and stores
+ *	This function converts a struct timespec to an offset and stores
  *	it in the skb.
  */
-static inline void skb_set_timestamp(struct sk_buff *skb, const struct timeval *stamp)
+static inline void skb_set_timestampns(struct sk_buff *skb, const struct timespec *stampns)
 {
-	skb->tstamp.off_sec  = stamp->tv_sec;
-	skb->tstamp.off_usec = stamp->tv_usec;
+	skb->tstamp.off_sec  = stampns->tv_sec;
+	skb->tstamp.off_nsec = stampns->tv_nsec;
 }
 
 extern void __net_timestamp(struct sk_buff *skb);
--- linux-2.6.21-rc2/include/net/sock.h	2007-02-28 20:54:35.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/net/sock.h	2007-03-02 02:37:09.000000000 +0100
@@ -244,7 +244,7 @@ struct sock {
 	struct sk_filter      	*sk_filter;
 	void			*sk_protinfo;
 	struct timer_list	sk_timer;
-	struct timeval		sk_stamp;
+	struct timespec		sk_stamp;
 	struct socket		*sk_socket;
 	void			*sk_user_data;
 	struct page		*sk_sndmsg_page;
@@ -390,6 +390,7 @@ enum sock_flags {
 	SOCK_USE_WRITE_QUEUE, /* whether to call sk->sk_write_space in sock_wfree */
 	SOCK_DBG, /* %SO_DEBUG setting */
 	SOCK_RCVTSTAMP, /* %SO_TIMESTAMP setting */
+	SOCK_RCVTSTAMPNS, /* %SO_TIMESTAMPNS setting */
 	SOCK_LOCALROUTE, /* route locally only, %SO_DONTROUTE setting */
 	SOCK_QUEUE_SHRUNK, /* write queue has been shrunk recently */
 };
@@ -1307,19 +1308,30 @@ static inline int sock_intr_errno(long t
 static __inline__ void
 sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
 {
-	struct timeval stamp;
+	struct timespec ts;
+	struct timeval tv;
 
-	skb_get_timestamp(skb, &stamp);
+	skb_get_timestampns(skb, &ts);
 	if (sock_flag(sk, SOCK_RCVTSTAMP)) {
 		/* Race occurred between timestamp enabling and packet
 		   receiving.  Fill in the current time for now. */
-		if (stamp.tv_sec == 0)
-			do_gettimeofday(&stamp);
-		skb_set_timestamp(skb, &stamp);
-		put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP, sizeof(struct timeval),
-			 &stamp);
+		if (ts.tv_sec == 0)
+			getnstimeofday(&ts);
+		skb_set_timestampns(skb, &ts);
+		tv.tv_sec = ts.tv_sec;
+		tv.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+		put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, sizeof(struct timeval),
+			 &tv);
+	} else if (sock_flag(sk, SOCK_RCVTSTAMPNS)) {
+		/* Race occurred between timestamp enabling and packet
+		   receiving.  Fill in the current time for now. */
+		if (ts.tv_sec == 0)
+			getnstimeofday(&ts);
+		skb_set_timestampns(skb, &ts);
+		put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, sizeof(struct timespec),
+			 &ts);
 	} else
-		sk->sk_stamp = stamp;
+		sk->sk_stamp = ts;
 }
 
 /**
@@ -1350,6 +1362,7 @@ static inline void sk_eat_skb(struct soc
 
 extern void sock_enable_timestamp(struct sock *sk);
 extern int sock_get_timestamp(struct sock *, struct timeval __user *);
+extern int sock_get_timestampns(struct sock *, struct timespec __user *);
 
 /* 
  *	Enable debug/info messages 
--- linux-2.6.21-rc2/include/net/compat.h	2007-02-28 20:54:35.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/net/compat.h	2007-02-28 20:54:35.000000000 +0100
@@ -25,6 +25,7 @@ struct compat_cmsghdr {
 };
 
 extern int compat_sock_get_timestamp(struct sock *, struct timeval __user *);
+extern int compat_sock_get_timestampns(struct sock *, struct timespec __user *);
 
 #else /* defined(CONFIG_COMPAT) */
 #define compat_msghdr	msghdr		/* to avoid compiler warnings */
--- linux-2.6.21-rc2/net/core/sock.c	2007-02-28 20:54:35.000000000 +0100
+++ linux-2.6.21-rc2-ed/net/core/sock.c	2007-03-02 02:38:39.000000000 +0100
@@ -524,12 +524,22 @@ set_rcvbuf:
 
 		case SO_TIMESTAMP:
 			if (valbool)  {
+				sock_reset_flag(sk, SOCK_RCVTSTAMPNS);
 				sock_set_flag(sk, SOCK_RCVTSTAMP);
 				sock_enable_timestamp(sk);
 			} else
 				sock_reset_flag(sk, SOCK_RCVTSTAMP);
 			break;
 
+		case SO_TIMESTAMPNS:
+			if (valbool)  {
+				sock_reset_flag(sk, SOCK_RCVTSTAMP);
+				sock_set_flag(sk, SOCK_RCVTSTAMPNS);
+				sock_enable_timestamp(sk);
+			} else
+				sock_reset_flag(sk, SOCK_RCVTSTAMPNS);
+			break;
+
 		case SO_RCVLOWAT:
 			if (val < 0)
 				val = INT_MAX;
@@ -722,6 +732,10 @@ int sock_getsockopt(struct socket *sock,
 			v.val = sock_flag(sk, SOCK_RCVTSTAMP);
 			break;
 
+		case SO_TIMESTAMPNS:
+			v.val = sock_flag(sk, SOCK_RCVTSTAMPNS);
+			break;
+
 		case SO_RCVTIMEO:
 			lv=sizeof(struct timeval);
 			if (sk->sk_rcvtimeo == MAX_SCHEDULE_TIMEOUT) {
@@ -1513,7 +1527,7 @@ void sock_init_data(struct socket *sock,
 	sk->sk_sndtimeo		=	MAX_SCHEDULE_TIMEOUT;
 
 	sk->sk_stamp.tv_sec     = -1L;
-	sk->sk_stamp.tv_usec    = -1L;
+	sk->sk_stamp.tv_nsec    = -1L;
 
 	atomic_set(&sk->sk_refcnt, 1);
 }
@@ -1554,17 +1568,33 @@ EXPORT_SYMBOL(release_sock);
 
 int sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp)
 {
+	struct timeval tstamp;
 	if (!sock_flag(sk, SOCK_TIMESTAMP))
 		sock_enable_timestamp(sk);
 	if (sk->sk_stamp.tv_sec == -1)
 		return -ENOENT;
 	if (sk->sk_stamp.tv_sec == 0)
-		do_gettimeofday(&sk->sk_stamp);
-	return copy_to_user(userstamp, &sk->sk_stamp, sizeof(struct timeval)) ?
+		getnstimeofday(&sk->sk_stamp);
+	tstamp.tv_sec = sk->sk_stamp.tv_sec;
+	tstamp.tv_usec = sk->sk_stamp.tv_nsec / NSEC_PER_USEC;
+	return copy_to_user(userstamp, &tstamp, sizeof(struct timeval)) ?
 		-EFAULT : 0;
 }
 EXPORT_SYMBOL(sock_get_timestamp);
 
+int sock_get_timestampns(struct sock *sk, struct timespec __user *userstamp)
+{
+	if (!sock_flag(sk, SOCK_TIMESTAMP))
+		sock_enable_timestamp(sk);
+	if (sk->sk_stamp.tv_sec == -1)
+		return -ENOENT;
+	if (sk->sk_stamp.tv_sec == 0)
+		getnstimeofday(&sk->sk_stamp);
+	return copy_to_user(userstamp, &sk->sk_stamp, sizeof(struct timespec)) ?
+		-EFAULT : 0;
+}
+EXPORT_SYMBOL(sock_get_timestampns);
+
 void sock_enable_timestamp(struct sock *sk)
 {
 	if (!sock_flag(sk, SOCK_TIMESTAMP)) {
--- linux-2.6.21-rc2/net/core/dev.c	2007-02-28 21:16:43.000000000 +0100
+++ linux-2.6.21-rc2-ed/net/core/dev.c	2007-03-01 23:53:23.000000000 +0100
@@ -1036,10 +1036,10 @@ void net_disable_timestamp(void)
 
 void __net_timestamp(struct sk_buff *skb)
 {
-	struct timeval tv;
+	struct timespec ts;
 
-	do_gettimeofday(&tv);
-	skb_set_timestamp(skb, &tv);
+	getnstimeofday(&ts);
+	skb_set_timestampns(skb, &ts);
 }
 EXPORT_SYMBOL(__net_timestamp);
 
@@ -1049,7 +1049,7 @@ static inline void net_timestamp(struct 
 		__net_timestamp(skb);
 	else {
 		skb->tstamp.off_sec = 0;
-		skb->tstamp.off_usec = 0;
+		skb->tstamp.off_nsec = 0;
 	}
 }
 
--- linux-2.6.21-rc2/net/ipv4/ip_fragment.c	2007-02-28 20:54:35.000000000 +0100
+++ linux-2.6.21-rc2-ed/net/ipv4/ip_fragment.c	2007-03-01 23:53:23.000000000 +0100
@@ -92,7 +92,7 @@ struct ipq {
 	spinlock_t	lock;
 	atomic_t	refcnt;
 	struct timer_list timer;	/* when will this queue expire?		*/
-	struct timeval	stamp;
+	struct timespec	stamp;
 	int             iif;
 	unsigned int    rid;
 	struct inet_peer *peer;
@@ -592,7 +592,7 @@ static void ip_frag_queue(struct ipq *qp
 	if (skb->dev)
 		qp->iif = skb->dev->ifindex;
 	skb->dev = NULL;
-	skb_get_timestamp(skb, &qp->stamp);
+	skb_get_timestampns(skb, &qp->stamp);
 	qp->meat += skb->len;
 	atomic_add(skb->truesize, &ip_frag_mem);
 	if (offset == 0)
@@ -674,7 +674,7 @@ static struct sk_buff *ip_frag_reasm(str
 
 	head->next = NULL;
 	head->dev = dev;
-	skb_set_timestamp(head, &qp->stamp);
+	skb_set_timestampns(head, &qp->stamp);
 
 	iph = head->nh.iph;
 	iph->frag_off = 0;
--- linux-2.6.21-rc2/net/ipv4/af_inet.c	2007-02-28 20:54:35.000000000 +0100
+++ linux-2.6.21-rc2-ed/net/ipv4/af_inet.c	2007-02-28 20:54:35.000000000 +0100
@@ -755,6 +755,9 @@ int inet_ioctl(struct socket *sock, unsi
 		case SIOCGSTAMP:
 			err = sock_get_timestamp(sk, (struct timeval __user *)arg);
 			break;
+		case SIOCGSTAMPNS:
+			err = sock_get_timestampns(sk, (struct timespec __user *)arg);
+			break;
 		case SIOCADDRT:
 		case SIOCDELRT:
 		case SIOCRTMSG:
--- linux-2.6.21-rc2/net/ipv6/af_inet6.c	2007-03-01 12:34:35.000000000 +0100
+++ linux-2.6.21-rc2-ed/net/ipv6/af_inet6.c	2007-03-01 12:34:35.000000000 +0100
@@ -437,6 +437,9 @@ int inet6_ioctl(struct socket *sock, uns
 	case SIOCGSTAMP:
 		return sock_get_timestamp(sk, (struct timeval __user *)arg);
 
+	case SIOCGSTAMPNS:
+		return sock_get_timestampns(sk, (struct timespec __user *)arg);
+
 	case SIOCADDRT:
 	case SIOCDELRT:
 
--- linux-2.6.21-rc2/net/packet/af_packet.c	2007-02-28 21:23:12.000000000 +0100
+++ linux-2.6.21-rc2-ed/net/packet/af_packet.c	2007-03-01 23:53:23.000000000 +0100
@@ -661,7 +661,7 @@ static int tpacket_rcv(struct sk_buff *s
 		sock_enable_timestamp(sk);
 	}
 	h->tp_sec = skb->tstamp.off_sec;
-	h->tp_usec = skb->tstamp.off_usec;
+	h->tp_usec = skb->tstamp.off_nsec / NSEC_PER_USEC;
 
 	sll = (struct sockaddr_ll*)((u8*)h + TPACKET_ALIGN(sizeof(*h)));
 	sll->sll_halen = 0;
@@ -1543,6 +1543,8 @@ static int packet_ioctl(struct socket *s
 		}
 		case SIOCGSTAMP:
 			return sock_get_timestamp(sk, (struct timeval __user *)arg);
+		case SIOCGSTAMPNS:
+			return sock_get_timestampns(sk, (struct timespec __user *)arg);
 
 #ifdef CONFIG_INET
 		case SIOCADDRT:
--- linux-2.6.21-rc2/net/sunrpc/svcsock.c	2007-02-28 20:54:35.000000000 +0100
+++ linux-2.6.21-rc2-ed/net/sunrpc/svcsock.c	2007-03-01 23:53:23.000000000 +0100
@@ -806,15 +806,14 @@ svc_udp_recvfrom(struct svc_rqst *rqstp)
 		dprintk("svc: recvfrom returned error %d\n", -err);
 	}
 	if (skb->tstamp.off_sec == 0) {
-		struct timeval tv;
+		struct timespec ts;
 
-		tv.tv_sec = xtime.tv_sec;
-		tv.tv_usec = xtime.tv_nsec / NSEC_PER_USEC;
-		skb_set_timestamp(skb, &tv);
+		ts = current_kernel_time();
+		skb_set_timestampns(skb, &ts);
 		/* Don't enable netstamp, sunrpc doesn't
 		   need that much accuracy */
 	}
-	skb_get_timestamp(skb, &svsk->sk_sk->sk_stamp);
+	skb_get_timestampns(skb, &svsk->sk_sk->sk_stamp);
 	set_bit(SK_DATA, &svsk->sk_flags); /* there may be more data... */
 
 	/*
--- linux-2.6.21-rc2/net/compat.c	2007-02-28 20:54:35.000000000 +0100
+++ linux-2.6.21-rc2-ed/net/compat.c	2007-03-02 02:10:08.000000000 +0100
@@ -215,6 +215,7 @@ Efault:
 int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *data)
 {
 	struct compat_timeval ctv;
+	struct compat_timespec cts;
 	struct compat_cmsghdr __user *cm = (struct compat_cmsghdr __user *) kmsg->msg_control;
 	struct compat_cmsghdr cmhdr;
 	int cmlen;
@@ -231,6 +232,13 @@ int put_cmsg_compat(struct msghdr *kmsg,
 		data = &ctv;
 		len = sizeof(struct compat_timeval);
 	}
+	if (level == SOL_SOCKET && type == SO_TIMESTAMPNS) {
+		struct timespec *ts = (struct timespec *)data;
+		cts.tv_sec = ts->tv_sec;
+		cts.tv_nsec = ts->tv_nsec;
+		data = &cts;
+		len = sizeof(struct compat_timespec);
+	}
 
 	cmlen = CMSG_COMPAT_LEN(len);
 	if(kmsg->msg_controllen < cmlen) {
@@ -545,20 +553,41 @@ int compat_sock_get_timestamp(struct soc
 	struct compat_timeval __user *ctv =
 			(struct compat_timeval __user*) userstamp;
 	int err = -ENOENT;
+	long usec;
 
 	if (!sock_flag(sk, SOCK_TIMESTAMP))
 		sock_enable_timestamp(sk);
 	if (sk->sk_stamp.tv_sec == -1)
 		return err;
 	if (sk->sk_stamp.tv_sec == 0)
-		do_gettimeofday(&sk->sk_stamp);
+		getnstimeofday(&sk->sk_stamp);
+	usec = sk->sk_stamp.tv_nsec / NSEC_PER_USEC;
 	if (put_user(sk->sk_stamp.tv_sec, &ctv->tv_sec) ||
-			put_user(sk->sk_stamp.tv_usec, &ctv->tv_usec))
+			put_user(usec, &ctv->tv_usec))
 		err = -EFAULT;
 	return err;
 }
 EXPORT_SYMBOL(compat_sock_get_timestamp);
 
+int compat_sock_get_timestampns(struct sock *sk, struct timespec __user *userstamp)
+{
+	struct compat_timespec __user *ctv =
+			(struct compat_timespec __user*) userstamp;
+	int err = -ENOENT;
+
+	if (!sock_flag(sk, SOCK_TIMESTAMP))
+		sock_enable_timestamp(sk);
+	if (sk->sk_stamp.tv_sec == -1)
+		return err;
+	if (sk->sk_stamp.tv_sec == 0)
+		getnstimeofday(&sk->sk_stamp);
+	if (put_user(sk->sk_stamp.tv_sec, &ctv->tv_sec) ||
+			put_user(sk->sk_stamp.tv_nsec, &ctv->tv_nsec))
+		err = -EFAULT;
+	return err;
+}
+EXPORT_SYMBOL(compat_sock_get_timestampns);
+
 asmlinkage long compat_sys_getsockopt(int fd, int level, int optname,
 				char __user *optval, int __user *optlen)
 {
--- linux-2.6.21-rc2/fs/compat_ioctl.c	2007-03-01 13:01:27.000000000 +0100
+++ linux-2.6.21-rc2-ed/fs/compat_ioctl.c	2007-03-01 13:01:27.000000000 +0100
@@ -265,6 +265,22 @@ static int do_siocgstamp(unsigned int fd
 	}
 	return err;
 }
+static int do_siocgstampns(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct compat_timespec __user *up = compat_ptr(arg);
+	struct timespec ktv;
+	mm_segment_t old_fs = get_fs();
+	int err;
+
+	set_fs(KERNEL_DS);
+	err = sys_ioctl(fd, cmd, (unsigned long)&ktv);
+	set_fs(old_fs);
+	if(!err) {
+		err = put_user(ktv.tv_sec, &up->tv_sec);
+		err |= __put_user(ktv.tv_nsec, &up->tv_nsec);
+	}
+	return err;
+}
 
 struct ifmap32 {
 	compat_ulong_t mem_start;
@@ -2437,6 +2453,7 @@ HANDLE_IOCTL(SIOCBRDELIF, dev_ifsioc)
 /* Note SIOCRTMSG is no longer, so this is safe and * the user would have seen just an -EINVAL anyways. */
 HANDLE_IOCTL(SIOCRTMSG, ret_einval)
 HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp)
+HANDLE_IOCTL(SIOCGSTAMPNS, do_siocgstampns)
 #endif
 #ifdef CONFIG_BLOCK
 HANDLE_IOCTL(HDIO_GETGEO, hdio_getgeo)
--- linux-2.6.21-rc2/net/appletalk/ddp.c	2007-03-01 12:56:02.000000000 +0100
+++ linux-2.6.21-rc2-ed/net/appletalk/ddp.c	2007-03-01 12:56:02.000000000 +0100
@@ -1768,6 +1768,9 @@ static int atalk_ioctl(struct socket *so
 		case SIOCGSTAMP:
 			rc = sock_get_timestamp(sk, argp);
 			break;
+		case SIOCGSTAMPNS:
+			rc = sock_get_timestampns(sk, argp);
+			break;
 		/* Routing */
 		case SIOCADDRT:
 		case SIOCDELRT:
--- linux-2.6.21-rc2/net/ax25/af_ax25.c	2007-03-01 12:56:02.000000000 +0100
+++ linux-2.6.21-rc2-ed/net/ax25/af_ax25.c	2007-03-01 12:56:02.000000000 +0100
@@ -1711,6 +1711,10 @@ static int ax25_ioctl(struct socket *soc
 		res = sock_get_timestamp(sk, argp);
 		break;
 
+	case SIOCGSTAMPNS:
+		res = sock_get_timestampns(sk, argp);
+		break;
+
 	case SIOCAX25ADDUID:	/* Add a uid to the uid/call map table */
 	case SIOCAX25DELUID:	/* Delete a uid from the uid/call map table */
 	case SIOCAX25GETUID: {
--- linux-2.6.21-rc2/net/atm/ioctl.c	2007-03-01 12:56:02.000000000 +0100
+++ linux-2.6.21-rc2-ed/net/atm/ioctl.c	2007-03-01 12:56:02.000000000 +0100
@@ -82,6 +82,9 @@ int vcc_ioctl(struct socket *sock, unsig
 		case SIOCGSTAMP: /* borrowed from IP */
 			error = sock_get_timestamp(sk, argp);
 			goto done;
+		case SIOCGSTAMPNS: /* borrowed from IP */
+			error = sock_get_timestampns(sk, argp);
+			goto done;
 		case ATM_SETSC:
 			printk(KERN_WARNING "ATM_SETSC is obsolete\n");
 			error = 0;
--- linux-2.6.21-rc2/net/econet/af_econet.c	2007-02-28 20:54:35.000000000 +0100
+++ linux-2.6.21-rc2-ed/net/econet/af_econet.c	2007-03-01 23:53:23.000000000 +0100
@@ -162,7 +162,7 @@ static int econet_recvmsg(struct kiocb *
 	err = memcpy_toiovec(msg->msg_iov, skb->data, copied);
 	if (err)
 		goto out_free;
-	skb_get_timestamp(skb, &sk->sk_stamp);
+	skb_get_timestampns(skb, &sk->sk_stamp);
 
 	if (msg->msg_name)
 		memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
@@ -727,6 +727,9 @@ static int econet_ioctl(struct socket *s
 		case SIOCGSTAMP:
 			return sock_get_timestamp(sk, argp);
 
+		case SIOCGSTAMPNS:
+			return sock_get_timestampns(sk, argp);
+
 		case SIOCSIFADDR:
 		case SIOCGIFADDR:
 			return ec_dev_ioctl(sock, cmd, argp);
--- linux-2.6.21-rc2/net/ipx/af_ipx.c	2007-02-28 20:54:35.000000000 +0100
+++ linux-2.6.21-rc2-ed/net/ipx/af_ipx.c	2007-03-01 23:53:23.000000000 +0100
@@ -1808,7 +1808,7 @@ static int ipx_recvmsg(struct kiocb *ioc
 	if (rc)
 		goto out_free;
 	if (skb->tstamp.off_sec)
-		skb_get_timestamp(skb, &sk->sk_stamp);
+		skb_get_timestampns(skb, &sk->sk_stamp);
 
 	msg->msg_namelen = sizeof(*sipx);
 
--- linux-2.6.21-rc2/net/netrom/af_netrom.c	2007-03-01 12:56:02.000000000 +0100
+++ linux-2.6.21-rc2-ed/net/netrom/af_netrom.c	2007-03-01 12:56:02.000000000 +0100
@@ -1208,6 +1208,11 @@ static int nr_ioctl(struct socket *sock,
 		ret = sock_get_timestamp(sk, argp);
 		release_sock(sk);
 		return ret;
+	case SIOCGSTAMPNS:
+		lock_sock(sk);
+		ret = sock_get_timestampns(sk, argp);
+		release_sock(sk);
+		return ret;
 
 	case SIOCGIFADDR:
 	case SIOCSIFADDR:
--- linux-2.6.21-rc2/net/rose/af_rose.c	2007-03-01 12:56:02.000000000 +0100
+++ linux-2.6.21-rc2-ed/net/rose/af_rose.c	2007-03-01 12:56:02.000000000 +0100
@@ -1271,6 +1271,8 @@ static int rose_ioctl(struct socket *soc
 
 	case SIOCGSTAMP:
 		return sock_get_timestamp(sk, (struct timeval __user *) argp);
+	case SIOCGSTAMPNS:
+		return sock_get_timestampns(sk, (struct timespec __user *) argp);
 
 	case SIOCGIFADDR:
 	case SIOCSIFADDR:
--- linux-2.6.21-rc2/net/wanrouter/af_wanpipe.c	2007-03-01 12:56:02.000000000 +0100
+++ linux-2.6.21-rc2-ed/net/wanrouter/af_wanpipe.c	2007-03-01 12:56:02.000000000 +0100
@@ -1770,6 +1770,9 @@ static int wanpipe_ioctl(struct socket *
 		case SIOCGSTAMP:
 			return sock_get_timestamp(sk, (struct timeval __user *)arg);
 
+		case SIOCGSTAMPNS:
+			return sock_get_timestampns(sk, (struct timespec __user *)arg);
+
 		case SIOC_WANPIPE_CHECK_TX:
 
 			return atomic_read(&sk->sk_wmem_alloc);
--- linux-2.6.21-rc2/net/x25/af_x25.c	2007-03-01 12:56:02.000000000 +0100
+++ linux-2.6.21-rc2-ed/net/x25/af_x25.c	2007-03-02 00:58:10.000000000 +0100
@@ -1280,6 +1280,12 @@ static int x25_ioctl(struct socket *sock
 				rc = sock_get_timestamp(sk,
 						(struct timeval __user *)argp);
 			break;
+		case SIOCGSTAMPNS:
+			rc = -EINVAL;
+			if (sk)
+				rc = sock_get_timestampns(sk,
+						(struct timespec __user *)argp);
+			break;
 		case SIOCGIFADDR:
 		case SIOCSIFADDR:
 		case SIOCGIFDSTADDR:
@@ -1521,6 +1527,12 @@ static int compat_x25_ioctl(struct socke
 			rc = compat_sock_get_timestamp(sk,
 					(struct timeval __user*)argp);
 		break;
+	case SIOCGSTAMPNS:
+		rc = -EINVAL;
+		if (sk)
+			rc = compat_sock_get_timestampns(sk,
+					(struct timespec __user*)argp);
+		break;
 	case SIOCGIFADDR:
 	case SIOCSIFADDR:
 	case SIOCGIFDSTADDR:
--- linux-2.6.21-rc2/net/bridge/netfilter/ebt_ulog.c	2007-03-01 13:09:56.000000000 +0100
+++ linux-2.6.21-rc2-ed/net/bridge/netfilter/ebt_ulog.c	2007-03-01 23:53:23.000000000 +0100
@@ -130,6 +130,7 @@ static void ebt_ulog_packet(unsigned int
 	unsigned int group = uloginfo->nlgroup;
 	ebt_ulog_buff_t *ub = &ulog_buffers[group];
 	spinlock_t *lock = &ub->lock;
+	struct timespec ts;
 
 	if ((uloginfo->cprange == 0) ||
 	    (uloginfo->cprange > skb->len + ETH_HLEN))
@@ -164,9 +165,11 @@ static void ebt_ulog_packet(unsigned int
 
 	/* Fill in the ulog data */
 	pm->version = EBT_ULOG_VERSION;
-	do_gettimeofday(&pm->stamp);
+	getnstimeofday(&ts);
+	pm->stamp.tv_sec = ts.tv_sec;
+	pm->stamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
 	if (ub->qlen == 1)
-		skb_set_timestamp(ub->skb, &pm->stamp);
+		skb_set_timestampns(ub->skb, &ts);
 	pm->data_len = copy_len;
 	pm->mark = skb->mark;
 	pm->hook = hooknr;
--- linux-2.6.21-rc2/net/ipv4/netfilter/ipt_ULOG.c	2007-03-02 00:37:08.000000000 +0100
+++ linux-2.6.21-rc2-ed/net/ipv4/netfilter/ipt_ULOG.c	2007-03-02 00:37:08.000000000 +0100
@@ -237,7 +237,7 @@ static void ipt_ulog_packet(unsigned int
 	/* copy hook, prefix, timestamp, payload, etc. */
 	pm->data_len = copy_len;
 	pm->timestamp_sec = skb->tstamp.off_sec;
-	pm->timestamp_usec = skb->tstamp.off_usec;
+	pm->timestamp_usec = skb->tstamp.off_nsec / NSEC_PER_USEC;
 	pm->mark = skb->mark;
 	pm->hook = hooknum;
 	if (prefix != NULL)
--- linux-2.6.21-rc2/net/ipv4/netfilter/ip_queue.c	2007-03-02 00:38:53.000000000 +0100
+++ linux-2.6.21-rc2-ed/net/ipv4/netfilter/ip_queue.c	2007-03-02 00:38:53.000000000 +0100
@@ -242,7 +242,7 @@ ipq_build_packet_message(struct ipq_queu
 	pmsg->packet_id       = (unsigned long )entry;
 	pmsg->data_len        = data_len;
 	pmsg->timestamp_sec   = entry->skb->tstamp.off_sec;
-	pmsg->timestamp_usec  = entry->skb->tstamp.off_usec;
+	pmsg->timestamp_usec  = entry->skb->tstamp.off_nsec / NSEC_PER_USEC;
 	pmsg->mark            = entry->skb->mark;
 	pmsg->hook            = entry->info->hook;
 	pmsg->hw_protocol     = entry->skb->protocol;
--- linux-2.6.21-rc2/net/ipv6/netfilter/ip6_queue.c	2007-03-02 00:40:37.000000000 +0100
+++ linux-2.6.21-rc2-ed/net/ipv6/netfilter/ip6_queue.c	2007-03-02 00:40:37.000000000 +0100
@@ -240,7 +240,7 @@ ipq_build_packet_message(struct ipq_queu
 	pmsg->packet_id       = (unsigned long )entry;
 	pmsg->data_len        = data_len;
 	pmsg->timestamp_sec   = entry->skb->tstamp.off_sec;
-	pmsg->timestamp_usec  = entry->skb->tstamp.off_usec;
+	pmsg->timestamp_usec  = entry->skb->tstamp.off_nsec / NSEC_PER_USEC;
 	pmsg->mark            = entry->skb->mark;
 	pmsg->hook            = entry->info->hook;
 	pmsg->hw_protocol     = entry->skb->protocol;
--- linux-2.6.21-rc2/net/netfilter/nfnetlink_queue.c	2007-02-28 05:59:12.000000000 +0100
+++ linux-2.6.21-rc2-ed/net/netfilter/nfnetlink_queue.c	2007-03-02 00:44:08.000000000 +0100
@@ -499,7 +499,7 @@ nfqnl_build_packet_message(struct nfqnl_
 		struct nfqnl_msg_packet_timestamp ts;
 
 		ts.sec = cpu_to_be64(entskb->tstamp.off_sec);
-		ts.usec = cpu_to_be64(entskb->tstamp.off_usec);
+		ts.usec = cpu_to_be64(entskb->tstamp.off_nsec / NSEC_PER_USEC);
 
 		NFA_PUT(skb, NFQA_TIMESTAMP, sizeof(ts), &ts);
 	}
--- linux-2.6.21-rc2/net/netfilter/nfnetlink_log.c	2007-03-02 00:44:45.000000000 +0100
+++ linux-2.6.21-rc2-ed/net/netfilter/nfnetlink_log.c	2007-03-02 00:47:08.000000000 +0100
@@ -514,7 +514,7 @@ __build_packet_message(struct nfulnl_ins
 		struct nfulnl_msg_packet_timestamp ts;
 
 		ts.sec = cpu_to_be64(skb->tstamp.off_sec);
-		ts.usec = cpu_to_be64(skb->tstamp.off_usec);
+		ts.usec = cpu_to_be64(skb->tstamp.off_nsec / NSEC_PER_USEC);
 
 		NFA_PUT(inst->skb, NFULA_TIMESTAMP, sizeof(ts), &ts);
 	}
--- linux-2.6.21-rc2/net/ipv6/netfilter/nf_conntrack_reasm.c	2007-03-01 13:09:56.000000000 +0100
+++ linux-2.6.21-rc2-ed/net/ipv6/netfilter/nf_conntrack_reasm.c	2007-03-01 13:15:07.000000000 +0100
@@ -82,7 +82,7 @@ struct nf_ct_frag6_queue
 	struct sk_buff		*fragments;
 	int			len;
 	int			meat;
-	struct timeval		stamp;
+	struct timespec		stamp;
 	unsigned int		csum;
 	__u8			last_in;	/* has first/last segment arrived? */
 #define COMPLETE		4
@@ -542,7 +542,7 @@ static int nf_ct_frag6_queue(struct nf_c
 		fq->fragments = skb;
 
 	skb->dev = NULL;
-	skb_get_timestamp(skb, &fq->stamp);
+	skb_get_timestampns(skb, &fq->stamp);
 	fq->meat += skb->len;
 	atomic_add(skb->truesize, &nf_ct_frag6_mem);
 
@@ -648,7 +648,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_que
 
 	head->next = NULL;
 	head->dev = dev;
-	skb_set_timestamp(head, &fq->stamp);
+	skb_set_timestampns(head, &fq->stamp);
 	head->nh.ipv6h->payload_len = htons(payload_len);
 
 	/* Yes, and fold redundant checksum back. 8) */
--- linux-2.6.21-rc2/net/ipv6/reassembly.c	2007-03-01 13:15:07.000000000 +0100
+++ linux-2.6.21-rc2-ed/net/ipv6/reassembly.c	2007-03-01 13:15:07.000000000 +0100
@@ -88,7 +88,7 @@ struct frag_queue
 	int			len;
 	int			meat;
 	int			iif;
-	struct timeval		stamp;
+	struct timespec		stamp;
 	unsigned int		csum;
 	__u8			last_in;	/* has first/last segment arrived? */
 #define COMPLETE		4
@@ -562,7 +562,7 @@ static void ip6_frag_queue(struct frag_q
 	if (skb->dev)
 		fq->iif = skb->dev->ifindex;
 	skb->dev = NULL;
-	skb_get_timestamp(skb, &fq->stamp);
+	skb_get_timestampns(skb, &fq->stamp);
 	fq->meat += skb->len;
 	atomic_add(skb->truesize, &ip6_frag_mem);
 
@@ -663,7 +663,7 @@ static int ip6_frag_reasm(struct frag_qu
 
 	head->next = NULL;
 	head->dev = dev;
-	skb_set_timestamp(head, &fq->stamp);
+	skb_set_timestampns(head, &fq->stamp);
 	head->nh.ipv6h->payload_len = htons(payload_len);
 	IP6CB(head)->nhoff = nhoff;
 
--- linux-2.6.21-rc2/include/asm-i386/socket.h	2007-03-02 02:10:08.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-i386/socket.h	2007-03-02 02:10:08.000000000 +0100
@@ -49,5 +49,7 @@
 
 #define SO_PEERSEC		31
 #define SO_PASSSEC		34
+#define SO_TIMESTAMPNS		35
+#define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
 #endif /* _ASM_SOCKET_H */
--- linux-2.6.21-rc2/include/asm-i386/sockios.h	2007-03-01 11:11:33.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-i386/sockios.h	2007-03-01 11:11:33.000000000 +0100
@@ -7,6 +7,7 @@
 #define FIOGETOWN	0x8903
 #define SIOCGPGRP	0x8904
 #define SIOCATMARK	0x8905
-#define SIOCGSTAMP	0x8906		/* Get stamp */
+#define SIOCGSTAMP	0x8906		/* Get stamp (timeval) */
+#define SIOCGSTAMPNS	0x8907		/* Get stamp (timespec) */
 
 #endif
--- linux-2.6.21-rc2/include/asm-x86_64/socket.h	2007-03-02 02:35:28.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-x86_64/socket.h	2007-03-02 02:35:28.000000000 +0100
@@ -49,5 +49,7 @@
 
 #define SO_PEERSEC             31
 #define SO_PASSSEC		34
+#define SO_TIMESTAMPNS		35
+#define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
 #endif /* _ASM_SOCKET_H */
--- linux-2.6.21-rc2/include/asm-x86_64/sockios.h	2007-02-28 21:19:22.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-x86_64/sockios.h	2007-03-01 11:11:33.000000000 +0100
@@ -7,6 +7,7 @@
 #define FIOGETOWN	0x8903
 #define SIOCGPGRP	0x8904
 #define SIOCATMARK	0x8905
-#define SIOCGSTAMP	0x8906		/* Get stamp */
+#define SIOCGSTAMP	0x8906		/* Get stamp (timeval) */
+#define SIOCGSTAMPNS	0x8907		/* Get stamp (timespec) */
 
 #endif
--- linux-2.6.21-rc2/include/asm-alpha/socket.h	2007-03-02 02:26:19.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-alpha/socket.h	2007-03-02 02:26:19.000000000 +0100
@@ -52,6 +52,8 @@
 
 #define SO_PEERSEC		30
 #define SO_PASSSEC		34
+#define SO_TIMESTAMPNS		35
+#define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION		19
--- linux-2.6.21-rc2/include/asm-alpha/sockios.h	2007-03-01 11:11:33.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-alpha/sockios.h	2007-03-01 11:11:33.000000000 +0100
@@ -11,5 +11,6 @@
 #define SIOCGPGRP	_IOR('s', 9, pid_t)
 
 #define SIOCGSTAMP	0x8906		/* Get stamp - linux-specific */
+#define SIOCGSTAMPNS	0x8907		/* Get stamp (timespec) */
 
 #endif /* _ASM_ALPHA_SOCKIOS_H */
--- linux-2.6.21-rc2/include/asm-arm/socket.h	2007-03-02 02:26:19.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-arm/socket.h	2007-03-02 02:26:19.000000000 +0100
@@ -49,5 +49,7 @@
 
 #define SO_PEERSEC		31
 #define SO_PASSSEC		34
+#define SO_TIMESTAMPNS		35
+#define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
 #endif /* _ASM_SOCKET_H */
--- linux-2.6.21-rc2/include/asm-arm26/socket.h	2007-03-02 02:26:19.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-arm26/socket.h	2007-03-02 02:26:19.000000000 +0100
@@ -49,5 +49,7 @@
 
 #define SO_PEERSEC		31
 #define SO_PASSSEC		34
+#define SO_TIMESTAMPNS		35
+#define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
 #endif /* _ASM_SOCKET_H */
--- linux-2.6.21-rc2/include/asm-arm26/sockios.h	2007-03-01 11:11:33.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-arm26/sockios.h	2007-03-01 11:11:33.000000000 +0100
@@ -7,6 +7,7 @@
 #define FIOGETOWN	0x8903
 #define SIOCGPGRP	0x8904
 #define SIOCATMARK	0x8905
-#define SIOCGSTAMP	0x8906		/* Get stamp */
+#define SIOCGSTAMP	0x8906		/* Get stamp (timeval) */
+#define SIOCGSTAMPNS	0x8907		/* Get stamp (timespec) */
 
 #endif
--- linux-2.6.21-rc2/include/asm-avr32/socket.h	2007-03-02 02:26:19.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-avr32/socket.h	2007-03-02 02:26:19.000000000 +0100
@@ -49,5 +49,7 @@
 
 #define SO_PEERSEC		31
 #define SO_PASSSEC		34
+#define SO_TIMESTAMPNS		35
+#define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
 #endif /* __ASM_AVR32_SOCKET_H */
--- linux-2.6.21-rc2/include/asm-avr32/sockios.h	2007-03-01 11:11:33.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-avr32/sockios.h	2007-03-01 11:11:33.000000000 +0100
@@ -7,6 +7,7 @@
 #define FIOGETOWN	0x8903
 #define SIOCGPGRP	0x8904
 #define SIOCATMARK	0x8905
-#define SIOCGSTAMP	0x8906		/* Get stamp */
+#define SIOCGSTAMP	0x8906		/* Get stamp (timeval) */
+#define SIOCGSTAMPNS	0x8907		/* Get stamp (timespec) */
 
 #endif /* __ASM_AVR32_SOCKIOS_H */
--- linux-2.6.21-rc2/include/asm-cris/sockios.h	2007-03-01 11:11:33.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-cris/sockios.h	2007-03-01 11:11:33.000000000 +0100
@@ -7,6 +7,7 @@
 #define FIOGETOWN	0x8903
 #define SIOCGPGRP	0x8904
 #define SIOCATMARK	0x8905
-#define SIOCGSTAMP	0x8906		/* Get stamp */
+#define SIOCGSTAMP	0x8906		/* Get stamp (timeval) */
+#define SIOCGSTAMPNS	0x8907		/* Get stamp (timespec) */
 
 #endif
--- linux-2.6.21-rc2/include/asm-frv/socket.h	2007-03-02 02:26:19.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-frv/socket.h	2007-03-02 02:26:19.000000000 +0100
@@ -49,6 +49,8 @@
 
 #define SO_PEERSEC		31
 #define SO_PASSSEC		34
+#define SO_TIMESTAMPNS		35
+#define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
 #endif /* _ASM_SOCKET_H */
 
--- linux-2.6.21-rc2/include/asm-frv/sockios.h	2007-03-01 11:11:33.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-frv/sockios.h	2007-03-01 11:11:33.000000000 +0100
@@ -7,7 +7,8 @@
 #define FIOGETOWN	0x8903
 #define SIOCGPGRP	0x8904
 #define SIOCATMARK	0x8905
-#define SIOCGSTAMP	0x8906		/* Get stamp */
+#define SIOCGSTAMP	0x8906		/* Get stamp (timeval) */
+#define SIOCGSTAMPNS	0x8907		/* Get stamp (timespec) */
 
 #endif /* _ASM_SOCKIOS__ */
 
--- linux-2.6.21-rc2/include/asm-h8300/socket.h	2007-03-02 02:26:19.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-h8300/socket.h	2007-03-02 02:26:19.000000000 +0100
@@ -49,5 +49,7 @@
 
 #define SO_PEERSEC		31
 #define SO_PASSSEC		34
+#define SO_TIMESTAMPNS		35
+#define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
 #endif /* _ASM_SOCKET_H */
--- linux-2.6.21-rc2/include/asm-h8300/sockios.h	2007-03-01 11:53:45.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-h8300/sockios.h	2007-03-01 11:53:45.000000000 +0100
@@ -7,6 +7,7 @@
 #define FIOGETOWN	0x8903
 #define SIOCGPGRP	0x8904
 #define SIOCATMARK	0x8905
-#define SIOCGSTAMP	0x8906		/* Get stamp */
+#define SIOCGSTAMP	0x8906		/* Get stamp (timeval) */
+#define SIOCGSTAMPNS	0x8907		/* Get stamp (timespec) */
 
 #endif /* __ARCH_H8300_SOCKIOS__ */
--- linux-2.6.21-rc2/include/asm-ia64/socket.h	2007-03-02 02:26:19.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-ia64/socket.h	2007-03-02 02:26:19.000000000 +0100
@@ -58,5 +58,7 @@
 
 #define SO_PEERSEC             31
 #define SO_PASSSEC		34
+#define SO_TIMESTAMPNS		35
+#define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
 #endif /* _ASM_IA64_SOCKET_H */
--- linux-2.6.21-rc2/include/asm-ia64/sockios.h	2007-03-01 11:11:33.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-ia64/sockios.h	2007-03-01 11:11:33.000000000 +0100
@@ -14,6 +14,7 @@
 #define FIOGETOWN	0x8903
 #define SIOCGPGRP	0x8904
 #define SIOCATMARK	0x8905
-#define SIOCGSTAMP	0x8906		/* Get stamp */
+#define SIOCGSTAMP	0x8906		/* Get stamp (timeval) */
+#define SIOCGSTAMPNS	0x8907		/* Get stamp (timespec) */
 
 #endif /* _ASM_IA64_SOCKIOS_H */
--- linux-2.6.21-rc2/include/asm-m32r/socket.h	2007-03-02 02:26:19.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-m32r/socket.h	2007-03-02 02:26:19.000000000 +0100
@@ -49,5 +49,7 @@
 
 #define SO_PEERSEC		31
 #define SO_PASSSEC		34
+#define SO_TIMESTAMPNS		35
+#define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
 #endif /* _ASM_M32R_SOCKET_H */
--- linux-2.6.21-rc2/include/asm-m32r/sockios.h	2007-03-01 11:11:33.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-m32r/sockios.h	2007-03-01 11:11:33.000000000 +0100
@@ -7,6 +7,7 @@
 #define FIOGETOWN	0x8903
 #define SIOCGPGRP	0x8904
 #define SIOCATMARK	0x8905
-#define SIOCGSTAMP	0x8906		/* Get stamp */
+#define SIOCGSTAMP	0x8906		/* Get stamp (timeval) */
+#define SIOCGSTAMPNS	0x8907		/* Get stamp (timespec) */
 
 #endif  /* _ASM_M32R_SOCKIOS_H */
--- linux-2.6.21-rc2/include/asm-m68k/socket.h	2007-03-02 02:26:19.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-m68k/socket.h	2007-03-02 02:26:19.000000000 +0100
@@ -49,5 +49,7 @@
 
 #define SO_PEERSEC             31
 #define SO_PASSSEC		34
+#define SO_TIMESTAMPNS		35
+#define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
 #endif /* _ASM_SOCKET_H */
--- linux-2.6.21-rc2/include/asm-m68k/sockios.h	2007-03-01 11:11:33.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-m68k/sockios.h	2007-03-01 11:11:33.000000000 +0100
@@ -7,6 +7,7 @@
 #define FIOGETOWN	0x8903
 #define SIOCGPGRP	0x8904
 #define SIOCATMARK	0x8905
-#define SIOCGSTAMP	0x8906		/* Get stamp */
+#define SIOCGSTAMP	0x8906		/* Get stamp (timeval) */
+#define SIOCGSTAMPNS	0x8907		/* Get stamp (timespec) */
 
 #endif /* __ARCH_M68K_SOCKIOS__ */
--- linux-2.6.21-rc2/include/asm-mips/socket.h	2007-03-02 02:33:47.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-mips/socket.h	2007-03-02 02:33:47.000000000 +0100
@@ -70,6 +70,8 @@ To add: #define SO_REUSEPORT 0x0200	/* A
 #define SO_SNDBUFFORCE		31
 #define SO_RCVBUFFORCE		33
 #define SO_PASSSEC		34
+#define SO_TIMESTAMPNS		35
+#define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
 #ifdef __KERNEL__
 
--- linux-2.6.21-rc2/include/asm-mips/sockios.h	2007-03-01 11:11:33.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-mips/sockios.h	2007-03-01 11:11:33.000000000 +0100
@@ -20,6 +20,7 @@
 #define SIOCSPGRP	_IOW('s', 8, pid_t)
 #define SIOCGPGRP	_IOR('s', 9, pid_t)
 
-#define SIOCGSTAMP	0x8906			/* Get stamp - linux-specific */
+#define SIOCGSTAMP	0x8906			/* Get stamp (timeval) */
+#define SIOCGSTAMPNS	0x8907		/* Get stamp (timespec) */
 
 #endif /* _ASM_SOCKIOS_H */
--- linux-2.6.21-rc2/include/asm-parisc/socket.h	2007-03-02 02:33:47.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-parisc/socket.h	2007-03-02 02:33:47.000000000 +0100
@@ -33,6 +33,8 @@
 #define SO_PEERCRED	0x4011
 #define SO_TIMESTAMP	0x4012
 #define SCM_TIMESTAMP	SO_TIMESTAMP
+#define SO_TIMESTAMPNS	0x4013
+#define SCM_TIMESTAMPNS	SO_TIMESTAMPNS
 
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION		0x4016
--- linux-2.6.21-rc2/include/asm-parisc/sockios.h	2007-03-01 11:11:33.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-parisc/sockios.h	2007-03-01 11:11:33.000000000 +0100
@@ -7,6 +7,7 @@
 #define FIOGETOWN	0x8903
 #define SIOCGPGRP	0x8904
 #define SIOCATMARK	0x8905
-#define SIOCGSTAMP	0x8906		/* Get stamp */
+#define SIOCGSTAMP	0x8906		/* Get stamp (timeval) */
+#define SIOCGSTAMPNS	0x8907		/* Get stamp (timespec) */
 
 #endif
--- linux-2.6.21-rc2/include/asm-powerpc/socket.h	2007-03-02 02:33:47.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-powerpc/socket.h	2007-03-02 02:33:47.000000000 +0100
@@ -56,5 +56,7 @@
 
 #define SO_PEERSEC		31
 #define SO_PASSSEC		34
+#define SO_TIMESTAMPNS		35
+#define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
 #endif	/* _ASM_POWERPC_SOCKET_H */
--- linux-2.6.21-rc2/include/asm-powerpc/sockios.h	2007-03-01 11:11:33.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-powerpc/sockios.h	2007-03-01 11:11:33.000000000 +0100
@@ -14,6 +14,7 @@
 #define FIOGETOWN	0x8903
 #define SIOCGPGRP	0x8904
 #define SIOCATMARK	0x8905
-#define SIOCGSTAMP	0x8906		/* Get stamp */
+#define SIOCGSTAMP	0x8906		/* Get stamp (timeval) */
+#define SIOCGSTAMPNS	0x8907		/* Get stamp (timespec) */
 
 #endif	/* _ASM_POWERPC_SOCKIOS_H */
--- linux-2.6.21-rc2/include/asm-s390/socket.h	2007-03-02 02:33:47.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-s390/socket.h	2007-02-28 05:59:12.000000000 +0100
@@ -57,7 +57,5 @@
 
 #define SO_PEERSEC		31
 #define SO_PASSSEC		34
-#define SO_TIMESTAMPNS		35
-#define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
 #endif /* _ASM_SOCKET_H */
--- linux-2.6.21-rc2/include/asm-s390/sockios.h	2007-03-01 11:11:33.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-s390/sockios.h	2007-03-01 11:11:33.000000000 +0100
@@ -15,6 +15,7 @@
 #define FIOGETOWN	0x8903
 #define SIOCGPGRP	0x8904
 #define SIOCATMARK	0x8905
-#define SIOCGSTAMP	0x8906		/* Get stamp */
+#define SIOCGSTAMP	0x8906		/* Get stamp (timeval) */
+#define SIOCGSTAMPNS	0x8907		/* Get stamp (timespec) */
 
 #endif
--- linux-2.6.21-rc2/include/asm-sh/socket.h	2007-03-02 02:33:47.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-sh/socket.h	2007-02-28 05:59:12.000000000 +0100
@@ -49,7 +49,5 @@
 
 #define SO_PEERSEC		31
 #define SO_PASSSEC		34
-#define SO_TIMESTAMPNS		35
-#define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
 #endif /* __ASM_SH_SOCKET_H */
--- linux-2.6.21-rc2/include/asm-sh/sockios.h	2007-03-01 11:11:33.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-sh/sockios.h	2007-03-01 11:11:33.000000000 +0100
@@ -10,4 +10,5 @@
 #define SIOCGPGRP	_IOR('s', 9, pid_t)
 
 #define SIOCGSTAMP	_IOR('s', 100, struct timeval) /* Get stamp - linux-specific */
+#define SIOCGSTAMPNS	_IOR('s', 101, struct timespec) /* Get stamp - linux-specific */
 #endif /* __ASM_SH_SOCKIOS_H */
--- linux-2.6.21-rc2/include/asm-sh64/sockios.h	2007-03-01 11:11:33.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-sh64/sockios.h	2007-03-01 11:11:33.000000000 +0100
@@ -21,4 +21,5 @@
 #define SIOCGPGRP	_IOR('s', 9, pid_t)
 
 #define SIOCGSTAMP	_IOR('s', 100, struct timeval) /* Get stamp - linux-specific */
+#define SIOCGSTAMPNS	_IOR('s', 101, struct timespec) /* Get stamp - linux-specific */
 #endif /* __ASM_SH64_SOCKIOS_H */
--- linux-2.6.21-rc2/include/asm-sparc/socket.h	2007-03-02 02:33:47.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-sparc/socket.h	2007-03-02 02:33:47.000000000 +0100
@@ -49,6 +49,8 @@
 
 #define SO_PEERSEC		0x001e
 #define SO_PASSSEC		0x001f
+#define SO_TIMESTAMPNS		0x0020
+#define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION		0x5001
--- linux-2.6.21-rc2/include/asm-sparc/sockios.h	2007-03-01 11:11:33.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-sparc/sockios.h	2007-03-01 11:11:33.000000000 +0100
@@ -7,7 +7,8 @@
 #define FIOGETOWN	0x8903
 #define SIOCGPGRP	0x8904
 #define SIOCATMARK	0x8905
-#define SIOCGSTAMP	0x8906		/* Get stamp */
+#define SIOCGSTAMP	0x8906		/* Get stamp (timeval) */
+#define SIOCGSTAMPNS	0x8907		/* Get stamp (timespec) */
 
 #endif /* !(_ASM_SPARC_SOCKIOS_H) */
 
--- linux-2.6.21-rc2/include/asm-sparc64/socket.h	2007-03-02 02:33:47.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-sparc64/socket.h	2007-03-02 02:33:47.000000000 +0100
@@ -49,6 +49,8 @@
 
 #define SO_PEERSEC		0x001e
 #define SO_PASSSEC		0x001f
+#define SO_TIMESTAMPNS		0x0020
+#define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION		0x5001
--- linux-2.6.21-rc2/include/asm-sparc64/sockios.h	2007-03-01 11:11:33.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-sparc64/sockios.h	2007-03-01 11:11:33.000000000 +0100
@@ -7,7 +7,8 @@
 #define FIOGETOWN	0x8903
 #define SIOCGPGRP	0x8904
 #define SIOCATMARK	0x8905
-#define SIOCGSTAMP	0x8906		/* Get stamp */
+#define SIOCGSTAMP	0x8906		/* Get stamp (timeval) */
+#define SIOCGSTAMPNS	0x8907		/* Get stamp (timespec) */
 
 #endif /* !(_ASM_SPARC64_SOCKIOS_H) */
 
--- linux-2.6.21-rc2/include/asm-v850/socket.h	2007-03-02 02:33:47.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-v850/socket.h	2007-03-02 02:33:47.000000000 +0100
@@ -49,5 +49,7 @@
 
 #define SO_PEERSEC		31
 #define SO_PASSSEC		34
+#define SO_TIMESTAMPNS		35
+#define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
 #endif /* __V850_SOCKET_H__ */
--- linux-2.6.21-rc2/include/asm-v850/sockios.h	2007-03-01 11:11:33.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-v850/sockios.h	2007-03-01 11:11:33.000000000 +0100
@@ -7,6 +7,7 @@
 #define FIOGETOWN	0x8903
 #define SIOCGPGRP	0x8904
 #define SIOCATMARK	0x8905
-#define SIOCGSTAMP	0x8906		/* Get stamp */
+#define SIOCGSTAMP	0x8906		/* Get stamp (timeval) */
+#define SIOCGSTAMPNS	0x8907		/* Get stamp (timespec) */
 
 #endif /* __V850_SOCKIOS_H__ */
--- linux-2.6.21-rc2/include/asm-xtensa/socket.h	2007-03-02 02:35:28.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-xtensa/socket.h	2007-03-02 02:35:28.000000000 +0100
@@ -60,5 +60,7 @@
 #define SO_ACCEPTCONN		30
 #define SO_PEERSEC		31
 #define SO_PASSSEC		34
+#define SO_TIMESTAMPNS		35
+#define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
 
 #endif	/* _XTENSA_SOCKET_H */
--- linux-2.6.21-rc2/include/asm-xtensa/sockios.h	2007-03-01 11:11:33.000000000 +0100
+++ linux-2.6.21-rc2-ed/include/asm-xtensa/sockios.h	2007-03-01 11:11:33.000000000 +0100
@@ -25,6 +25,7 @@
 #define SIOCSPGRP	_IOW('s', 8, pid_t)
 #define SIOCGPGRP	_IOR('s', 9, pid_t)
 
-#define SIOCGSTAMP	0x8906		/* Get stamp - linux-specific */
+#define SIOCGSTAMP	0x8906		/* Get stamp (timeval) */
+#define SIOCGSTAMPNS	0x8907		/* Get stamp (timespec) */
 
 #endif	/* _XTENSA_SOCKIOS_H */