All of lore.kernel.org
 help / color / mirror / Atom feed
* CLOCK_MONOTONIC datagram timestamps by the kernel
@ 2007-02-25 21:29 John
  2007-02-26 10:26 ` John
  0 siblings, 1 reply; 22+ messages in thread
From: John @ 2007-02-25 21:29 UTC (permalink / raw)
  To: linux-kernel; +Cc: johnstul, mingo, zippel, tglx, linux.kernel, akpm

Hello,

It is possible to ask Linux to timestamp incoming datagrams when they
are received, then to retrieve this timestamp with an ioctl command or
a recvmsg call (which would save one round trip to kernel space).

SIOCGSTAMP
     Return a struct timeval with the receive timestamp of the last
packet passed to the user. This is useful for accurate round trip time
measurements. See setitimer(2) for a description of struct timeval.

As far as I understand, this timestamp is given by the CLOCK_REALTIME
clock. I would like to get the timestamp given by a different clock: the
CLOCK_MONOTONIC clock.

In other words, I would like the kernel to do the equivalent of

   struct timespec spec;
   clock_gettime(CLOCK_MONOTONIC, &spec)

for each datagram the system receives, as soon as it is received.

Is there a way to achieve that?

Is there a different ioctl perhaps? (I don't think so.)

Regards.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: CLOCK_MONOTONIC datagram timestamps by the kernel
  2007-02-25 21:29 CLOCK_MONOTONIC datagram timestamps by the kernel John
@ 2007-02-26 10:26 ` John
  2007-02-26 12:20   ` Andi Kleen
  0 siblings, 1 reply; 22+ messages in thread
From: John @ 2007-02-26 10:26 UTC (permalink / raw)
  To: linux-kernel
  Cc: johnstul, mingo, zippel, tglx, akpm, ak, jbohac, linux.kernel

John wrote:

> It is possible to ask Linux to timestamp incoming datagrams when they
> are received, then to retrieve this timestamp with an ioctl command or
> a recvmsg call (which would save one round trip to kernel space).
> 
> SIOCGSTAMP
>     Return a struct timeval with the receive timestamp of the last
> packet passed to the user. This is useful for accurate round trip time
> measurements. See setitimer(2) for a description of struct timeval.
> 
> As far as I understand, this timestamp is given by the CLOCK_REALTIME
> clock. I would like to get the timestamp given by a different clock:
> the CLOCK_MONOTONIC clock.
> 
> In other words, I would like the kernel to do the equivalent of
> 
>   struct timespec spec;
>   clock_gettime(CLOCK_MONOTONIC, &spec)
> 
> for each datagram the system receives, as soon as it is received.
> 
> Is there a way to achieve that?
> 
> Is there a different ioctl perhaps? (I don't think so.)

I've been reading the following documents:

Clocks and Timers
http://www.opengroup.org/onlinepubs/009695399/xrat/xsh_chap02.html#tag_03_02_08_18

Rationale for the Monotonic Clock
http://www.opengroup.org/onlinepubs/009695399/xrat/xsh_chap02.html#tag_03_02_08_19

"For those applications that use time services to achieve realtime 
behavior, changing the value of the clock on which these services rely 
may cause erroneous timing behavior. For these applications, it is 
necessary to have a monotonic clock which cannot run backwards, and 
which has a maximum clock jump that is required to be documented by the 
implementation. Additionally, it is desirable (but not required by IEEE 
Std 1003.1-2001) that the monotonic clock increases its value uniformly. 
This clock should not be affected by changes to the system time; for 
example, to synchronize the clock with an external source or to account 
for leap seconds. Such changes would cause errors in the measurement of 
time intervals for those time services that use the absolute value of 
the clock."

clock and timer functions
http://www.opengroup.org/onlinepubs/009695399/functions/clock_settime.html

"If the value of the CLOCK_REALTIME clock is set via clock_settime(), 
the new value of the clock shall be used to determine the time of 
expiration for absolute time services based upon the CLOCK_REALTIME 
clock. This applies to the time at which armed absolute timers expire. 
If the absolute time requested at the invocation of such a time service 
is before the new value of the clock, the time service shall expire 
immediately as if the clock had reached the requested time normally."

"The effect of setting a clock via clock_settime() on armed per-process 
timers associated with a clock other than CLOCK_REALTIME is 
implementation-defined."


Here's some background on what I'm trying to do:

My app expects a stream of UDP datagrams containing compressed video.
These datagrams have been time stamped by the source using a high 
resolution clock.

The video stream is played out in real-time. I buffer several packets, 
then repeatedly arm a one-shot timer (with TIMER_ABSTIME set) to wait 
until it's time to send the oldest packet.

AFAIU, if I use the CLOCK_REALTIME clock in my app, and if the sysadmin 
changes the date, hell will break loose in my app. Hence my need for 
CLOCK_MONOTONIC.


On a related note, I see that do_gettimeofday() in kernel/timer.c 
actually gets a struct timespec from __get_realtime_clock_ts() then 
throws bits away in the ns to us conversion. The integer division is 
also a waste of cycles in my case, as I want the result in ns.

I suppose that if I change sock_get_timestamp() in core/sock.c to call 
__get_realtime_clock_ts() instead of do_gettimeofday() I'll break 50 
billion applications (ping? traceroute?) that expect a struct timeval?

Anyway, thanks for reading this far.

Regards.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: CLOCK_MONOTONIC datagram timestamps by the kernel
  2007-02-26 10:26 ` John
@ 2007-02-26 12:20   ` Andi Kleen
  2007-02-26 14:17     ` John
  0 siblings, 1 reply; 22+ messages in thread
From: Andi Kleen @ 2007-02-26 12:20 UTC (permalink / raw)
  To: John; +Cc: linux-kernel, johnstul, mingo, zippel, tglx, akpm, jbohac


Mr Anonymous,

> 
> My app expects a stream of UDP datagrams containing compressed video.
> These datagrams have been time stamped by the source using a high 
> resolution clock.

Why do you need another time stamp them? 
> 
> The video stream is played out in real-time. I buffer several packets, 
> then repeatedly arm a one-shot timer (with TIMER_ABSTIME set) to wait 
> until it's time to send the oldest packet.
> 
> AFAIU, if I use the CLOCK_REALTIME clock in my app, and if the sysadmin 
> changes the date, hell will break loose in my app.

Only if your app cannot handle time going backwards.

> I suppose that if I change sock_get_timestamp() in core/sock.c to call 
> __get_realtime_clock_ts() instead of do_gettimeofday() I'll break 50 
> billion applications (ping? traceroute?) that expect a struct timeval?

Not that many, but some probably. 

