Skip to content

Commit 363ec39

Browse files
edumazetdavem330
authored andcommitted
net: add skb_mstamp infrastructure
ktime_get() is too expensive on some cases, and we'd like to get usec resolution timestamps in TCP stack. This patch adds a light weight facility using a combination of local_clock() and jiffies samples. Instead of : u64 t0, t1; t0 = ktime_get(); // stuff t1 = ktime_get(); delta_us = ktime_us_delta(t1, t0); use : struct skb_mstamp t0, t1; skb_mstamp_get(&t0); // stuff skb_mstamp_get(&t1); delta_us = skb_mstamp_us_delta(&t1, &t0); Note : local_clock() might have a (bounded) drift between cpus. Do not use this infra in place of ktime_get() without understanding the issues. Signed-off-by: Eric Dumazet <[email protected]> Cc: Stephen Hemminger <[email protected]> Cc: Yuchung Cheng <[email protected]> Cc: Neal Cardwell <[email protected]> Cc: Larry Brakmo <[email protected]> Cc: Julian Anastasov <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 20d8435 commit 363ec39

File tree

1 file changed

+57
-2
lines changed

1 file changed

+57
-2
lines changed

include/linux/skbuff.h

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <linux/hrtimer.h>
3333
#include <linux/dma-mapping.h>
3434
#include <linux/netdev_features.h>
35+
#include <linux/sched.h>
3536
#include <net/flow_keys.h>
3637

3738
/* A. Checksumming of received packets by device.
@@ -356,11 +357,62 @@ typedef unsigned int sk_buff_data_t;
356357
typedef unsigned char *sk_buff_data_t;
357358
#endif
358359

360+
/**
361+
* struct skb_mstamp - multi resolution time stamps
362+
* @stamp_us: timestamp in us resolution
363+
* @stamp_jiffies: timestamp in jiffies
364+
*/
365+
struct skb_mstamp {
366+
union {
367+
u64 v64;
368+
struct {
369+
u32 stamp_us;
370+
u32 stamp_jiffies;
371+
};
372+
};
373+
};
374+
375+
/**
376+
* skb_mstamp_get - get current timestamp
377+
* @cl: place to store timestamps
378+
*/
379+
static inline void skb_mstamp_get(struct skb_mstamp *cl)
380+
{
381+
u64 val = local_clock();
382+
383+
do_div(val, NSEC_PER_USEC);
384+
cl->stamp_us = (u32)val;
385+
cl->stamp_jiffies = (u32)jiffies;
386+
}
387+
388+
/**
389+
* skb_mstamp_delta - compute the difference in usec between two skb_mstamp
390+
* @t1: pointer to newest sample
391+
* @t0: pointer to oldest sample
392+
*/
393+
static inline u32 skb_mstamp_us_delta(const struct skb_mstamp *t1,
394+
const struct skb_mstamp *t0)
395+
{
396+
s32 delta_us = t1->stamp_us - t0->stamp_us;
397+
u32 delta_jiffies = t1->stamp_jiffies - t0->stamp_jiffies;
398+
399+
/* If delta_us is negative, this might be because interval is too big,
400+
* or local_clock() drift is too big : fallback using jiffies.
401+
*/
402+
if (delta_us <= 0 ||
403+
delta_jiffies >= (INT_MAX / (USEC_PER_SEC / HZ)))
404+
405+
delta_us = jiffies_to_usecs(delta_jiffies);
406+
407+
return delta_us;
408+
}
409+
410+
359411
/**
360412
* struct sk_buff - socket buffer
361413
* @next: Next buffer in list
362414
* @prev: Previous buffer in list
363-
* @tstamp: Time we arrived
415+
* @tstamp: Time we arrived/left
364416
* @sk: Socket we are owned by
365417
* @dev: Device we arrived on/are leaving by
366418
* @cb: Control buffer. Free for use by every layer. Put private vars here
@@ -429,7 +481,10 @@ struct sk_buff {
429481
struct sk_buff *next;
430482
struct sk_buff *prev;
431483

432-
ktime_t tstamp;
484+
union {
485+
ktime_t tstamp;
486+
struct skb_mstamp skb_mstamp;
487+
};
433488

434489
struct sock *sk;
435490
struct net_device *dev;

0 commit comments

Comments
 (0)