diff options
author | Patrick Ohly <patrick.ohly@intel.com> | 2009-02-12 00:03:37 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-02-16 01:43:34 -0500 |
commit | ac45f602ee3d1b6f326f68bc0c2591ceebf05ba4 (patch) | |
tree | c92c86bd0d89b844a3794c0e441aa2fccb36725f /net/core/skbuff.c | |
parent | cb9eff097831007afb30d64373f29d99825d0068 (diff) |
net: infrastructure for hardware time stamping
The additional per-packet information (16 bytes for time stamps, 1
byte for flags) is stored for all packets in the skb_shared_info
struct. This implementation detail is hidden from users of that
information via skb_* accessor functions. A separate struct resp.
union is used for the additional information so that it can be
stored/copied easily outside of skb_shared_info.
Compared to previous implementations (reusing the tstamp field
depending on the context, optional additional structures) this
is the simplest solution. It does not extend sk_buff itself.
TX time stamping is implemented in software if the device driver
doesn't support hardware time stamping.
The new semantic for hardware/software time stamping around
ndo_start_xmit() is based on two assumptions about existing
network device drivers which don't support hardware time
stamping and know nothing about it:
- they leave the new skb_shared_tx unmodified
- the keep the connection to the originating socket in skb->sk
alive, i.e., don't call skb_orphan()
Given that skb_shared_tx is new, the first assumption is safe.
The second is only true for some drivers. As a result, software
TX time stamping currently works with the bnx2 driver, but not
with the unmodified igb driver (the two drivers this patch series
was tested with).
Signed-off-by: Patrick Ohly <patrick.ohly@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/skbuff.c')
-rw-r--r-- | net/core/skbuff.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index ab7d2e9f02fa..e5a8351ff12d 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -55,6 +55,7 @@ | |||
55 | #include <linux/rtnetlink.h> | 55 | #include <linux/rtnetlink.h> |
56 | #include <linux/init.h> | 56 | #include <linux/init.h> |
57 | #include <linux/scatterlist.h> | 57 | #include <linux/scatterlist.h> |
58 | #include <linux/errqueue.h> | ||
58 | 59 | ||
59 | #include <net/protocol.h> | 60 | #include <net/protocol.h> |
60 | #include <net/dst.h> | 61 | #include <net/dst.h> |
@@ -215,7 +216,9 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, | |||
215 | shinfo->gso_segs = 0; | 216 | shinfo->gso_segs = 0; |
216 | shinfo->gso_type = 0; | 217 | shinfo->gso_type = 0; |
217 | shinfo->ip6_frag_id = 0; | 218 | shinfo->ip6_frag_id = 0; |
219 | shinfo->tx_flags.flags = 0; | ||
218 | shinfo->frag_list = NULL; | 220 | shinfo->frag_list = NULL; |
221 | memset(&shinfo->hwtstamps, 0, sizeof(shinfo->hwtstamps)); | ||
219 | 222 | ||
220 | if (fclone) { | 223 | if (fclone) { |
221 | struct sk_buff *child = skb + 1; | 224 | struct sk_buff *child = skb + 1; |
@@ -2945,6 +2948,44 @@ int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer) | |||
2945 | } | 2948 | } |
2946 | EXPORT_SYMBOL_GPL(skb_cow_data); | 2949 | EXPORT_SYMBOL_GPL(skb_cow_data); |
2947 | 2950 | ||
2951 | void skb_tstamp_tx(struct sk_buff *orig_skb, | ||
2952 | struct skb_shared_hwtstamps *hwtstamps) | ||
2953 | { | ||
2954 | struct sock *sk = orig_skb->sk; | ||
2955 | struct sock_exterr_skb *serr; | ||
2956 | struct sk_buff *skb; | ||
2957 | int err; | ||
2958 | |||
2959 | if (!sk) | ||
2960 | return; | ||
2961 | |||
2962 | skb = skb_clone(orig_skb, GFP_ATOMIC); | ||
2963 | if (!skb) | ||
2964 | return; | ||
2965 | |||
2966 | if (hwtstamps) { | ||
2967 | *skb_hwtstamps(skb) = | ||
2968 | *hwtstamps; | ||
2969 | } else { | ||
2970 | /* | ||
2971 | * no hardware time stamps available, | ||
2972 | * so keep the skb_shared_tx and only | ||
2973 | * store software time stamp | ||
2974 | */ | ||
2975 | skb->tstamp = ktime_get_real(); | ||
2976 | } | ||
2977 | |||
2978 | serr = SKB_EXT_ERR(skb); | ||
2979 | memset(serr, 0, sizeof(*serr)); | ||
2980 | serr->ee.ee_errno = ENOMSG; | ||
2981 | serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING; | ||
2982 | err = sock_queue_err_skb(sk, skb); | ||
2983 | if (err) | ||
2984 | kfree_skb(skb); | ||
2985 | } | ||
2986 | EXPORT_SYMBOL_GPL(skb_tstamp_tx); | ||
2987 | |||
2988 | |||
2948 | /** | 2989 | /** |
2949 | * skb_partial_csum_set - set up and verify partial csum values for packet | 2990 | * skb_partial_csum_set - set up and verify partial csum values for packet |
2950 | * @skb: the skb to set | 2991 | * @skb: the skb to set |