Letting the kernel do the time stamping is usually quite useless anyways. 
You can as well do it in your application when you receive it. After all
you're interested in when you can read the packet in your app, 
not when the driver processes it.

The kernel time stamping is mainly for sniffing applications that want
to know exactly what's going on on the wire. But even then it's fairly
arbitary because it can be a long time between the packet arriving 
on the PHY and being processed by the driver.

-Andi

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: CLOCK_MONOTONIC datagram timestamps by the kernel
  2007-02-26 12:20   ` Andi Kleen
@ 2007-02-26 14:17     ` John
  2007-02-28 11:23       ` John
  0 siblings, 1 reply; 22+ messages in thread
From: John @ 2007-02-26 14:17 UTC (permalink / raw)
  To: Andi Kleen
  Cc: linux-kernel, johnstul, mingo, zippel, tglx, akpm, jbohac, linux.kernel

Andi Kleen wrote:

> John wrote:
> 
>> My app expects a stream of UDP datagrams containing compressed video.
>> These datagrams have been time stamped by the source using a high
>> resolution clock.
> 
> Why do you need another time stamp then?

Source and receiver do not share a common clock. Thus, I have to monitor 
clock skew. If I simply use the time stamps produced by the source, my 
buffer will eventually underflow or overflow.

As far as I have seen, clock skew is on the order of ±10^-5, i.e. when 
the source thinks 100000 seconds have elapsed, the receiver thinks 
100001 seconds have elapsed.

>> The video stream is played out in real-time. I buffer several packets,
>> then repeatedly arm a one-shot timer (with TIMER_ABSTIME set) to wait
>> until it's time to send the oldest packet.
>>
>> AFAIU, if I use the CLOCK_REALTIME clock in my app, and if the sysadmin 
>> changes the date, hell will break loose in my app.
> 
> Only if your app cannot handle time going backwards.

My app cannot handle time going backwards.

The algorithm looks like:

/* Start transmission, record start date */
NEXT_DEADLINE = now;

while ( 1 )
{
   send(oldest_packet);
   recv_available_packets();
   /* compute next deadline */
   NEXT_DEADLINE += time_to_wait_until_next_packet();
   sleep_until(NEXT_DEADLINE);
}

If the clock changes under me, I'm toast.

>> I suppose that if I change sock_get_timestamp() in core/sock.c to call 
>> __get_realtime_clock_ts() instead of do_gettimeofday() I'll break 50 
>> billion applications (ping? traceroute?) that expect a struct timeval?
> 
> Not that many, but some probably.

Another option would be to change sock_get_timestamp() to call 
ktime_get_ts() instead of do_gettimeofday() and convert ns to us.

i.e. I still return a struct timeval, but using CLOCK_MONOTONIC.

> Letting the kernel do the time stamping is usually quite useless anyways. 
> You can as well do it in your application when you receive it. After all
> you're interested in when you can read the packet in your app, 
> not when the driver processes it.

I use clock_nanosleep() to sleep until it's time to send the next 
packet. I check for packets when I wake up. I need the kernel to time 
stamp the packets because I was sleeping when they reached the system.

I try to do it this way because I read this:

http://rt.wiki.kernel.org/index.php/High_resolution_timers

"Note that (clock_)nanosleep functions do not suffer from this problem 
as the wakeup function at timer expiry is executed in the context of the 
high resolution timer interrupt. If an application is not using 
asynchronous signal handlers, it is recommended to use the 
clock_nanosleep() function with the TIMER_ABSTIME flag set instead of 
waiting for the periodic timer signal delivery. The application has to 
maintain the absolute expiry time for the next interval itself, but this 
is a lightweight operation of adding and normalizing two struct timespec 
values. The benefit is significantly lower maximum latencies (~50us) and 
less OS overhead in general."

Regards.


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: CLOCK_MONOTONIC datagram timestamps by the kernel
  2007-02-26 14:17     ` John
@ 2007-02-28 11:23       ` John
  0 siblings, 0 replies; 22+ messages in thread
From: John @ 2007-02-28 11:23 UTC (permalink / raw)
  To: linux-kernel
  Cc: Andi Kleen, johnstul, mingo, zippel, tglx, akpm, jbohac, linux.kernel

John wrote:

> Andi Kleen wrote:
> 
>> John wrote:
>>
>>> My app expects a stream of UDP datagrams containing compressed video.
>>> These datagrams have been time stamped by the source using a high
>>> resolution clock.
>>
>> Why do you need another time stamp then?
> 
> Source and receiver do not share a common clock. Thus, I have to monitor
> clock skew. If I simply use the time stamps produced by the source, my
> buffer will eventually underflow or overflow.
> 
> As far as I have seen, clock skew is on the order of ±10^-5, i.e. when
> the source thinks 100000 seconds have elapsed, the receiver thinks
> 100001 seconds have elapsed.

I've considered running NTP to synchronize the clocks, but I'm afraid it 
wouldn't help, for several reasons:

1) The 40.5 MHz clock used to timestamp datagrams at the source is 
located on a PCI board. I have read access to a 32-bit counter that is 
incremented every cycle (somewhat like the TSC on x86).

2) Source and receiver are inside a VPN, and do not have access to the 
Internet. I don't think I can keep NTP happy if it can't talk to any NTP 
servers.

(I'm not snipping the rest of the message in case someone is willing
to comment.)

>>> The video stream is played out in real-time. I buffer several packets,
>>> then repeatedly arm a one-shot timer (with TIMER_ABSTIME set) to wait
>>> until it's time to send the oldest packet.
>>>
>>> AFAIU, if I use the CLOCK_REALTIME clock in my app, and if the 
>>> sysadmin changes the date, hell will break loose in my app.
>>
>> Only if your app cannot handle time going backwards.
> 
> My app cannot handle time going backwards.
> 
> The algorithm looks like:
> 
> /* Start transmission, record start date */
> NEXT_DEADLINE = now;
> 
> while ( 1 )
> {
>   send(oldest_packet);
>   recv_available_packets();
>   /* compute next deadline */
>   NEXT_DEADLINE += time_to_wait_until_next_packet();
>   sleep_until(NEXT_DEADLINE);
> }
> 
> If the clock changes under me, I'm toast.
> 
>>> I suppose that if I change sock_get_timestamp() in core/sock.c to
>>> call __get_realtime_clock_ts() instead of do_gettimeofday() I'll
>>> break 50 billion applications (ping? traceroute?) that expect a
>>> struct timeval?
>>
>> Not that many, but some probably.
> 
> Another option would be to change sock_get_timestamp() to call
> ktime_get_ts() instead of do_gettimeofday() and convert ns to us.
> 
> i.e. I still return a struct timeval, but using CLOCK_MONOTONIC.
> 
>> Letting the kernel do the time stamping is usually quite useless
>> anyways. You can as well do it in your application when you receive
>> it. After all you're interested in when you can read the packet in
>> your app, not when the driver processes it.
> 
> I use clock_nanosleep() to sleep until it's time to send the next
> packet. I check for packets when I wake up. I need the kernel to time
> stamp the packets because I was sleeping when they reached the system.
> 
> I try to do it this way because I read this:
> 
> http://rt.wiki.kernel.org/index.php/High_resolution_timers
> 
> "Note that (clock_)nanosleep functions do not suffer from this problem
> as the wakeup function at timer expiry is executed in the context of the
> high resolution timer interrupt. If an application is not using
> asynchronous signal handlers, it is recommended to use the
> clock_nanosleep() function with the TIMER_ABSTIME flag set instead of
> waiting for the periodic timer signal delivery. The application has to
> maintain the absolute expiry time for the next interval itself, but this
> is a lightweight operation of adding and normalizing two struct timespec
> values. The benefit is significantly lower maximum latencies (~50us) and
> less OS overhead in general."


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: CLOCK_MONOTONIC datagram timestamps by the kernel
  2007-03-02  9:26             ` John
