diff options
author | Willem de Bruijn <willemb@google.com> | 2014-08-04 22:11:48 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-08-05 19:35:54 -0400 |
commit | e7fd2885385157d46c85f282fc6d7d297db43e1f (patch) | |
tree | 14e9d00ed87b2b45882c8cb8dd1b9b4d221724f8 | |
parent | 09c2d251b70723650ba47e83571ff49281320f7c (diff) |
net-timestamp: SCHED timestamp on entering packet scheduler
Kernel transmit latency is often incurred in the packet scheduler.
Introduce a new timestamp on transmission just before entering the
scheduler. When data travels through multiple devices (bonding,
tunneling, ...) each device will export an individual timestamp.
Signed-off-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/skbuff.h | 11 | ||||
-rw-r--r-- | include/uapi/linux/errqueue.h | 1 | ||||
-rw-r--r-- | include/uapi/linux/net_tstamp.h | 3 | ||||
-rw-r--r-- | net/core/dev.c | 4 | ||||
-rw-r--r-- | net/core/skbuff.c | 16 | ||||
-rw-r--r-- | net/socket.c | 3 |
6 files changed, 31 insertions, 7 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 0e35b3af7317..50e1e9b3a5a5 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
@@ -229,7 +229,7 @@ enum { | |||
229 | /* generate hardware time stamp */ | 229 | /* generate hardware time stamp */ |
230 | SKBTX_HW_TSTAMP = 1 << 0, | 230 | SKBTX_HW_TSTAMP = 1 << 0, |
231 | 231 | ||
232 | /* generate software time stamp */ | 232 | /* generate software time stamp when queueing packet to NIC */ |
233 | SKBTX_SW_TSTAMP = 1 << 1, | 233 | SKBTX_SW_TSTAMP = 1 << 1, |
234 | 234 | ||
235 | /* device driver is going to provide hardware time stamp */ | 235 | /* device driver is going to provide hardware time stamp */ |
@@ -247,9 +247,12 @@ enum { | |||
247 | * all frags to avoid possible bad checksum | 247 | * all frags to avoid possible bad checksum |
248 | */ | 248 | */ |
249 | SKBTX_SHARED_FRAG = 1 << 5, | 249 | SKBTX_SHARED_FRAG = 1 << 5, |
250 | |||
251 | /* generate software time stamp when entering packet scheduling */ | ||
252 | SKBTX_SCHED_TSTAMP = 1 << 6, | ||
250 | }; | 253 | }; |
251 | 254 | ||
252 | #define SKBTX_ANY_SW_TSTAMP SKBTX_SW_TSTAMP | 255 | #define SKBTX_ANY_SW_TSTAMP (SKBTX_SW_TSTAMP | SKBTX_SCHED_TSTAMP) |
253 | #define SKBTX_ANY_TSTAMP (SKBTX_HW_TSTAMP | SKBTX_ANY_SW_TSTAMP) | 256 | #define SKBTX_ANY_TSTAMP (SKBTX_HW_TSTAMP | SKBTX_ANY_SW_TSTAMP) |
254 | 257 | ||
255 | /* | 258 | /* |
@@ -2695,6 +2698,10 @@ static inline bool skb_defer_rx_timestamp(struct sk_buff *skb) | |||
2695 | void skb_complete_tx_timestamp(struct sk_buff *skb, | 2698 | void skb_complete_tx_timestamp(struct sk_buff *skb, |
2696 | struct skb_shared_hwtstamps *hwtstamps); | 2699 | struct skb_shared_hwtstamps *hwtstamps); |
2697 | 2700 | ||
2701 | void __skb_tstamp_tx(struct sk_buff *orig_skb, | ||
2702 | struct skb_shared_hwtstamps *hwtstamps, | ||
2703 | struct sock *sk, int tstype); | ||
2704 | |||
2698 | /** | 2705 | /** |
2699 | * skb_tstamp_tx - queue clone of skb with send time stamps | 2706 | * skb_tstamp_tx - queue clone of skb with send time stamps |
2700 | * @orig_skb: the original outgoing packet | 2707 | * @orig_skb: the original outgoing packet |
diff --git a/include/uapi/linux/errqueue.h b/include/uapi/linux/errqueue.h index accee72cae7c..17437cf297b7 100644 --- a/include/uapi/linux/errqueue.h +++ b/include/uapi/linux/errqueue.h | |||
@@ -39,6 +39,7 @@ struct scm_timestamping { | |||
39 | */ | 39 | */ |
40 | enum { | 40 | enum { |
41 | SCM_TSTAMP_SND, /* driver passed skb to NIC, or HW */ | 41 | SCM_TSTAMP_SND, /* driver passed skb to NIC, or HW */ |
42 | SCM_TSTAMP_SCHED, /* data entered the packet scheduler */ | ||
42 | }; | 43 | }; |
43 | 44 | ||
44 | #endif /* _UAPI_LINUX_ERRQUEUE_H */ | 45 | #endif /* _UAPI_LINUX_ERRQUEUE_H */ |
diff --git a/include/uapi/linux/net_tstamp.h b/include/uapi/linux/net_tstamp.h index 1e861d2e1a31..60733845fcdd 100644 --- a/include/uapi/linux/net_tstamp.h +++ b/include/uapi/linux/net_tstamp.h | |||
@@ -21,8 +21,9 @@ enum { | |||
21 | SOF_TIMESTAMPING_SYS_HARDWARE = (1<<5), | 21 | SOF_TIMESTAMPING_SYS_HARDWARE = (1<<5), |
22 | SOF_TIMESTAMPING_RAW_HARDWARE = (1<<6), | 22 | SOF_TIMESTAMPING_RAW_HARDWARE = (1<<6), |
23 | SOF_TIMESTAMPING_OPT_ID = (1<<7), | 23 | SOF_TIMESTAMPING_OPT_ID = (1<<7), |
24 | SOF_TIMESTAMPING_TX_SCHED = (1<<8), | ||
24 | 25 | ||
25 | SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_OPT_ID, | 26 | SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_TX_SCHED, |
26 | SOF_TIMESTAMPING_MASK = (SOF_TIMESTAMPING_LAST - 1) | | 27 | SOF_TIMESTAMPING_MASK = (SOF_TIMESTAMPING_LAST - 1) | |
27 | SOF_TIMESTAMPING_LAST | 28 | SOF_TIMESTAMPING_LAST |
28 | }; | 29 | }; |
diff --git a/net/core/dev.c b/net/core/dev.c index b370230fe1d3..1c15b189c52b 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -132,6 +132,7 @@ | |||
132 | #include <linux/hashtable.h> | 132 | #include <linux/hashtable.h> |
133 | #include <linux/vmalloc.h> | 133 | #include <linux/vmalloc.h> |
134 | #include <linux/if_macvlan.h> | 134 | #include <linux/if_macvlan.h> |
135 | #include <linux/errqueue.h> | ||
135 | 136 | ||
136 | #include "net-sysfs.h" | 137 | #include "net-sysfs.h" |
137 | 138 | ||
@@ -2876,6 +2877,9 @@ static int __dev_queue_xmit(struct sk_buff *skb, void *accel_priv) | |||
2876 | 2877 | ||
2877 | skb_reset_mac_header(skb); | 2878 | skb_reset_mac_header(skb); |
2878 | 2879 | ||
2880 | if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_SCHED_TSTAMP)) | ||
2881 | __skb_tstamp_tx(skb, NULL, skb->sk, SCM_TSTAMP_SCHED); | ||
2882 | |||
2879 | /* Disable soft irqs for various locks below. Also | 2883 | /* Disable soft irqs for various locks below. Also |
2880 | * stops preemption for RCU. | 2884 | * stops preemption for RCU. |
2881 | */ | 2885 | */ |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 0df4f1d14c5a..9705c0732aab 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -3490,10 +3490,10 @@ int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb) | |||
3490 | } | 3490 | } |
3491 | EXPORT_SYMBOL(sock_queue_err_skb); | 3491 | EXPORT_SYMBOL(sock_queue_err_skb); |
3492 | 3492 | ||
3493 | void skb_tstamp_tx(struct sk_buff *orig_skb, | 3493 | void __skb_tstamp_tx(struct sk_buff *orig_skb, |
3494 | struct skb_shared_hwtstamps *hwtstamps) | 3494 | struct skb_shared_hwtstamps *hwtstamps, |
3495 | struct sock *sk, int tstype) | ||
3495 | { | 3496 | { |
3496 | struct sock *sk = orig_skb->sk; | ||
3497 | struct sock_exterr_skb *serr; | 3497 | struct sock_exterr_skb *serr; |
3498 | struct sk_buff *skb; | 3498 | struct sk_buff *skb; |
3499 | int err; | 3499 | int err; |
@@ -3521,7 +3521,7 @@ void skb_tstamp_tx(struct sk_buff *orig_skb, | |||
3521 | memset(serr, 0, sizeof(*serr)); | 3521 | memset(serr, 0, sizeof(*serr)); |
3522 | serr->ee.ee_errno = ENOMSG; | 3522 | serr->ee.ee_errno = ENOMSG; |
3523 | serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING; | 3523 | serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING; |
3524 | serr->ee.ee_info = SCM_TSTAMP_SND; | 3524 | serr->ee.ee_info = tstype; |
3525 | if (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) | 3525 | if (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) |
3526 | serr->ee.ee_data = skb_shinfo(skb)->tskey; | 3526 | serr->ee.ee_data = skb_shinfo(skb)->tskey; |
3527 | 3527 | ||
@@ -3530,6 +3530,14 @@ void skb_tstamp_tx(struct sk_buff *orig_skb, | |||
3530 | if (err) | 3530 | if (err) |
3531 | kfree_skb(skb); | 3531 | kfree_skb(skb); |
3532 | } | 3532 | } |
3533 | EXPORT_SYMBOL_GPL(__skb_tstamp_tx); | ||
3534 | |||
3535 | void skb_tstamp_tx(struct sk_buff *orig_skb, | ||
3536 | struct skb_shared_hwtstamps *hwtstamps) | ||
3537 | { | ||
3538 | return __skb_tstamp_tx(orig_skb, hwtstamps, orig_skb->sk, | ||
3539 | SCM_TSTAMP_SND); | ||
3540 | } | ||
3533 | EXPORT_SYMBOL_GPL(skb_tstamp_tx); | 3541 | EXPORT_SYMBOL_GPL(skb_tstamp_tx); |
3534 | 3542 | ||
3535 | void skb_complete_wifi_ack(struct sk_buff *skb, bool acked) | 3543 | void skb_complete_wifi_ack(struct sk_buff *skb, bool acked) |
diff --git a/net/socket.c b/net/socket.c index 255d9b802723..3a2778d71631 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -617,6 +617,9 @@ void sock_tx_timestamp(struct sock *sk, __u8 *tx_flags) | |||
617 | *tx_flags |= SKBTX_HW_TSTAMP; | 617 | *tx_flags |= SKBTX_HW_TSTAMP; |
618 | if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_SOFTWARE) | 618 | if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_SOFTWARE) |
619 | *tx_flags |= SKBTX_SW_TSTAMP; | 619 | *tx_flags |= SKBTX_SW_TSTAMP; |
620 | if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_SCHED) | ||
621 | *tx_flags |= SKBTX_SCHED_TSTAMP; | ||
622 | |||
620 | if (sock_flag(sk, SOCK_WIFI_STATUS)) | 623 | if (sock_flag(sk, SOCK_WIFI_STATUS)) |
621 | *tx_flags |= SKBTX_WIFI_STATUS; | 624 | *tx_flags |= SKBTX_WIFI_STATUS; |
622 | } | 625 | } |