Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 325ed823 authored by Herbert Xu's avatar Herbert Xu Committed by David S. Miller
Browse files

[NET]: Fix packet timestamping.



I've found the problem in general.  It affects any 64-bit
architecture.  The problem occurs when you change the system time.

Suppose that when you boot your system clock is forward by a day.
This gets recorded down in skb_tv_base.  You then wind the clock back
by a day.  From that point onwards the offset will be negative which
essentially overflows the 32-bit variables they're stored in.

In fact, why don't we just store the real time stamp in those 32-bit
variables? After all, we're not going to overflow for quite a while
yet.

When we do overflow, we'll need a better solution of course.

Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ddea7be0
Loading
Loading
Loading
Loading
+3 −9
Original line number Diff line number Diff line
@@ -155,8 +155,6 @@ struct skb_shared_info {
#define SKB_DATAREF_SHIFT 16
#define SKB_DATAREF_MASK ((1 << SKB_DATAREF_SHIFT) - 1)

extern struct timeval skb_tv_base;

struct skb_timeval {
	u32	off_sec;
	u32	off_usec;
@@ -175,7 +173,7 @@ enum {
 *	@prev: Previous buffer in list
 *	@list: List we are on
 *	@sk: Socket we are owned by
 *	@tstamp: Time we arrived stored as offset to skb_tv_base
 *	@tstamp: Time we arrived
 *	@dev: Device we arrived on/are leaving by
 *	@input_dev: Device we arrived on
 *	@h: Transport layer header
@@ -1255,10 +1253,6 @@ static inline void skb_get_timestamp(const struct sk_buff *skb, struct timeval *
{
	stamp->tv_sec  = skb->tstamp.off_sec;
	stamp->tv_usec = skb->tstamp.off_usec;
	if (skb->tstamp.off_sec) {
		stamp->tv_sec  += skb_tv_base.tv_sec;
		stamp->tv_usec += skb_tv_base.tv_usec;
	}
}

/**
@@ -1272,8 +1266,8 @@ static inline void skb_get_timestamp(const struct sk_buff *skb, struct timeval *
 */
static inline void skb_set_timestamp(struct sk_buff *skb, const struct timeval *stamp)
{
	skb->tstamp.off_sec  = stamp->tv_sec - skb_tv_base.tv_sec;
	skb->tstamp.off_usec = stamp->tv_usec - skb_tv_base.tv_usec;
	skb->tstamp.off_sec  = stamp->tv_sec;
	skb->tstamp.off_usec = stamp->tv_usec;
}

extern void __net_timestamp(struct sk_buff *skb);
+0 −5
Original line number Diff line number Diff line
@@ -71,8 +71,6 @@
static kmem_cache_t *skbuff_head_cache __read_mostly;
static kmem_cache_t *skbuff_fclone_cache __read_mostly;

struct timeval __read_mostly skb_tv_base;

/*
 *	Keep out-of-line to prevent kernel bloat.
 *	__builtin_return_address is not used because it is not always
@@ -1708,8 +1706,6 @@ void __init skb_init(void)
						NULL, NULL);
	if (!skbuff_fclone_cache)
		panic("cannot create skbuff cache");

	do_gettimeofday(&skb_tv_base);
}

EXPORT_SYMBOL(___pskb_trim);
@@ -1743,4 +1739,3 @@ EXPORT_SYMBOL(skb_prepare_seq_read);
EXPORT_SYMBOL(skb_seq_read);
EXPORT_SYMBOL(skb_abort_seq_read);
EXPORT_SYMBOL(skb_find_text);
EXPORT_SYMBOL(skb_tv_base);
+2 −2
Original line number Diff line number Diff line
@@ -240,8 +240,8 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp)

	pmsg->packet_id       = (unsigned long )entry;
	pmsg->data_len        = data_len;
	pmsg->timestamp_sec   = skb_tv_base.tv_sec + entry->skb->tstamp.off_sec;
	pmsg->timestamp_usec  = skb_tv_base.tv_usec + entry->skb->tstamp.off_usec;
	pmsg->timestamp_sec   = entry->skb->tstamp.off_sec;
	pmsg->timestamp_usec  = entry->skb->tstamp.off_usec;
	pmsg->mark            = entry->skb->nfmark;
	pmsg->hook            = entry->info->hook;
	pmsg->hw_protocol     = entry->skb->protocol;
+2 −2
Original line number Diff line number Diff line
@@ -225,8 +225,8 @@ static void ipt_ulog_packet(unsigned int hooknum,

	/* copy hook, prefix, timestamp, payload, etc. */
	pm->data_len = copy_len;
	pm->timestamp_sec = skb_tv_base.tv_sec + skb->tstamp.off_sec;
	pm->timestamp_usec = skb_tv_base.tv_usec + skb->tstamp.off_usec;
	pm->timestamp_sec = skb->tstamp.off_sec;
	pm->timestamp_usec = skb->tstamp.off_usec;
	pm->mark = skb->nfmark;
	pm->hook = hooknum;
	if (prefix != NULL)
+2 −2
Original line number Diff line number Diff line
@@ -238,8 +238,8 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp)

	pmsg->packet_id       = (unsigned long )entry;
	pmsg->data_len        = data_len;
	pmsg->timestamp_sec   = skb_tv_base.tv_sec + entry->skb->tstamp.off_sec;
	pmsg->timestamp_usec  = skb_tv_base.tv_usec + entry->skb->tstamp.off_usec;
	pmsg->timestamp_sec   = entry->skb->tstamp.off_sec;
	pmsg->timestamp_usec  = entry->skb->tstamp.off_usec;
	pmsg->mark            = entry->skb->nfmark;
	pmsg->hook            = entry->info->hook;
	pmsg->hw_protocol     = entry->skb->protocol;
Loading