@ 2007-03-02 10:11               ` Eric Dumazet
  0 siblings, 0 replies; 22+ messages in thread
From: Eric Dumazet @ 2007-03-02 10:11 UTC (permalink / raw)
  To: John; +Cc: netdev, Stephen Hemminger

On Friday 02 March 2007 10:26, John wrote:
> Eric Dumazet wrote:

> > Anyway, if you want to play, you can apply this patch on top of
> > linux-2.6.21-rc2  (nanosecond resolution infrastructure needs 2.6.21)
> > I let you do the adjustments for rt kernel.
>
> Why does it require 2.6.21?

Well, this patch was done on top of the latest kernel for obvious practical 
reasons, but you probably can adapt it on the kernel of your choice.


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: CLOCK_MONOTONIC datagram timestamps by the kernel
  2007-03-01 11:30           ` Eric Dumazet
  2007-03-01 15:54             ` Stephen Hemminger
  2007-03-01 18:53             ` Stephen Hemminger
@ 2007-03-02  9:26             ` John
  2007-03-02 10:11               ` Eric Dumazet
  2 siblings, 1 reply; 22+ messages in thread
From: John @ 2007-03-02  9:26 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: linux-net, netdev, Stephen Hemminger, linux.kernel

Eric Dumazet wrote:

> John wrote:
> 
>> Consider an idle Linux 2.6.20-rt8 system, equipped with a single PCI-E
>> gigabit Ethernet NIC, running on a modern CPU (e.g. Core 2 Duo E6700).
>> All this system does is time stamp 1000 packets per second.
>>
>> Are you claiming that this platform *cannot* handle most packets within
>> less than 1 microsecond of their arrival?
> 
> Yes I claim it. You expect too much of this platform, unless "most" means
> 10 % for you ;)

By "most" I meant more than 50%.

Has someone tried to measure interrupt latency in Linux? I'd like to 
plot the distribution of network IRQ to interrupt handler latencies.

> If you replace "1 us" by "50 us", then yes, it probably can do it, if "most" 
> means 99%, (not 99.999 %)

I think we need cold, hard numbers at this point :-)

> Anyway, if you want to play, you can apply this patch on top of 
> linux-2.6.21-rc2  (nanosecond resolution infrastructure needs 2.6.21)
> I let you do the adjustments for rt kernel.

Why does it require 2.6.21?

> This patch converts sk_buff timestamp to use new nanosecond infra
> (added in 2.6.21)

Is this mentioned somewhere in the 2.6.21-rc1 ChangeLog?
http://kernel.org/pub/linux/kernel/v2.6/testing/ChangeLog-2.6.21-rc1

Regards.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: CLOCK_MONOTONIC datagram timestamps by the kernel
  2007-03-01 23:34                 ` Stephen Hemminger
@ 2007-03-02  0:56                   ` Eric Dumazet
  0 siblings, 0 replies; 22+ messages in thread
From: Eric Dumazet @ 2007-03-02  0:56 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: John find, linux-net, netdev

