diff options
| author | Eric Dumazet <edumazet@google.com> | 2014-02-26 17:02:11 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2014-02-26 17:08:39 -0500 |
| commit | 363ec392352e55c61ce2799c3f15f89f9429bba7 (patch) | |
| tree | 7457074aafefd96ae6885038c040cad8d31853d9 /include/linux | |
| parent | 20d8435a1cffa04992f1db6b199a5f0ccec2ff06 (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.h | 59 |
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; | |||
| 356 | typedef unsigned char *sk_buff_data_t; | 357 | typedef 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 | */ | ||
| 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 | |||
| 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; |
