Skip to contentSkip to conversation

packet: clarify timestamp overflow

PATCH In review Arnd Bergmann 5 participants 25 messages Nov 27, 2017 – Nov 30, 2017

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

PATCH 1/2 packet: clarify timestamp overflow

The memory mapped packet socket data structure in version 1 through 3 all contain 32-bit second values for the packet time stamps, which makes them suffer from the overflow of time_t in y2038 or y2106 (depending on whether user space interprets the value as signed or unsigned).

The implementation uses the deprecated getnstimeofday() function.

In order to get rid of that, this changes the code to use ktime_get_real_ts64() as a replacement, documenting the nature of the overflow. As long as the user applications treat the timestamps as unsigned, or only use the difference between timestamps, they are fine, and changing the timestamps to 64-bit wouldn't require a more invasive user space API change.

Note: a lot of other APIs suffer from incompatible structures when time_t gets redefined to 64-bit in 32-bit user space, but this one does not.

---
 net/packet/af_packet.c | 27 +++++++++++++++++----------
 1 file changed, 17 insertions(+), 10 deletions(-)
net/packet/af_packet.c +17 -10
index 737092ca9b4e..7432c6699818 100644
@@ -439,17 +439,17 @@ static int __packet_get_status(struct packet_sock *po, void *frame)
 	}
 }
 
