aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/dev.c
diff options
context:
space:
mode:
authorPatrick Ohly <patrick.ohly@intel.com>2009-02-12 00:03:37 -0500
committerDavid S. Miller <davem@davemloft.net>2009-02-16 01:43:34 -0500
commitac45f602ee3d1b6f326f68bc0c2591ceebf05ba4 (patch)
treec92c86bd0d89b844a3794c0e441aa2fccb36725f /net/core/dev.c
parentcb9eff097831007afb30d64373f29d99825d0068 (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/dev.c')
-rw-r--r--net/core/dev.c32
1 files changed, 30 insertions, 2 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 1e27a67df24..d20c28e839d 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);