From: Patrick Ohly <patrick.ohly@intel.com>
To: netdev@vger.kernel.org
Cc: Octavian Purdila <opurdila@ixiacom.com>,
Stephen Hemminger <shemminger@vyatta.com>,
Ingo Oeser <netdev@axxeo.de>, Andi Kleen <ak@linux.intel.com>,
John Ronciak <john.ronciak@intel.com>,
Eric Dumazet <dada1@cosmosbay.com>,
Oliver Hartkopp <oliver@hartkopp.net>
Subject: [RFC PATCH 02/13] extended semantic of sk_buff::tstamp: lowest bit marks hardware time stamps
Date: Wed, 22 Oct 2008 10:17:24 +0200 [thread overview]
Message-ID: <1226415407.31699.1.camel@ecld0pohly> (raw)
In-Reply-To: <1226414697.17450.852.camel@ecld0pohly>
If generated in hardware, then the driver must convert to system
time before storing the transformed value in sk_buff with skb_hwtstamp_set().
If conversion back to the original hardware time stamp is desired,
then the driver needs to implement the hwtstamp_raw() callback, which
is called by skb_hwtstamp_raw().
The purpose of the new skb_* methods is the hiding of how hardware
time stamps are really stored. Later they might be stored in an extra
field instead of mangling the existing tstamp.
Signed-off-by: Patrick Ohly <patrick.ohly@intel.com>
---
include/linux/netdevice.h | 12 +++++++
include/linux/skbuff.h | 76 +++++++++++++++++++++++++++++++++++++++++++-
net/core/skbuff.c | 32 +++++++++++++++++++
3 files changed, 118 insertions(+), 2 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 488c56e..4da51cb 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -749,6 +749,18 @@ struct net_device
/* for setting kernel sock attribute on TCP connection setup */
#define GSO_MAX_SIZE 65536
unsigned int gso_max_size;
+
+ /* hardware time stamping support */
+#define HAVE_HW_TIME_STAMP
+ /* Transforms skb->tstamp back to the original, raw hardware
+ * time stamp. The value must have been generated by the
+ * device. Implementing this is optional, but necessary for
+ * SO_TIMESTAMP_HARDWARE.
+ *
+ * Returns 1 if value could be retrieved, 0 otherwise.
+ */
+ int (*hwtstamp_raw)(const struct sk_buff *skb,
+ struct timespec *stamp);
};
#define to_net_dev(d) container_of(d, struct net_device, dev)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 9099237..0b3b36a 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -199,7 +199,10 @@ typedef unsigned char *sk_buff_data_t;
* @next: Next buffer in list
* @prev: Previous buffer in list
* @sk: Socket we are owned by
- * @tstamp: Time we arrived
+ * @tstamp: Time we arrived: usually generated by ktime_get_real() and
+ * thus is recorded in system time. If the lowest bit is set,
+ * then the value was originally generated by a different clock
+ * in the receiving hardware and then transformed to system time.
* @dev: Device we arrived on/are leaving by
* @transport_header: Transport layer header
* @network_header: Network layer header
@@ -1524,23 +1527,52 @@ static inline void skb_copy_to_linear_data_offset(struct sk_buff *skb,
extern void skb_init(void);
+/** returns skb->tstamp without the bit which marks hardware time stamps */
+static inline union ktime skb_get_ktime(const struct sk_buff *skb)
+{
+#if BITS_PER_LONG != 64 && !defined(CONFIG_KTIME_SCALAR)
+ return ktime_set(skb->tstamp.tv.sec,
+ skb->tstamp.tv.nsec & ~1);
+#else
+ return (ktime_t) { .tv64 = skb->tstamp.tv64 & ~1UL };
+#endif
+}
+
/**
* 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.
+ * The lowest bit is set if and only if the time stamp was originally
+ * created by hardware when processing the packet.
+ *
* 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 = ktime_to_timeval(skb->tstamp);
+ *stamp = ktime_to_timeval(skb_get_ktime(skb));
+}
+
+static inline void skb_get_timestampns(const struct sk_buff *skb, struct timespec *stamp)
+{
+ *stamp = ktime_to_timespec(skb_get_ktime(skb));
}
static inline void __net_timestamp(struct sk_buff *skb)
{
skb->tstamp = ktime_get_real();
+
+ /*
+ * make sure that lowest bit is never set: it marks hardware
+ * time stamps
+ */
+#if BITS_PER_LONG != 64 && !defined(CONFIG_KTIME_SCALAR)
+ skb->tstamp.tv.sec = skb->tstamp.tv.sec / 2 * 2;
+#else
+ skb->tstamp.tv64 = skb->tstamp.tv64 / 2 * 2;
+#endif
}
static inline ktime_t net_timedelta(ktime_t t)
@@ -1553,6 +1585,46 @@ static inline ktime_t net_invalid_timestamp(void)
return ktime_set(0, 0);
}
+/**
+ * checks whether the time stamp value has been set (= non-zero)
+ * and really came from hardware
+ */
+static inline int skb_hwtstamp_available(const struct sk_buff *skb)
+{
+ return skb->tstamp.tv64 & 1;
+}
+
+static inline void skb_hwtstamp_set(struct sk_buff *skb,
+ union ktime stamp)
+{
+#if BITS_PER_LONG != 64 && !defined(CONFIG_KTIME_SCALAR)
+ skb->tstamp.tv.sec = stamp.tv.sec;
+ skb->tstamp.tv.nsec = stamp.tv.nsec | 1;
+#else
+ skb->tstamp.tv64 = stamp.tv64 | 1;
+#endif
+}
+
+/**
+ * Fills the timespec with the original, "raw" time stamp as generated
+ * by the hardware when it processed the packet and returns 1 if such
+ * a hardware time stamp is unavailable or cannot be inferred. Otherwise
+ * it returns 0;
+ */
+int skb_hwtstamp_raw(const struct sk_buff *skb, struct timespec *stamp);
+
+/**
+ * Fills the timespec with the hardware time stamp generated when the
+ * hardware processed the packet, transformed to system time. Beware
+ * that this transformation is not perfect: packet A received on
+ * interface 1 before packet B on interface 2 might have a higher
+ * transformed time stamp.
+ *
+ * Returns 1 if a transformed hardware time stamp is available, 0
+ * otherwise.
+ */
+int skb_hwtstamp_transformed(const struct sk_buff *skb, struct timespec *stamp);
+
extern __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len);
extern __sum16 __skb_checksum_complete(struct sk_buff *skb);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index ca1ccdf..7a95062 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -44,6 +44,7 @@
#include <linux/in.h>
#include <linux/inet.h>
#include <linux/slab.h>
+#include <linux/inetdevice.h>
#include <linux/netdevice.h>
#ifdef CONFIG_NET_CLS_ACT
#include <net/pkt_sched.h>
@@ -2323,6 +2324,37 @@ err:
EXPORT_SYMBOL_GPL(skb_segment);
+int skb_hwtstamp_raw(const struct sk_buff *skb, struct timespec *stamp)
+{
+ struct rtable *rt;
+ struct in_device *idev;
+ struct net_device *netdev;
+
+ if (skb_hwtstamp_available(skb) &&
+ (rt = skb->rtable) != NULL &&
+ (idev = rt->idev) != NULL &&
+ (netdev = idev->dev) != NULL &&
+ netdev->hwtstamp_raw) {
+ return netdev->hwtstamp_raw(skb, stamp);
+ } else {
+ return 0;
+ }
+}
+
+EXPORT_SYMBOL_GPL(skb_hwtstamp_raw);
+
+int skb_hwtstamp_transformed(const struct sk_buff *skb, struct timespec *stamp)
+{
+ if (skb_hwtstamp_available(skb)) {
+ skb_get_timestampns(skb, stamp);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+EXPORT_SYMBOL_GPL(skb_hwtstamp_transformed);
+
void __init skb_init(void)
{
skbuff_head_cache = kmem_cache_create("skbuff_head_cache",
--
1.6.0.4
next prev parent reply other threads:[~2008-11-11 14:56 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-11-11 14:44 [RFC PATCH 00/13] hardware time stamping + igb example implementation Patrick Ohly
2008-10-22 8:17 ` Patrick Ohly [this message]
2008-11-12 7:41 ` [RFC PATCH 02/13] extended semantic of sk_buff::tstamp: lowest bit marks hardware time stamps Eric Dumazet
2008-11-12 8:09 ` Patrick Ohly
2008-11-12 10:09 ` David Miller
2008-11-12 9:58 ` David Miller
2008-11-19 12:50 ` Patrick Ohly
2008-10-22 12:46 ` [RFC PATCH 01/13] put_cmsg_compat + SO_TIMESTAMP[NS]: use same name for value as caller Patrick Ohly
2008-11-12 9:55 ` David Miller
2008-10-22 15:01 ` [RFC PATCH 03/13] user space API for time stamping of incoming and outgoing packets Patrick Ohly
2008-11-12 10:02 ` David Miller
2008-10-24 13:41 ` [RFC PATCH 04/13] net: implement generic SOF_TIMESTAMPING_TX_* support Patrick Ohly
2008-11-11 23:15 ` Octavian Purdila
2008-11-12 8:38 ` Patrick Ohly
2008-10-24 13:49 ` [RFC PATCH 05/13] ip: support for TX timestamps on UDP and RAW sockets Patrick Ohly
2008-11-12 9:59 ` David Miller
2008-10-29 14:48 ` [RFC PATCH 06/13] workaround: detect time stamp when command flags are expected Patrick Ohly
2008-11-12 10:00 ` David Miller
2008-10-31 11:43 ` [RFC PATCH 07/13] net: add SIOCSHWTSTAMP - hardware time stamping of packets Patrick Ohly
2008-10-31 12:21 ` [RFC PATCH 08/13] igb: stub support for SIOCSHWTSTAMP Patrick Ohly
2008-11-04 9:23 ` [RFC PATCH 09/13] clocksource: allow usage independent of timekeeping.c Patrick Ohly
2008-11-12 10:04 ` David Miller
2008-11-04 9:27 ` [RFC PATCH 10/13] igb: infrastructure for hardware time stamping Patrick Ohly
2008-11-05 9:58 ` [RFC PATCH 11/13] time sync: generic infrastructure to map between time stamps generated by a clock source and system time Patrick Ohly
2008-11-11 16:18 ` Andi Kleen
2008-11-12 8:01 ` Patrick Ohly
2008-11-12 10:08 ` David Miller
2008-11-12 16:14 ` Patrick Ohly
2008-11-12 16:28 ` Eric Dumazet
2008-11-12 10:05 ` David Miller
2008-11-06 11:13 ` [RFC PATCH 12/13] igb: use clocksync to implement hardware time stamping Patrick Ohly
2008-11-07 9:26 ` [RFC PATCH 13/13] skbuff: optionally store hardware time stamps in new field Patrick Ohly
2008-11-12 16:06 ` [RFC PATCH 00/13] hardware time stamping + igb example implementation Andi Kleen
2008-11-12 16:25 ` Patrick Ohly
2008-11-12 18:44 ` Oliver Hartkopp
2008-11-12 19:22 ` Eric Dumazet
2008-11-12 20:23 ` Andi Kleen
2008-11-12 20:23 ` Andi Kleen
2008-11-12 20:56 ` Eric Dumazet
2008-11-12 21:34 ` Andi Kleen
2008-11-12 22:26 ` Oliver Hartkopp
2008-11-13 15:53 ` Ohly, Patrick
2008-11-13 6:15 ` Oliver Hartkopp
2008-11-13 6:29 ` Eric Dumazet
2008-11-13 16:05 ` Ohly, Patrick
2008-11-16 8:15 ` Andrew Shewmaker
2008-11-12 22:17 ` David Miller
2008-11-19 12:39 ` Patrick Ohly
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1226415407.31699.1.camel@ecld0pohly \
--to=patrick.ohly@intel.com \
--cc=ak@linux.intel.com \
--cc=dada1@cosmosbay.com \
--cc=john.ronciak@intel.com \
--cc=netdev@axxeo.de \
--cc=netdev@vger.kernel.org \
--cc=oliver@hartkopp.net \
--cc=opurdila@ixiacom.com \
--cc=shemminger@vyatta.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox