CLOCK_MONOTONIC datagram timestamps by the kernel
Subsystems (14)
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.
Quoted 3 lines · John
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.
Quoted 8 lines · John
Quoted 3 lines · John
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_timevalto 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
Quoted 10 lines · Eric Dumazet
Quoted 8 lines
Quoted 3 lines · John
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_timevalto 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.
Quoted 1 line
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).
Quoted 1 line
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.
Quoted 1 line
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.
Quoted 6 lines · John
Quoted 5 lines · Eric Dumazet
Quoted 5 lines
Quoted 3 lines · John
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.
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines
Has it ever been proposed to modify struct
skb_timevalto 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)
Quoted 3 lines
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...
Quoted 31 lines · Eric Dumazet
Quoted 5 lines · John
Quoted 4 lines · Eric Dumazet
Quoted 4 lines
Quoted 3 lines · John
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.
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Has it ever been proposed to modify struct
skb_timevalto 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: 0rx-usecs: 300
rx-frames: 60
rx-usecs-irq: 300
rx-frames-irq: 60
Quoted 7 lines
tx-usecs: 200
tx-frames: 53
tx-usecs-irq: 200
tx-frames-irq: 53You 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.
Quoted 2 lines
Quoted 2 lines
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.
Quoted 4 lines
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?
Quoted 2 lines
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.
Quoted 1 line
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.
Quoted 5 lines · John
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.
Signature · 1 line
Evgeniy Polyakov
Quoted 7 lines · John
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)
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(-)
include/linux/skbuff.h +30 -12
@@ -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);
include/net/sock.h +10 -6
@@ -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 tstatic __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 socextern 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
include/net/compat.h +1 -0
@@ -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 */
net/core/sock.c +22 -6
@@ -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 )) {
net/core/dev.c +7 -7
@@ -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(structif (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 *skif (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)
net/core/skbuff.c +2 -2
@@ -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
net/ipv4/ip_fragment.c +3 -3
@@ -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 *qpif (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 ;
net/ipv4/af_inet.c +3 -0
@@ -755,6 +755,9 @@ int inet_ioctl(struct socket *sock, unsicase 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 :
net/ipv4/tcp_output.c +1 -1
@@ -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);
net/ipv6/af_inet6.c +3 -0
@@ -437,6 +437,9 @@ int inet6_ioctl(struct socket *sock, unscase 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 :
net/packet/af_packet.c +5 -3
@@ -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 :
net/sunrpc/svcsock.c +4 -5
@@ -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... */ /*
net/compat.c +26 -5
@@ -545,20 +545,41 @@ int compat_sock_get_timestamp(struct socstruct 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) {
fs/compat_ioctl.c +17 -0
@@ -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)
net/appletalk/ddp.c +3 -0
@@ -1768,6 +1768,9 @@ static int atalk_ioctl(struct socket *socase SIOCGSTAMP : rc =sock_get_timestamp (sk, argp);break ; +case SIOCGSTAMPNS : + rc =sock_get_timestampns (sk, argp); +break ;/* Routing */ case SIOCADDRT :case SIOCDELRT :
net/ax25/af_ax25.c +4 -0
@@ -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 : {
net/atm/ioctl.c +3 -0
@@ -82,6 +82,9 @@ int vcc_ioctl(struct socket *sock, unsigcase 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 ;
net/econet/af_econet.c +3 -1
@@ -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 *sswitch (cmd) {case SIOCGSTAMP :return sock_get_timestamp (sk, argp); +case SIOCGSTAMPNS : +return sock_get_timestampns (sk, argp);case SIOCSIFADDR :case SIOCGIFADDR :
net/ipx/af_ipx.c +1 -1
@@ -1808,7 +1808,7 @@ static int ipx_recvmsg(struct kiocb *iocif (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);
net/netrom/af_netrom.c +5 -0
@@ -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 :
net/rose/af_rose.c +2 -0
@@ -1271,6 +1271,8 @@ static int rose_ioctl(struct socket *soccase 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 :
net/wanrouter/af_wanpipe.c +3 -0
@@ -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);
net/x25/af_x25.c +12 -0
@@ -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 :
net/bridge/netfilter/ebt_ulog.c +1 -1
@@ -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;
net/ipv6/netfilter/nf_conntrack_reasm.c +3 -3
@@ -82,7 +82,7 @@ struct nf_ct_frag6_queuestruct 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) */
net/ipv6/reassembly.c +3 -3
@@ -88,7 +88,7 @@ struct frag_queueint 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_qif (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;
include/asm-i386/sockios.h +2 -1
@@ -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
include/asm-x86_64/sockios.h +2 -1
@@ -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
include/asm-alpha/sockios.h +1 -0
@@ -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 */
include/asm-arm26/sockios.h +2 -1
@@ -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
include/asm-avr32/sockios.h +2 -1
@@ -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 */
include/asm-cris/sockios.h +2 -1
@@ -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
include/asm-frv/sockios.h +2 -1
@@ -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__ */
include/asm-h8300/sockios.h +2 -1
@@ -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__ */
include/asm-ia64/sockios.h +2 -1
@@ -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 */
include/asm-m32r/sockios.h +2 -1
@@ -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 */
include/asm-m68k/sockios.h +2 -1
@@ -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__ */
include/asm-mips/sockios.h +2 -1
@@ -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 */
include/asm-parisc/sockios.h +2 -1
@@ -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
include/asm-powerpc/sockios.h +2 -1
@@ -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 */
include/asm-s390/sockios.h +2 -1
@@ -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
include/asm-sh/sockios.h +1 -0
@@ -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 */
include/asm-sh64/sockios.h +1 -0
@@ -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 */
include/asm-sparc/sockios.h +2 -1
@@ -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) */
include/asm-sparc64/sockios.h +2 -1
@@ -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) */
include/asm-v850/sockios.h +2 -1
@@ -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__ */
include/asm-xtensa/sockios.h +2 -1
@@ -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 */
Quoted 11 lines · Eric Dumazet
Quoted 7 lines · John
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?
Quoted 10 lines
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.
Quoted 3 lines
I compiled it on my i386 machine, and tested it with a patched libpcap/tcpdump
I assume old tcpdump works as expected.
Quoted 4 lines · Stephen Hemminger
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...
Quoted 2 lines
I assume old tcpdump works as expected.
Yes, of course...
PATCH 1/1 NET : convert network timestamps to ktime_t
In reply to Stephen HemmingerWe currently use a special structure (struct skb_timeval) and plain 'struct timeval' to store packet timestamps in sk_buffs and struct sock.
This has some drawbacks :
- Fixed resolution of micro second.
- Waste of space on 64bit platforms where sizeof(struct timeval)=16
I suggest using ktime_t that is a nice abstraction of high resolution time services, currently capable of nanosecond resolution.
As sizeof(ktime_t) is 8 bytes, using ktime_t in 'struct sock' permits a 8 byte shrink of this structure on 64bit architectures. Some other structures also benefit from this size reduction (struct ipq in ipv4/ip_fragment.c, struct frag_queue in ipv6/reassembly.c, ...)
Once this ktime infrastructure adopted, we can more easily provide nanosecond resolution on top of it. (ioctl SIOCGSTAMPNS and/or SO_TIMESTAMPNS/SCM_TIMESTAMPNS)
Note : this patch includes a bug correction in compat_sock_get_timestamp() where a "err = 0;" was missing (so this syscall returned -ENOENT instead of
0)
include/linux/skbuff.h | 26 ++++------------------ include/net/sock.h | 18 +++++++-------- net/bridge/netfilter/ebt_ulog.c | 6 +++-- net/compat.c | 15 ++++++++---- net/core/dev.c | 19 +++------------- net/core/sock.c | 16 +++++++------ net/econet/af_econet.c | 2 - net/ipv4/ip_fragment.c | 6 ++--- net/ipv4/netfilter/ip_queue.c | 6 +++-- net/ipv4/netfilter/ipt_ULOG.c | 8 ++++-- net/ipv6/exthdrs.c | 2 - net/ipv6/netfilter/ip6_queue.c | 6 +++-- net/ipv6/netfilter/nf_conntrack_reasm.c | 6 ++--- net/ipv6/reassembly.c | 6 ++--- net/ipx/af_ipx.c | 4 +-- net/netfilter/nfnetlink_log.c | 8 +++--- net/netfilter/nfnetlink_queue.c | 8 +++--- net/packet/af_packet.c | 8 ++++-- 18 files changed, 80 insertions(+), 90 deletions(-)
include/linux/skbuff.h +5 -21
@@ -27,6 +27,7 @@ #include <linux/textsearch.h>#include <net/checksum.h> #include <linux/rcupdate.h> #include <linux/dmaengine.h> +#include <linux/hrtimer.h> #define HAVE_ALLOC_SKB /* For the drivers to know */ #define HAVE_ALIGNABLE_SKB /* Ditto 8) */
@@ -156,11 +157,6 @@ struct skb_shared_info {#define SKB_DATAREF_SHIFT 16#define SKB_DATAREF_MASK ((1 << SKB_DATAREF_SHIFT) - 1) -struct skb_timeval { -u32 off_sec; -u32 off_usec; -}; -enum {SKB_FCLONE_UNAVAILABLE ,
@@ -233,7 +229,7 @@ struct sk_buff {struct sk_buff *prev;struct sock *sk; -struct skb_timeval tstamp; +ktime_t tstamp;struct net_device *dev;struct net_device *input_dev;
@@ -1360,26 +1356,14 @@ 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 =ktime_to_timeval (skb->tstamp); } -/** -* 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. -*/ -static inline void skb_set_timestamp (struct sk_buff *skb,const struct timeval *stamp) +static inline void __net_timestamp (struct sk_buff *skb) { - skb->tstamp.off_sec = stamp->tv_sec; - skb->tstamp.off_usec = stamp->tv_usec; + skb->tstamp =ktime_get_real (); } -extern void __net_timestamp (struct sk_buff *skb);extern __sum16 __skb_checksum_complete (struct sk_buff *skb);
include/net/sock.h +9 -9
@@ -244,7 +244,7 @@ #define sk_prot __sk_common.skc_protstruct sk_filter *sk_filter;void *sk_protinfo;struct timer_list sk_timer; -struct timeval sk_stamp; +ktime_t sk_stamp;struct socket *sk_socket;void *sk_user_data;struct page *sk_sndmsg_page;
@@ -1307,19 +1307,19 @@ static inline int sock_intr_errno(long tstatic __inline__void sock_recv_timestamp (struct msghdr *msg,struct sock *sk,struct sk_buff *skb) { -struct timeval stamp; +ktime_t kt = skb->tstamp; -skb_get_timestamp (skb, &stamp);if (sock_flag (sk,SOCK_RCVTSTAMP )) { +struct timeval tv;/* 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 (kt.tv64 ==0 ) + kt =ktime_get_real (); + skb->tstamp = kt; + tv =ktime_to_timeval (kt); +put_cmsg (msg,SOL_SOCKET ,SO_TIMESTAMP ,sizeof (tv), &tv); }else - sk->sk_stamp = stamp; + sk->sk_stamp = kt; }/**
net/bridge/netfilter/ebt_ulog.c +4 -2
@@ -130,6 +130,7 @@ static void ebt_ulog_packet(unsigned intunsigned int group = uloginfo->nlgroup;ebt_ulog_buff_t *ub = &ulog_buffers[group];spinlock_t *lock = &ub->lock; +ktime_t kt;if ((uloginfo->cprange ==0 ) || (uloginfo->cprange > skb->len +ETH_HLEN ))
@@ -164,9 +165,10 @@ static void ebt_ulog_packet(unsigned int/* Fill in the ulog data */ pm->version =EBT_ULOG_VERSION ; -do_gettimeofday (&pm->stamp); + kt =ktime_get_real (); + pm->stamp =ktime_to_timeval (kt);if (ub->qlen ==1 ) -skb_set_timestamp (ub->skb, &pm->stamp); + ub->skb->tstamp = kt; pm->data_len = copy_len; pm->mark = skb->mark; pm->hook = hooknr;
net/compat.c +10 -5
@@ -545,15 +545,20 @@ int compat_sock_get_timestamp(struct socstruct compat_timeval __user *ctv = (struct compat_timeval __user *) userstamp;int err = -ENOENT ; +struct timeval tv;if (!sock_flag (sk,SOCK_TIMESTAMP ))sock_enable_timestamp (sk); -if (sk->sk_stamp.tv_sec ==-1 ) + tv =ktime_to_timeval (sk->sk_stamp); +if (tv.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 (tv.tv_sec ==0 ) { + sk->sk_stamp =ktime_get_real (); + tv =ktime_to_timeval (sk->sk_stamp); + } + err =0 ; +if (put_user (tv.tv_sec, &ctv->tv_sec) || +put_user (tv.tv_usec, &ctv->tv_usec)) err = -EFAULT ;return err; }
net/core/dev.c +4 -15
@@ -1034,23 +1034,12 @@ void net_disable_timestamp(void)atomic_dec (&netstamp_needed); } -void __net_timestamp (struct sk_buff *skb) -{ -struct timeval tv; - -do_gettimeofday (&tv); -skb_set_timestamp (skb, &tv); -} -EXPORT_SYMBOL (__net_timestamp); -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 ; - } +else + skb->tstamp.tv64 =0 ; }/*
@@ -1580,7 +1569,7 @@ int netif_rx(struct sk_buff *skb)if (netpoll_rx (skb))return NET_RX_DROP ; -if (!skb->tstamp.off_sec) +if (!skb->tstamp.tv64)net_timestamp (skb);/*
@@ -1772,7 +1761,7 @@ int netif_receive_skb(struct sk_buff *skif (skb->dev->poll &&netpoll_rx (skb))return NET_RX_DROP ; -if (!skb->tstamp.off_sec) +if (!skb->tstamp.tv64)net_timestamp (skb);if (!skb->input_dev)
net/core/sock.c +9 -7
@@ -1512,8 +1512,7 @@ #endif 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_stamp =ktime_set (-1L ,-1L );atomic_set (&sk->sk_refcnt,1 ); }
@@ -1554,14 +1553,17 @@ EXPORT_SYMBOL(release_sock);int sock_get_timestamp (struct sock *sk,struct timeval __user *userstamp) { +struct timeval tv;if (!sock_flag (sk,SOCK_TIMESTAMP ))sock_enable_timestamp (sk); -if (sk->sk_stamp.tv_sec ==-1 ) + tv =ktime_to_timeval (sk->sk_stamp); +if (tv.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 )) ? - -EFAULT :0 ; +if (tv.tv_sec ==0 ) { + sk->sk_stamp =ktime_get_real (); + tv =ktime_to_timeval (sk->sk_stamp); + } +return copy_to_user (userstamp, &tv,sizeof (tv)) ? -EFAULT :0 ; }EXPORT_SYMBOL (sock_get_timestamp);
net/econet/af_econet.c +1 -1
@@ -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); + sk->sk_stamp = skb->tstamp;if (msg->msg_name)memcpy (msg->msg_name, skb->cb, msg->msg_namelen);
net/ipv4/ip_fragment.c +3 -3
@@ -92,7 +92,7 @@ #define LAST_IN 1spinlock_t lock;atomic_t refcnt;struct timer_list timer;/* when will this queue expire? */ -struct timeval stamp; +ktime_t stamp;int iif;unsigned int rid;struct inet_peer *peer;
@@ -592,7 +592,7 @@ static void ip_frag_queue(struct ipq *qpif (skb->dev) qp->iif = skb->dev->ifindex; skb->dev =NULL ; -skb_get_timestamp (skb, &qp->stamp); + qp->stamp = skb->tstamp; 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); + head->tstamp = qp->stamp; iph = head->nh.iph; iph->frag_off =0 ;
net/ipv4/netfilter/ip_queue.c +4 -2
@@ -197,6 +197,7 @@ ipq_build_packet_message(struct ipq_queustruct sk_buff *skb;struct ipq_packet_msg *pmsg;struct nlmsghdr *nlh; +struct timeval tv;read_lock_bh (&queue_lock);
@@ -241,8 +242,9 @@ 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; + tv =ktime_to_timeval (entry->skb->tstamp); + pmsg->timestamp_sec = tv.tv_sec; + pmsg->timestamp_usec = tv.tv_usec; pmsg->mark = entry->skb->mark; pmsg->hook = entry->info->hook; pmsg->hw_protocol = entry->skb->protocol;
net/ipv4/netfilter/ipt_ULOG.c +5 -3
@@ -186,6 +186,7 @@ static void ipt_ulog_packet(unsigned intulog_packet_msg_t *pm;size_t size, copy_len;struct nlmsghdr *nlh; +struct timeval tv;/* ffs == find first bit set, necessary because userspace * is already shifting groupnumber, but we need unshifted.
@@ -231,13 +232,14 @@ static void ipt_ulog_packet(unsigned int pm =NLMSG_DATA (nlh);/* We might not have a timestamp, get one */ -if (skb->tstamp.off_sec ==0 ) +if (skb->tstamp.tv64 ==0 )__net_timestamp ((struct sk_buff *)skb);/* 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; + tv =ktime_to_timeval (skb->tstamp); + pm->timestamp_sec = tv.tv_sec; + pm->timestamp_usec = tv.tv_usec; pm->mark = skb->mark; pm->hook = hooknum;if (prefix !=NULL )
net/ipv6/exthdrs.c +1 -1
@@ -255,7 +255,7 @@ static int ipv6_dest_hao(struct sk_buffipv6_addr_copy (&ipv6h->saddr, &hao->addr);ipv6_addr_copy (&hao->addr, &tmp_addr); -if (skb->tstamp.off_sec ==0 ) +if (skb->tstamp.tv64 ==0 )__net_timestamp (skb);return 1 ;
net/ipv6/netfilter/ip6_queue.c +4 -2
@@ -195,6 +195,7 @@ ipq_build_packet_message(struct ipq_queustruct sk_buff *skb;struct ipq_packet_msg *pmsg;struct nlmsghdr *nlh; +struct timeval tv;read_lock_bh (&queue_lock);
@@ -239,8 +240,9 @@ 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; + tv =ktime_to_timeval (entry->skb->tstamp); + pmsg->timestamp_sec = tv.tv_sec; + pmsg->timestamp_usec = tv.tv_usec; pmsg->mark = entry->skb->mark; pmsg->hook = entry->info->hook; pmsg->hw_protocol = entry->skb->protocol;
net/ipv6/netfilter/nf_conntrack_reasm.c +3 -3
@@ -82,7 +82,7 @@ struct nf_ct_frag6_queuestruct sk_buff *fragments;int len;int meat; -struct timeval stamp; +ktime_t 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); + fq->stamp = skb->tstamp; 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); + head->tstamp = fq->stamp; head->nh.ipv6h->payload_len =htons (payload_len);/* Yes, and fold redundant checksum back. 8) */
net/ipv6/reassembly.c +3 -3
@@ -88,7 +88,7 @@ struct frag_queueint len;int meat;int iif; -struct timeval stamp; +ktime_t 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_qif (skb->dev) fq->iif = skb->dev->ifindex; skb->dev =NULL ; -skb_get_timestamp (skb, &fq->stamp); + fq->stamp = skb->tstamp; 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); + head->tstamp = fq->stamp; head->nh.ipv6h->payload_len =htons (payload_len);IP6CB (head)->nhoff = nhoff;
net/ipx/af_ipx.c +2 -2
@@ -1807,8 +1807,8 @@ #endif /* CONFIG_IPX_INTERN */ copied);if (rc) goto out_free; -if (skb->tstamp.off_sec) -skb_get_timestamp (skb, &sk->sk_stamp); +if (skb->tstamp.tv64) + sk->sk_stamp = skb->tstamp; msg->msg_namelen =sizeof (*sipx);
net/netfilter/nfnetlink_log.c +4 -4
@@ -510,11 +510,11 @@ #endifNFA_PUT (inst->skb,NFULA_HWADDR ,sizeof (phw), &phw); } -if (skb->tstamp.off_sec) { +if (skb->tstamp.tv64) {struct nfulnl_msg_packet_timestamp ts; - - ts.sec =cpu_to_be64 (skb->tstamp.off_sec); - ts.usec =cpu_to_be64 (skb->tstamp.off_usec); +struct timeval tv =ktime_to_timeval (skb->tstamp); + ts.sec =cpu_to_be64 (tv.tv_sec); + ts.usec =cpu_to_be64 (tv.tv_usec);NFA_PUT (inst->skb,NFULA_TIMESTAMP ,sizeof (ts), &ts); }
net/netfilter/nfnetlink_queue.c +4 -4
@@ -495,11 +495,11 @@ #endifNFA_PUT (skb,NFQA_HWADDR ,sizeof (phw), &phw); } -if (entskb->tstamp.off_sec) { +if (entskb->tstamp.tv64) {struct nfqnl_msg_packet_timestamp ts; - - ts.sec =cpu_to_be64 (entskb->tstamp.off_sec); - ts.usec =cpu_to_be64 (entskb->tstamp.off_usec); +struct timeval tv =ktime_to_timeval (entskb->tstamp); + ts.sec =cpu_to_be64 (tv.tv_sec); + ts.usec =cpu_to_be64 (tv.tv_usec);NFA_PUT (skb,NFQA_TIMESTAMP ,sizeof (ts), &ts); }
net/packet/af_packet.c +5 -3
@@ -582,6 +582,7 @@ static int tpacket_rcv(struct sk_buff *sunsigned long status =TP_STATUS_LOSING |TP_STATUS_USER ;unsigned short macoff, netoff;struct sk_buff *copy_skb =NULL ; +struct timeval tv;if (skb->pkt_type ==PACKET_LOOPBACK ) goto drop;
@@ -656,12 +657,13 @@ 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->tstamp.tv64 ==0 ) {__net_timestamp (skb);sock_enable_timestamp (sk); } - h->tp_sec = skb->tstamp.off_sec; - h->tp_usec = skb->tstamp.off_usec; + tv =ktime_to_timeval (skb->tstamp); + h->tp_sec = tv.tv_sec; + h->tp_usec = tv.tv_usec; sll = (struct sockaddr_ll *)((u8 *)h +TPACKET_ALIGN (sizeof (*h))); sll->sll_halen =0 ;
Re: [PATCH] NET : convert network timestamps to ktime_t
Quoted 7 lines · On Fri, 2 Mar 2007 15:38:41 +0100 Eric Dumazet <[email protected]> wrote:
We currently use a special structure (struct
skb_timeval) and plain 'struct timeval' to store packet timestamps insk_buffsand struct sock.This has some drawbacks :
- Fixed resolution of micro second.
- Waste of space on 64bit platforms where sizeof(struct timeval)=16
Quoted 7 lines
I suggest using
ktime_tthat is a nice abstraction of high resolution time services, currently capable of nanosecond resolution.As
sizeof(ktime_t)is 8 bytes, usingktime_tin 'struct sock' permits a 8 byte shrink of this structure on 64bit architectures. Some other structures also benefit from this size reduction (struct ipq inipv4/ip_fragment.c, structfrag_queueinipv6/reassembly.c, ...)
This is even better. Also comparing ktime_t's is easier if some code needs to do that.
Re: [PATCH] NET : convert network timestamps to ktime_t
In reply to Eric DumazetQuoted 7 lines · On Fri, 2 Mar 2007 15:38:41 +0100 Eric Dumazet <[email protected]> wrote:
We currently use a special structure (struct
skb_timeval) and plain 'struct timeval' to store packet timestamps insk_buffsand struct sock.This has some drawbacks :
- Fixed resolution of micro second.
- Waste of space on 64bit platforms where sizeof(struct timeval)=16
Quoted 9 lines
I suggest using
ktime_tthat is a nice abstraction of high resolution time services, currently capable of nanosecond resolution.As
sizeof(ktime_t)is 8 bytes, usingktime_tin 'struct sock' permits a 8 byte shrink of this structure on 64bit architectures. Some other structures also benefit from this size reduction (struct ipq inipv4/ip_fragment.c, structfrag_queueinipv6/reassembly.c, ...)
You missed a couple of spots.
net/sunrpc/svcsock.c +2 -9
@@ -805,16 +805,9 @@/* possibly an icmp error */ dprintk ("svc: recvfrom returned error %d\n" , -err); } -if (skb->tstamp.off_sec ==0 ) { -struct timeval tv; - tv.tv_sec = xtime.tv_sec; - tv.tv_usec = xtime.tv_nsec /NSEC_PER_USEC ; -skb_set_timestamp (skb, &tv); -/* Don't enable netstamp, sunrpc doesn't -need that much accuracy */ - } -skb_get_timestamp (skb, &svsk->sk_sk->sk_stamp); + svsk->sk_sk->sk_stamp = (skb->tstamp.tv64 !=0 ) ? skb->tstamp + :ktime_get_real ();set_bit (SK_DATA , &svsk->sk_flags);/* there may be more data... */ /*
kernel/time.c +2 -0
@@ -469,6 +469,8 @@return tv; } +EXPORT_SYMBOL (ns_to_timeval); +/* * Convert jiffies to milliseconds and back.
Signature · 1 line
Stephen Hemminger <[email protected]>
Re: [PATCH] NET : convert network timestamps to ktime_t
Quoted 9 lines · Stephen Hemminger
Quoted 6 lines · On Fri, 2 Mar 2007 15:38:41 +0100 Eric Dumazet <[email protected]> wrote:
We currently use a special structure (struct
skb_timeval) and plain 'struct timeval' to store packet timestamps insk_buffsand struct sock.This has some drawbacks :
- Fixed resolution of micro second.
- Waste of space on 64bit platforms where sizeof(struct timeval)=16
Quoted 7 lines
Quoted 5 lines
I suggest using
ktime_tthat is a nice abstraction of high resolution time services, currently capable of nanosecond resolution.As
sizeof(ktime_t)is 8 bytes, usingktime_tin 'struct sock' permits a 8 byte shrink of this structure on 64bit architectures. Some other structures also benefit from this size reduction (struct ipq inipv4/ip_fragment.c, structfrag_queueinipv6/reassembly.c, ...)You missed a couple of spots.
Arg yes...
Quoted 9 lines
net/sunrpc/svcsock.c +0
-2@@ -805,16 +805,9 @@/* possibly an icmp error */ dprintk ("svc: recvfrom returned error %d\n" , -err); } -if (skb->tstamp.off_sec ==0 ) { -struct timeval tv;
net/sunrpc/svcsock.c line 810
Quoted 10 lines
net/sunrpc/svcsock.c +2
-7- tv.tv_sec = xtime.tv_sec; - tv.tv_usec = xtime.tv_nsec /NSEC_PER_USEC ; -skb_set_timestamp (skb, &tv); -/* Don't enable netstamp, sunrpc doesn't -need that much accuracy */ - } -skb_get_timestamp (skb, &svsk->sk_sk->sk_stamp); + svsk->sk_sk->sk_stamp = (skb->tstamp.tv64 !=0 ) ? skb->tstamp + :ktime_get_real ();
Well, if we want to stay in the spirit of old code, we probably want to use current_kernel_time() (+ timespec_to_ktime()), because its less expensive.
And also setting the skb tstamp, no ?
David Miller
maintainerRe: [PATCH] NET : convert network timestamps to ktime_t
From: Eric Dumazet <[email protected]>
Date: Fri, 02 Mar 2007 23:46:14 +0100
Quoted 4 lines
Quoted 1 line · Stephen Hemminger
You missed a couple of spots.
Arg yes...
...
Quoted 9 lines
net/sunrpc/svcsock.c line 810
Quoted 4 lines
net/sunrpc/svcsock.c +2
-2- } -skb_get_timestamp (skb, &svsk->sk_sk->sk_stamp); + svsk->sk_sk->sk_stamp = (skb->tstamp.tv64 !=0 ) ? skb->tstamp + :ktime_get_real ();Well, if we want to stay in the spirit of old code, we probably want to use
current_kernel_time()(+timespec_to_ktime()), because its less expensive.And also setting the skb tstamp, no ?
Can you guys cook up an integrated patch with all the missing cases fixed up as desired, so I can add this to net-2.6.22, thanks?
Re: [PATCH] NET : convert network timestamps to ktime_t
Quoted 13 lines · David Miller
From: Eric Dumazet <[email protected]>
Date: Fri, 02 Mar 2007 23:46:14 +0100Quoted 3 lines
Quoted 1 line · Stephen Hemminger
You missed a couple of spots.
Arg yes...
...
Quoted 6 lines
net/sunrpc/svcsock.c line 810
Quoted 4 lines
net/sunrpc/svcsock.c +2
-2- } -skb_get_timestamp (skb, &svsk->sk_sk->sk_stamp); + svsk->sk_sk->sk_stamp = (skb->tstamp.tv64 !=0 ) ? skb->tstamp + :ktime_get_real ();Well, if we want to stay in the spirit of old code, we probably want to use
current_kernel_time()(+timespec_to_ktime()), because its less expensive.
Quoted 4 lines
Quoted 1 line
And also setting the skb tstamp, no ?
Can you guys cook up an integrated patch with all the missing cases fixed up as desired, so I can add this to net-2.6.22, thanks?
Yes, I will send the patch against net-2.6.22 this morning.
PATCH 1/1 NET : convert network timestamps to ktime_t
Hi David
Here is the second version of this patch, including missing bits spoted by Stephen. This is against net-2.6.22
Thank you
[PATCH] NET : convert network timestamps to ktime_t
We currently use a special structure (struct skb_timeval) and plain 'struct timeval' to store packet timestamps in sk_buffs and struct sock.
This has some drawbacks :
- Fixed resolution of micro second.
- Waste of space on 64bit platforms where sizeof(struct timeval)=16
I suggest using ktime_t that is a nice abstraction of high resolution time services, currently capable of nanosecond resolution.
As sizeof(ktime_t) is 8 bytes, using ktime_t in 'struct sock' permits a 8 byte shrink of this structure on 64bit architectures. Some other structures also benefit from this size reduction (struct ipq in ipv4/ip_fragment.c, struct frag_queue in ipv6/reassembly.c, ...)
Once this ktime infrastructure adopted, we can more easily provide nanosecond resolution on top of it. (ioctl SIOCGSTAMPNS and/or SO_TIMESTAMPNS/SCM_TIMESTAMPNS)
Note : this patch includes a bug correction in compat_sock_get_timestamp() where a "err = 0;" was missing (so this syscall returned -ENOENT instead of
0)
include/linux/skbuff.h | 26 ++++------------------ include/net/sock.h | 18 +++++++-------- kernel/time.c | 1 net/bridge/netfilter/ebt_ulog.c | 6 +++-- net/compat.c | 15 ++++++++---- net/core/dev.c | 19 +++------------- net/core/sock.c | 16 +++++++------ net/econet/af_econet.c | 2 - net/ipv4/ip_fragment.c | 8 +++--- net/ipv4/netfilter/ip_queue.c | 6 +++-- net/ipv4/netfilter/ipt_ULOG.c | 8 ++++-- net/ipv6/exthdrs.c | 2 - net/ipv6/netfilter/ip6_queue.c | 6 +++-- net/ipv6/netfilter/nf_conntrack_reasm.c | 6 ++--- net/ipv6/reassembly.c | 6 ++--- net/ipx/af_ipx.c | 4 +-- net/netfilter/nfnetlink_log.c | 8 +++--- net/netfilter/nfnetlink_queue.c | 8 +++--- net/packet/af_packet.c | 8 ++++-- net/sunrpc/svcsock.c | 10 ++------ 20 files changed, 85 insertions(+), 98 deletions(-)
include/linux/skbuff.h +5 -21
@@ -27,6 +27,7 @@ #include <linux/textsearch.h>#include <net/checksum.h> #include <linux/rcupdate.h> #include <linux/dmaengine.h> +#include <linux/hrtimer.h> #define HAVE_ALLOC_SKB /* For the drivers to know */ #define HAVE_ALIGNABLE_SKB /* Ditto 8) */
@@ -156,11 +157,6 @@ struct skb_shared_info {#define SKB_DATAREF_SHIFT 16#define SKB_DATAREF_MASK ((1 << SKB_DATAREF_SHIFT) - 1) -struct skb_timeval { -u32 off_sec; -u32 off_usec; -}; -enum {SKB_FCLONE_UNAVAILABLE ,
@@ -233,7 +229,7 @@ struct sk_buff {struct sk_buff *prev;struct sock *sk; -struct skb_timeval tstamp; +ktime_t tstamp;struct net_device *dev;struct net_device *input_dev;
@@ -1360,26 +1356,14 @@ 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 =ktime_to_timeval (skb->tstamp); } -/** -* 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. -*/ -static inline void skb_set_timestamp (struct sk_buff *skb,const struct timeval *stamp) +static inline void __net_timestamp (struct sk_buff *skb) { - skb->tstamp.off_sec = stamp->tv_sec; - skb->tstamp.off_usec = stamp->tv_usec; + skb->tstamp =ktime_get_real (); } -extern void __net_timestamp (struct sk_buff *skb);extern __sum16 __skb_checksum_complete (struct sk_buff *skb);
include/net/sock.h +9 -9
@@ -244,7 +244,7 @@ #define sk_prot __sk_common.skc_protstruct sk_filter *sk_filter;void *sk_protinfo;struct timer_list sk_timer; -struct timeval sk_stamp; +ktime_t sk_stamp;struct socket *sk_socket;void *sk_user_data;struct page *sk_sndmsg_page;
@@ -1307,19 +1307,19 @@ static inline int sock_intr_errno(long tstatic __inline__void sock_recv_timestamp (struct msghdr *msg,struct sock *sk,struct sk_buff *skb) { -struct timeval stamp; +ktime_t kt = skb->tstamp; -skb_get_timestamp (skb, &stamp);if (sock_flag (sk,SOCK_RCVTSTAMP )) { +struct timeval tv;/* 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 (kt.tv64 ==0 ) + kt =ktime_get_real (); + skb->tstamp = kt; + tv =ktime_to_timeval (kt); +put_cmsg (msg,SOL_SOCKET ,SO_TIMESTAMP ,sizeof (tv), &tv); }else - sk->sk_stamp = stamp; + sk->sk_stamp = kt; }/**
kernel/time.c +1 -0
@@ -469,6 +469,7 @@ struct timeval ns_to_timeval(const s64 nreturn tv; } +EXPORT_SYMBOL (ns_to_timeval);/* * Convert jiffies to milliseconds and back.
net/bridge/netfilter/ebt_ulog.c +4 -2
@@ -130,6 +130,7 @@ static void ebt_ulog_packet(unsigned intunsigned int group = uloginfo->nlgroup;ebt_ulog_buff_t *ub = &ulog_buffers[group];spinlock_t *lock = &ub->lock; +ktime_t kt;if ((uloginfo->cprange ==0 ) || (uloginfo->cprange > skb->len +ETH_HLEN ))
@@ -164,9 +165,10 @@ static void ebt_ulog_packet(unsigned int/* Fill in the ulog data */ pm->version =EBT_ULOG_VERSION ; -do_gettimeofday (&pm->stamp); + kt =ktime_get_real (); + pm->stamp =ktime_to_timeval (kt);if (ub->qlen ==1 ) -skb_set_timestamp (ub->skb, &pm->stamp); + ub->skb->tstamp = kt; pm->data_len = copy_len; pm->mark = skb->mark; pm->hook = hooknr;
net/compat.c +10 -5
@@ -545,15 +545,20 @@ int compat_sock_get_timestamp(struct socstruct compat_timeval __user *ctv = (struct compat_timeval __user *) userstamp;int err = -ENOENT ; +struct timeval tv;if (!sock_flag (sk,SOCK_TIMESTAMP ))sock_enable_timestamp (sk); -if (sk->sk_stamp.tv_sec ==-1 ) + tv =ktime_to_timeval (sk->sk_stamp); +if (tv.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 (tv.tv_sec ==0 ) { + sk->sk_stamp =ktime_get_real (); + tv =ktime_to_timeval (sk->sk_stamp); + } + err =0 ; +if (put_user (tv.tv_sec, &ctv->tv_sec) || +put_user (tv.tv_usec, &ctv->tv_usec)) err = -EFAULT ;return err; }
net/core/dev.c +4 -15
@@ -1034,23 +1034,12 @@ void net_disable_timestamp(void)atomic_dec (&netstamp_needed); } -void __net_timestamp (struct sk_buff *skb) -{ -struct timeval tv; - -do_gettimeofday (&tv); -skb_set_timestamp (skb, &tv); -} -EXPORT_SYMBOL (__net_timestamp); -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 ; - } +else + skb->tstamp.tv64 =0 ; }/*
@@ -1580,7 +1569,7 @@ int netif_rx(struct sk_buff *skb)if (netpoll_rx (skb))return NET_RX_DROP ; -if (!skb->tstamp.off_sec) +if (!skb->tstamp.tv64)net_timestamp (skb);/*
@@ -1772,7 +1761,7 @@ int netif_receive_skb(struct sk_buff *skif (skb->dev->poll &&netpoll_rx (skb))return NET_RX_DROP ; -if (!skb->tstamp.off_sec) +if (!skb->tstamp.tv64)net_timestamp (skb);if (!skb->input_dev)
net/core/sock.c +9 -7
@@ -1512,8 +1512,7 @@ #endif 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_stamp =ktime_set (-1L ,-1L );atomic_set (&sk->sk_refcnt,1 ); }
@@ -1554,14 +1553,17 @@ EXPORT_SYMBOL(release_sock);int sock_get_timestamp (struct sock *sk,struct timeval __user *userstamp) { +struct timeval tv;if (!sock_flag (sk,SOCK_TIMESTAMP ))sock_enable_timestamp (sk); -if (sk->sk_stamp.tv_sec ==-1 ) + tv =ktime_to_timeval (sk->sk_stamp); +if (tv.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 )) ? - -EFAULT :0 ; +if (tv.tv_sec ==0 ) { + sk->sk_stamp =ktime_get_real (); + tv =ktime_to_timeval (sk->sk_stamp); + } +return copy_to_user (userstamp, &tv,sizeof (tv)) ? -EFAULT :0 ; }EXPORT_SYMBOL (sock_get_timestamp);
net/econet/af_econet.c +1 -1
@@ -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); + sk->sk_stamp = skb->tstamp;if (msg->msg_name)memcpy (msg->msg_name, skb->cb, msg->msg_namelen);
net/ipv4/ip_fragment.c +4 -4
@@ -92,7 +92,7 @@ #define LAST_IN 1spinlock_t lock;atomic_t refcnt;struct timer_list timer;/* when will this queue expire? */ -struct timeval stamp; +ktime_t stamp;int iif;unsigned int rid;struct inet_peer *peer;
@@ -592,7 +592,7 @@ static void ip_frag_queue(struct ipq *qpif (skb->dev) qp->iif = skb->dev->ifindex; skb->dev =NULL ; -skb_get_timestamp (skb, &qp->stamp); + qp->stamp = skb->tstamp; 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); + head->tstamp = qp->stamp; iph = head->nh.iph; iph->frag_off =0 ;
@@ -734,7 +734,7 @@ struct sk_buff *ip_defrag(struct sk_buffreturn NULL ; } -void ipfrag_init (void ) +void __init ipfrag_init (void ) { ipfrag_hash_rnd = (u32) ((num_physpages ^ (num_physpages>>7 )) ^ (jiffies ^ (jiffies >>6 )));
net/ipv4/netfilter/ip_queue.c +4 -2
@@ -197,6 +197,7 @@ ipq_build_packet_message(struct ipq_queustruct sk_buff *skb;struct ipq_packet_msg *pmsg;struct nlmsghdr *nlh; +struct timeval tv;read_lock_bh (&queue_lock);
@@ -241,8 +242,9 @@ 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; + tv =ktime_to_timeval (entry->skb->tstamp); + pmsg->timestamp_sec = tv.tv_sec; + pmsg->timestamp_usec = tv.tv_usec; pmsg->mark = entry->skb->mark; pmsg->hook = entry->info->hook; pmsg->hw_protocol = entry->skb->protocol;
net/ipv4/netfilter/ipt_ULOG.c +5 -3
@@ -186,6 +186,7 @@ static void ipt_ulog_packet(unsigned intulog_packet_msg_t *pm;size_t size, copy_len;struct nlmsghdr *nlh; +struct timeval tv;/* ffs == find first bit set, necessary because userspace * is already shifting groupnumber, but we need unshifted.
@@ -231,13 +232,14 @@ static void ipt_ulog_packet(unsigned int pm =NLMSG_DATA (nlh);/* We might not have a timestamp, get one */ -if (skb->tstamp.off_sec ==0 ) +if (skb->tstamp.tv64 ==0 )__net_timestamp ((struct sk_buff *)skb);/* 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; + tv =ktime_to_timeval (skb->tstamp); + pm->timestamp_sec = tv.tv_sec; + pm->timestamp_usec = tv.tv_usec; pm->mark = skb->mark; pm->hook = hooknum;if (prefix !=NULL )
net/ipv6/exthdrs.c +1 -1
@@ -255,7 +255,7 @@ static int ipv6_dest_hao(struct sk_buffipv6_addr_copy (&ipv6h->saddr, &hao->addr);ipv6_addr_copy (&hao->addr, &tmp_addr); -if (skb->tstamp.off_sec ==0 ) +if (skb->tstamp.tv64 ==0 )__net_timestamp (skb);return 1 ;
net/ipv6/netfilter/ip6_queue.c +4 -2
@@ -195,6 +195,7 @@ ipq_build_packet_message(struct ipq_queustruct sk_buff *skb;struct ipq_packet_msg *pmsg;struct nlmsghdr *nlh; +struct timeval tv;read_lock_bh (&queue_lock);
@@ -239,8 +240,9 @@ 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; + tv =ktime_to_timeval (entry->skb->tstamp); + pmsg->timestamp_sec = tv.tv_sec; + pmsg->timestamp_usec = tv.tv_usec; pmsg->mark = entry->skb->mark; pmsg->hook = entry->info->hook; pmsg->hw_protocol = entry->skb->protocol;
net/ipv6/netfilter/nf_conntrack_reasm.c +3 -3
@@ -82,7 +82,7 @@ struct nf_ct_frag6_queuestruct sk_buff *fragments;int len;int meat; -struct timeval stamp; +ktime_t 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); + fq->stamp = skb->tstamp; 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); + head->tstamp = fq->stamp; head->nh.ipv6h->payload_len =htons (payload_len);/* Yes, and fold redundant checksum back. 8) */
net/ipv6/reassembly.c +3 -3
@@ -88,7 +88,7 @@ struct frag_queueint len;int meat;int iif; -struct timeval stamp; +ktime_t 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_qif (skb->dev) fq->iif = skb->dev->ifindex; skb->dev =NULL ; -skb_get_timestamp (skb, &fq->stamp); + fq->stamp = skb->tstamp; 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); + head->tstamp = fq->stamp; head->nh.ipv6h->payload_len =htons (payload_len);IP6CB (head)->nhoff = nhoff;
net/ipx/af_ipx.c +2 -2
@@ -1807,8 +1807,8 @@ #endif /* CONFIG_IPX_INTERN */ copied);if (rc) goto out_free; -if (skb->tstamp.off_sec) -skb_get_timestamp (skb, &sk->sk_stamp); +if (skb->tstamp.tv64) + sk->sk_stamp = skb->tstamp; msg->msg_namelen =sizeof (*sipx);
net/netfilter/nfnetlink_log.c +4 -4
@@ -510,11 +510,11 @@ #endifNFA_PUT (inst->skb,NFULA_HWADDR ,sizeof (phw), &phw); } -if (skb->tstamp.off_sec) { +if (skb->tstamp.tv64) {struct nfulnl_msg_packet_timestamp ts; - - ts.sec =cpu_to_be64 (skb->tstamp.off_sec); - ts.usec =cpu_to_be64 (skb->tstamp.off_usec); +struct timeval tv =ktime_to_timeval (skb->tstamp); + ts.sec =cpu_to_be64 (tv.tv_sec); + ts.usec =cpu_to_be64 (tv.tv_usec);NFA_PUT (inst->skb,NFULA_TIMESTAMP ,sizeof (ts), &ts); }
net/netfilter/nfnetlink_queue.c +4 -4
@@ -495,11 +495,11 @@ #endifNFA_PUT (skb,NFQA_HWADDR ,sizeof (phw), &phw); } -if (entskb->tstamp.off_sec) { +if (entskb->tstamp.tv64) {struct nfqnl_msg_packet_timestamp ts; - - ts.sec =cpu_to_be64 (entskb->tstamp.off_sec); - ts.usec =cpu_to_be64 (entskb->tstamp.off_usec); +struct timeval tv =ktime_to_timeval (entskb->tstamp); + ts.sec =cpu_to_be64 (tv.tv_sec); + ts.usec =cpu_to_be64 (tv.tv_usec);NFA_PUT (skb,NFQA_TIMESTAMP ,sizeof (ts), &ts); }
net/packet/af_packet.c +5 -3
@@ -582,6 +582,7 @@ static int tpacket_rcv(struct sk_buff *sunsigned long status =TP_STATUS_LOSING |TP_STATUS_USER ;unsigned short macoff, netoff;struct sk_buff *copy_skb =NULL ; +struct timeval tv;if (skb->pkt_type ==PACKET_LOOPBACK ) goto drop;
@@ -656,12 +657,13 @@ 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->tstamp.tv64 ==0 ) {__net_timestamp (skb);sock_enable_timestamp (sk); } - h->tp_sec = skb->tstamp.off_sec; - h->tp_usec = skb->tstamp.off_usec; + tv =ktime_to_timeval (skb->tstamp); + h->tp_sec = tv.tv_sec; + h->tp_usec = tv.tv_usec; sll = (struct sockaddr_ll *)((u8 *)h +TPACKET_ALIGN (sizeof (*h))); sll->sll_halen =0 ;
net/sunrpc/svcsock.c +3 -7
@@ -805,16 +805,12 @@ svc_udp_recvfrom(struct svc_rqst *rqstp)/* possibly an icmp error */ dprintk ("svc: recvfrom returned error %d\n" , -err); } -if (skb->tstamp.off_sec ==0 ) { -struct timeval tv; - - tv.tv_sec = xtime.tv_sec; - tv.tv_usec = xtime.tv_nsec /NSEC_PER_USEC ; -skb_set_timestamp (skb, &tv); +if (skb->tstamp.tv64 ==0 ) { + skb->tstamp =ktime_get_real ();/* Don't enable netstamp, sunrpc doesn't need that much accuracy */ } -skb_get_timestamp (skb, &svsk->sk_sk->sk_stamp); + svsk->sk_sk->sk_stamp = skb->tstamp;set_bit (SK_DATA , &svsk->sk_flags);/* there may be more data... */ /*
Re: [PATCH] NET : convert network timestamps to ktime_t
From: Eric Dumazet <[email protected]>
Date: Mon, 05 Mar 2007 08:40:03 +0100
Quoted 2 lines
Here is the second version of this patch, including missing bits spoted by Stephen. This is against net-2.6.22
Applied, thanks a lot.
Quoted 3 lines
Note : this patch includes a bug correction in
compat_sock_get_timestamp()where a "err = 0;" was missing (so this syscall returned-ENOENTinstead of
0)
Grrr, good spotting. Eric can you send me a version of just this bug fix against 2.6.21? I'll push that to Linus and 2.6.x-stable.
I guess most applications don't even bother to check the getsockopt() return value. :-)
Thanks a lot!
Re: [PATCH] NET : convert network timestamps to ktime_t
Quoted 5 lines · David Miller
From: Eric Dumazet <[email protected]>
Date: Mon, 05 Mar 2007 08:40:03 +0100Quoted 1 line
Here is the second version of this patch, including missing bits spoted by Stephen. This is against net-2.6.22
Quoted 8 lines
Applied, thanks a lot.
Quoted 3 lines
Note : this patch includes a bug correction in
compat_sock_get_timestamp()where a "err = 0;" was missing (so this syscall returned-ENOENTinstead of
0)Grrr, good spotting. Eric can you send me a version of just this bug fix against 2.6.21? I'll push that to Linus and 2.6.x-stable.
Yes I will do it. But, are your sure its really used ?
I dont know very much this compat stuff, but I found compat_sock_get_timestamp() only called from net/x25/af_x25.c
I wonder how a 32 bit task on x86_64 can enter this compat code on other sockets ?
David Miller
maintainerRe: [PATCH] NET : convert network timestamps to ktime_t
From: Eric Dumazet <[email protected]>
Date: Mon, 05 Mar 2007 09:21:30 +0100
Quoted 2 lines
I dont know very much this compat stuff, but I found
compat_sock_get_timestamp()only called fromnet/x25/af_x25.c
Good point, I thought for some reason that this function was used for all SO_TIMESTAMP handling, but looking again I see that the main stuff is handled in put_cmsg() compat code.
PATCH 1/1 NET : Introduce SIOCGSTAMPNS ioctl to get timestamps with nanosec resolution
In reply to Eric DumazetHi David
This patch is for net-2.6.22 git tree.
A separate patch will follow for SO_TIMESTAMPNS / SCM_TIMESTAMPNS support.
Thank you
[PATCH] NET : Introduce SIOCGSTAMPNS ioctl to get timestamps with nanosec resolution
Now network timestamps use ktime_t infrastructure, we can add a new ioctl() SIOCGSTAMPNS command to get timestamps in 'struct timespec'. User programs can thus access to nanosecond resolution.
fs/compat_ioctl.c | 18 ++++++++++++++++++ include/asm-alpha/sockios.h | 3 ++- include/asm-arm/sockios.h | 3 ++- 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 | 3 ++- include/asm-sh64/sockios.h | 3 ++- 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/net/compat.h | 1 + include/net/sock.h | 1 + net/appletalk/ddp.c | 3 +++ net/atm/ioctl.c | 3 +++ net/ax25/af_ax25.c | 4 ++++ net/compat.c | 24 ++++++++++++++++++++++++ net/core/sock.c | 16 ++++++++++++++++ net/econet/af_econet.c | 3 +++ net/ipv4/af_inet.c | 3 +++ net/ipv6/af_inet6.c | 3 +++ net/netrom/af_netrom.c | 6 ++++++ net/packet/af_packet.c | 2 ++ net/rose/af_rose.c | 3 +++ net/wanrouter/af_wanpipe.c | 3 +++ net/x25/af_x25.c | 12 ++++++++++++ 38 files changed, 149 insertions(+), 22 deletions(-)
fs/compat_ioctl.c +18 -0
@@ -266,6 +266,23 @@ static int do_siocgstamp(unsigned int fdreturn err; } +static int do_siocgstampns (unsigned int fd,unsigned int cmd,unsigned long arg) +{ +struct compat_timespec __user *up =compat_ptr (arg); +struct timespec kts; +mm_segment_t old_fs =get_fs (); +int err; + +set_fs (KERNEL_DS ); + err =sys_ioctl (fd, cmd, (unsigned long )&kts); +set_fs (old_fs); +if (!err) { + err =put_user (kts.tv_sec, &up->tv_sec); + err |=__put_user (kts.tv_nsec, &up->tv_nsec); + } +return err; +} +struct ifmap32 {compat_ulong_t mem_start;compat_ulong_t mem_end;
@@ -2437,6 +2454,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)
include/asm-alpha/sockios.h +2 -1
@@ -10,6 +10,7 @@ #define SIOCATMARK _IOR('s', 7, int)#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_ALPHA_SOCKIOS_H */
include/asm-arm/sockios.h +2 -1
@@ -7,6 +7,7 @@ #define SIOCSPGRP 0x8902#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
include/asm-arm26/sockios.h +2 -1
@@ -7,6 +7,7 @@ #define SIOCSPGRP 0x8902#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
include/asm-avr32/sockios.h +2 -1
@@ -7,6 +7,7 @@ #define SIOCSPGRP 0x8902#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 */
include/asm-cris/sockios.h +2 -1
@@ -7,6 +7,7 @@ #define SIOCSPGRP 0x8902#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
include/asm-frv/sockios.h +2 -1
@@ -7,7 +7,8 @@ #define SIOCSPGRP 0x8902#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__ */
include/asm-h8300/sockios.h +2 -1
@@ -7,6 +7,7 @@ #define SIOCSPGRP 0x8902#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__ */
include/asm-i386/sockios.h +2 -1
@@ -7,6 +7,7 @@ #define SIOCSPGRP 0x8902#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
include/asm-ia64/sockios.h +2 -1
@@ -14,6 +14,7 @@ #define SIOCSPGRP 0x8902#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 */
include/asm-m32r/sockios.h +2 -1
@@ -7,6 +7,7 @@ #define SIOCSPGRP 0x8902#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 */
include/asm-m68k/sockios.h +2 -1
@@ -7,6 +7,7 @@ #define SIOCSPGRP 0x8902#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__ */
include/asm-mips/sockios.h +2 -1
@@ -20,6 +20,7 @@ #define SIOCATMARK _IOR('s', 7, int)#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 */
include/asm-parisc/sockios.h +2 -1
@@ -7,6 +7,7 @@ #define SIOCSPGRP 0x8902#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
include/asm-powerpc/sockios.h +2 -1
@@ -14,6 +14,7 @@ #define SIOCSPGRP 0x8902#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 */
include/asm-s390/sockios.h +2 -1
@@ -15,6 +15,7 @@ #define SIOCSPGRP 0x8902#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
include/asm-sh/sockios.h +2 -1
@@ -9,5 +9,6 @@ #define SIOCATMARK _IOR('s', 7, int)#define SIOCSPGRP _IOW('s', 8, pid_t)#define SIOCGPGRP _IOR('s', 9, pid_t) -#define SIOCGSTAMP _IOR('s', 100, struct timeval)/* Get stamp - linux-specific */ +#define SIOCGSTAMP _IOR('s', 100, struct timeval)/* Get stamp (timeval) */ +#define SIOCGSTAMPNS _IOR('s', 101, struct timespec)/* Get stamp (timespec) */ #endif /* __ASM_SH_SOCKIOS_H */
include/asm-sh64/sockios.h +2 -1
@@ -20,5 +20,6 @@ #define SIOCATMARK _IOR('s', 7, int)#define SIOCSPGRP _IOW('s', 8, pid_t)#define SIOCGPGRP _IOR('s', 9, pid_t) -#define SIOCGSTAMP _IOR('s', 100, struct timeval)/* Get stamp - linux-specific */ +#define SIOCGSTAMP _IOR('s', 100, struct timeval)/* Get stamp (timeval) */ +#define SIOCGSTAMPNS _IOR('s', 101, struct timespec)/* Get stamp (timespec) */ #endif /* __ASM_SH64_SOCKIOS_H */
include/asm-sparc/sockios.h +2 -1
@@ -7,7 +7,8 @@ #define SIOCSPGRP 0x8902#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) */
include/asm-sparc64/sockios.h +2 -1
@@ -7,7 +7,8 @@ #define SIOCSPGRP 0x8902#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) */
include/asm-v850/sockios.h +2 -1
@@ -7,6 +7,7 @@ #define SIOCSPGRP 0x8902#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__ */
include/asm-x86_64/sockios.h +2 -1
@@ -7,6 +7,7 @@ #define SIOCSPGRP 0x8902#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
include/asm-xtensa/sockios.h +2 -1
@@ -25,6 +25,7 @@ #define SIOCATMARK _IOR('s', 7, int)#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 */
include/net/compat.h +1 -0
@@ -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 */
include/net/sock.h +1 -0
@@ -1329,6 +1329,7 @@ #endifextern 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
net/appletalk/ddp.c +3 -0
@@ -1768,6 +1768,9 @@ static int atalk_ioctl(struct socket *socase SIOCGSTAMP : rc =sock_get_timestamp (sk, argp);break ; +case SIOCGSTAMPNS : + rc =sock_get_timestampns (sk, argp); +break ;/* Routing */ case SIOCADDRT :case SIOCDELRT :
net/atm/ioctl.c +3 -0
@@ -82,6 +82,9 @@ int vcc_ioctl(struct socket *sock, unsigcase 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 ;
net/ax25/af_ax25.c +4 -0
@@ -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 : {
net/compat.c +24 -0
@@ -564,6 +564,30 @@ int compat_sock_get_timestamp(struct soc }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 ; +struct timespec ts; + +if (!sock_flag (sk,SOCK_TIMESTAMP )) +sock_enable_timestamp (sk); + ts =ktime_to_timespec (sk->sk_stamp); +if (ts.tv_sec ==-1 ) +return err; +if (ts.tv_sec ==0 ) { + sk->sk_stamp =ktime_get_real (); + ts =ktime_to_timespec (sk->sk_stamp); + } + err =0 ; +if (put_user (ts.tv_sec, &ctv->tv_sec) || +put_user (ts.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) {
net/core/sock.c +16 -0
@@ -1567,6 +1567,22 @@ int sock_get_timestamp(struct sock *sk, }EXPORT_SYMBOL (sock_get_timestamp); +int sock_get_timestampns (struct sock *sk,struct timespec __user *userstamp) +{ +struct timespec ts; +if (!sock_flag (sk,SOCK_TIMESTAMP )) +sock_enable_timestamp (sk); + ts =ktime_to_timespec (sk->sk_stamp); +if (ts.tv_sec ==-1 ) +return -ENOENT ; +if (ts.tv_sec ==0 ) { + sk->sk_stamp =ktime_get_real (); + ts =ktime_to_timespec (sk->sk_stamp); + } +return copy_to_user (userstamp, &ts,sizeof (ts)) ? -EFAULT :0 ; +} +EXPORT_SYMBOL (sock_get_timestampns); +void sock_enable_timestamp (struct sock *sk) {if (!sock_flag (sk,SOCK_TIMESTAMP )) {
net/econet/af_econet.c +3 -0
@@ -727,6 +727,9 @@ static int econet_ioctl(struct socket *scase 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);
net/ipv4/af_inet.c +3 -0
@@ -755,6 +755,9 @@ int inet_ioctl(struct socket *sock, unsicase 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 :
net/ipv6/af_inet6.c +3 -0
@@ -443,6 +443,9 @@ int inet6_ioctl(struct socket *sock, unscase 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 :
net/netrom/af_netrom.c +6 -0
@@ -1209,6 +1209,12 @@ static int nr_ioctl(struct socket *sock,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 :case SIOCGIFDSTADDR :
net/packet/af_packet.c +2 -0
@@ -1545,6 +1545,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 :
net/rose/af_rose.c +3 -0
@@ -1272,6 +1272,9 @@ static int rose_ioctl(struct socket *soccase 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 :case SIOCGIFDSTADDR :
net/wanrouter/af_wanpipe.c +3 -0
@@ -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);
net/x25/af_x25.c +12 -0
@@ -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 :
Re: [PATCH] NET : Introduce SIOCGSTAMPNS ioctl to get timestamps with nanosec resolution
include/asm-mips/sockios.h #define SIOCATMARK _IOR('s', 7, int) · line 24
Quoted 9 lines · Eric Dumazet
include/asm-mips/sockios.h +2
-1@@ -20,6 +20,7 @@ #define SIOCATMARK _IOR('s', 7, int)#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) */
You might want to CC linux-arch or the architecture maintainers. Last time I changed something in this area I got complaints because it affected syscall emulation for non-Linux binaries or something like that.
Re: [PATCH] NET : Introduce SIOCGSTAMPNS ioctl to get timestamps with nanosec resolution
Quoted 7 lines · Patrick McHardy
Quoted 6 lines · Eric Dumazet
include/asm-mips/sockios.h +0
-0@@ -20,6 +20,7 @@ #define SIOCATMARK _IOR('s', 7, int)#define SIOCSPGRP _IOW('s', 8, pid_t)#define SIOCGPGRP _IOR('s', 9, pid_t)
Quoted 8 lines
include/asm-mips/sockios.h #define SIOCATMARK _IOR('s', 7, int) · line 24
Quoted 3 lines
include/asm-mips/sockios.h +2
-1-#define SIOCGSTAMP 0x8906/* Get stamp - linux-specific */ +#define SIOCGSTAMP 0x8906/* Get stamp (timeval) */ +#define SIOCGSTAMPNS 0x8907/* Get stamp (timespec) */ You might want to CC linux-arch or the architecture maintainers. Last time I changed something in this area I got complaints because it affected syscall emulation for non-Linux binaries or something like that.
I really dont see how this change could break syscall emulation for non-Linux binaries. SIOCGSTAMP{NS} is linux specific.
Could you please give the context of your past problems ?
Thank you
Re: [PATCH] NET : Introduce SIOCGSTAMPNS ioctl to get timestamps with nanosec resolution
Quoted 17 lines · Eric Dumazet
Quoted 6 lines · Patrick McHardy
Quoted 6 lines
include/asm-mips/sockios.h +0
-0@@ -20,6 +20,7 @@ #define SIOCATMARK _IOR('s', 7, int)#define SIOCSPGRP _IOW('s', 8, pid_t)#define SIOCGPGRP _IOR('s', 9, pid_t)Quoted 8 lines
include/asm-mips/sockios.h #define SIOCATMARK _IOR('s', 7, int) · line 24
Quoted 3 lines
include/asm-mips/sockios.h +2
-1-#define SIOCGSTAMP 0x8906/* Get stamp - linux-specific */ +#define SIOCGSTAMP 0x8906/* Get stamp (timeval) */ +#define SIOCGSTAMPNS 0x8907/* Get stamp (timespec) */ You might want to CC linux-arch or the architecture maintainers. Last time I changed something in this area I got complaints because it affected syscall emulation for non-Linux binaries or something like that.
Quoted 4 lines
I really dont see how this change could break syscall emulation for non-Linux binaries. SIOCGSTAMP{NS} is linux specific.
Could you please give the context of your past problems ?
It was when I added the SO_SNDBUFFORCE/SO_RCVBUFFORCE setsockopt options. IIRC the values I chose where already used differently for non-Linux MIPS binaries.
Re: [PATCH] NET : Introduce SIOCGSTAMPNS ioctl to get timestamps with nanosec resolution
In reply to Eric DumazetFrom: Eric Dumazet <[email protected]>
Date: Thu, 8 Mar 2007 15:17:57 +0100
Quoted 9 lines
[PATCH] NET : Introduce SIOCGSTAMPNS ioctl to get timestamps with nanosec resolution
Now network timestamps use
ktime_tinfrastructure, we can add a newioctl()SIOCGSTAMPNS command to get timestamps in 'struct timespec'. User programs can thus access to nanosecond resolution.Signed-off-by Eric Dumazet <[email protected]>CC Stephen Hemminger <[email protected]>
Applied, thanks Eric.
This patch points out a potential compat layer problem which sh64. It defines the SIOCGSTAMP (and not SIOCGSTAMPNS) ioctls as not constants, but rather constant values that depend upon the size of the structure passed in.
But the compat bridges for these timestamp ioctls simply match on the native ioctl value and then pass it in unchanged to the real handler. That won't work for sh64 compat layer for 32-bit sh applications.
That's what they get for being different :-)
PATCH 1/1 NET : Adding SO_TIMESTAMPNS / SCM_TIMESTAMPNS support
In reply to Eric DumazetHi David
This patch is against net-2.6.22 git tree.
Thank you
[PATCH] NET : Adding SO_TIMESTAMPNS / SCM_TIMESTAMPNS support
Now that network timestamps use ktime_t infrastructure, we can add a new SOL_SOCKET sockopt SO_TIMESTAMPNS.
This command is similar to SO_TIMESTAMP, but permits transmission of a 'timespec struct' instead of a 'timeval struct' control message. (nanosecond resolution instead of microsecond)
Control message is labelled SCM_TIMESTAMPNS instead of SCM_TIMESTAMP
A socket cannot mix SO_TIMESTAMP and SO_TIMESTAMPNS : the two modes are mutually exclusive.
sock_recv_timestamp() became too big to be fully inlined so I added a __sock_recv_timestamp() helper function.
include/net/sock.h +7 -10
@@ -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 */ };
@@ -1283,21 +1284,17 @@ static inline int sock_intr_errno(long treturn timeo ==MAX_SCHEDULE_TIMEOUT ? -ERESTARTSYS : -EINTR ; } +extern void __sock_recv_timestamp (struct msghdr *msg,struct sock *sk, +struct sk_buff *skb); +static __inline__void sock_recv_timestamp (struct msghdr *msg,struct sock *sk,struct sk_buff *skb) {ktime_t kt = skb->tstamp; -if (sock_flag (sk,SOCK_RCVTSTAMP )) { -struct timeval tv; -/* Race occurred between timestamp enabling and packet -receiving. Fill in the current time for now. */ -if (kt.tv64 ==0 ) - kt =ktime_get_real (); - skb->tstamp = kt; - tv =ktime_to_timeval (kt); -put_cmsg (msg,SOL_SOCKET ,SO_TIMESTAMP ,sizeof (tv), &tv); - }else +if (sock_flag (sk,SOCK_RCVTSTAMP )) +__sock_recv_timestamp (msg, sk, skb); +else sk->sk_stamp = kt; }
net/compat.c +9 -1
@@ -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;
@@ -229,7 +230,14 @@ int put_cmsg_compat(struct msghdr *kmsg, ctv.tv_sec = tv->tv_sec; ctv.tv_usec = tv->tv_usec; data = &ctv; - len =sizeof (struct compat_timeval ); + len =sizeof (ctv); + } +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 (cts); } cmlen =CMSG_COMPAT_LEN (len);
net/core/sock.c +14 -2
@@ -521,11 +521,18 @@ #endifbreak ;case SO_TIMESTAMP : +case SO_TIMESTAMPNS :if (valbool) { +if (optname ==SO_TIMESTAMP ) +sock_reset_flag (sk,SOCK_RCVTSTAMPNS ); +else +sock_set_flag (sk,SOCK_RCVTSTAMPNS );sock_set_flag (sk,SOCK_RCVTSTAMP );sock_enable_timestamp (sk); - }else + }else {sock_reset_flag (sk,SOCK_RCVTSTAMP ); +sock_reset_flag (sk,SOCK_RCVTSTAMPNS ); + }break ;case SO_RCVLOWAT :
@@ -715,7 +722,12 @@ int sock_getsockopt(struct socket *sock,break ;case SO_TIMESTAMP : - v.val =sock_flag (sk,SOCK_RCVTSTAMP ); + v.val =sock_flag (sk,SOCK_RCVTSTAMP ) && + !sock_flag (sk,SOCK_RCVTSTAMPNS ); +break ; + +case SO_TIMESTAMPNS : + v.val =sock_flag (sk,SOCK_RCVTSTAMPNS );break ;case SO_RCVTIMEO :
net/socket.c +29 -0
@@ -585,6 +585,35 @@ int kernel_sendmsg(struct socket *sock,return result; } +/* +* called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP) +*/ +void __sock_recv_timestamp (struct msghdr *msg,struct sock *sk, +struct sk_buff *skb) +{ +ktime_t kt = skb->tstamp; + +if (!sock_flag (sk,SOCK_RCVTSTAMPNS )) { +struct timeval tv; +/* Race occurred between timestamp enabling and packet +receiving. Fill in the current time for now. */ +if (kt.tv64 ==0 ) + kt =ktime_get_real (); + skb->tstamp = kt; + tv =ktime_to_timeval (kt); +put_cmsg (msg,SOL_SOCKET ,SCM_TIMESTAMP ,sizeof (tv), &tv); + }else { +struct timespec ts; +/* Race occurred between timestamp enabling and packet +receiving. Fill in the current time for now. */ +if (kt.tv64 ==0 ) + kt =ktime_get_real (); + skb->tstamp = kt; + ts =ktime_to_timespec (kt); +put_cmsg (msg,SOL_SOCKET ,SCM_TIMESTAMPNS ,sizeof (ts), &ts); + } +} +static inline int __sock_recvmsg (struct kiocb *iocb,struct socket *sock,struct msghdr *msg,size_t size,int flags) {
include/asm-alpha/socket.h +2 -0
@@ -52,6 +52,8 @@ #define SCM_TIMESTAMP SO_TIMESTAMP#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
include/asm-arm/socket.h +2 -0
@@ -49,5 +49,7 @@ #define SO_ACCEPTCONN 30#define SO_PEERSEC 31#define SO_PASSSEC 34 +#define SO_TIMESTAMPNS 35 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS#endif /* _ASM_SOCKET_H */
include/asm-arm26/socket.h +2 -0
@@ -49,5 +49,7 @@ #define SO_ACCEPTCONN 30#define SO_PEERSEC 31#define SO_PASSSEC 34 +#define SO_TIMESTAMPNS 35 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS#endif /* _ASM_SOCKET_H */
include/asm-avr32/socket.h +2 -0
@@ -49,5 +49,7 @@ #define SO_ACCEPTCONN 30#define SO_PEERSEC 31#define SO_PASSSEC 34 +#define SO_TIMESTAMPNS 35 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS#endif /* __ASM_AVR32_SOCKET_H */
include/asm-cris/socket.h +2 -0
@@ -51,6 +51,8 @@ #define SO_ACCEPTCONN 30#define SO_PEERSEC 31#define SO_PASSSEC 34 +#define SO_TIMESTAMPNS 35 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS#endif /* _ASM_SOCKET_H */
include/asm-frv/socket.h +2 -0
@@ -49,6 +49,8 @@ #define SO_ACCEPTCONN 30#define SO_PEERSEC 31#define SO_PASSSEC 34 +#define SO_TIMESTAMPNS 35 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS#endif /* _ASM_SOCKET_H */
include/asm-h8300/socket.h +2 -0
@@ -49,5 +49,7 @@ #define SO_ACCEPTCONN 30#define SO_PEERSEC 31#define SO_PASSSEC 34 +#define SO_TIMESTAMPNS 35 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS#endif /* _ASM_SOCKET_H */
include/asm-i386/socket.h +2 -0
@@ -49,5 +49,7 @@ #define SO_ACCEPTCONN 30#define SO_PEERSEC 31#define SO_PASSSEC 34 +#define SO_TIMESTAMPNS 35 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS#endif /* _ASM_SOCKET_H */
include/asm-ia64/socket.h +2 -0
@@ -58,5 +58,7 @@ #define SO_ACCEPTCONN 30#define SO_PEERSEC 31#define SO_PASSSEC 34 +#define SO_TIMESTAMPNS 35 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS#endif /* _ASM_IA64_SOCKET_H */
include/asm-m32r/socket.h +2 -0
@@ -49,5 +49,7 @@ #define SO_ACCEPTCONN 30#define SO_PEERSEC 31#define SO_PASSSEC 34 +#define SO_TIMESTAMPNS 35 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS#endif /* _ASM_M32R_SOCKET_H */
include/asm-m68k/socket.h +2 -0
@@ -49,5 +49,7 @@ #define SO_ACCEPTCONN 30#define SO_PEERSEC 31#define SO_PASSSEC 34 +#define SO_TIMESTAMPNS 35 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS#endif /* _ASM_SOCKET_H */
include/asm-mips/socket.h +2 -0
@@ -70,6 +70,8 @@ #define SO_PEERSEC 30#define SO_SNDBUFFORCE 31#define SO_RCVBUFFORCE 33#define SO_PASSSEC 34 +#define SO_TIMESTAMPNS 35 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS#ifdef __KERNEL__
include/asm-parisc/socket.h +2 -0
@@ -33,6 +33,8 @@ #define SO_PASSCRED 0x4010#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
include/asm-powerpc/socket.h +2 -0
@@ -56,5 +56,7 @@ #define SO_ACCEPTCONN 30#define SO_PEERSEC 31#define SO_PASSSEC 34 +#define SO_TIMESTAMPNS 35 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS#endif /* _ASM_POWERPC_SOCKET_H */
include/asm-s390/socket.h +2 -0
@@ -57,5 +57,7 @@ #define SO_ACCEPTCONN 30#define SO_PEERSEC 31#define SO_PASSSEC 34 +#define SO_TIMESTAMPNS 35 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS#endif /* _ASM_SOCKET_H */
include/asm-sh/socket.h +2 -0
@@ -49,5 +49,7 @@ #define SO_ACCEPTCONN 30#define SO_PEERSEC 31#define SO_PASSSEC 34 +#define SO_TIMESTAMPNS 35 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS#endif /* __ASM_SH_SOCKET_H */
include/asm-sparc/socket.h +2 -0
@@ -49,6 +49,8 @@ #define SCM_TIMESTAMP SO_TIMESTAMP#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
include/asm-sparc64/socket.h +2 -0
@@ -49,6 +49,8 @@ #define SCM_TIMESTAMP SO_TIMESTAMP#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
include/asm-v850/socket.h +2 -0
@@ -49,5 +49,7 @@ #define SO_ACCEPTCONN 30#define SO_PEERSEC 31#define SO_PASSSEC 34 +#define SO_TIMESTAMPNS 35 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS#endif /* __V850_SOCKET_H__ */
include/asm-x86_64/socket.h +2 -0
@@ -49,5 +49,7 @@ #define SO_ACCEPTCONN 30#define SO_PEERSEC 31#define SO_PASSSEC 34 +#define SO_TIMESTAMPNS 35 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS#endif /* _ASM_SOCKET_H */
include/asm-xtensa/socket.h +2 -0
@@ -60,5 +60,7 @@ #define SCM_TIMESTAMP SO_TIMESTAMP#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 */
Re: [PATCH] NET : Adding SO_TIMESTAMPNS / SCM_TIMESTAMPNS support
From: Eric Dumazet <[email protected]>
Date: Fri, 9 Mar 2007 19:39:42 +0100
Quoted 11 lines
[PATCH] NET : Adding
SO_TIMESTAMPNS/SCM_TIMESTAMPNSsupportNow that network timestamps use
ktime_tinfrastructure, we can add a newSOL_SOCKETsockoptSO_TIMESTAMPNS.This command is similar to
SO_TIMESTAMP, but permits transmission of a 'timespec struct' instead of a 'timeval struct' control message. (nanosecond resolution instead of microsecond)Control message is labelled
SCM_TIMESTAMPNSinstead ofSCM_TIMESTAMP
Quoted 9 lines
A socket cannot mix
SO_TIMESTAMPandSO_TIMESTAMPNS: the two modes are mutually exclusive.
sock_recv_timestamp()became too big to be fully inlined so I added a__sock_recv_timestamp()helper function.Signed-off-by Eric Dumazet <[email protected]>
Applied, thanks for following up on all of this nanosecond timestamp work.
Quoted 29 lines · On Thu, 1 Mar 2007 12:30:50 +0100 Eric Dumazet <[email protected]> wrote:
Quoted 7 lines · John
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.
Quoted 7 lines
This patch converts
sk_bufftimestamp 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 <[email protected]>
You probably want to add a SO_TIMESTAMPNS setsockopt() value like existing SO_TIMESTAMP
Also use NSEC_PER_USEC rather than hardcoded 1000.
Signature · 1 line
Stephen Hemminger <[email protected]>
Quoted 2 lines · Stephen Hemminger
You probably want to add a
SO_TIMESTAMPNSsetsockopt()value like existingSO_TIMESTAMP
You mean an alias like this ?
#define SO_TIMESTAMPNS SO_TIMESTAMP
Or should we really use another value ?
Quoted 4 lines
Also use
NSEC_PER_USECrather than hardcoded 1000.
Yes I will resubmit a patch including your suggestions (I discovered some missing bits after a make allyesconfig)
Thank you
Quoted 10 lines · On Fri, 02 Mar 2007 00:14:37 +0100 Eric Dumazet <[email protected]> wrote:
Quoted 2 lines · Stephen Hemminger
You probably want to add a
SO_TIMESTAMPNSsetsockopt()value like existingSO_TIMESTAMPYou mean an alias like this ?
#define
SO_TIMESTAMPNSSO_TIMESTAMPOr 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
Signature · 1 line
Stephen Hemminger <[email protected]>
Quoted 16 lines · Stephen Hemminger
Another value since if someone turns on
SO_TIMESTAMPthey want usec (timeval) andSO_TIMESTAMPNSwould be for nanosecond values. Trying to set both flags would be not allowed.- original -
If the
SO_TIMESTAMPoption is enabled on aSOCK_DGRAMsocket, the recvmsg(2) call will return a timestamp corresponding to when the data- gram was received. Themsg_controlfield 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
Quoted 6 lines
- add -
If theSO_TIMESTAMPNSoption is enabled on aSOCK_DGRAMsocket,
...
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 andSO_TIMESTAMPNS are mutually exclusive.
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(-)
include/linux/skbuff.h +28 -10
@@ -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);
include/net/sock.h +22 -9
@@ -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 tstatic __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 socextern 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
include/net/compat.h +1 -0
@@ -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 */
net/core/sock.c +33 -3
@@ -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 )) {
net/core/dev.c +4 -4
@@ -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 ; } }
net/ipv4/ip_fragment.c +3 -3
@@ -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 *qpif (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 ;
net/ipv4/af_inet.c +3 -0
@@ -755,6 +755,9 @@ int inet_ioctl(struct socket *sock, unsicase 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 :
net/ipv6/af_inet6.c +3 -0
@@ -437,6 +437,9 @@ int inet6_ioctl(struct socket *sock, unscase 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 :
net/packet/af_packet.c +3 -1
@@ -661,7 +661,7 @@ static int tpacket_rcv(struct sk_buff *ssock_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 :
net/sunrpc/svcsock.c +4 -5
@@ -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... */ /*
net/compat.c +31 -2
@@ -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 socstruct 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) {
fs/compat_ioctl.c +17 -0
@@ -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)
net/appletalk/ddp.c +3 -0
@@ -1768,6 +1768,9 @@ static int atalk_ioctl(struct socket *socase SIOCGSTAMP : rc =sock_get_timestamp (sk, argp);break ; +case SIOCGSTAMPNS : + rc =sock_get_timestampns (sk, argp); +break ;/* Routing */ case SIOCADDRT :case SIOCDELRT :
net/ax25/af_ax25.c +4 -0
@@ -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 : {
net/atm/ioctl.c +3 -0
@@ -82,6 +82,9 @@ int vcc_ioctl(struct socket *sock, unsigcase 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 ;
net/econet/af_econet.c +4 -1
@@ -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 *scase 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);
net/ipx/af_ipx.c +1 -1
@@ -1808,7 +1808,7 @@ static int ipx_recvmsg(struct kiocb *iocif (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);
net/netrom/af_netrom.c +5 -0
@@ -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 :
net/rose/af_rose.c +2 -0
@@ -1271,6 +1271,8 @@ static int rose_ioctl(struct socket *soccase 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 :
net/wanrouter/af_wanpipe.c +3 -0
@@ -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);
net/x25/af_x25.c +12 -0
@@ -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 :
net/bridge/netfilter/ebt_ulog.c +5 -2
@@ -130,6 +130,7 @@ static void ebt_ulog_packet(unsigned intunsigned 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;
net/ipv4/netfilter/ipt_ULOG.c +1 -1
@@ -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 )
net/ipv4/netfilter/ip_queue.c +1 -1
@@ -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;
net/ipv6/netfilter/ip6_queue.c +1 -1
@@ -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;
net/netfilter/nfnetlink_queue.c +1 -1
@@ -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); }
net/netfilter/nfnetlink_log.c +1 -1
@@ -514,7 +514,7 @@ __build_packet_message(struct nfulnl_insstruct 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); }
net/ipv6/netfilter/nf_conntrack_reasm.c +3 -3
@@ -82,7 +82,7 @@ struct nf_ct_frag6_queuestruct 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) */
net/ipv6/reassembly.c +3 -3
@@ -88,7 +88,7 @@ struct frag_queueint 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_qif (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;
include/asm-i386/socket.h +2 -0
@@ -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 */
include/asm-i386/sockios.h +2 -1
@@ -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
include/asm-x86_64/socket.h +2 -0
@@ -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 */
include/asm-x86_64/sockios.h +2 -1
@@ -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
include/asm-alpha/socket.h +2 -0
@@ -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
include/asm-alpha/sockios.h +1 -0
@@ -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 */
include/asm-arm/socket.h +2 -0
@@ -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 */
include/asm-arm26/socket.h +2 -0
@@ -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 */
include/asm-arm26/sockios.h +2 -1
@@ -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
include/asm-avr32/socket.h +2 -0
@@ -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 */
include/asm-avr32/sockios.h +2 -1
@@ -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 */
include/asm-cris/sockios.h +2 -1
@@ -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
include/asm-frv/socket.h +2 -0
@@ -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 */
include/asm-frv/sockios.h +2 -1
@@ -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__ */
include/asm-h8300/socket.h +2 -0
@@ -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 */
include/asm-h8300/sockios.h +2 -1
@@ -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__ */
include/asm-ia64/socket.h +2 -0
@@ -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 */
include/asm-ia64/sockios.h +2 -1
@@ -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 */
include/asm-m32r/socket.h +2 -0
@@ -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 */
include/asm-m32r/sockios.h +2 -1
@@ -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 */
include/asm-m68k/socket.h +2 -0
@@ -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 */
include/asm-m68k/sockios.h +2 -1
@@ -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__ */
include/asm-mips/socket.h +2 -0
@@ -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__
include/asm-mips/sockios.h +2 -1
@@ -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 */
include/asm-parisc/socket.h +2 -0
@@ -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
include/asm-parisc/sockios.h +2 -1
@@ -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
include/asm-powerpc/socket.h +2 -0
@@ -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 */
include/asm-powerpc/sockios.h +2 -1
@@ -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 */
include/asm-s390/socket.h +0 -2
@@ -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 */
include/asm-s390/sockios.h +2 -1
@@ -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
include/asm-sh/socket.h +0 -2
@@ -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 */
include/asm-sh/sockios.h +1 -0
@@ -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 */
include/asm-sh64/sockios.h +1 -0
@@ -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 */
include/asm-sparc/socket.h +2 -0
@@ -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
include/asm-sparc/sockios.h +2 -1
@@ -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) */
include/asm-sparc64/socket.h +2 -0
@@ -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
include/asm-sparc64/sockios.h +2 -1
@@ -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) */
include/asm-v850/socket.h +2 -0
@@ -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__ */
include/asm-v850/sockios.h +2 -1
@@ -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__ */
include/asm-xtensa/socket.h +2 -0
@@ -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 */
include/asm-xtensa/sockios.h +2 -1
@@ -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 */
Quoted 11 lines · Eric Dumazet
Quoted 6 lines · John
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.
Quoted 1 line
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 :-)
Quoted 2 lines
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?
Quoted 2 lines
This patch converts
sk_bufftimestamp 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.
Quoted 7 lines · John
Quoted 3 lines · Eric Dumazet
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.
Quoted 10 lines · On Wed, 28 Feb 2007 14:37:49 +0100 John <[email protected]> wrote:
Quoted 3 lines · John
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_timevalto 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.