All of lore.kernel.org
 help / color / mirror / Atom feed
* Possible bug: SO_TIMESTAMPING 2.6.30+
@ 2009-11-10  0:40 Marcus D. Leech
  2009-11-10  8:12 ` Christopher Zimmermann
  0 siblings, 1 reply; 5+ messages in thread
From: Marcus D. Leech @ 2009-11-10  0:40 UTC (permalink / raw)
  To: netdev

I've searched both the LKML archives, and the patchsets for kernels 
since 2.6.30 to see if
   this problem has been observed.

I have an Ethernet driver that supports hardware timestamping, and it 
has been working
   swimmingly well for several months using the SO_TIMESTAMPING 
infrastructure that
   Patrick Ohly put in the kernel starting around 2.6.30.

What I've discovered, that really causes me to pull my hair out, is that 
packets that are
   either AF_INET6 or AF_PACKET, *are not* getting Tx (transmit) 
timestamps.  Diving into
   the driver, I've discovered that the sk_buffs associated with these 
packets *dont* have
   the appropriate skb_tx state in the skb:

               shtx = skb_tx(skb);
               if (shtx->hardware)
               {
                        /* Do the timestamping thing */
                }

Now the puzzling thing is that the socket that originates these packets 
has SO_TIMESTAMPING
   turned on, and was created as an AF_INET6 socket, but carries both V4 
and V6 traffic.  The
   V4 traffic skbs  have  shtx->hardware  true appropriately,  but the 
V6 traffic doesn't.  Using
   Wireshark, I can clearly see the V6 packets leaving the interface, so 
it's not like they're
   getting routed somewhere else, and debugging in the driver *clearly* 
shows that V4 packets
   have shtx->hardware, while the V6 ones (from the SAME SOCKET) do not.

I know that Patrick Ohly has essentially moved on from doing the 
SO_TIMESTAMPING stuff, so
   who's maintaining it now?

When I look at the V6 udp code, it seems to call the same udp_sendmsg() 
function that V4
   uses, which appears to support Tx timestamping the way it should.

Any clues anyone?

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

* Re: Possible bug: SO_TIMESTAMPING 2.6.30+
  2009-11-10  0:40 Possible bug: SO_TIMESTAMPING 2.6.30+ Marcus D. Leech
@ 2009-11-10  8:12 ` Christopher Zimmermann
  2009-11-10  8:44   ` Eric Dumazet
  2009-11-10 22:03   ` Christopher Zimmermann
  0 siblings, 2 replies; 5+ messages in thread
From: Christopher Zimmermann @ 2009-11-10  8:12 UTC (permalink / raw)
  To: Marcus D. Leech; +Cc: netdev

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

On Mon, 09 Nov 2009 19:40:30 -0500
"Marcus D. Leech" <mleech@ripnet.com> wrote:


> I know that Patrick Ohly has essentially moved on from doing the 
> SO_TIMESTAMPING stuff, so
>    who's maintaining it now?

I worked on it a month ago or so and have a patchset from Patick Ohly
and some changes by me which fix software timestamping and make the
ioctl interface to the hardware more flexible (keeping backwards
compatibility). Patches are attached.
Still I never tried IPv6 and don't think the patches do anything about
it.
It would be nice to know weather software tx timestamps work
with/without the patches.


Christopher

