aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Borkmann <dborkman@redhat.com>2013-04-22 20:39:29 -0400
committerDavid S. Miller <davem@davemloft.net>2013-04-25 01:22:22 -0400
commit7a51384cc9f4145de352d266821b63f1bb0d46ff (patch)
treedf7b1de730a738dd537fba17b6e17aec509d812e
parent2e31396fa14be50a98c5d2b00416ebd74d381c1f (diff)
packet: enable hardware tx timestamping on tpacket ring
Currently, we only have software timestamping for the TX ring buffer path, but this limitation stems rather from the implementation. By just reusing tpacket_get_timestamp(), we can also allow hardware timestamping just as in the RX path. Signed-off-by: Daniel Borkmann <dborkman@redhat.com> Acked-by: Willem de Bruijn <willemb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/packet/af_packet.c50
1 files changed, 25 insertions, 25 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index ec8ea27733ac..9d46a07a15c0 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -339,14 +339,33 @@ static int __packet_get_status(struct packet_sock *po, void *frame)
339 } 339 }
340} 340}
341 341
342static bool tpacket_get_timestamp(struct sk_buff *skb, struct timespec *ts,
343 unsigned int flags)
344{
345 struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
346
347 if (shhwtstamps) {
348 if ((flags & SOF_TIMESTAMPING_SYS_HARDWARE) &&
349 ktime_to_timespec_cond(shhwtstamps->syststamp, ts))
350 return true;
351 if ((flags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
352 ktime_to_timespec_cond(shhwtstamps->hwtstamp, ts))
353 return true;
354 }
355
356 if (ktime_to_timespec_cond(skb->tstamp, ts))
357 return true;
358
359 return false;
360}
361
342static void __packet_set_timestamp(struct packet_sock *po, void *frame, 362static void __packet_set_timestamp(struct packet_sock *po, void *frame,
343 ktime_t tstamp) 363 struct sk_buff *skb)
344{ 364{
345 union tpacket_uhdr h; 365 union tpacket_uhdr h;
346 struct timespec ts; 366 struct timespec ts;
347 367
348 if (!ktime_to_timespec_cond(tstamp, &ts) || 368 if (!tpacket_get_timestamp(skb, &ts, po->tp_tstamp))
349 !sock_flag(&po->sk, SOCK_TIMESTAMPING_SOFTWARE))
350 return; 369 return;
351 370
352 h.raw = frame; 371 h.raw = frame;
@@ -1688,26 +1707,6 @@ drop:
1688 return 0; 1707 return 0;
1689} 1708}
1690 1709
1691static void tpacket_get_timestamp(struct sk_buff *skb, struct timespec *ts,
1692 unsigned int flags)
1693{
1694 struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
1695
1696 if (shhwtstamps) {
1697 if ((flags & SOF_TIMESTAMPING_SYS_HARDWARE) &&
1698 ktime_to_timespec_cond(shhwtstamps->syststamp, ts))
1699 return;
1700 if ((flags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
1701 ktime_to_timespec_cond(shhwtstamps->hwtstamp, ts))
1702 return;
1703 }
1704
1705 if (ktime_to_timespec_cond(skb->tstamp, ts))
1706 return;
1707
1708 getnstimeofday(ts);
1709}
1710
1711static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, 1710static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
1712 struct packet_type *pt, struct net_device *orig_dev) 1711 struct packet_type *pt, struct net_device *orig_dev)
1713{ 1712{
@@ -1804,7 +1803,8 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
1804 spin_unlock(&sk->sk_receive_queue.lock); 1803 spin_unlock(&sk->sk_receive_queue.lock);
1805 1804
1806 skb_copy_bits(skb, 0, h.raw + macoff, snaplen); 1805 skb_copy_bits(skb, 0, h.raw + macoff, snaplen);
1807 tpacket_get_timestamp(skb, &ts, po->tp_tstamp); 1806 if (!tpacket_get_timestamp(skb, &ts, po->tp_tstamp))
1807 getnstimeofday(&ts);
1808 1808
1809 switch (po->tp_version) { 1809 switch (po->tp_version) {
1810 case TPACKET_V1: 1810 case TPACKET_V1:
@@ -1908,7 +1908,7 @@ static void tpacket_destruct_skb(struct sk_buff *skb)
1908 ph = skb_shinfo(skb)->destructor_arg; 1908 ph = skb_shinfo(skb)->destructor_arg;
1909 BUG_ON(atomic_read(&po->tx_ring.pending) == 0); 1909 BUG_ON(atomic_read(&po->tx_ring.pending) == 0);
1910 atomic_dec(&po->tx_ring.pending); 1910 atomic_dec(&po->tx_ring.pending);
1911 __packet_set_timestamp(po, ph, skb->tstamp); 1911 __packet_set_timestamp(po, ph, skb);
1912 __packet_set_status(po, ph, TP_STATUS_AVAILABLE); 1912 __packet_set_status(po, ph, TP_STATUS_AVAILABLE);
1913 } 1913 }
1914 1914