[-- Attachment #1: Type: text/plain, Size: 5336 bytes --]

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 <dada1@cosmosbay.com>

  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(-)


[-- Attachment #2: net_nanosec_stamp.patch --]
[-- Type: text/plain, Size: 42389 bytes --]

--- 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 */

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: CLOCK_MONOTONIC datagram timestamps by the kernel
  2007-03-01 23:14               ` Eric Dumazet
@ 2007-03-01 23:34                 ` Stephen Hemminger
  2007-03-02  0:56                   ` Eric Dumazet
  0 siblings, 1 reply; 22+ messages in thread
From: Stephen Hemminger @ 2007-03-01 23:34 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: John find, linux-net, netdev

On Fri, 02 Mar 2007 00:14:37 +0100
Eric Dumazet <dada1@cosmosbay.com> wrote:

> Stephen Hemminger a écrit :
> 
> > 
> > You probably want to add a SO_TIMESTAMPNS setsockopt() value like existing SO_TIMESTAMP
> 
> You mean an alias like this ?
> 
> #define SO_TIMESTAMPNS SO_TIMESTAMP
> 
> Or should we really use another value ?

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
-- 
Stephen Hemminger <shemminger@linux-foundation.org>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: CLOCK_MONOTONIC datagram timestamps by the kernel
  2007-03-01 18:53             ` Stephen Hemminger
@ 2007-03-01 23:14               ` Eric Dumazet
  2007-03-01 23:34                 ` Stephen Hemminger
  0 siblings, 1 reply; 22+ messages in thread
From: Eric Dumazet @ 2007-03-01 23:14 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: John find, linux-net, netdev

Stephen Hemminger a écrit :

> 
> You probably want to add a SO_TIMESTAMPNS setsockopt() value like existing SO_TIMESTAMP

You mean an alias like this ?

#define SO_TIMESTAMPNS SO_TIMESTAMP

Or should we really use another value ?

> 
> Also use NSEC_PER_USEC rather than hardcoded 1000.
> 
> 

Yes I will resubmit a patch including your suggestions (I discovered some 
missing bits after a make allyesconfig)

Thank you


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: CLOCK_MONOTONIC datagram timestamps by the kernel
  2007-03-01 11:30           ` Eric Dumazet
  2007-03-01 15:54             ` Stephen Hemminger
@ 2007-03-01 18:53             ` Stephen Hemminger
  2007-03-01 23:14               ` Eric Dumazet
  2007-03-02  9:26             ` John
  2 siblings, 1 reply; 22+ messages in thread
From: Stephen Hemminger @ 2007-03-01 18:53 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: John find, linux-net, netdev

On Thu, 1 Mar 2007 12:30:50 +0100
Eric Dumazet <dada1@cosmosbay.com> wrote:

> On Wednesday 28 February 2007 17:07, John wrote:
> 
> >
> > Consider an idle Linux 2.6.20-rt8 system, equipped with a single PCI-E
> > gigabit Ethernet NIC, running on a modern CPU (e.g. Core 2 Duo E6700).
> > All this system does is time stamp 1000 packets per second.
> >
> > Are you claiming that this platform *cannot* handle most packets within
> > less than 1 microsecond of their arrival?
> 
> Yes I claim it.
> 
> You expect too much of this platform, unless "most" means 10 % for 
> you ;)
> 
> If you replace "1 us" by "50 us", then yes, it probably can do it, if "most" 
> means 99%, (not 99.999 %)
> 
> Anyway, if you want to play, you can apply this patch on top of 
> linux-2.6.21-rc2  (nanosecond resolution infrastruture needs 2.6.21)
> I let you do the adjustments for rt kernel.
> 
> I compiled it on my i386 machine, and tested it with a patched libpcap/tcpdump
> 
> [PATCH] NET : introduce nanosecond time infrastructure and SIOCGSTAMPNS
> 
> 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)
> 
> 
> Signed-off-by: Eric Dumazet <dada1@cosmosbay.com>
>

You probably want to add a SO_TIMESTAMPNS setsockopt() value like existing SO_TIMESTAMP

Also use NSEC_PER_USEC rather than hardcoded 1000.


-- 
Stephen Hemminger <shemminger@linux-foundation.org>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: CLOCK_MONOTONIC datagram timestamps by the kernel
  2007-03-01 15:54             ` Stephen Hemminger
@ 2007-03-01 16:13               ` Eric Dumazet
  0 siblings, 0 replies; 22+ messages in thread
From: Eric Dumazet @ 2007-03-01 16:13 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: John find, linux-net, netdev

On Thursday 01 March 2007 16:54, Stephen Hemminger wrote:
>
> I like it except changing stamp to stampns all over the place is
> unnecessary, just change the
> type.

Well... After seeing the compat code using casts, I felt some external users 
could try to cast it as well and not detect the new type...

>
> I assume old tcpdump works as expected.

Yes, of course...

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: CLOCK_MONOTONIC datagram timestamps by the kernel
  2007-03-01 11:30           ` Eric Dumazet
@ 2007-03-01 15:54             ` Stephen Hemminger
  2007-03-01 16:13               ` Eric Dumazet
  2007-03-01 18:53             ` Stephen Hemminger
  2007-03-02  9:26             ` John
  2 siblings, 1 reply; 22+ messages in thread
From: Stephen Hemminger @ 2007-03-01 15:54 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: John find, linux-net, netdev

Eric Dumazet wrote:
> On Wednesday 28 February 2007 17:07, John wrote:
>
>   
>> Consider an idle Linux 2.6.20-rt8 system, equipped with a single PCI-E
>> gigabit Ethernet NIC, running on a modern CPU (e.g. Core 2 Duo E6700).
>> All this system does is time stamp 1000 packets per second.
>>
>> Are you claiming that this platform *cannot* handle most packets within
>> less than 1 microsecond of their arrival?
>>     
>
> Yes I claim it.
>
> You expect too much of this platform, unless "most" means 10 % for 
> you ;)
>
> If you replace "1 us" by "50 us", then yes, it probably can do it, if "most" 
> means 99%, (not 99.999 %)
>
> Anyway, if you want to play, you can apply this patch on top of 
> linux-2.6.21-rc2  (nanosecond resolution infrastruture needs 2.6.21)
> I let you do the adjustments for rt kernel.
>
>   
I like it except changing stamp to stampns all over the place is 
unnecessary, just change the
type.

> I compiled it on my i386 machine, and tested it with a patched libpcap/tcpdump
>
>   
I assume old tcpdump works as expected.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: CLOCK_MONOTONIC datagram timestamps by the kernel
  2007-02-28 16:07         ` John
  2007-03-01 10:03           ` Evgeniy Polyakov
@ 2007-03-01 11:30           ` Eric Dumazet
  2007-03-01 15:54             ` Stephen Hemminger
                               ` (2 more replies)
  1 sibling, 3 replies; 22+ messages in thread
From: Eric Dumazet @ 2007-03-01 11:30 UTC (permalink / raw)
  To: John find; +Cc: linux-net, netdev, Stephen Hemminger

[-- Attachment #1: Type: text/plain, Size: 3766 bytes --]

On Wednesday 28 February 2007 17:07, John wrote:

>
> Consider an idle Linux 2.6.20-rt8 system, equipped with a single PCI-E
> gigabit Ethernet NIC, running on a modern CPU (e.g. Core 2 Duo E6700).
> All this system does is time stamp 1000 packets per second.
>
> Are you claiming that this platform *cannot* handle most packets within
> less than 1 microsecond of their arrival?

Yes I claim it.

You expect too much of this platform, unless "most" means 10 % for 
you ;)

If you replace "1 us" by "50 us", then yes, it probably can do it, if "most" 
means 99%, (not 99.999 %)

Anyway, if you want to play, you can apply this patch on top of 
linux-2.6.21-rc2  (nanosecond resolution infrastruture needs 2.6.21)
I let you do the adjustments for rt kernel.

I compiled it on my i386 machine, and tested it with a patched libpcap/tcpdump

[PATCH] NET : introduce nanosecond time infrastructure and SIOCGSTAMPNS

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)


Signed-off-by: Eric Dumazet <dada1@cosmosbay.com>

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


[-- Attachment #2: net_nanosec_stamp.patch --]
[-- Type: text/plain, Size: 31832 bytes --]

--- 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 13:15:07.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;
 };
 
 
@@ -186,7 +190,7 @@ enum {
  *	@next: Next buffer in list
  *	@prev: Previous buffer in list
  *	@sk: Socket we are owned by
- *	@tstamp: Time we arrived
+ *	@tstampns: Time we arrived
  *	@dev: Device we arrived on/are leaving by
  *	@input_dev: Device we arrived on
  *	@h: Transport layer header
@@ -233,7 +237,7 @@ struct sk_buff {
 	struct sk_buff		*prev;
 
 	struct sock		*sk;
-	struct skb_timeval	tstamp;
+	struct skb_timespec	tstampns;
 	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->tstampns.off_sec;
+	stampns->tv_nsec = skb->tstampns.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
@@ -1360,23 +1378,23 @@ 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_sec  = skb->tstampns.off_sec;
+	stamp->tv_usec = skb->tstampns.off_nsec/1000;
 }
 
 /**
- * 	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->tstampns.off_sec  = stampns->tv_sec;
+	skb->tstampns.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-01 11:37:34.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_stampns;
 	struct socket		*sk_socket;
 	void			*sk_user_data;
 	struct page		*sk_sndmsg_page;
@@ -1307,19 +1307,22 @@ 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 timespec stampns;
 	struct timeval stamp;
 
-	skb_get_timestamp(skb, &stamp);
+	skb_get_timestampns(skb, &stampns);
 	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);
+		if (stampns.tv_sec == 0)
+			getnstimeofday(&stampns);
+		skb_set_timestampns(skb, &stampns);
+		stamp.tv_sec = stampns.tv_sec;
+		stamp.tv_usec = stampns.tv_nsec/1000;
 		put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP, sizeof(struct timeval),
 			 &stamp);
 	} else
-		sk->sk_stamp = stamp;
+		sk->sk_stampns = stampns;
 }
 
 /**
@@ -1350,6 +1353,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-02-28 21:16:43.000000000 +0100
@@ -1512,8 +1512,8 @@ void sock_init_data(struct socket *sock,
 	sk->sk_rcvtimeo		=	MAX_SCHEDULE_TIMEOUT;
 	sk->sk_sndtimeo		=	MAX_SCHEDULE_TIMEOUT;
 
-	sk->sk_stamp.tv_sec     = -1L;
-	sk->sk_stamp.tv_usec    = -1L;
+	sk->sk_stampns.tv_sec     = -1L;
+	sk->sk_stampns.tv_nsec    = -1L;
 
 	atomic_set(&sk->sk_refcnt, 1);
 }
@@ -1554,17 +1554,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)
+	if (sk->sk_stampns.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)) ?
+	if (sk->sk_stampns.tv_sec == 0)
+		getnstimeofday(&sk->sk_stampns);
+	tstamp.tv_sec = sk->sk_stampns.tv_sec;
+	tstamp.tv_usec = sk->sk_stampns.tv_nsec/1000;
+	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_stampns.tv_sec == -1)
+		return -ENOENT;
+	if (sk->sk_stampns.tv_sec == 0)
+		getnstimeofday(&sk->sk_stampns);
+	return copy_to_user(userstamp, &sk->sk_stampns, 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 11:43:38.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);
 
@@ -1048,8 +1048,8 @@ static inline void net_timestamp(struct 
 	if (atomic_read(&netstamp_needed))
 		__net_timestamp(skb);
 	else {
-		skb->tstamp.off_sec = 0;
-		skb->tstamp.off_usec = 0;
+		skb->tstampns.off_sec = 0;
+		skb->tstampns.off_nsec = 0;
 	}
 }
 
@@ -1580,7 +1580,7 @@ int netif_rx(struct sk_buff *skb)
 	if (netpoll_rx(skb))
 		return NET_RX_DROP;
 
-	if (!skb->tstamp.off_sec)
+	if (!skb->tstampns.off_sec)
 		net_timestamp(skb);
 
 	/*
@@ -1772,7 +1772,7 @@ int netif_receive_skb(struct sk_buff *sk
 	if (skb->dev->poll && netpoll_rx(skb))
 		return NET_RX_DROP;
 
-	if (!skb->tstamp.off_sec)
+	if (!skb->tstampns.off_sec)
 		net_timestamp(skb);
 
 	if (!skb->input_dev)
--- linux-2.6.21-rc2/net/core/skbuff.c	2007-03-01 11:41:01.000000000 +0100
+++ linux-2.6.21-rc2-ed/net/core/skbuff.c	2007-03-01 11:41:25.000000000 +0100
@@ -449,7 +449,7 @@ struct sk_buff *skb_clone(struct sk_buff
 
 	n->next = n->prev = NULL;
 	n->sk = NULL;
-	C(tstamp);
+	C(tstampns);
 	C(dev);
 	C(h);
 	C(nh);
@@ -534,7 +534,7 @@ static void copy_skb_header(struct sk_bu
 	new->local_df	= old->local_df;
 	new->fclone	= SKB_FCLONE_UNAVAILABLE;
 	new->pkt_type	= old->pkt_type;
-	new->tstamp	= old->tstamp;
+	new->tstampns	= old->tstampns;
 	new->destructor = NULL;
 	new->mark	= old->mark;
 #ifdef CONFIG_NETFILTER
--- 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 11:45:09.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	stampns;
 	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->stampns);
 	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->stampns);
 
 	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/ipv4/tcp_output.c	2007-03-01 11:45:09.000000000 +0100
+++ linux-2.6.21-rc2-ed/net/ipv4/tcp_output.c	2007-03-01 11:45:09.000000000 +0100
@@ -661,7 +661,7 @@ int tcp_fragment(struct sock *sk, struct
 	 * skbs, which it never sent before. --ANK
 	 */
 	TCP_SKB_CB(buff)->when = TCP_SKB_CB(skb)->when;
-	buff->tstamp = skb->tstamp;
+	buff->tstampns = skb->tstampns;
 
 	old_factor = tcp_skb_pcount(skb);
 
--- 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 12:32:56.000000000 +0100
@@ -656,12 +656,12 @@ static int tpacket_rcv(struct sk_buff *s
 	h->tp_snaplen = snaplen;
 	h->tp_mac = macoff;
 	h->tp_net = netoff;
-	if (skb->tstamp.off_sec == 0) {
+	if (skb->tstampns.off_sec == 0) {
 		__net_timestamp(skb);
 		sock_enable_timestamp(sk);
 	}
-	h->tp_sec = skb->tstamp.off_sec;
-	h->tp_usec = skb->tstamp.off_usec;
+	h->tp_sec = skb->tstampns.off_sec;
+	h->tp_usec = skb->tstampns.off_nsec/1000;
 
 	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 13:15:07.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_stampns);
 	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-01 12:56:02.000000000 +0100
@@ -545,20 +545,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)
+	if (sk->sk_stampns.tv_sec == -1)
 		return err;
-	if (sk->sk_stamp.tv_sec == 0)
-		do_gettimeofday(&sk->sk_stamp);
-	if (put_user(sk->sk_stamp.tv_sec, &ctv->tv_sec) ||
-			put_user(sk->sk_stamp.tv_usec, &ctv->tv_usec))
+	if (sk->sk_stampns.tv_sec == 0)
+		getnstimeofday(&sk->sk_stampns);
+	usec = sk->sk_stampns.tv_nsec / 1000;
+	if (put_user(sk->sk_stampns.tv_sec, &ctv->tv_sec) ||
+			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_stampns.tv_sec == -1)
+		return err;
+	if (sk->sk_stampns.tv_sec == 0)
+		getnstimeofday(&sk->sk_stampns);
+	if (put_user(sk->sk_stampns.tv_sec, &ctv->tv_sec) ||
+			put_user(sk->sk_stampns.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 12:56:02.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_stampns);
 
 	if (msg->msg_name)
 		memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
@@ -726,6 +726,8 @@ static int econet_ioctl(struct socket *s
 	switch(cmd) {
 		case SIOCGSTAMP:
 			return sock_get_timestamp(sk, argp);
+		case SIOCGSTAMPNS:
+			return sock_get_timestampns(sk, argp);
 
 		case SIOCSIFADDR:
 		case SIOCGIFADDR:
--- 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 11:34:07.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_stampns);
 
 	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-01 12:56:02.000000000 +0100
@@ -1280,6 +1280,12 @@ static int x25_ioctl(struct socket *sock
 				rc = sock_get_timestamp(sk,
 						(struct timeval __user *)argp);
 			break;
+		case SIOCGSTAMP:
+			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 SIOCGSTAMP:
+		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 13:09:56.000000000 +0100
@@ -166,7 +166,7 @@ static void ebt_ulog_packet(unsigned int
 	pm->version = EBT_ULOG_VERSION;
 	do_gettimeofday(&pm->stamp);
 	if (ub->qlen == 1)
-		skb_set_timestamp(ub->skb, &pm->stamp);
+		skb_set_timestampus(ub->skb, &pm->stamp);
 	pm->data_len = copy_len;
 	pm->mark = skb->mark;
 	pm->hook = hooknr;
--- 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/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/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/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-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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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 */

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: CLOCK_MONOTONIC datagram timestamps by the kernel
  2007-02-28 16:07         ` John
@ 2007-03-01 10:03           ` Evgeniy Polyakov
  2007-03-01 11:30           ` Eric Dumazet
  1 sibling, 0 replies; 22+ messages in thread
From: Evgeniy Polyakov @ 2007-03-01 10:03 UTC (permalink / raw)
  To: John; +Cc: Eric Dumazet, linux-net, netdev

On Wed, Feb 28, 2007 at 05:07:10PM +0100, John (linux.kernel@free.fr) wrote:
> Again, this is irrelevant. We are discussing whether it would make sense 
> to support sub-microsecond resolution. If there is one platform that can 
> achieve sub-microsecond precision, there is a need for sub-microsecond 
> resolution. As long as we are changing the resolution, we might as well 
> use something standard like struct timespec.

You can not blindly change skb timestamps to different entities - you
need to change all users (at least in kernel).
Exporting it to userspace must require new socket option and old one ust
be changed accordingly, but there is nothing wrong in having nanosecond
resolution in packet timestamp except that it might not be 100% correct
receiving time.

-- 
	Evgeniy Polyakov

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: CLOCK_MONOTONIC datagram timestamps by the kernel
  2007-02-28 13:37 ` John
  2007-02-28 13:55   ` Eric Dumazet
@ 2007-02-28 18:22   ` Stephen Hemminger
  1 sibling, 0 replies; 22+ messages in thread
From: Stephen Hemminger @ 2007-02-28 18:22 UTC (permalink / raw)
  To: John; +Cc: linux-net, netdev, linux.kernel

On Wed, 28 Feb 2007 14:37:49 +0100
John <linux.kernel@free.fr> wrote:

> John wrote:
> 
> > I know it's possible to have Linux timestamp incoming datagrams as soon
> > as they are received, then for one to retrieve this timestamp later with
> > an ioctl command or a recvmsg call.
> 
> Has it ever been proposed to modify struct skb_timeval to hold 
> nanosecond stamps instead of just microsecond stamps? Then make the 
> improved precision somehow available to user space.
> 

I am playing with a couple of possible future changes.
1. Change skb timestamp to be a timespec instead of timeval, for ABI
   compatiablity the existing SO_TIMESTAMP has to stay microseconds,
   but add a new SO_TIMESPEC to get the nanosecond version.

   The change gets non trivial because of other uses of timestamp (like vegas)
   so I gave up for now.

2. Use hardware receive timestamp in Yukon2 to put actual receive time
   into skb timestamp.  Works, but still figuring out how to manage
   clock skew/resync.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: CLOCK_MONOTONIC datagram timestamps by the kernel
  2007-02-28 14:55       ` Eric Dumazet
@ 2007-02-28 16:07         ` John
  2007-03-01 10:03           ` Evgeniy Polyakov
  2007-03-01 11:30           ` Eric Dumazet
  0 siblings, 2 replies; 22+ messages in thread
From: John @ 2007-02-28 16:07 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: linux-net, netdev, linux.kernel

Eric Dumazet wrote:
> On Wednesday 28 February 2007 15:23, John wrote:
>> Eric Dumazet wrote:
>>>> John wrote:
>>>>> I know it's possible to have Linux timestamp incoming datagrams as soon
>>>>> as they are received, then for one to retrieve this timestamp later
>>>>> with an ioctl command or a recvmsg call.
>>>> Has it ever been proposed to modify struct skb_timeval to hold
>>>> nanosecond stamps instead of just microsecond stamps? Then make the
>>>> improved precision somehow available to user space.
>>> Most modern NICS are able to delay packet delivery, in order to reduce
>>> number of interrupts and benefit from better cache hits.
>>
>> You are referring to NAPI interrupt mitigation, right?
> 
> Nope; I am referring to hardware features. NAPI is software.
> 
> See ethtool -c eth0
> 
> # ethtool -c eth0
> Coalesce parameters for eth0:
> Adaptive RX: off  TX: off
> stats-block-usecs: 1000000
> sample-interval: 0
> pkt-rate-low: 0
> pkt-rate-high: 0
> 
> rx-usecs: 300
> rx-frames: 60
> rx-usecs-irq: 300
> rx-frames-irq: 60
> 
> tx-usecs: 200
> tx-frames: 53
> tx-usecs-irq: 200
> tx-frames-irq: 53
> 
> You can see on this setup, rx interrupts can be delayed up to 300 us (up to 60
> packets might be delayed)

One can disable interrupt mitigation. Your argument that it introduces 
latency therefore becomes irrelevant.

>> POSIX is moving to nanoseconds interfaces.
>> http://www.opengroup.org/onlinepubs/009695399/functions/clock_settime.html

You snipped too much. I also wrote:

struct timeval and struct timespec take as much space (64 bits).

If the hardware can indeed manage sub-microsecond accuracy, a struct
timeval forces the kernel to discard valuable information.

> The fact that you are able to give nanosecond timestamps inside kernel is not 
> sufficient. It is necessary of course, but not sufficient. This precision is 
> OK to time locally generated events. The moment you ask a 'nanosecond' 
> timestamp, it's usually long before/after the real event.
> 
> If you rely on nanosecond precision on network packets, then something is 
> wrong with your algo. Even rt patches wont make sure your cpu caches are 
> pre-filled, or that the routers/links between your machines are not busy.
> A cache miss cost 40 ns for example. A typical interrupt handler or rx 
> processing can trigger 100 cache misses, or not at all if cache is hot.

Consider an idle Linux 2.6.20-rt8 system, equipped with a single PCI-E 
gigabit Ethernet NIC, running on a modern CPU (e.g. Core 2 Duo E6700). 
All this system does is time stamp 1000 packets per second.

Are you claiming that this platform *cannot* handle most packets within 
less than 1 microsecond of their arrival?

If there are platforms that can achieve sub-microsecond precision, and 
if it is not more expensive to support nanosecond resolution (I said 
resolution not precision), then it makes sense to support nanosecond 
resolution in Linux. Right?

> You said that rt gives highest priority to interrupt handlers :
> If you have several nics, what will happen if you receive packets on both 
> nics, or if the NIC interrupt happens in the same time than timer interrupt ? 
> One timestamp will be wrong for sure.

Again, this is irrelevant. We are discussing whether it would make sense 
to support sub-microsecond resolution. If there is one platform that can 
achieve sub-microsecond precision, there is a need for sub-microsecond 
resolution. As long as we are changing the resolution, we might as well 
use something standard like struct timespec.

> For sure we could timestamp packets with nanosecond resolution, and eventually 
> with MONOTONIC value too, but it will give you (and others) false confidence 
> on the real precision. us timestamps are already wrong...

IMHO, this is not true for all platforms.

Regards.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: CLOCK_MONOTONIC datagram timestamps by the kernel
  2007-02-28 14:23     ` John
@ 2007-02-28 14:55       ` Eric Dumazet
  2007-02-28 16:07         ` John
  0 siblings, 1 reply; 22+ messages in thread
From: Eric Dumazet @ 2007-02-28 14:55 UTC (permalink / raw)
  To: John; +Cc: linux-net, netdev

On Wednesday 28 February 2007 15:23, John wrote:
> Eric Dumazet wrote:
> >> John wrote:
> >>> I know it's possible to have Linux timestamp incoming datagrams as soon
> >>> as they are received, then for one to retrieve this timestamp later
> >>> with an ioctl command or a recvmsg call.
> >>
> >> Has it ever been proposed to modify struct skb_timeval to hold
> >> nanosecond stamps instead of just microsecond stamps? Then make the
> >> improved precision somehow available to user space.
> >
> > Most modern NICS are able to delay packet delivery, in order to reduce
> > number of interrupts and benefit from better cache hits.
>
> You are referring to NAPI interrupt mitigation, right?

Nope; I am referring to hardware features. NAPI is software.

See ethtool -c eth0

# ethtool -c eth0
Coalesce parameters for eth0:
Adaptive RX: off  TX: off
stats-block-usecs: 1000000
sample-interval: 0
pkt-rate-low: 0
pkt-rate-high: 0

rx-usecs: 300
rx-frames: 60
rx-usecs-irq: 300
rx-frames-irq: 60

tx-usecs: 200
tx-frames: 53
tx-usecs-irq: 200
tx-frames-irq: 53

You can see on this setup, rx interrupts can be delayed up to 300 us (up to 60 
packets might be delayed)

>
> POSIX is moving to nanoseconds interfaces.
> http://www.opengroup.org/onlinepubs/009695399/functions/clock_settime.html

The fact that you are able to give nanosecond timestamps inside kernel is not 
sufficient. It is necessary of course, but not sufficient. This precision is 
OK to time locally generated events. The moment you ask a 'nanosecond' 
timestamp, it's usually long before/after the real event.

If you rely on nanosecond precision on network packets, then something is 
wrong with your algo. Even rt patches wont make sure your cpu caches are 
pre-filled, or that the routers/links between your machines are not busy.
A cache miss cost 40 ns for example. A typical interrupt handler or rx 
processing can trigger 100 cache misses, or not at all if cache is hot.

You said that rt gives highest priority to interrupt handlers :
If you have several nics, what will happen if you receive packets on both 
nics, or if the NIC interrupt happens in the same time than timer interrupt ? 
One timestamp will be wrong for sure.

For sure we could timestamp packets with nanosecond resolution, and eventually 
with MONOTONIC value too, but it will give you (and others) false confidence 
on the real precision. us timestamps are already wrong...

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: CLOCK_MONOTONIC datagram timestamps by the kernel
  2007-02-28 13:55   ` Eric Dumazet
@ 2007-02-28 14:23     ` John
  2007-02-28 14:55       ` Eric Dumazet
  0 siblings, 1 reply; 22+ messages in thread
From: John @ 2007-02-28 14:23 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: linux-net, netdev, linux.kernel

Eric Dumazet wrote:

>> John wrote:
>> 
>>> I know it's possible to have Linux timestamp incoming datagrams as soon
>>> as they are received, then for one to retrieve this timestamp later with
>>> an ioctl command or a recvmsg call.
>> Has it ever been proposed to modify struct skb_timeval to hold
>> nanosecond stamps instead of just microsecond stamps? Then make the
>> improved precision somehow available to user space.
> 
> Most modern NICS are able to delay packet delivery, in order to reduce number 
> of interrupts and benefit from better cache hits.

You are referring to NAPI interrupt mitigation, right?

AFAIU, it is possible to disable this feature.

I'm dealing with 200-4000 packets per second. I don't think I'd save 
much with interrupt mitigation. Please correct any misconception.

> Then kernel is not realtime and some delays can occur between the hardware 
> interrupt and the very moment we timestamp the packet. If CPU caches are 
> cold, even the instruction fetches could easily add some us.

I've applied the real-time patch.
http://rt.wiki.kernel.org/index.php/Main_Page
This doesn't make Linux hard real-time, but the interrupt handlers can 
run with the highest priority (even kernel threads are preempted).

> Enabling nanosecond stamps would be a lie to users, because real accuracy is 
> not nanosecond, but in the order of 10 us (at least)

POSIX is moving to nanoseconds interfaces.
http://www.opengroup.org/onlinepubs/009695399/functions/clock_settime.html

struct timeval and struct timespec take as much space (64 bits).

If the hardware can indeed manage sub-microsecond accuracy, a struct 
timeval forces the kernel to discard valuable information.

> If you depend on a < 50 us precision, then linux might be the wrong OS for 
> your application. Or maybe you need a NIC that is able to provide a timestamp 
> in the packet itself (well... along with the packet...) , so that kernel 
> latencies are not a problem.

Does Linux support NICs that can do that?

Regards.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: CLOCK_MONOTONIC datagram timestamps by the kernel
  2007-02-28 13:37 ` John
@ 2007-02-28 13:55   ` Eric Dumazet
  2007-02-28 14:23     ` John
  2007-02-28 18:22   ` Stephen Hemminger
  1 sibling, 1 reply; 22+ messages in thread
From: Eric Dumazet @ 2007-02-28 13:55 UTC (permalink / raw)
  To: John; +Cc: linux-net, netdev

On Wednesday 28 February 2007 14:37, John wrote:
> John wrote:
> > I know it's possible to have Linux timestamp incoming datagrams as soon
> > as they are received, then for one to retrieve this timestamp later with
> > an ioctl command or a recvmsg call.
>
> Has it ever been proposed to modify struct skb_timeval to hold
> nanosecond stamps instead of just microsecond stamps? Then make the
> improved precision somehow available to user space.

John, 

Most modern NICS are able to delay packet delivery, in order to reduce number 
of interrupts and benefit from better cache hits.

tg3 for example are able to delay up to 1024 us.

Then kernel is not realtime and some delays can occur between the hardware 
interrupt and the very moment we timestamp the packet. If CPU caches are 
cold, even the instruction fetches could easily add some us.

Enabling nanosecond stamps would be a lie to users, because real accuracy is 
not nanosecond, but in the order of 10 us (at least)

If you depend on a < 50 us precision, then linux might be the wrong OS for 
your application. Or maybe you need a NIC that is able to provide a timestamp 
in the packet itself (well... along with the packet...) , so that kernel 
latencies are not a problem.

Eric

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: CLOCK_MONOTONIC datagram timestamps by the kernel
  2007-02-28 10:18 John
@ 2007-02-28 13:37 ` John
  2007-02-28 13:55   ` Eric Dumazet
  2007-02-28 18:22   ` Stephen Hemminger
  0 siblings, 2 replies; 22+ messages in thread
From: John @ 2007-02-28 13:37 UTC (permalink / raw)
  To: linux-net; +Cc: netdev, linux.kernel

John wrote:

> I know it's possible to have Linux timestamp incoming datagrams as soon
> as they are received, then for one to retrieve this timestamp later with
> an ioctl command or a recvmsg call.

Has it ever been proposed to modify struct skb_timeval to hold 
nanosecond stamps instead of just microsecond stamps? Then make the 
improved precision somehow available to user space.

On a related note, the comment for skb_set_timestamp() states:

/**
  * skb_set_timestamp - set timestamp of a skb
  * @skb: skb to set stamp of
  * @stamp: pointer to struct timeval 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
  * it in the skb.
  */

But there is no mention of an offset in the code:

static inline void skb_set_timestamp(
   struct sk_buff *skb, const struct timeval *stamp)
{
   skb->tstamp.off_sec  = stamp->tv_sec;
   skb->tstamp.off_usec = stamp->tv_usec;
}

Likewise for skb_get_timestamp:

/**
  * skb_get_timestamp - get timestamp from a skb
  * @skb: skb to get stamp from
  * @stamp: pointer to struct timeval 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 timeval and stores
  * it in stamp.
  */

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;
}

