summaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2014-02-26 17:02:11 -0500
committerDavid S. Miller <davem@davemloft.net>2014-02-26 17:08:39 -0500
commit363ec392352e55c61ce2799c3f15f89f9429bba7 (patch)
tree7457074aafefd96ae6885038c040cad8d31853d9 /include/linux
parent20d8435a1cffa04992f1db6b199a5f0ccec2ff06 (diff)
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 <edumazet@google.com> Cc: Stephen Hemminger <stephen@networkplumber.org> Cc: Yuchung Cheng <ycheng@google.com> Cc: Neal Cardwell <ncardwell@google.com> Cc: Larry Brakmo <brakmo@google.com> Cc: Julian Anastasov <ja@ssi.bg> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/skbuff.h59
1 files changed, 57 insertions, 2 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 11b6925f0e96..6d8ed22accb4 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -32,6 +32,7 @@
32#include <linux/hrtimer.h> 32#include <linux/hrtimer.h>
33#include <linux/dma-mapping.h> 33#include <linux/dma-mapping.h>
34#include <linux/netdev_features.h> 34#include <linux/netdev_features.h>
35#include <linux/sched.h>
35#include <net/flow_keys.h> 36#include <net/flow_keys.h>
36 37
37/* A. Checksumming of received packets by device. 38/* A. Checksumming of received packets by device.
@@ -356,11 +357,62 @@ typedef unsigned int sk_buff_data_t;
356typedef unsigned char *sk_buff_data_t; 357typedef unsigned char *sk_buff_data_t;
357#endif 358#endif
358 359
360/**
361 * struct skb_mstamp - multi resolution time stamps
362 * @stamp_us: timestamp in us resolution
363 * @stamp_jiffies: timestamp in jiffies
364 */
365struct 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 */
379static 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 */
393static 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
359/** 411/**
360 * struct sk_buff - socket buffer 412 * struct sk_buff - socket buffer
361 * @next: Next buffer in list 413 * @next: Next buffer in list
362 * @prev: Previous buffer in list 414 * @prev: Previous buffer in list
363 * @tstamp: Time we arrived 415 * @tstamp: Time we arrived/left
364 * @sk: Socket we are owned by 416 * @sk: Socket we are owned by
365 * @dev: Device we arrived on/are leaving by 417 * @dev: Device we arrived on/are leaving by
366 * @cb: Control buffer. Free for use by every layer. Put private vars here 418 * @cb: Control buffer. Free for use by every layer. Put private vars here
@@ -429,7 +481,10 @@ struct sk_buff {
429 struct sk_buff *next; 481 struct sk_buff *next;
430 struct sk_buff *prev; 482 struct sk_buff *prev;
431 483
432 ktime_t tstamp; 484 union {
485 ktime_t tstamp;
486 struct skb_mstamp skb_mstamp;
487 };
433 488
434 struct sock *sk; 489 struct sock *sk;
435 struct net_device *dev; 490 struct net_device *dev;