[-- Attachment #2: 0001-timecompare-use-ARRAY_SIZE-macro.patch --]
[-- Type: text/x-patch, Size: 941 bytes --]

>From 5e408d962dbbafc581d4442d2e920dc667c0d078 Mon Sep 17 00:00:00 2001
From: Christopher Zimmermann <madroach@zakweb.de>
Date: Mon, 17 Aug 2009 21:26:17 +0200
Subject: [PATCH 1/3] timecompare: use ARRAY_SIZE() macro

---
 kernel/time/timecompare.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/kernel/time/timecompare.c b/kernel/time/timecompare.c
index 71e7f1a..fe24977 100644
--- a/kernel/time/timecompare.c
+++ b/kernel/time/timecompare.c
@@ -56,11 +56,11 @@ int timecompare_offset(struct timecompare *sync,
 	int index;
 	int num_samples = sync->num_samples;
 
-	if (num_samples > sizeof(buffer)/sizeof(buffer[0])) {
+	if (num_samples > ARRAY_SIZE(buffer)) {
 		samples = kmalloc(sizeof(*samples) * num_samples, GFP_ATOMIC);
 		if (!samples) {
 			samples = buffer;
-			num_samples = sizeof(buffer)/sizeof(buffer[0]);
+			num_samples = ARRAY_SIZE(buffer);
 		}
 	} else {
 		samples = buffer;
-- 
1.6.3.3


[-- Attachment #3: 0002-net-software-TX-time-stamping.patch --]
[-- Type: text/x-patch, Size: 6336 bytes --]

>From 50d8dfcf781fd3e9ad1d6123ff204b9f77a185ea Mon Sep 17 00:00:00 2001
From: Christopher Zimmermann <madroach@zakweb.de>
Date: Mon, 17 Aug 2009 21:27:50 +0200
Subject: [PATCH 2/3] net: software TX time stamping

This patch implements the software fallback to TX time stamping. The
necessary access to the buffer and socket are secured by taking
references before calling ndo_start_xmit().

That avoids race conditions (buffer remains available even if
transmission completes before ndo_start_xmit() returns) and works
even if the driver calls skb_orphan().

The caller of skb_tstamp_tx() is now responsible for providing the
socket, which requires minor changes in users of the previous call:
add skb->sk as parameter to get the old behavior.
---
 drivers/net/igb/igb_main.c |    2 +-
 include/linux/skbuff.h     |   11 +++++---
 net/core/dev.c             |   65 ++++++++++++++++++++++++++++++++++++++++++++
 net/core/skbuff.c          |    4 +-
 4 files changed, 75 insertions(+), 7 deletions(-)

diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index adb09d3..3ce4d78 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -4370,7 +4370,7 @@ static void igb_tx_hwtstamp(struct igb_adapter *adapter, struct sk_buff *skb)
 			shhwtstamps.hwtstamp = ns_to_ktime(ns);
 			shhwtstamps.syststamp =
 				timecompare_transform(&adapter->compare, ns);
-			skb_tstamp_tx(skb, &shhwtstamps);
+			skb_tstamp_tx(skb, skb->sk, &shhwtstamps);
 		}
 	}
 }
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index f2c69a2..e29e43d 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1873,17 +1873,20 @@ static inline ktime_t net_invalid_timestamp(void)
 
 /**
  * skb_tstamp_tx - queue clone of skb with send time stamps
- * @orig_skb:	the original outgoing packet
+ * @skb:	the original outgoing packet
+ * @sk:		sending socket (either from skb->sk or previous sock_get()),
+ *		may be NULL
  * @hwtstamps:	hardware time stamps, may be NULL if not available
  *
- * If the skb has a socket associated, then this function clones the
+ * If the socket is available, then this function clones the
  * skb (thus sharing the actual data and optional structures), stores
  * the optional hardware time stamping information (if non NULL) or
  * generates a software time stamp (otherwise), then queues the clone
  * to the error queue of the socket.  Errors are silently ignored.
  */
-extern void skb_tstamp_tx(struct sk_buff *orig_skb,
-			struct skb_shared_hwtstamps *hwtstamps);
+extern void skb_tstamp_tx(struct sk_buff *skb,
+			  struct sock *sk,
+			  struct skb_shared_hwtstamps *hwtstamps);
 
 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/dev.c b/net/core/dev.c
index 6a94475..e20e3ca 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1679,10 +1679,71 @@ static int dev_gso_segment(struct sk_buff *skb)
 	return 0;
 }
 
+/**
+ * struct tx_tstamp_context - context for software TX time stamping
+ * @sk: socket reference, NULL if nothing to do
+ * @skb: packet reference
+ */
+struct tx_tstamp_context {
+	struct sock *sk;
+	struct sk_buff *skb;
+};
+
+/**
+ * tx_tstamp_start - check for TX software time stamping and prepare for it
+ * @skb: buffer which is being sent
+ * @context: needs to be initialized for tx_tstamp_end()
+ */
+static void tx_tstamp_start(struct sk_buff *skb,
+			    struct tx_tstamp_context *context)
+{
+	union skb_shared_tx *shtx = skb_tx(skb);
+	/*
+	 * Prepare for TX time stamping in software if requested.
+	 * This could be optimized so that device drivers
+	 * do that themselves, which avoids the skb/sk ref/unref
+	 * overhead.
+	 */
+	if (unlikely(shtx->software &&
+		     skb->sk)) {
+		context->sk = skb->sk;
+		sock_hold(skb->sk);
+		context->skb = skb_get(skb);
+	} else {
+		/* TX software time stamping not requested/not possible. */
+		context->sk = NULL;
+	}
+}
+
+/**
+ * tx_tstamp_end - finish the work started by tx_tstamp_end()
+ * @context: may contain socket and buffer references
+ * @rc: result of ndo_start_xmit() - only do time stamping if packet was sent
+ */
+static void tx_tstamp_end(struct tx_tstamp_context *context, int rc)
+{
+	if (unlikely(context->sk)) {
+		union skb_shared_tx *shtx = skb_tx(context->skb);
+		/*
+		 * Checking shtx->software again is a bit redundant: it must
+		 * have been set in tx_tstamp_start(), but perhaps it
+		 * was cleared in the meantime to disable the TX software
+		 * fallback.
+		 */
+		if (likely(!rc) &&
+		    unlikely(shtx->software &&
+			     !shtx->in_progress))
+			skb_tstamp_tx(context->skb, context->sk, NULL);
+		sock_put(context->sk);
+		kfree_skb(context->skb);
+	}
+}
+
 int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
 			struct netdev_queue *txq)
 {
 	const struct net_device_ops *ops = dev->netdev_ops;
+	struct tx_tstamp_context context;
 	int rc;
 
 	if (likely(!skb->next)) {
@@ -1703,6 +1764,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
 		if (dev->priv_flags & IFF_XMIT_DST_RELEASE)
 			skb_dst_drop(skb);
 
+		tx_tstamp_start(skb, &context);
 		rc = ops->ndo_start_xmit(skb, dev);
 		if (rc == 0)
 			txq_trans_update(txq);
@@ -1720,6 +1782,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
 		 * the skb destructor before the call and restoring it
 		 * afterwards, then doing the skb_orphan() ourselves?
 		 */
+		tx_tstamp_end(&context, rc);
 		return rc;
 	}
 
@@ -1729,7 +1792,9 @@ gso:
 
 		skb->next = nskb->next;
 		nskb->next = NULL;
+		tx_tstamp_start(skb, &context);
 		rc = ops->ndo_start_xmit(nskb, dev);
+		tx_tstamp_end(&context, rc);
 		if (unlikely(rc)) {
 			nskb->next = skb->next;
 			skb->next = nskb;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 9e0597d..78ae3e9 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2971,9 +2971,9 @@ int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer)
 EXPORT_SYMBOL_GPL(skb_cow_data);
 
 void skb_tstamp_tx(struct sk_buff *orig_skb,
-		struct skb_shared_hwtstamps *hwtstamps)
+		   struct sock *sk,
+		   struct skb_shared_hwtstamps *hwtstamps)
 {
-	struct sock *sk = orig_skb->sk;
 	struct sock_exterr_skb *serr;
 	struct sk_buff *skb;
 	int err;
-- 
1.6.3.3


[-- Attachment #4: 0003-Change-kernel-timestamping-interface.patch --]
[-- Type: text/x-patch, Size: 11963 bytes --]

>From fc396501b8d0906253b1f85945b86da4130ee665 Mon Sep 17 00:00:00 2001
From: Christopher Zimmermann <madroach@sancho.(none)>
Date: Wed, 7 Oct 2009 17:28:26 +0200
Subject: [PATCH 3/3] Change kernel timestamping interface

Allow userspace to fine-tune hardware registers.
Stay backwards compatible to old userspace?
---
 .gitignore                   |    1 +
 drivers/net/igb/e1000_regs.h |   41 ++++++++++--------
 drivers/net/igb/igb_main.c   |   95 +++++++++++++++++++++++++----------------
 include/linux/net_tstamp.h   |   35 +++++++++++----
 4 files changed, 107 insertions(+), 65 deletions(-)

diff --git a/.gitignore b/.gitignore
index b93fb7e..6fac88c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,6 +32,7 @@
 #
 # Top-level generic files
 #
+debian
 tags
 TAGS
 vmlinux
diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h
index 6e59245..1785b30 100644
--- a/drivers/net/igb/e1000_regs.h
+++ b/drivers/net/igb/e1000_regs.h
@@ -83,30 +83,33 @@
 #define E1000_TSYNCRXCTL_VALID (1<<0)
 #define E1000_TSYNCRXCTL_ENABLED (1<<4)
 enum {
+	/* bits 1 to 3 need leftshift <<1 for direct register access. */
 	E1000_TSYNCRXCTL_TYPE_L2_V2 = 0,
-	E1000_TSYNCRXCTL_TYPE_L4_V1 = (1<<1),
-	E1000_TSYNCRXCTL_TYPE_L2_L4_V2 = (1<<2),
-	E1000_TSYNCRXCTL_TYPE_ALL = (1<<3),
-	E1000_TSYNCRXCTL_TYPE_EVENT_V2 = (1<<3) | (1<<1),
+	E1000_TSYNCRXCTL_TYPE_L4_V1 = (1<<0),
+	E1000_TSYNCRXCTL_TYPE_L2_L4_V2 = (1<<1),
+	E1000_TSYNCRXCTL_TYPE_ALL = (1<<2),
+	E1000_TSYNCRXCTL_TYPE_EVENT_V2 = (1<<2) | (1<<0),
 };
 #define E1000_TSYNCRXCFG 0x05F50
 enum {
-	E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE = 0<<0,
-	E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE = 1<<0,
-	E1000_TSYNCRXCFG_PTP_V1_FOLLOWUP_MESSAGE = 2<<0,
-	E1000_TSYNCRXCFG_PTP_V1_DELAY_RESP_MESSAGE = 3<<0,
-	E1000_TSYNCRXCFG_PTP_V1_MANAGEMENT_MESSAGE = 4<<0,
+	/* bits 0 to 7 */
+	E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE = 0,
+	E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE = 1,
+	E1000_TSYNCRXCFG_PTP_V1_FOLLOWUP_MESSAGE = 2,
+	E1000_TSYNCRXCFG_PTP_V1_DELAY_RESP_MESSAGE = 3,
+	E1000_TSYNCRXCFG_PTP_V1_MANAGEMENT_MESSAGE = 4,
 
-	E1000_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE = 0<<8,
-	E1000_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE = 1<<8,
-	E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_REQ_MESSAGE = 2<<8,
-	E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_RESP_MESSAGE = 3<<8,
-	E1000_TSYNCRXCFG_PTP_V2_FOLLOWUP_MESSAGE = 8<<8,
-	E1000_TSYNCRXCFG_PTP_V2_DELAY_RESP_MESSAGE = 9<<8,
-	E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_FOLLOWUP_MESSAGE = 0xA<<8,
-	E1000_TSYNCRXCFG_PTP_V2_ANNOUNCE_MESSAGE = 0xB<<8,
-	E1000_TSYNCRXCFG_PTP_V2_SIGNALLING_MESSAGE = 0xC<<8,
-	E1000_TSYNCRXCFG_PTP_V2_MANAGEMENT_MESSAGE = 0xD<<8,
+	/* bits 8 to 11 need leftshift <<8 for direct register access */
+	E1000_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE = 0,
+	E1000_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE = 1,
+	E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_REQ_MESSAGE = 2,
+	E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_RESP_MESSAGE = 3,
+	E1000_TSYNCRXCFG_PTP_V2_FOLLOWUP_MESSAGE = 8,
+	E1000_TSYNCRXCFG_PTP_V2_DELAY_RESP_MESSAGE = 9,
+	E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_FOLLOWUP_MESSAGE = 0xA,
+	E1000_TSYNCRXCFG_PTP_V2_ANNOUNCE_MESSAGE = 0xB,
+	E1000_TSYNCRXCFG_PTP_V2_SIGNALLING_MESSAGE = 0xC,
+	E1000_TSYNCRXCFG_PTP_V2_MANAGEMENT_MESSAGE = 0xD,
 };
 #define E1000_SYSTIML 0x0B600
 #define E1000_SYSTIMH 0x0B604
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index adb09d3..17bfd5b 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -1512,7 +1512,7 @@ static int __devinit igb_probe(struct pci_dev *pdev,
 	wr32(E1000_TIMINCA,
 	     (1<<24) |
 	     IGB_TSYNC_CYCLE_TIME_IN_NANOSECONDS * IGB_TSYNC_SCALE);
-#if 0
+#if 1
 	/*
 	 * Avoid rollover while we initialize by resetting the time counter.
 	 */
@@ -4881,28 +4881,33 @@ static int igb_hwtstamp_ioctl(struct net_device *netdev,
 	struct igb_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
 	struct hwtstamp_config config;
+#if 0
 	u32 tsync_tx_ctl_bit = E1000_TSYNCTXCTL_ENABLED;
 	u32 tsync_rx_ctl_bit = E1000_TSYNCRXCTL_ENABLED;
 	u32 tsync_rx_ctl_type = 0;
 	u32 tsync_rx_cfg = 0;
 	int is_l4 = 0;
 	int is_l2 = 0;
-	short port = 319; /* PTP */
+#endif
 	u32 regval;
 
+	memset(&config, 0, sizeof(config));
+        /* TODO: first check, weather old or new interface is passed. */
 	if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
 		return -EFAULT;
 
 	/* reserved for future extensions */
 	if (config.flags)
-		return -EINVAL;
+		goto manual;
 
 	switch (config.tx_type) {
 	case HWTSTAMP_TX_OFF:
-		tsync_tx_ctl_bit = 0;
+		//tsync_tx_ctl_bit = 0;
+		config.flags &= ~HWTSTAMP_TX;
 		break;
 	case HWTSTAMP_TX_ON:
-		tsync_tx_ctl_bit = E1000_TSYNCTXCTL_ENABLED;
+		//tsync_tx_ctl_bit = E1000_TSYNCTXCTL_ENABLED;
+		config.flags |= HWTSTAMP_TX;
 		break;
 	default:
 		return -ERANGE;
@@ -4910,7 +4915,7 @@ static int igb_hwtstamp_ioctl(struct net_device *netdev,
 
 	switch (config.rx_filter) {
 	case HWTSTAMP_FILTER_NONE:
-		tsync_rx_ctl_bit = 0;
+		config.flags &= ~HWTSTAMP_RX;
 		break;
 	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
 	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
@@ -4921,57 +4926,68 @@ static int igb_hwtstamp_ioctl(struct net_device *netdev,
 		 * possible to time stamp both Sync and Delay_Req messages
 		 * => fall back to time stamping all packets
 		 */
-		tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_ALL;
+		//tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_ALL;
+		config.igb.ptp_type = E1000_TSYNCRXCTL_TYPE_ALL;
 		config.rx_filter = HWTSTAMP_FILTER_ALL;
 		break;
 	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
-		tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_L4_V1;
-		tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE;
-		is_l4 = 1;
+		config.igb.ptp_type = E1000_TSYNCRXCTL_TYPE_L4_V1;
+		config.igb.ptp1_control = E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE;
+		config.igb.port = htons(319); /* PTP */
 		break;
 	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
-		tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_L4_V1;
-		tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE;
-		is_l4 = 1;
+		config.igb.ptp_type = E1000_TSYNCRXCTL_TYPE_L4_V1;
+		config.igb.ptp1_control = E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE;
+		config.igb.port = htons(319); /* PTP */
 		break;
 	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
 	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
-		tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_L2_L4_V2;
-		tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE;
-		is_l2 = 1;
-		is_l4 = 1;
+		config.igb.ptp_type = E1000_TSYNCRXCTL_TYPE_L2_L4_V2;
+		config.igb.ptp2_id = E1000_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE;
+		config.igb.etype = 0x88F7;
+		config.igb.port = htons(319); /* PTP */
 		config.rx_filter = HWTSTAMP_FILTER_SOME;
 		break;
 	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
 	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
-		tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_L2_L4_V2;
-		tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE;
-		is_l2 = 1;
-		is_l4 = 1;
+		config.igb.ptp_type = E1000_TSYNCRXCTL_TYPE_L2_L4_V2;
+		config.igb.ptp2_id = E1000_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE;
+		config.igb.etype = 0x88F7;
+		config.igb.port = htons(319); /* PTP */
 		config.rx_filter = HWTSTAMP_FILTER_SOME;
 		break;
 	case HWTSTAMP_FILTER_PTP_V2_EVENT:
 	case HWTSTAMP_FILTER_PTP_V2_SYNC:
 	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
-		tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_EVENT_V2;
+		config.igb.ptp_type = E1000_TSYNCRXCTL_TYPE_EVENT_V2;
 		config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
-		is_l2 = 1;
+		config.igb.etype = 0x88F7;
 		break;
 	default:
 		return -ERANGE;
 	}
 
+manual:
 	/* enable/disable TX */
 	regval = rd32(E1000_TSYNCTXCTL);
-	regval = (regval & ~E1000_TSYNCTXCTL_ENABLED) | tsync_tx_ctl_bit;
+	if(config.flags & HWTSTAMP_TX)
+		regval = (regval | E1000_TSYNCTXCTL_ENABLED);
+	else	regval = (regval & ~E1000_TSYNCTXCTL_ENABLED);
 	wr32(E1000_TSYNCTXCTL, regval);
 
 	/* enable/disable RX, define which PTP packets are time stamped */
 	regval = rd32(E1000_TSYNCRXCTL);
-	regval = (regval & ~E1000_TSYNCRXCTL_ENABLED) | tsync_rx_ctl_bit;
-	regval = (regval & ~0xE) | tsync_rx_ctl_type;
+	if(config.flags & HWTSTAMP_RX)
+		regval = (regval | E1000_TSYNCRXCTL_ENABLED);
+	else	regval = (regval & ~E1000_TSYNCRXCTL_ENABLED);
+	regval = (regval & ~0xE) | config.igb.ptp_type << 1;
 	wr32(E1000_TSYNCRXCTL, regval);
-	wr32(E1000_TSYNCRXCFG, tsync_rx_cfg);
+
+	/* we don't need to read since we can reset the whole register. */
+	regval =  config.igb.ptp1_control
+		| config.igb.ptp2_id << 8
+		| config.igb.ptp2_val << 12;
+	wr32(E1000_TSYNCRXCFG, regval);
 
 	/*
 	 * Ethertype Filter Queue Filter[0][15:0] = 0x88F7
@@ -4979,27 +4995,32 @@ static int igb_hwtstamp_ioctl(struct net_device *netdev,
 	 * Ethertype Filter Queue Filter[0][26] = 0x1 (Enable filter)
 	 * Ethertype Filter Queue Filter[0][30] = 0x1 (Enable Timestamping)
 	 */
-	wr32(E1000_ETQF0, is_l2 ? 0x440088f7 : 0);
+	wr32(E1000_ETQF0, config.igb.etype ? 0x4400 << 16 | config.igb.etype : 0);
 
 	/* L4 Queue Filter[0]: only filter by source and destination port */
-	wr32(E1000_SPQF0, htons(port));
-	wr32(E1000_IMIREXT(0), is_l4 ?
+	/* wr32(E1000_SPQF0, port); XXX why source port? */
+	wr32(E1000_IMIREXT(0), config.igb.port ?
 	     ((1<<12) | (1<<19) /* bypass size and control flags */) : 0);
-	wr32(E1000_IMIR(0), is_l4 ?
-	     (htons(port)
+	wr32(E1000_IMIR(0), config.igb.port ?
+	     (config.igb.port
 	      | (0<<16) /* immediate interrupt disabled */
-	      | 0 /* (1<<17) bit cleared: do not bypass
+	      | (0<<17) /* (1<<17) bit cleared: do not bypass
 		     destination port check */)
 		: 0);
-	wr32(E1000_FTQF0, is_l4 ?
+	wr32(E1000_FTQF0, config.igb.port ?
 	     (0x11 /* UDP */
 	      | (1<<15) /* VF not compared */
 	      | (1<<27) /* Enable Timestamping */
+#if 0
 	      | (7<<28) /* only source port filter enabled,
 			   source/target address and protocol
-			   masked */)
-	     : ((1<<15) | (15<<28) /* all mask bits set = filter not
-				      enabled */));
+			   masked */
+#endif
+	      | (0xe<<28) /* only protocol filter enabled
+			   * everything else is masked. */
+	     )
+	     : (1<<15) | (15<<28) /* all mask bits set = filter not
+				      enabled */);
 
 	wrfl();
 
diff --git a/include/linux/net_tstamp.h b/include/linux/net_tstamp.h
index a3b8546..7b069dd 100644
--- a/include/linux/net_tstamp.h
+++ b/include/linux/net_tstamp.h
@@ -40,26 +40,43 @@ enum {
  */
 struct hwtstamp_config {
 	int flags;
-	int tx_type;
-	int rx_filter;
+	/* deprecated, only used for backwards compatibility when flags == 0 */
+	int tx_type;            /* put this into flags ? */
+	int rx_filter;          /* deprecated */
+	/* hardware dependend part starts here */
+	union {
+		struct {
+			unsigned short port;  /* for dst port filter, zero to disable */
+			unsigned short etype; /* for ethertype filter, zero to disable */
+			unsigned ptp1_control	:8; /* TSYNCRXCFG.CTRLT */
+			/* Careful! According to reference manual message ids
+			 * 2 and 3 always get timestamped. */
+			unsigned ptp2_id	:4; /* TSYNCRXCFG.MSGT */
+			unsigned ptp2_val	:4; /* TSYNCRXCFG.TRNSSPC */
+			unsigned ptp_type	:3; /* TSYNCRXCTL.Type */
+		} igb;
+	};
 };
 
-/* possible values for hwtstamp_config->tx_type */
+/* flags for hwtstamp_config */
 enum {
 	/*
-	 * No outgoing packet will need hardware time stamping;
-	 * should a packet arrive which asks for it, no hardware
-	 * time stamping will be done.
+	 * these first two values are the only allowed values in
+	 * deprecated hwtstamp_config->tx_type
 	 */
-	HWTSTAMP_TX_OFF,
-
 	/*
 	 * Enables hardware time stamping for outgoing packets;
 	 * the sender of the packet decides which are to be
 	 * time stamped by setting %SOF_TIMESTAMPING_TX_SOFTWARE
 	 * before sending the packet.
+	 * If disabled no packet will be timestamped; even if it
+	 * asks for it.
 	 */
-	HWTSTAMP_TX_ON,
+	HWTSTAMP_TX_OFF = 0, /* only used in hwtstamp_config->tx_type */
+	HWTSTAMP_TX_ON = 1,
+	HWTSTAMP_TX = 1,
+
+	HWTSTAMP_RX = 2
 };
 
 /* possible values for hwtstamp_config->rx_filter */
-- 
1.6.3.3


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

* Re: Possible bug: SO_TIMESTAMPING 2.6.30+
  2009-11-10  8:12 ` Christopher Zimmermann
@ 2009-11-10  8:44   ` Eric Dumazet
  2009-11-10 22:03   ` Christopher Zimmermann
  1 sibling, 0 replies; 5+ messages in thread
From: Eric Dumazet @ 2009-11-10  8:44 UTC (permalink / raw)
  To: Christopher Zimmermann; +Cc: Marcus D. Leech, netdev

Christopher Zimmermann a écrit :
> On Mon, 09 Nov 2009 19:40:30 -0500
> "Marcus D. Leech" <mleech@ripnet.com> wrote:
> 
> 
>> I know that Patrick Ohly has essentially moved on from doing the 
>> SO_TIMESTAMPING stuff, so
>>    who's maintaining it now?
> 
> I worked on it a month ago or so and have a patchset from Patick Ohly
> and some changes by me which fix software timestamping and make the
> ioctl interface to the hardware more flexible (keeping backwards
> compatibility). Patches are attached.
> Still I never tried IPv6 and don't think the patches do anything about
> it.
> It would be nice to know weather software tx timestamps work
> with/without the patches.
> 
> 
> Christopher
> 

I see some sock_put()/sock_hold() stuff in your second patch.

We removed these things on transmit path, please dont add them back...

If skb->sk is set, it probably also has a destructor and a reference already taken.

(This reference being on sk_wmem_alloc by the way, not on sk_refcnt)

You probably can try to change skb destructor ?



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

* Re: Possible bug: SO_TIMESTAMPING 2.6.30+
  2009-11-10  8:12 ` Christopher Zimmermann
  2009-11-10  8:44   ` Eric Dumazet
@ 2009-11-10 22:03   ` Christopher Zimmermann
  2009-11-11  0:13     ` Marcus D. Leech
  1 sibling, 1 reply; 5+ messages in thread
From: Christopher Zimmermann @ 2009-11-10 22:03 UTC (permalink / raw)
  Cc: Marcus D. Leech, netdev

On Tue, 10 Nov 2009 09:12:52 +0100
Christopher Zimmermann <madroach@zakweb.de> wrote:

> On Mon, 09 Nov 2009 19:40:30 -0500
> "Marcus D. Leech" <mleech@ripnet.com> wrote:
> 
> 
> > I know that Patrick Ohly has essentially moved on from doing the 
> > SO_TIMESTAMPING stuff, so
> >    who's maintaining it now?
> 
> I worked on it a month ago or so and have a patchset from Patick Ohly
> and some changes by me which fix software timestamping and make the
> ioctl interface to the hardware more flexible (keeping backwards
> compatibility). Patches are attached.
> Still I never tried IPv6 and don't think the patches do anything about
> it.
> It would be nice to know weather software tx timestamps work
> with/without the patches.
> 
> 
> Christopher

Have a look at commit 51f31cabe3ce5345b51e4a4f82138b38c4d5dc91.
It adds support for SO_TIMESTAMPING in the transport layer, but only
for the ipv4 variants.
Good news is, it does look like it was simple to do the same to
ipv6/udp.c. Have fun.


    ip: support for TX timestamps on UDP and RAW sockets
    
    Instructions for time stamping outgoing packets are take from the
    socket layer and later copied into the new skb.
    
    Signed-off-by: Patrick Ohly <patrick.ohly@intel.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>


But only in ipv4/udp.c:

-------------------------------- net/ipv4/udp.c
-------------------------------- index c47c989..4bd178a 100644
@@ -596,6 +596,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock
*sk, struct msghdr *msg, return -EOPNOTSUPP;
 
 	ipc.opt = NULL;
+	ipc.shtx.flags = 0;
 
 	if (up->pending) {
 		/*
@@ -643,6 +644,9 @@ int udp_sendmsg(struct kiocb *iocb, struct sock
*sk, struct msghdr *msg, ipc.addr = inet->saddr;
 
 	ipc.oif = sk->sk_bound_dev_if;
+	err = sock_tx_timestamp(msg, sk, &ipc.shtx);
+	if (err)
+		return err;
 	if (msg->msg_controllen) {
 		err = ip_cmsg_send(sock_net(sk), msg, &ipc);
 		if (err)

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

* Re: Possible bug: SO_TIMESTAMPING 2.6.30+
  2009-11-10 22:03   ` Christopher Zimmermann
@ 2009-11-11  0:13     ` Marcus D. Leech
  0 siblings, 0 replies; 5+ messages in thread
From: Marcus D. Leech @ 2009-11-11  0:13 UTC (permalink / raw)
  To: Christopher Zimmermann; +Cc: netdev

Christopher Zimmermann wrote:
>
>
> -------------------------------- net/ipv4/udp.c
> -------------------------------- index c47c989..4bd178a 100644
> @@ -596,6 +596,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock
> *sk, struct msghdr *msg, return -EOPNOTSUPP;
>  
>  	ipc.opt = NULL;
> +	ipc.shtx.flags = 0;
>  
>  	if (up->pending) {
>  		/*
> @@ -643,6 +644,9 @@ int udp_sendmsg(struct kiocb *iocb, struct sock
> *sk, struct msghdr *msg, ipc.addr = inet->saddr;
>  
>  	ipc.oif = sk->sk_bound_dev_if;
> +	err = sock_tx_timestamp(msg, sk, &ipc.shtx);
> +	if (err)
> +		return err;
>  	if (msg->msg_controllen) {
>  		err = ip_cmsg_send(sock_net(sk), msg, &ipc);
>  		if (err)
>
>   
That is already in 2.6.30

I took a look this afternoon at ipv6/udp.c and ipv6/ip6_output.c   and
was able to glue-in a small (a few lines) piece of code
  that apparently makes TX timestamping work for V6 DATAGRAM sockets--I
had to do it in ipv6/ip6_output.c, otherwise,
  I'd have to modify calls to the v6 _append function to pass in an
extra parameter to indicate hardware Tx timestamping.
  It was easier to simply pick up shtx->hardware in the _append
function, and then check to see if sk->sk_type == SOCK_DGRAM,
  and then set the appropriate fields in the skb.  In ipv4/udp.c, this
is done in udp_sendmsg(), before calling the _append function.

Doing this in AF_PACKET looked like it was going to be *very* easy, but
in my tests so far, it doesn't do anything useful.  More
  investigation in the lab this evening, and then I'll put together some
cdiffs against 2.6.32-rc5.  Once that's done, perhaps I can get
  some guidance about how to post those patches?

The same kind of stuff doesn't appear to work for AF_PACKET, so once I
have AF_PACKET working, I'll perhaps post a
  patch set.  I'm very new to this community, so I don't know how to go
about posting patches "officially" etc.  But it seems that
  getting this working for at least:

     V4  SOCK_DGRAM
     V6  SOCK_DGRAM
     AF_PACKET SOCK_DGRAM/SOCK_RAW

Should be quite straightforward--using the existing code in ipv4/udp.c 
as a guide.   Hopefully, if I can get this going for all 3, I'll get
  to keep my job :-)   [just kidding!].


Cheers
Marcus
currently a IEEE 1588-2008 code monkey at a semiconductor company

-- 
Marcus Leech
Principal Investigator, Shirleys Bay Radio Astronomy Consortium
http://www.sbrac.org


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

end of thread, other threads:[~2009-11-11  0:13 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-10  0:40 Possible bug: SO_TIMESTAMPING 2.6.30+ Marcus D. Leech
2009-11-10  8:12 ` Christopher Zimmermann
2009-11-10  8:44   ` Eric Dumazet
2009-11-10 22:03   ` Christopher Zimmermann
2009-11-11  0:13     ` Marcus D. Leech

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