Are the comments related to code that has since been modified?

Regards.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* CLOCK_MONOTONIC datagram timestamps by the kernel
@ 2007-02-28 10:18 John
  2007-02-28 13:37 ` John
  0 siblings, 1 reply; 22+ messages in thread
From: John @ 2007-02-28 10:18 UTC (permalink / raw)
  To: linux-net; +Cc: netdev, linux.kernel

Hello,

I know it's possible to have Linux timestamp incoming datagrams as soon 
as they are received, then for one to retrieve this timestamp later with 
an ioctl command or a recvmsg call.

As far as I understand, one can either do

   const int on = 1;
   setsockopt(sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof on);

then use recvmsg()

or not set the SO_TIMESTAMP socket option and just call

   ioctl(sock, SIOCGSTAMP, &tv);

after each datagram has been received.

SIOCGSTAMP
     Return a struct timeval with the receive timestamp of the last
packet passed to the user. This is useful for accurate round trip time
measurements. See setitimer(2) for a description of struct timeval.


As far as I understand, this timestamp is given by the CLOCK_REALTIME 
clock. However, I would like to obtain a timestamp given by the 
CLOCK_MONOTONIC clock.

Relevant parts of the code (I think):

net/core/dev.c

void net_enable_timestamp(void)
{
   atomic_inc(&netstamp_needed);
}

void __net_timestamp(struct sk_buff *skb)
{
   struct timeval tv;

   do_gettimeofday(&tv);
   skb_set_timestamp(skb, &tv);
}

static inline void net_timestamp(struct sk_buff *skb)
{
   if (atomic_read(&netstamp_needed))
     __net_timestamp(skb);
   else {
     skb->tstamp.off_sec = 0;
     skb->tstamp.off_usec = 0;
   }
}

do_gettimeofday() just calls __get_realtime_clock_ts()

Would it be possible to replace do_gettimeofday() by ktime_get_ts() with 
the appropriate division by 1000 to convert the struct timespec back 
into a struct timeval?

void __net_timestamp(struct sk_buff *skb)
{
   struct timespec now;
   struct timeval tv;

   ktime_get_ts(&ts);
   tv.tv_sec = now.tv_sec;
   tv->tv_usec = now.tv_nsec/1000;
   skb_set_timestamp(skb, &tv);
}

How many apps / drivers would this break?

Is there perhaps a different way to achieve this?

Regards.


^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2007-03-02 10:11 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-02-25 21:29 CLOCK_MONOTONIC datagram timestamps by the kernel John
2007-02-26 10:26 ` John
2007-02-26 12:20   ` Andi Kleen
2007-02-26 14:17     ` John
2007-02-28 11:23       ` John
2007-02-28 10:18 John
2007-02-28 13:37 ` John
2007-02-28 13:55   ` Eric Dumazet
2007-02-28 14:23     ` John
2007-02-28 14:55       ` Eric Dumazet
2007-02-28 16:07         ` John
2007-03-01 10:03           ` Evgeniy Polyakov
2007-03-01 11:30           ` Eric Dumazet
2007-03-01 15:54             ` Stephen Hemminger
2007-03-01 16:13               ` Eric Dumazet
2007-03-01 18:53             ` Stephen Hemminger
2007-03-01 23:14               ` Eric Dumazet
2007-03-01 23:34                 ` Stephen Hemminger
2007-03-02  0:56                   ` Eric Dumazet
2007-03-02  9:26             ` John
2007-03-02 10:11               ` Eric Dumazet
2007-02-28 18:22   ` Stephen Hemminger

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.