aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/skbuff.h91
-rw-r--r--net/core/dev.c32
-rw-r--r--net/core/skbuff.c41
3 files changed, 161 insertions, 3 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 924700844580..f96bc91bf0a3 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -132,6 +132,57 @@ struct skb_frag_struct {
132 __u32 size; 132 __u32 size;
133}; 133};
134 134
135#define HAVE_HW_TIME_STAMP
136
137/**
138 * skb_shared_hwtstamps - hardware time stamps
139 *
140 * @hwtstamp: hardware time stamp transformed into duration
141 * since arbitrary point in time
142 * @syststamp: hwtstamp transformed to system time base
143 *
144 * Software time stamps generated by ktime_get_real() are stored in
145 * skb->tstamp. The relation between the different kinds of time
146 * stamps is as follows:
147 *
148 * syststamp and tstamp can be compared against each other in
149 * arbitrary combinations. The accuracy of a
150 * syststamp/tstamp/"syststamp from other device" comparison is
151 * limited by the accuracy of the transformation into system time
152 * base. This depends on the device driver and its underlying
153 * hardware.
154 *
155 * hwtstamps can only be compared against other hwtstamps from
156 * the same device.
157 *
158 * This structure is attached to packets as part of the
159 * &skb_shared_info. Use skb_hwtstamps() to get a pointer.
160 */
161struct skb_shared_hwtstamps {
162 ktime_t hwtstamp;
163 ktime_t syststamp;
164};
165
166/**
167 * skb_shared_tx - instructions for time stamping of outgoing packets
168 *
169 * @hardware: generate hardware time stamp
170 * @software: generate software time stamp
171 * @in_progress: device driver is going to provide
172 * hardware time stamp
173 *
174 * These flags are attached to packets as part of the
175 * &skb_shared_info. Use skb_tx() to get a pointer.
176 */
177union skb_shared_tx {
178 struct {
179 __u8 hardware:1,
180 software:1,
181 in_progress:1;
182 };
183 __u8 flags;
184};
185
135/* This data is invariant across clones and lives at 186/* This data is invariant across clones and lives at
136 * the end of the header data, ie. at skb->end. 187 * the end of the header data, ie. at skb->end.
137 */ 188 */
@@ -143,10 +194,12 @@ struct skb_shared_info {
143 unsigned short gso_segs; 194 unsigned short gso_segs;
144 unsigned short gso_type; 195 unsigned short gso_type;
145 __be32 ip6_frag_id; 196 __be32 ip6_frag_id;
197 union skb_shared_tx tx_flags;
146#ifdef CONFIG_HAS_DMA 198#ifdef CONFIG_HAS_DMA
147 unsigned int num_dma_maps; 199 unsigned int num_dma_maps;
148#endif 200#endif
149 struct sk_buff *frag_list; 201 struct sk_buff *frag_list;
202 struct skb_shared_hwtstamps hwtstamps;
150 skb_frag_t frags[MAX_SKB_FRAGS]; 203 skb_frag_t frags[MAX_SKB_FRAGS];
151#ifdef CONFIG_HAS_DMA 204#ifdef CONFIG_HAS_DMA
152 dma_addr_t dma_maps[MAX_SKB_FRAGS + 1]; 205 dma_addr_t dma_maps[MAX_SKB_FRAGS + 1];
@@ -465,6 +518,16 @@ static inline unsigned char *skb_end_pointer(const struct sk_buff *skb)
465/* Internal */ 518/* Internal */
466#define skb_shinfo(SKB) ((struct skb_shared_info *)(skb_end_pointer(SKB))) 519#define skb_shinfo(SKB) ((struct skb_shared_info *)(skb_end_pointer(SKB)))
467 520
521static inline struct skb_shared_hwtstamps *skb_hwtstamps(struct sk_buff *skb)
522{
523 return &skb_shinfo(skb)->hwtstamps;
524}
525
526static inline union skb_shared_tx *skb_tx(struct sk_buff *skb)
527{
528 return &skb_shinfo(skb)->tx_flags;
529}
530
468/** 531/**
469 * skb_queue_empty - check if a queue is empty 532 * skb_queue_empty - check if a queue is empty
470 * @list: queue head 533 * @list: queue head
@@ -1730,6 +1793,11 @@ static inline void skb_copy_to_linear_data_offset(struct sk_buff *skb,
1730 1793
1731extern void skb_init(void); 1794extern void skb_init(void);
1732 1795
1796static inline ktime_t skb_get_ktime(const struct sk_buff *skb)
1797{
1798 return skb->tstamp;
1799}
1800
1733/** 1801/**
1734 * skb_get_timestamp - get timestamp from a skb 1802 * skb_get_timestamp - get timestamp from a skb
1735 * @skb: skb to get stamp from 1803 * @skb: skb to get stamp from
@@ -1739,11 +1807,18 @@ extern void skb_init(void);
1739 * This function converts the offset back to a struct timeval and stores 1807 * This function converts the offset back to a struct timeval and stores
1740 * it in stamp. 1808 * it in stamp.
1741 */ 1809 */
1742static inline void skb_get_timestamp(const struct sk_buff *skb, struct timeval *stamp) 1810static inline void skb_get_timestamp(const struct sk_buff *skb,
1811 struct timeval *stamp)
1743{ 1812{
1744 *stamp = ktime_to_timeval(skb->tstamp); 1813 *stamp = ktime_to_timeval(skb->tstamp);
1745} 1814}
1746 1815
1816static inline void skb_get_timestampns(const struct sk_buff *skb,
1817 struct timespec *stamp)
1818{
1819 *stamp = ktime_to_timespec(skb->tstamp);
1820}
1821
1747static inline void __net_timestamp(struct sk_buff *skb) 1822static inline void __net_timestamp(struct sk_buff *skb)
1748{ 1823{
1749 skb->tstamp = ktime_get_real(); 1824 skb->tstamp = ktime_get_real();
@@ -1759,6 +1834,20 @@ static inline ktime_t net_invalid_timestamp(void)
1759 return ktime_set(0, 0); 1834 return ktime_set(0, 0);
1760} 1835}
1761 1836
1837/**
1838 * skb_tstamp_tx - queue clone of skb with send time stamps
1839 * @orig_skb: the original outgoing packet
1840 * @hwtstamps: hardware time stamps, may be NULL if not available
1841 *
1842 * If the skb has a socket associated, then this function clones the
1843 * skb (thus sharing the actual data and optional structures), stores
1844 * the optional hardware time stamping information (if non NULL) or
1845 * generates a software time stamp (otherwise), then queues the clone
1846 * to the error queue of the socket. Errors are silently ignored.
1847 */
1848extern void skb_tstamp_tx(struct sk_buff *orig_skb,
1849 struct skb_shared_hwtstamps *hwtstamps);
1850
1762extern __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len); 1851extern __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len);
1763extern __sum16 __skb_checksum_complete(struct sk_buff *skb); 1852extern __sum16 __skb_checksum_complete(struct sk_buff *skb);
1764 1853
diff --git a/net/core/dev.c b/net/core/dev.c
index 1e27a67df242..d20c28e839d3 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1672,10 +1672,21 @@ static int dev_gso_segment(struct sk_buff *skb)
1672 return 0; 1672 return 0;
1673} 1673}
1674 1674
1675static void tstamp_tx(struct sk_buff *skb)
1676{
1677 union skb_shared_tx *shtx =
1678 skb_tx(skb);
1679 if (unlikely(shtx->software &&
1680 !shtx->in_progress)) {
1681 skb_tstamp_tx(skb, NULL);
1682 }
1683}
1684
1675int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, 1685int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
1676 struct netdev_queue *txq) 1686 struct netdev_queue *txq)
1677{ 1687{
1678 const struct net_device_ops *ops = dev->netdev_ops; 1688 const struct net_device_ops *ops = dev->netdev_ops;
1689 int rc;
1679 1690
1680 prefetch(&dev->netdev_ops->ndo_start_xmit); 1691 prefetch(&dev->netdev_ops->ndo_start_xmit);
1681 if (likely(!skb->next)) { 1692 if (likely(!skb->next)) {
@@ -1689,13 +1700,29 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
1689 goto gso; 1700 goto gso;
1690 } 1701 }
1691 1702
1692 return ops->ndo_start_xmit(skb, dev); 1703 rc = ops->ndo_start_xmit(skb, dev);
1704 /*
1705 * TODO: if skb_orphan() was called by
1706 * dev->hard_start_xmit() (for example, the unmodified
1707 * igb driver does that; bnx2 doesn't), then
1708 * skb_tx_software_timestamp() will be unable to send
1709 * back the time stamp.
1710 *
1711 * How can this be prevented? Always create another
1712 * reference to the socket before calling
1713 * dev->hard_start_xmit()? Prevent that skb_orphan()
1714 * does anything in dev->hard_start_xmit() by clearing
1715 * the skb destructor before the call and restoring it
1716 * afterwards, then doing the skb_orphan() ourselves?
1717 */
1718 if (likely(!rc))
1719 tstamp_tx(skb);
1720 return rc;
1693 } 1721 }
1694 1722
1695gso: 1723gso:
1696 do { 1724 do {
1697 struct sk_buff *nskb = skb->next; 1725 struct sk_buff *nskb = skb->next;
1698 int rc;
1699 1726
1700 skb->next = nskb->next; 1727 skb->next = nskb->next;
1701 nskb->next = NULL; 1728 nskb->next = NULL;
@@ -1705,6 +1732,7 @@ gso:
1705 skb->next = nskb; 1732 skb->next = nskb;
1706 return rc; 1733 return rc;
1707 } 1734 }
1735 tstamp_tx(skb);
1708 if (unlikely(netif_tx_queue_stopped(txq) && skb->next)) 1736 if (unlikely(netif_tx_queue_stopped(txq) && skb->next))
1709 return NETDEV_TX_BUSY; 1737 return NETDEV_TX_BUSY;
1710 } while (skb->next); 1738 } while (skb->next);
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}
2946EXPORT_SYMBOL_GPL(skb_cow_data); 2949EXPORT_SYMBOL_GPL(skb_cow_data);
2947 2950
2951void 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}
2986EXPORT_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