-static __u32 tpacket_get_timestamp(struct sk_buff *skb, struct timespec *ts,
+static __u32 tpacket_get_timestamp(struct sk_buff *skb, struct timespec64 *ts,
 				   unsigned int flags)
 {
 	struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
 
 	if (shhwtstamps &&
 	    (flags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
-	    ktime_to_timespec_cond(shhwtstamps->hwtstamp, ts))
+	    ktime_to_timespec64_cond(shhwtstamps->hwtstamp, ts))
 		return TP_STATUS_TS_RAW_HARDWARE;
 
-	if (ktime_to_timespec_cond(skb->tstamp, ts))
+	if (ktime_to_timespec64_cond(skb->tstamp, ts))
 		return TP_STATUS_TS_SOFTWARE;
 
 	return 0;
@@ -459,13 +459,20 @@ static __u32 __packet_set_timestamp(struct packet_sock *po, void *frame,
 				    struct sk_buff *skb)
 {
 	union tpacket_uhdr h;
-	struct timespec ts;
+	struct timespec64 ts;
 	__u32 ts_status;
 
 	if (!(ts_status = tpacket_get_timestamp(skb, &ts, po->tp_tstamp)))
 		return 0;
 
 	h.raw = frame;
+	/*
+	 * versions 1 through 3 overflow the timestamps in y2106, since they
+	 * all store the seconds in a 32-bit unsigned integer.
+	 * If we create a version 4, that should have a 64-bit timestamp,
+	 * either 64-bit seconds + 32-bit nanoseconds, or just 64-bit
+	 * nanoseconds.
+	 */
 	switch (po->tp_version) {
 	case TPACKET_V1:
 		h.h1->tp_sec = ts.tv_sec;
@@ -805,8 +812,8 @@ static void prb_close_block(struct tpacket_kbdq_core *pkc1,
 		 * It shouldn't really happen as we don't close empty
 		 * blocks. See prb_retire_rx_blk_timer_expired().
 		 */
-		struct timespec ts;
-		getnstimeofday(&ts);
+		struct timespec64 ts;
+		ktime_get_real_ts64(&ts);
 		h1->ts_last_pkt.ts_sec = ts.tv_sec;
 		h1->ts_last_pkt.ts_nsec	= ts.tv_nsec;
 	}
@@ -836,7 +843,7 @@ static void prb_thaw_queue(struct tpacket_kbdq_core *pkc)
 static void prb_open_block(struct tpacket_kbdq_core *pkc1,
 	struct tpacket_block_desc *pbd1)
 {
-	struct timespec ts;
+	struct timespec64 ts;
 	struct tpacket_hdr_v1 *h1 = &pbd1->hdr.bh1;
 
 	smp_rmb();
@@ -849,7 +856,7 @@ static void prb_open_block(struct tpacket_kbdq_core *pkc1,
 	BLOCK_NUM_PKTS(pbd1) = 0;
 	BLOCK_LEN(pbd1) = BLK_PLUS_PRIV(pkc1->blk_sizeof_priv);
 
-	getnstimeofday(&ts);
+	ktime_get_real_ts64(&ts);
 
 	h1->ts_first_pkt.ts_sec = ts.tv_sec;
 	h1->ts_first_pkt.ts_nsec = ts.tv_nsec;
@@ -2184,7 +2191,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
 	unsigned long status = TP_STATUS_USER;
 	unsigned short macoff, netoff, hdrlen;
 	struct sk_buff *copy_skb = NULL;
-	struct timespec ts;
+	struct timespec64 ts;
 	__u32 ts_status;
 	bool is_drop_n_account = false;
 	bool do_vnet = false;
@@ -2312,7 +2319,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
 	skb_copy_bits(skb, 0, h.raw + macoff, snaplen);
 
 	if (!(ts_status = tpacket_get_timestamp(skb, &ts, po->tp_tstamp)))
-		getnstimeofday(&ts);
+		ktime_get_real_ts64(&ts);
 
 	status |= ts_status;
 
Signature · 1 line
2.9.0
#1 lore raw

RFC PATCH 2/2 packet: experimental support for 64-bit timestamps

I tried to figure out what it would take to do a version 4 mmap packet socket interface to completely avoid the y2106 overflow problem. This is what I came up with, reusing most of the v3 code, except for the parts where we access the timestamps.

For kselftest, I'm adding support for testing v4 in addition to v1-v3, but the test currently does not look at the timestamps, so it won't check that the timestamp format actually works as intended, only that I didn't break the parts that worked in the v3 selftest.

Overall, this is more of a mess than I expected, so it's probably not worth doing a v4 format just for the timestamp, but the patch can serve as a reference for anyone that needs a new format for other reasons and fixes this along with the other changes.

Signed-off-by Arnd Bergmann <arnd at arndb.de>

---
Untested and rather invasive, so don't apply this part without discussion and testing

---
 include/uapi/linux/if_packet.h              |  24 +++++-
 net/packet/af_packet.c                      | 115 ++++++++++++++++++++--------
 tools/testing/selftests/net/psock_tpacket.c |  65 +++++++++-------
 3 files changed, 142 insertions(+), 62 deletions(-)
include/uapi/linux/if_packet.h +22 -2
index 67b61d91d89b..c2cf29acdd40 100644
@@ -177,8 +177,27 @@ struct tpacket3_hdr {
 	__u8		tp_padding[8];
 };
 
+struct tpacket4_hdr {
+	__u32		tp_next_offset;
+	__u32		tp_nsec_hi;
+	__u32		tp_nsec_lo;
+	__u32		tp_snaplen;
+	__u32		tp_len;
+	__u32		tp_status;
+	__u16		tp_mac;
+	__u16		tp_net;
+	/* pkt_hdr variants */
+	union {
+		struct tpacket_hdr_variant1 hv1;
+	};
+	__u8		tp_padding[8];
+};
+
 struct tpacket_bd_ts {
-	unsigned int ts_sec;
+	union {
+		unsigned int ts_nsec_hi;
+		unsigned int ts_sec;
+	};
 	union {
 		unsigned int ts_usec;
 		unsigned int ts_nsec;
@@ -250,7 +269,8 @@ struct tpacket_block_desc {
 enum tpacket_versions {
 	TPACKET_V1,
 	TPACKET_V2,
-	TPACKET_V3
+	TPACKET_V3,
+	TPACKET_V4,
 };
 
 /*
net/packet/af_packet.c +82 -33

319 lines not on this page · raw message

tools/testing/selftests/net/psock_tpacket.c +38 -27

210 lines not on this page · raw message

Signature · 6 lines
2.9.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#2 lore raw

Re: [PATCH 2/2] [RFC] packet: experimental support for 64-bit timestamps

Quoted 17 lines · Mon, Nov 27, 2017@05:19:25PM CET, [email protected] wrote:

I tried to figure out what it would take to do a version 4 mmap packet socket interface to completely avoid the y2106 overflow problem. This is what I came up with, reusing most of the v3 code, except for the parts where we access the timestamps.

For kselftest, I'm adding support for testing v4 in addition to v1-v3, but the test currently does not look at the timestamps, so it won't check that the timestamp format actually works as intended, only that I didn't break the parts that worked in the v3 selftest.

Overall, this is more of a mess than I expected, so it's probably not worth doing a v4 format just for the timestamp, but the patch can serve as a reference for anyone that needs a new format for other reasons and fixes this along with the other changes.

Signed-off-by Arnd Bergmann <arnd at arndb.de>

---

[...]

include/uapi/linux/if_packet.h struct tpacket_block_desc { · line 273

Quoted 7 lines
include/uapi/linux/if_packet.h +2 -1
@@ -250,7 +269,8 @@ struct tpacket_block_desc {
 enum tpacket_versions {
 	TPACKET_V1,
 	TPACKET_V2,
-	TPACKET_V3
+	TPACKET_V3,
+	TPACKET_V4,

I wonder with how many versions are we going to eventually end up with :O --
To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

maintainer
#3 lore raw

Re: [PATCH 2/2] [RFC] packet: experimental support for 64-bit timestamps

Quoted 22 lines · Jiri Pirko
Quoted 17 lines · Mon, Nov 27, 2017@05:19:25PM CET, [email protected] wrote:

I tried to figure out what it would take to do a version 4 mmap packet socket interface to completely avoid the y2106 overflow problem. This is what I came up with, reusing most of the v3 code, except for the parts where we access the timestamps.

For kselftest, I'm adding support for testing v4 in addition to v1-v3, but the test currently does not look at the timestamps, so it won't check that the timestamp format actually works as intended, only that I didn't break the parts that worked in the v3 selftest.

Overall, this is more of a mess than I expected, so it's probably not worth doing a v4 format just for the timestamp, but the patch can serve as a reference for anyone that needs a new format for other reasons and fixes this along with the other changes.

Signed-off-by Arnd Bergmann <arnd at arndb.de>

---

[...]

Quoted 9 lines

include/uapi/linux/if_packet.h struct tpacket_block_desc { · line 273

Quoted 7 lines
include/uapi/linux/if_packet.h +2 -1
@@ -250,7 +269,8 @@ struct tpacket_block_desc {
 enum tpacket_versions {
      TPACKET_V1,
      TPACKET_V2,
-      TPACKET_V3
+      TPACKET_V3,
+      TPACKET_V4,

I wonder with how many versions are we going to eventually end up with :O

There already is an effort to come up with a new AF_PACKET V4 [1]. We should make sure that any new interface does not have the Y2038/Y2106 issue. But, if a new version is being developed and that subsumes all existing use cases, then there probably is no need for another version that is a very small diff to V3.

If adding support for existing applications is useful, another approach would be to add a new socket option that changes the semantics for the two u32 fields in each of V1, V2 and V3 to hold nsec. Add a single check after filling in those structs whether the option is set and, if so, overwrite the two fields.

[1] https://lwn.net/Articles/737947/
--
To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

#4 lore raw

Re: [PATCH 2/2] [RFC] packet: experimental support for 64-bit timestamps

Quoted 33 lines · Willem de Bruijn
Quoted 22 lines · Jiri Pirko
Quoted 17 lines · Mon, Nov 27, 2017@05:19:25PM CET, [email protected] wrote:

I tried to figure out what it would take to do a version 4 mmap packet socket interface to completely avoid the y2106 overflow problem. This is what I came up with, reusing most of the v3 code, except for the parts where we access the timestamps.

For kselftest, I'm adding support for testing v4 in addition to v1-v3, but the test currently does not look at the timestamps, so it won't check that the timestamp format actually works as intended, only that I didn't break the parts that worked in the v3 selftest.

Overall, this is more of a mess than I expected, so it's probably not worth doing a v4 format just for the timestamp, but the patch can serve as a reference for anyone that needs a new format for other reasons and fixes this along with the other changes.

Signed-off-by Arnd Bergmann <arnd at arndb.de>

---

[...]

Quoted 9 lines

include/uapi/linux/if_packet.h struct tpacket_block_desc { · line 273

Quoted 7 lines
include/uapi/linux/if_packet.h +2 -1
@@ -250,7 +269,8 @@ struct tpacket_block_desc {
 enum tpacket_versions {
      TPACKET_V1,
      TPACKET_V2,
-      TPACKET_V3
+      TPACKET_V3,
+      TPACKET_V4,

I wonder with how many versions are we going to eventually end up with :O

Quoted 5 lines

There already is an effort to come up with a new AF_PACKET V4 [1]. We should make sure that any new interface does not have the Y2038/Y2106 issue. But, if a new version is being developed and that subsumes all existing use cases, then there probably is no need for another version that is a very small diff to V3.

Ah, perfect, that's good timing. Adding Björn to Cc here.

Quoted 7 lines

If adding support for existing applications is useful, another approach would be to add a new socket option that changes the semantics for the two u32 fields in each of V1, V2 and V3 to hold nsec. Add a single check after filling in those structs whether the option is set and, if so, overwrite the two fields.

[1] https://lwn.net/Articles/737947/

I don't think that's necessary. As long as the V4 capabilities are a superset of V1-V3, we should be able to just require all users to move to V4 (or later) in the next 89 years, and make sure that they use unsigned seconds if they care about 2038.

Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

#5 lore raw

Re: [PATCH 2/2] [RFC] packet: experimental support for 64-bit timestamps

2017-11-27 21:51 GMT+01:00 Arnd Bergmann <arnd at arndb.de>:
[...]

Quoted 8 lines
Quoted 5 lines

There already is an effort to come up with a new AF_PACKET V4 [1]. We should make sure that any new interface does not have the Y2038/Y2106 issue. But, if a new version is being developed and that subsumes all existing use cases, then there probably is no need for another version that is a very small diff to V3.

Ah, perfect, that's good timing. Adding Björn to Cc here.

Unfortunately, for the Y2038/Y2106 cases, we'll be (as a result of netdevconf discussions) moving the AF_PACKET V4 implementation to a separate, new, address/packet family.

Quoted 6 lines
Quoted 6 lines

If adding support for existing applications is useful, another approach would be to add a new socket option that changes the semantics for the two u32 fields in each of V1, V2 and V3 to hold nsec. Add a single check after filling in those structs whether the option is set and, if so, overwrite the two fields.

Quoted 7 lines
Quoted 1 line

[1] https://lwn.net/Articles/737947/

I don't think that's necessary. As long as the V4 capabilities are a superset of V1-V3, we should be able to just require all users to move to V4 (or later) in the next 89 years, and make sure that they use unsigned seconds if they care about 2038.

Given that V4 wont be around for AF_PACKET -- at least not in the shape of our patches -- Willem's suggestion is probably a good way forward.

Quoted 1 line

Arnd

--
To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

#6 lore raw

Re: [PATCH 2/2] [RFC] packet: experimental support for 64-bit timestamps

Quoted 8 lines · Björn Töpel

2017-11-27 21:51 GMT+01:00 Arnd Bergmann <arnd at arndb.de>:
[...]

Quoted 6 lines
Quoted 5 lines

There already is an effort to come up with a new AF_PACKET V4 [1]. We should make sure that any new interface does not have the Y2038/Y2106 issue. But, if a new version is being developed and that subsumes all existing use cases, then there probably is no need for another version that is a very small diff to V3.

Quoted 6 lines
Quoted 2 lines

Ah, perfect, that's good timing. Adding Björn to Cc here.

Unfortunately, for the Y2038/Y2106 cases, we'll be (as a result of netdevconf discussions) moving the AF_PACKET V4 implementation to a separate, new, address/packet family.

Ok, I see.

Quoted 14 lines
Quoted 6 lines
Quoted 6 lines

If adding support for existing applications is useful, another approach would be to add a new socket option that changes the semantics for the two u32 fields in each of V1, V2 and V3 to hold nsec. Add a single check after filling in those structs whether the option is set and, if so, overwrite the two fields.

Quoted 7 lines
Quoted 1 line

[1] https://lwn.net/Articles/737947/

I don't think that's necessary. As long as the V4 capabilities are a superset of V1-V3, we should be able to just require all users to move to V4 (or later) in the next 89 years, and make sure that they use unsigned seconds if they care about 2038.

Quoted 3 lines

Given that V4 wont be around for AF_PACKET -- at least not in the shape of our patches -- Willem's suggestion is probably a good way forward.

That leaves one question: should we do that now, or wait until some other reason for a V4 comes up? I don't mind creating another patch for this, just want to get a feeling of whether the API clutter is worth it when we have a way out that works until y2106 (at which point we run into other problems as well).

Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

#7 lore raw

RFC PATCH v2 1/1 packet: experimental support for 64-bit timestamps

This is a second attempt to allow 64-bit timestamps in packet sockets, this time retaining the existing three API versions, and instead using flags for the timestamping interface that let us reinterpret the existing fields.

We already have an interface to select the timestamp source to be either software or hardware timestamps, using the SOF_TIMESTAMPING_RAW_HARDWARE flag in the PACKET_TIMESTAMP option that gets passed to setsockopt().

This patch adds another two flags for the same interface:
SOF_TIMESTAMPING_SKIP makes all timestamps zero, which can save a few cycles per packet when we don't have to touch an expensive clocksource hardware. When SOF_TIMESTAMPING_OPT_NS64 gets added to the flag, we reinterpret the tp_sec/tp_nsec fields to be the upper and lower half of the 64-bit nanosecond value. This lets us use the interface until year 2554, when 64-bit unsigned nanoseconds overflow.

The implementation is fairly straightforward, but I'm less sure about the interface. Using SOF_TIMESTAMPING_* flags in PACKET_TIMESTAMP is a bit odd already since most of the other flags make no sense here. Adding two more flags that only make sense for packet sockets but not the normal SO_TIMESTAMPING option on other sockets makes this even more confusing.

---
This is only a proof-of-concept patch, only compile-tested and put here for discussion about whether we want it in principle.

---
 include/uapi/linux/net_tstamp.h |   4 +-
 net/packet/af_packet.c          | 129 +++++++++++++++++++++++++---------------
 2 files changed, 85 insertions(+), 48 deletions(-)
include/uapi/linux/net_tstamp.h +3 -1
index 4fe104b2411f..1b312d35fa41 100644
@@ -30,8 +30,10 @@ enum {
 	SOF_TIMESTAMPING_OPT_STATS = (1<<12),
 	SOF_TIMESTAMPING_OPT_PKTINFO = (1<<13),
 	SOF_TIMESTAMPING_OPT_TX_SWHW = (1<<14),
+	SOF_TIMESTAMPING_SKIP = (1<<15),
+	SOF_TIMESTAMPING_OPT_NS64 = (1<<16),
 
-	SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_OPT_TX_SWHW,
+	SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_OPT_NS64,
 	SOF_TIMESTAMPING_MASK = (SOF_TIMESTAMPING_LAST - 1) |
 				 SOF_TIMESTAMPING_LAST
 };
net/packet/af_packet.c +82 -47

238 lines not on this page · raw message

Signature · 1 line
2.9.0
maintainer
#8 lore raw

Re: [PATCH] [RFC v2] packet: experimental support for 64-bit timestamps

Quoted 1 line · Arnd Bergmann

This is a second attempt to allow 64-bit timestamps in packet sockets,

Thanks for coding up this variant.

Quoted 5 lines

The implementation is fairly straightforward, but I'm less sure about the interface. Using SOF_TIMESTAMPING_* flags in PACKET_TIMESTAMP is a bit odd already since most of the other flags make no sense here. Adding two more flags that only make sense for packet sockets but not the normal SO_TIMESTAMPING option on other sockets makes this even more confusing.

Agreed.

Unfortunately, we're already stuck with SOL_PACKET/PACKET_TIMESTAMP accepting SOF_TIMESTAMPING_RAW_HARDWARE.

Perhaps we can define a new PF_PACKET specific enum where the equivalent option has the same value, so is backwards compatible:

enum {
PACKET_TIMESTAMP_ORIG = 0,
PACKET_TIMESTAMP_ZERO = 1 << 0,
PACKET_TIMESTAMP_NS64 = 1 << 1,
PACKET_TIMESTAMP_HW = 1 << 6
};

and BUILD_BUG_ON(PACKET_TIMESTAMP_RAW != SOF_TIMESTAMPING_RAW_HARDWARE) to document the dependency.

At high level, the code looks great to me, itself.

#9 lore raw

Re: [PATCH] [RFC v2] packet: experimental support for 64-bit timestamps

Quoted 15 lines · Willem de Bruijn

On Tue, Nov 28, 2017 at 8:14 AM, Arnd Bergmann <[email protected]> wrote:

Unfortunately, we're already stuck with SOL_PACKET/PACKET_TIMESTAMP accepting SOF_TIMESTAMPING_RAW_HARDWARE.

Perhaps we can define a new PF_PACKET specific enum where the equivalent option has the same value, so is backwards compatible:

enum {
PACKET_TIMESTAMP_ORIG = 0,
PACKET_TIMESTAMP_ZERO = 1 << 0,
PACKET_TIMESTAMP_NS64 = 1 << 1,
PACKET_TIMESTAMP_HW = 1 << 6
};

Quoted 2 lines

and BUILD_BUG_ON(PACKET_TIMESTAMP_RAW != SOF_TIMESTAMPING_RAW_HARDWARE) to document the dependency.

Yes, that would be much cleaner, but in order to do this, we have to be relatively
confident that existing users don't pass any flags other than SOF_TIMESTAMPING_RAW_HARDWARE. It might be safer to start at bit 31 for the new flags to minimize that risk:

/*
* we used to pass SOF_TIMESTAMPING_RAW_HARDWARE from user space,
* but really want our own flags here, so define PACKET_TIMESTAMP_HW to the
* existing value and use the high bits for new non-overlapping flags. */

enum {
       PACKET_TIMESTAMP_ORIG = 0,
       PACKET_TIMESTAMP_HW = 1 << 6,
       PACKET_TIMESTAMP_ZERO = 1 << 30,
       PACKET_TIMESTAMP_NS64 = 1 << 31,
};
Quoted 1 line

At high level, the code looks great to me, itself.

Thanks,

Arnd

maintainer
#10 lore raw

Re: [PATCH] [RFC v2] packet: experimental support for 64-bit timestamps

In reply to Arnd Bergmann

From: Arnd Bergmann <[email protected]>
Date: Tue, 28 Nov 2017 14:14:05 +0100

Quoted 5 lines

The implementation is fairly straightforward, but I'm less sure about the interface. Using SOF_TIMESTAMPING_* flags in PACKET_TIMESTAMP is a bit odd already since most of the other flags make no sense here. Adding two more flags that only make sense for packet sockets but not the normal SO_TIMESTAMPING option on other sockets makes this even more confusing.

We unfortunately never enforced any checking whatsoever of the PACKET_TIMESTAMP mask the user gives us, we accept anything.

That makes any changes in this area effectively a grenade ready to go off potentially at any moment.

We can't add new checks without potentially making existing apps stop working. And at least theoretically if we add new bits it is possible for an existing app passing those bits in by accident to start behaving improperly.

I know it sounds like overkill for this, but maybe we can add a new socket option for the SKIP and 64-bit stuff. That would be %100 safe.

#11 lore raw

Re: [PATCH] [RFC v2] packet: experimental support for 64-bit timestamps

Quoted 15 lines · David Miller

From: Arnd Bergmann <[email protected]>
Date: Tue, 28 Nov 2017 14:14:05 +0100

Quoted 5 lines

The implementation is fairly straightforward, but I'm less sure about the interface. Using SOF_TIMESTAMPING_* flags in PACKET_TIMESTAMP is a bit odd already since most of the other flags make no sense here. Adding two more flags that only make sense for packet sockets but not the normal SO_TIMESTAMPING option on other sockets makes this even more confusing.

We unfortunately never enforced any checking whatsoever of the PACKET_TIMESTAMP mask the user gives us, we accept anything.

That makes any changes in this area effectively a grenade ready to go off potentially at any moment.

Quoted 7 lines

We can't add new checks without potentially making existing apps stop working. And at least theoretically if we add new bits it is possible for an existing app passing those bits in by accident to start behaving improperly.

I know it sounds like overkill for this, but maybe we can add a new socket option for the SKIP and 64-bit stuff. That would be %100 safe.

Sure, it's easy enough to do, I'll cook something up.

Does this mean you think the general idea of an extended interface for 64-bit timestamps is useful for traditional packet sockets? I think that was still an open question, though we seem to be getting closer to consensus on the implementation and the interface that it should use if we want it.

Arnd

maintainer
#12 lore raw

Re: [PATCH] [RFC v2] packet: experimental support for 64-bit timestamps

From: Arnd Bergmann <[email protected]>
Date: Tue, 28 Nov 2017 21:02:05 +0100

Quoted 5 lines

Does this mean you think the general idea of an extended interface for 64-bit timestamps is useful for traditional packet sockets? I think that was still an open question, though we seem to be getting closer to consensus on the implementation and the interface that it should use if we want it.

If it can be done reasonably easy, which you patches seem to indicate is the case, I have no objections to extending packet socket for 64-bit timestamps.

I hope that AF_CAPTURE will be designed in such a way that all apps can migrate to it, and I will be making sure it is implemented appropriately with that in mind.

But I don't think AF_CAPTURE should block your work here.

#13 lore raw

Re: [PATCH] [RFC v2] packet: experimental support for 64-bit timestamps

Quoted 13 lines · David Miller

From: Arnd Bergmann <[email protected]>
Date: Tue, 28 Nov 2017 21:02:05 +0100

Quoted 5 lines

Does this mean you think the general idea of an extended interface for 64-bit timestamps is useful for traditional packet sockets? I think that was still an open question, though we seem to be getting closer to consensus on the implementation and the interface that it should use if we want it.

If it can be done reasonably easy, which you patches seem to indicate is the case, I have no objections to extending packet socket for 64-bit timestamps.

Quoted 5 lines

I hope that AF_CAPTURE will be designed in such a way that all apps can migrate to it, and I will be making sure it is implemented appropriately with that in mind.

But I don't think AF_CAPTURE should block your work here.

To clarify where I'm coming from, my interest is mainly in the first patch to remove all users of 'struct timespec' in order to weed out the users that are actually broken in 2038. I added the comment about it breaking in 2106 and how it could be fixed, and then decided to try out how ugly that fix would get.

I'll follow up with v3 that should address the comments I got so far, but a conclusion of 'nobody is asking for it' would be fine too, and then the patch could get dropped.

I'll also look at the AF_CAPTURE patches to make sure that the timestamping aspect is handled in a safe way there.

Arnd

#14 lore raw

RFC PATCH v3 1/1 packet: experimental support for 64-bit timestamps

As I noticed in my previous patch to remove the 'timespec' usage in the packet socket, the timestamps in the packet socket are slightly inefficient as they convert a nanosecond value into seconds/nanoseconds or seconds/microseconds.

This adds two new socket options for the timestamp to resolve that:

PACKET_SKIPTIMESTAMP sets a flag to indicate whether to generate timestamps at all. When this is set, all timestamps are hardcoded to zero, which saves a few cycles for the conversion and the access of the hardware clocksource. The idea was taken from pktgen, which has an F_NO_TIMESTAMP option for the same purpose.

PACKET_TIMESTAMP_NS64 changes the interpretation of the time stamp fields:
instead of having 32 bits for seconds plus 32 bits for nanoseconds or microseconds, we now always send down 64 bits worth of nanoseconds when this flag is set.

---
I still have not done any runtime testing on this patch, only implemented the suggestions from the previous versions.

While I don't think anyone is actively looking for this feature, I don't think there are any reasons left against merging it either, and it might come in handy for someone.

---
 include/uapi/linux/if_packet.h |   2 +
 net/packet/af_packet.c         | 159 +++++++++++++++++++++++++++++------------
 net/packet/internal.h          |   2 +
 3 files changed, 116 insertions(+), 47 deletions(-)
include/uapi/linux/if_packet.h +2 -0
index 67b61d91d89b..2eba54770e6b 100644
@@ -57,6 +57,8 @@ struct sockaddr_ll {
 #define PACKET_QDISC_BYPASS		20
 #define PACKET_ROLLOVER_STATS		21
 #define PACKET_FANOUT_DATA		22
+#define PACKET_SKIPTIMESTAMP		23
+#define PACKET_TIMESTAMP_NS64		24
 
 #define PACKET_FANOUT_HASH		0
 #define PACKET_FANOUT_LB		1
net/packet/af_packet.c +112 -47

280 lines not on this page · raw message

net/packet/internal.h +2 -0
index 562fbc155006..20b69512210f 100644
@@ -128,6 +128,8 @@ struct packet_sock {
 	unsigned int		tp_reserve;
 	unsigned int		tp_loss:1;
 	unsigned int		tp_tx_has_off:1;
+	unsigned int		tp_skiptstamp:1;
+	unsigned int		tp_tstamp_ns64:1;
 	unsigned int		tp_tstamp;
 	struct net_device __rcu	*cached_dev;
 	int			(*xmit)(struct sk_buff *skb);
Signature · 1 line
2.9.0
maintainer
#15 lore raw

Re: [PATCH] [RFC v3] packet: experimental support for 64-bit timestamps

Quoted 13 lines · Arnd Bergmann

As I noticed in my previous patch to remove the 'timespec' usage in the packet socket, the timestamps in the packet socket are slightly inefficient as they convert a nanosecond value into seconds/nanoseconds or seconds/microseconds.

This adds two new socket options for the timestamp to resolve that:

PACKET_SKIPTIMESTAMP sets a flag to indicate whether to generate timestamps at all. When this is set, all timestamps are hardcoded to zero, which saves a few cycles for the conversion and the access of the hardware clocksource. The idea was taken from pktgen, which has an F_NO_TIMESTAMP option for the same purpose.

Quoted 8 lines

PACKET_TIMESTAMP_NS64 changes the interpretation of the time stamp fields:
instead of having 32 bits for seconds plus 32 bits for nanoseconds or microseconds, we now always send down 64 bits worth of nanoseconds when this flag is set.

This works. Another option would be to add a PACKET_TIMESTAMP_EX with the semantics we discussed previously + fail hard when any undefined bits are set. I don't feel strong either way, we don't intend to extend further.

If taking this approach, it might be good to split into separate patches, one for each flag?

net/packet/af_packet.c static int __packet_get_status(struct packet_sock *po, void *frame) · line 443

Quoted 3 lines
net/packet/af_packet.c +1 -1
-static __u32 tpacket_get_timestamp(struct sk_buff *skb, struct timespec64 *ts,
+static __u32 tpacket_get_timestamp(struct sk_buff *skb, __u32 *hi, __u32 *lo,
                                   unsigned int flags)

Argument flags is no longer used.

Quoted 27 lines

{

net/packet/af_packet.c +17 -5
+       struct packet_sock *po = pkt_sk(skb->sk);
        struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
+       ktime_t stamp;
+       u32 type;
+
+       if (po->tp_skiptstamp)
+               return 0;
 
        if (shhwtstamps &&
-           (flags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
-           ktime_to_timespec64_cond(shhwtstamps->hwtstamp, ts))
-               return TP_STATUS_TS_RAW_HARDWARE;
+           (po->tp_tstamp & SOF_TIMESTAMPING_RAW_HARDWARE) &&
+           shhwtstamps->hwtstamp) {
+               stamp = shhwtstamps->hwtstamp;
+               type = TP_STATUS_TS_RAW_HARDWARE;
+       } else if (skb->tstamp) {
+               stamp = skb->tstamp;
+               type = TP_STATUS_TS_SOFTWARE;
+       } else {
+               return 0;
+       }
 
-       if (ktime_to_timespec64_cond(skb->tstamp, ts))
-               return TP_STATUS_TS_SOFTWARE;
+       if (po->tp_tstamp_ns64) {

net/packet/af_packet.c static int __packet_get_status(struct packet_sock *po, void *frame) · line 474

Quoted 10 lines
net/packet/af_packet.c +8 -1
+               __u64 ns = ktime_to_ns(stamp);
 
-       return 0;
+               *hi = upper_32_bits(ns);
+               *lo = lower_32_bits(ns);
+       } else {
+               struct timespec64 ts = ktime_to_timespec64(stamp);
+
+               *hi = ts.tv_sec;
+               if (po->tp_version == TPACKET_V1)

Very minor: may want to invert test to make newer the protocols the likely branch.

Quoted 10 lines

static __u32 __packet_set_timestamp(struct packet_sock *po, void *frame,
struct sk_buff *skb)

 {
        union tpacket_uhdr h;
net/packet/af_packet.c +2 -3
-       struct timespec64 ts;
-       __u32 ts_status;
+       __u32 ts_status, hi, lo;
 
-       if (!(ts_status = tpacket_get_timestamp(skb, &ts, po->tp_tstamp)))
+       if (!(ts_status = tpacket_get_timestamp(skb, &hi, &lo, po->tp_tstamp)))

net/packet/af_packet.c static int __packet_get_status(struct packet_sock *po, void *frame) · line 475

Quoted 10 lines
net/packet/af_packet.c +0 -7
                return 0;
 
        h.raw = frame;
-       /*
-        * versions 1 through 3 overflow the timestamps in y2106, since they
-        * all store the seconds in a 32-bit unsigned integer.
-        * If we create a version 4, that should have a 64-bit timestamp,
-        * either 64-bit seconds + 32-bit nanoseconds, or just 64-bit
-        * nanoseconds.
-        */

Probably no need to introduce this in patch 1/2 when removing it in 2/2.

net/packet/af_packet.c static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, · line 2230

Quoted 7 lines
net/packet/af_packet.c +1 -1
@@ -2191,8 +2226,8 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
        unsigned long status = TP_STATUS_USER;
        unsigned short macoff, netoff, hdrlen;
        struct sk_buff *copy_skb = NULL;
-       struct timespec64 ts;
        __u32 ts_status;
+       __u32 hi, lo;

since this function is not time-specific, the context of hi and lo is not immediately obvious here. tstamp_hi, tstamp_lo? Or even __u32 tstamp[2] and have tpacket_get_timestamp and packet_get_time take one fewer argument.

#16 lore raw

Re: [PATCH] [RFC v3] packet: experimental support for 64-bit timestamps

Quoted 27 lines · Willem de Bruijn
Quoted 13 lines · Arnd Bergmann

As I noticed in my previous patch to remove the 'timespec' usage in the packet socket, the timestamps in the packet socket are slightly inefficient as they convert a nanosecond value into seconds/nanoseconds or seconds/microseconds.

This adds two new socket options for the timestamp to resolve that:

PACKET_SKIPTIMESTAMP sets a flag to indicate whether to generate timestamps at all. When this is set, all timestamps are hardcoded to zero, which saves a few cycles for the conversion and the access of the hardware clocksource. The idea was taken from pktgen, which has an F_NO_TIMESTAMP option for the same purpose.

Quoted 8 lines

PACKET_TIMESTAMP_NS64 changes the interpretation of the time stamp fields:
instead of having 32 bits for seconds plus 32 bits for nanoseconds or microseconds, we now always send down 64 bits worth of nanoseconds when this flag is set.

This works. Another option would be to add a PACKET_TIMESTAMP_EX with the semantics we discussed previously + fail hard when any undefined bits are set. I don't feel strong either way, we don't intend to extend further.

Quoted 8 lines

If taking this approach, it might be good to split into separate patches, one for each flag?

net/packet/af_packet.c static int __packet_get_status(struct packet_sock *po, void *frame) · line 443

Quoted 3 lines
net/packet/af_packet.c +1 -1
-static __u32 tpacket_get_timestamp(struct sk_buff *skb, struct timespec64 *ts,
+static __u32 tpacket_get_timestamp(struct sk_buff *skb, __u32 *hi, __u32 *lo,
                                   unsigned int flags)

Argument flags is no longer used.

Fixed

Quoted 11 lines

net/packet/af_packet.c static int __packet_get_status(struct packet_sock *po, void *frame) · line 474

Quoted 8 lines
net/packet/af_packet.c +7 -1
-       return 0;
+               *hi = upper_32_bits(ns);
+               *lo = lower_32_bits(ns);
+       } else {
+               struct timespec64 ts = ktime_to_timespec64(stamp);
+
+               *hi = ts.tv_sec;
+               if (po->tp_version == TPACKET_V1)

Very minor: may want to invert test to make newer the protocols the likely branch.

Ok. I didn't think this would make any difference to the compiler, but for readability it seems at least as good, so I've changed it as you suggested and use "po->tp_version > TPACKET_V1".

Quoted 21 lines
Quoted 10 lines

static __u32 __packet_set_timestamp(struct packet_sock *po, void *frame,
struct sk_buff *skb)

 {
        union tpacket_uhdr h;
net/packet/af_packet.c +2 -3
-       struct timespec64 ts;
-       __u32 ts_status;
+       __u32 ts_status, hi, lo;
 
-       if (!(ts_status = tpacket_get_timestamp(skb, &ts, po->tp_tstamp)))
+       if (!(ts_status = tpacket_get_timestamp(skb, &hi, &lo, po->tp_tstamp)))

net/packet/af_packet.c static int __packet_get_status(struct packet_sock *po, void *frame) · line 475

Quoted 10 lines
net/packet/af_packet.c +0 -7
                return 0;
 
        h.raw = frame;
-       /*
-        * versions 1 through 3 overflow the timestamps in y2106, since they
-        * all store the seconds in a 32-bit unsigned integer.
-        * If we create a version 4, that should have a 64-bit timestamp,
-        * either 64-bit seconds + 32-bit nanoseconds, or just 64-bit
-        * nanoseconds.
-        */
Quoted 1 line

Probably no need to introduce this in patch 1/2 when removing it in 2/2.

I'm still considering this patch as experimental, since I haven't done any actual testing on it, so I'm not sure it gets merged at the same time. If patch 1 gets merged separately, I'd rather keep the comment in place.

Quoted 4 lines
Quoted 4 lines
net/packet/af_packet.c +0 -0
@@ -2191,8 +2226,8 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
        unsigned long status = TP_STATUS_USER;
        unsigned short macoff, netoff, hdrlen;
        struct sk_buff *copy_skb = NULL;
Quoted 8 lines

net/packet/af_packet.c static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, · line 2230

Quoted 3 lines
net/packet/af_packet.c +1 -1
-       struct timespec64 ts;
        __u32 ts_status;
+       __u32 hi, lo;

since this function is not time-specific, the context of hi and lo is not immediately obvious here. tstamp_hi, tstamp_lo? Or even __u32 tstamp[2] and have tpacket_get_timestamp and packet_get_time take one fewer argument.

Fixed.

Thanks for the review! Any suggestions for how to do the testing? If you have existing test cases, could you give my next version a test run to see if there are any regressions and if the timestamps work as expected?

I see that there are test cases in tools/testing/selftests/net/, but none of them seem to use the time stamps so far, and I'm not overly familiar with how it works in the details to extend it in a meaningful way.

arnd

maintainer
#17 lore raw

Re: [PATCH] [RFC v3] packet: experimental support for 64-bit timestamps

Quoted 7 lines

Thanks for the review! Any suggestions for how to do the testing? If you have existing test cases, could you give my next version a test run to see if there are any regressions and if the timestamps work as expected?

I see that there are test cases in tools/testing/selftests/net/, but none of them seem to use the time stamps so far, and I'm not overly familiar with how it works in the details to extend it in a meaningful way.

I could not find any good tests for this interface, either. The only user of the interface I found was a little tool I wrote a few years ago that compares timestamps at multiple points in the transmit path for latency measurement [1]. But it may be easier to just write a new test under tools/testing/selftests/net for this purpose. I can help with that, too, if you want.

[1] https://github.com/wdebruij/kerneltools/blob/master/tools/tcplate/tcplate.c

#18 lore raw

Re: [PATCH] [RFC v3] packet: experimental support for 64-bit timestamps

Quoted 8 lines · Willem de Bruijn
Quoted 7 lines

Thanks for the review! Any suggestions for how to do the testing? If you have existing test cases, could you give my next version a test run to see if there are any regressions and if the timestamps work as expected?

I see that there are test cases in tools/testing/selftests/net/, but none of them seem to use the time stamps so far, and I'm not overly familiar with how it works in the details to extend it in a meaningful way.

Quoted 6 lines

I could not find any good tests for this interface, either. The only user of the interface I found was a little tool I wrote a few years ago that compares timestamps at multiple points in the transmit path for latency measurement [1]. But it may be easier to just write a new test under tools/testing/selftests/net for this purpose. I can help with that, too, if you want.

Thanks, that would be great!

Arnd

maintainer
#19 lore raw

Re: [PATCH] [RFC v3] packet: experimental support for 64-bit timestamps

Quoted 10 lines · Arnd Bergmann
Quoted 8 lines · Willem de Bruijn
Quoted 7 lines

Thanks for the review! Any suggestions for how to do the testing? If you have existing test cases, could you give my next version a test run to see if there are any regressions and if the timestamps work as expected?

I see that there are test cases in tools/testing/selftests/net/, but none of them seem to use the time stamps so far, and I'm not overly familiar with how it works in the details to extend it in a meaningful way.

Quoted 8 lines
Quoted 6 lines

I could not find any good tests for this interface, either. The only user of the interface I found was a little tool I wrote a few years ago that compares timestamps at multiple points in the transmit path for latency measurement [1]. But it may be easier to just write a new test under tools/testing/selftests/net for this purpose. I can help with that, too, if you want.

Thanks, that would be great!

I'll reply to this thread with git send-email with an extension to tools/testing/selftests/net/psock_tpacket.c. I can resend that for submission after your feature is merged (as it depends on it) or feel free to include it in your patchset. The test currently fails for the ns64 case. I probably did not convert correctly, but have to leave the office and want to send what I have.

Two other comments: the test crashed the kernel due to a NULL ptr in tpacket_get_timestamp. We cannot rely on skb->sk being set to the packet socket here. And assignment to bitfield requires a cast to boolean.

net/packet/af_packet.c +0 -0
index f55f330ab547..e9decc7fc5c3 100644
@@ -439,9 +439,9 @@ static int __packet_get_status(struct packet_sock

*po, void *frame)

        }

}

-static __u32 tpacket_get_timestamp(struct sk_buff *skb, __u32 *hi, __u32 *lo) +static __u32 tpacket_get_timestamp(struct packet_sock *po, struct sk_buff *skb,
+ __u32 *hi, __u32 *lo)
{

-       struct packet_sock *po = pkt_sk(skb->sk);
        struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
        ktime_t stamp;
        u32 type;
@@ -508,7 +508,7 @@ static __u32 __packet_set_timestamp(struct
packet_sock *po, void *frame,
        union tpacket_uhdr h;
        __u32 ts_status, hi, lo;

- if (!(ts_status = tpacket_get_timestamp(skb, &hi, &lo)))
+ if (!(ts_status = tpacket_get_timestamp(po, skb, &hi, &lo)))

                return 0;

        h.raw = frame;

@@ -2352,7 +2352,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,

        skb_copy_bits(skb, 0, h.raw + macoff, snaplen);

- if (!(ts_status = tpacket_get_timestamp(skb, &tstamp_hi, &tstamp_lo)))
+ if (!(ts_status = tpacket_get_timestamp(po, skb, &tstamp_hi,
&tstamp_lo)))

                packet_get_time(po, &tstamp_hi, &tstamp_lo);

        status |= ts_status;

@@ -3835,7 +3835,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
if (copy_from_user(&val, optval, sizeof(val)))
return -EFAULT;

- po->tp_skiptstamp = val;

+               po->tp_skiptstamp = !!val;
                return 0;
        }
        case PACKET_TIMESTAMP_NS64:

@@ -3847,7 +3847,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
if (copy_from_user(&val, optval, sizeof(val)))
return -EFAULT;

- po->tp_tstamp_ns64 = val;

+               po->tp_tstamp_ns64 = !!val;
                return 0;
        }
        case PACKET_FANOUT:
maintainer
#20 lore raw

RFC PATCH 1/1 selftests: test timestamps in psock_tpacket

From: Willem de Bruijn <[email protected]>

Packet rings can return timestamps. Optionally test this path.

Verify that the returned values are sane.
Also test new timestamp modes skip and ns64.

---
 tools/testing/selftests/net/psock_tpacket.c | 125 +++++++++++++++++++++++++++-
 1 file changed, 124 insertions(+), 1 deletion(-)
tools/testing/selftests/net/psock_tpacket.c +124 -1
index 7f6cd9fdacf3..5af11016a5de 100644
@@ -36,6 +36,7 @@
  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/types.h>
@@ -57,6 +58,7 @@
 #include <net/if.h>
 #include <inttypes.h>
 #include <poll.h>
+#include <sys/time.h>
 
 #include "psock_lib.h"
 
@@ -75,6 +77,19 @@
 #define NUM_PACKETS		100
 #define ALIGN_8(x)		(((x) + 8 - 1) & ~(8 - 1))
 
+const uint64_t tstamp_bound_ns64 = 1000UL * 1000 * 1000;
+
+enum cfg_tstamp_type {
+	tstype_none,
+	tstype_default,
+	tstype_skip,
+	tstype_ns64
+};
+
+static enum cfg_tstamp_type cfg_tstamp;
+
+static uint64_t tstamp_start_ns64;
+
 struct ring {
 	struct iovec *rd;
 	uint8_t *mm_space;
@@ -150,6 +165,43 @@ static void test_payload(void *pay, size_t len)
 	}
 }
 
+static void test_tstamp(uint32_t sec, uint32_t nsec)
+{
+	uint64_t tstamp_ns64;
+
+	if (!cfg_tstamp)
+		return;
+
+	if (cfg_tstamp == tstype_skip) {
+		if (sec || nsec) {
+			fprintf(stderr, "%s: unexpected tstamp %u:%u\n",
+				__func__, sec, nsec);
+			exit(1);
+		}
+		return;
+	}
+
+	if (cfg_tstamp == tstype_ns64)
+		tstamp_ns64 = (((uint64_t) sec) << 32) | nsec;
+	else
+		tstamp_ns64 = (sec * 1000UL * 1000 * 1000) + nsec;
+
+	if (tstamp_ns64 < tstamp_start_ns64) {
+		fprintf(stderr, "tstamp: %lu lowerbound=%lu under=%lu\n",
+				tstamp_ns64, tstamp_start_ns64,
+				tstamp_start_ns64 - tstamp_ns64);
+		exit(1);
+	}
+	if (tstamp_ns64 > tstamp_start_ns64 + tstamp_bound_ns64) {
+		fprintf(stderr, "tstamp: %lu upperbound=%lu over=%lu\n",
+				tstamp_ns64,
+				tstamp_start_ns64 + tstamp_bound_ns64,
+				tstamp_ns64 - (tstamp_start_ns64 +
+					       tstamp_bound_ns64));
+		exit(1);
+	}
+}
+
 static void create_payload(void *pay, size_t *len)
 {
 	int i;
@@ -256,12 +308,18 @@ static void walk_v1_v2_rx(int sock, struct ring *ring)
 			case TPACKET_V1:
 				test_payload((uint8_t *) ppd.raw + ppd.v1->tp_h.tp_mac,
 					     ppd.v1->tp_h.tp_snaplen);
+				test_tstamp(ppd.v1->tp_h.tp_sec,
+					    cfg_tstamp == tstype_ns64 ?
+					    ppd.v1->tp_h.tp_usec :
+					    ppd.v1->tp_h.tp_usec * 1000);
 				total_bytes += ppd.v1->tp_h.tp_snaplen;
 				break;
 
 			case TPACKET_V2:
 				test_payload((uint8_t *) ppd.raw + ppd.v2->tp_h.tp_mac,
 					     ppd.v2->tp_h.tp_snaplen);
+				test_tstamp(ppd.v2->tp_h.tp_sec,
+					    ppd.v2->tp_h.tp_nsec);
 				total_bytes += ppd.v2->tp_h.tp_snaplen;
 				break;
 			}
@@ -572,6 +630,7 @@ static void __v3_walk_block(struct block_desc *pbd, const int block_num)
 			bytes_with_padding += ALIGN_8(ppd->tp_snaplen + ppd->tp_mac);
 
 		test_payload((uint8_t *) ppd + ppd->tp_mac, ppd->tp_snaplen);
+		test_tstamp(ppd->tp_sec, ppd->tp_nsec);
 
 		status_bar_update();
 		total_packets++;
@@ -766,6 +825,38 @@ static void unmap_ring(int sock, struct ring *ring)
 	free(ring->rd);
 }
 
+static void setup_tstamp(int sock)
+{
+	struct timeval tv;
+	int one = 1;
+
+	gettimeofday(&tv, NULL);
+	tstamp_start_ns64 = (tv.tv_sec * 1000UL * 1000 * 1000) +
+			    (tv.tv_usec * 1000UL);
+
+/* TODO: remove before submit: temporary */
+#ifndef PACKET_SKIPTIMESTAMP
+#define PACKET_SKIPTIMESTAMP	23
+#endif
+#ifndef PACKET_TIMESTAMP_NS64
+#define PACKET_TIMESTAMP_NS64	24
+#endif
+
+	if (cfg_tstamp == tstype_skip) {
+		if (setsockopt(sock, SOL_PACKET, PACKET_SKIPTIMESTAMP,
+			       &one, sizeof(one))) {
+			perror("setsockopt skiptimestamp");
+			exit(1);
+		}
+	} else if (cfg_tstamp == tstype_ns64) {
+		if (setsockopt(sock, SOL_PACKET, PACKET_TIMESTAMP_NS64,
+			       &one, sizeof(one))) {
+			perror("setsockopt timestamp ns64");
+			exit(1);
+		}
+	}
+}
+
 static int test_kernel_bit_width(void)
 {
 	char in[512], *ptr;
@@ -829,6 +920,8 @@ static int test_tpacket(int version, int type)
 	}
 
 	sock = pfsocket(version);
+	if (cfg_tstamp)
+		setup_tstamp(sock);
 	memset(&ring, 0, sizeof(ring));
 	setup_ring(sock, &ring, version, type);
 	mmap_ring(sock, &ring);
@@ -841,10 +934,40 @@ static int test_tpacket(int version, int type)
 	return 0;
 }
 
-int main(void)
+static void usage(const char *filepath)
+{
+	fprintf(stderr, "Usage: %s [-t <default|skip|ns64>]\n", filepath);
+	exit(1);
+}
+
+static void parse_opts(int argc, char **argv)
+{
+	int c;
+
+	while ((c = getopt(argc, argv, "t:")) != -1) {
+		switch (c) {
+		case 't':
+			if (!strcmp(optarg, "default"))
+				cfg_tstamp = tstype_default;
+			else if (!strcmp(optarg, "skip"))
+				cfg_tstamp = tstype_skip;
+			else if (!strcmp(optarg, "ns64"))
+				cfg_tstamp = tstype_ns64;
+			else
+				usage(argv[0]);
+			break;
+		default:
+			usage(argv[0]);
+		}
+	}
+}
+
+int main(int argc, char **argv)
 {
 	int ret = 0;
 
+	parse_opts(argc, argv);
+
 	ret |= test_tpacket(TPACKET_V1, PACKET_RX_RING);
 	ret |= test_tpacket(TPACKET_V1, PACKET_TX_RING);
 
Signature · 1 line
2.15.0.531.g2ccb3012c9-goog
maintainer
#21 lore raw

Re: [PATCH] [RFC v3] packet: experimental support for 64-bit timestamps

In reply to Willem de Bruijn
Quoted 18 lines · Willem de Bruijn
Quoted 17 lines · Arnd Bergmann
Quoted 14 lines · Willem de Bruijn
Quoted 7 lines

Thanks for the review! Any suggestions for how to do the testing? If you have existing test cases, could you give my next version a test run to see if there are any regressions and if the timestamps work as expected?

I see that there are test cases in tools/testing/selftests/net/, but none of them seem to use the time stamps so far, and I'm not overly familiar with how it works in the details to extend it in a meaningful way.

I could not find any good tests for this interface, either. The only user of the interface I found was a little tool I wrote a few years ago that compares timestamps at multiple points in the transmit path for latency measurement [1]. But it may be easier to just write a new test under tools/testing/selftests/net for this purpose. I can help with that, too, if you want.

Quoted 4 lines
Quoted 1 line

Thanks, that would be great!

I'll reply to this thread with git send-email with an extension to tools/testing/selftests/net/psock_tpacket.c.

It appears that it did not end up in this thread. At least not when using gmail threading. Patch at http://patchwork.ozlabs.org/patch/842854/

#22 lore raw

RFC PATCH v4 1/1 packet: experimental support for 64-bit timestamps

In reply to Arnd Bergmann

As I noticed in my previous patch to remove the 'timespec' usage in the packet socket, the timestamps in the packet socket are slightly inefficient as they convert a nanosecond value into seconds/nanoseconds or seconds/microseconds.

This adds two new socket options for the timestamp to resolve that:

PACKET_SKIPTIMESTAMP sets a flag to indicate whether to generate timestamps at all. When this is set, all timestamps are hardcoded to zero, which saves a few cycles for the conversion and the access of the hardware clocksource. The idea was taken from pktgen, which has an F_NO_TIMESTAMP option for the same purpose.

PACKET_TIMESTAMP_NS64 changes the interpretation of the time stamp fields:
instead of having 32 bits for seconds plus 32 bits for nanoseconds or microseconds, we now always send down 64 bits worth of nanoseconds when this flag is set.

---
I still have not done any runtime testing on this patch, only implemented the suggestions from the previous versions.

While I don't think anyone is actively looking for this feature, I don't think there are any reasons left against merging it either, and it might come in handy for someone.

v4: address minor comments from Willem
v3: rework to use setsockopt
v2: use new tstamp flags instead of a new version
v1: original implementation using TPACKET_V4

---
 include/uapi/linux/if_packet.h |   2 +
 net/packet/af_packet.c         | 160 ++++++++++++++++++++++++++++-------------
 net/packet/internal.h          |   2 +
 3 files changed, 116 insertions(+), 48 deletions(-)
include/uapi/linux/if_packet.h +2 -0
index 67b61d91d89b..2eba54770e6b 100644
@@ -57,6 +57,8 @@ struct sockaddr_ll {
 #define PACKET_QDISC_BYPASS		20
 #define PACKET_ROLLOVER_STATS		21
 #define PACKET_FANOUT_DATA		22
+#define PACKET_SKIPTIMESTAMP		23
+#define PACKET_TIMESTAMP_NS64		24
 
 #define PACKET_FANOUT_HASH		0
 #define PACKET_FANOUT_LB		1
net/packet/af_packet.c +112 -48

280 lines not on this page · raw message

net/packet/internal.h +2 -0
index 562fbc155006..20b69512210f 100644
@@ -128,6 +128,8 @@ struct packet_sock {
 	unsigned int		tp_reserve;
 	unsigned int		tp_loss:1;
 	unsigned int		tp_tx_has_off:1;
+	unsigned int		tp_skiptstamp:1;
+	unsigned int		tp_tstamp_ns64:1;
 	unsigned int		tp_tstamp;
 	struct net_device __rcu	*cached_dev;
 	int			(*xmit)(struct sk_buff *skb);
Signature · 1 line
2.9.0
maintainer
#23 lore raw

Re: [PATCH 2/2] [RFC] packet: experimental support for 64-bit timestamps

In reply to Arnd Bergmann
Quoted 9 lines · Arnd Bergmann
Quoted 8 lines · Björn Töpel

2017-11-27 21:51 GMT+01:00 Arnd Bergmann <arnd at arndb.de>:
[...]

Quoted 6 lines
Quoted 5 lines

There already is an effort to come up with a new AF_PACKET V4 [1]. We should make sure that any new interface does not have the Y2038/Y2106 issue. But, if a new version is being developed and that subsumes all existing use cases, then there probably is no need for another version that is a very small diff to V3.

Quoted 8 lines
Quoted 6 lines
Quoted 2 lines

Ah, perfect, that's good timing. Adding Björn to Cc here.

Unfortunately, for the Y2038/Y2106 cases, we'll be (as a result of netdevconf discussions) moving the AF_PACKET V4 implementation to a separate, new, address/packet family.

Ok, I see.

Does it matter whether the replacement is a new version or a new packet family?

Quoted 18 lines
Quoted 14 lines
Quoted 6 lines
Quoted 6 lines

If adding support for existing applications is useful, another approach would be to add a new socket option that changes the semantics for the two u32 fields in each of V1, V2 and V3 to hold nsec. Add a single check after filling in those structs whether the option is set and, if so, overwrite the two fields.

Quoted 7 lines
Quoted 1 line

[1] https://lwn.net/Articles/737947/

I don't think that's necessary. As long as the V4 capabilities are a superset of V1-V3, we should be able to just require all users to move to V4 (or later) in the next 89 years, and make sure that they use unsigned seconds if they care about 2038.

Quoted 3 lines

Given that V4 wont be around for AF_PACKET -- at least not in the shape of our patches -- Willem's suggestion is probably a good way forward.

Quoted 5 lines

That leaves one question: should we do that now, or wait until some other reason for a V4 comes up? I don't mind creating another patch for this, just want to get a feeling of whether the API clutter is worth it when we have a way out that works until y2106 (at which point we run into other problems as well).

I don't expect that we'll have another packet version independent from the work that Björn is doing. The choice to implement using a new packet family is given by the complexity of the existing code, especially the various locking mechanisms.

Quoted 1 line

From that point of view, and if we want to offer a Y2106 proof

AF_PACKET independent from the above, no reason to wait.
--
To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

#24 lore raw

Re: [PATCH 2/2] [RFC] packet: experimental support for 64-bit timestamps

Quoted 13 lines · Willem de Bruijn
Quoted 12 lines · Arnd Bergmann
Quoted 11 lines · Björn Töpel

2017-11-27 21:51 GMT+01:00 Arnd Bergmann <arnd at arndb.de>:
[...]

Quoted 8 lines
Quoted 5 lines

There already is an effort to come up with a new AF_PACKET V4 [1]. We should make sure that any new interface does not have the Y2038/Y2106 issue. But, if a new version is being developed and that subsumes all existing use cases, then there probably is no need for another version that is a very small diff to V3.

Ah, perfect, that's good timing. Adding Björn to Cc here.

Quoted 8 lines
Quoted 5 lines
Quoted 3 lines

Unfortunately, for the Y2038/Y2106 cases, we'll be (as a result of netdevconf discussions) moving the AF_PACKET V4 implementation to a separate, new, address/packet family.

Ok, I see.

Does it matter whether the replacement is a new version or a new packet family?

It depends on whether the new packet family provides a superset of the AF_PACKET features or not. If we can expect that all users of AF_PACKET can migrate to the replacement over time, then doing it there is sufficient, otherwise adding 64-bit timestamps into AF_PACKET may be a better way to upgrade existing users.

Quoted 24 lines
Quoted 18 lines
Quoted 14 lines
Quoted 6 lines
Quoted 6 lines

If adding support for existing applications is useful, another approach would be to add a new socket option that changes the semantics for the two u32 fields in each of V1, V2 and V3 to hold nsec. Add a single check after filling in those structs whether the option is set and, if so, overwrite the two fields.

Quoted 7 lines
Quoted 1 line

[1] https://lwn.net/Articles/737947/

I don't think that's necessary. As long as the V4 capabilities are a superset of V1-V3, we should be able to just require all users to move to V4 (or later) in the next 89 years, and make sure that they use unsigned seconds if they care about 2038.

Quoted 3 lines

Given that V4 wont be around for AF_PACKET -- at least not in the shape of our patches -- Willem's suggestion is probably a good way forward.

Quoted 5 lines

That leaves one question: should we do that now, or wait until some other reason for a V4 comes up? I don't mind creating another patch for this, just want to get a feeling of whether the API clutter is worth it when we have a way out that works until y2106 (at which point we run into other problems as well).

Quoted 4 lines

I don't expect that we'll have another packet version independent from the work that Björn is doing. The choice to implement using a new packet family is given by the complexity of the existing code, especially the various locking mechanisms.

Ok.

Quoted 2 lines

From that point of view, and if we want to offer a Y2106 proof AF_PACKET independent from the above, no reason to wait.

Agreed.

Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-kselftest" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html