aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-04-25 01:22:53 -0400
committerDavid S. Miller <davem@davemloft.net>2013-04-25 01:22:53 -0400
commit660f7d22298ceb82facd2088c197f2de5cbfb7d6 (patch)
tree2413117b5a07e3632a392e4f03a76ebb37e9c157 /net
parent92dea7c06656f709a3957aacef20574ce3dbe6fc (diff)
parent2940b26bec9fe5bf183c994678e62b55d35717e6 (diff)
Merge branch 'af_packet-timestamp'
Daniel Borkmann says: ==================== This is a joint effort with Willem to bring optional i) tx hw/sw timestamping into PF_PACKET, that was reported by Paul Chavent, and ii) to expose the type of timestamp to the user, which is in the current situation not possible to distinguish with the RX_RING and TX_RING API (but distinguishable through the normal timestamping API), reported by Richard Cochran. This set is based on top of ``packet: account statistics only in tpacket_stats_u''. Related discussion can be found in: http://patchwork.ozlabs.org/patch/238125/ ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/skbuff.c12
-rw-r--r--net/packet/af_packet.c87
2 files changed, 71 insertions, 28 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 898cf5c566f9..af9185d0be6a 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -3327,12 +3327,8 @@ void skb_tstamp_tx(struct sk_buff *orig_skb,
3327 if (!sk) 3327 if (!sk)
3328 return; 3328 return;
3329 3329
3330 skb = skb_clone(orig_skb, GFP_ATOMIC);
3331 if (!skb)
3332 return;
3333
3334 if (hwtstamps) { 3330 if (hwtstamps) {
3335 *skb_hwtstamps(skb) = 3331 *skb_hwtstamps(orig_skb) =
3336 *hwtstamps; 3332 *hwtstamps;
3337 } else { 3333 } else {
3338 /* 3334 /*
@@ -3340,9 +3336,13 @@ void skb_tstamp_tx(struct sk_buff *orig_skb,
3340 * so keep the shared tx_flags and only 3336 * so keep the shared tx_flags and only
3341 * store software time stamp 3337 * store software time stamp
3342 */ 3338 */
3343 skb->tstamp = ktime_get_real(); 3339 orig_skb->tstamp = ktime_get_real();
3344 } 3340 }
3345 3341
3342 skb = skb_clone(orig_skb, GFP_ATOMIC);
3343 if (!skb)
3344 return;
3345
3346 serr = SKB_EXT_ERR(skb); 3346 serr = SKB_EXT_ERR(skb);
3347 memset(serr, 0, sizeof(*serr)); 3347 memset(serr, 0, sizeof(*serr));
3348 serr->ee.ee_errno = ENOMSG; 3348 serr->ee.ee_errno = ENOMSG;
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 7e387ff64465..ba8309a3e01b 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -339,6 +339,59 @@ static int __packet_get_status(struct packet_sock *po, void *frame)
339 } 339 }
340} 340}
341 341
342static __u32 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 TP_STATUS_TS_SYS_HARDWARE;
351 if ((flags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
352 ktime_to_timespec_cond(shhwtstamps->hwtstamp, ts))
353 return TP_STATUS_TS_RAW_HARDWARE;
354 }
355
356 if (ktime_to_timespec_cond(skb->tstamp, ts))
357 return TP_STATUS_TS_SOFTWARE;
358
359 return 0;
360}
361
362static __u32 __packet_set_timestamp(struct packet_sock *po, void *frame,
363 struct sk_buff *skb)
364{
365 union tpacket_uhdr h;
366 struct timespec ts;
367 __u32 ts_status;
368
369 if (!(ts_status = tpacket_get_timestamp(skb, &ts, po->tp_tstamp)))
370 return 0;
371
372 h.raw = frame;
373 switch (po->tp_version) {
374 case TPACKET_V1:
375 h.h1->tp_sec = ts.tv_sec;
376 h.h1->tp_usec = ts.tv_nsec / NSEC_PER_USEC;
377 break;
378 case TPACKET_V2:
379 h.h2->tp_sec = ts.tv_sec;
380 h.h2->tp_nsec = ts.tv_nsec;
381 break;
382 case TPACKET_V3:
383 default:
384 WARN(1, "TPACKET version not supported.\n");
385 BUG();
386 }
387
388 /* one flush is safe, as both fields always lie on the same cacheline */
389 flush_dcache_page(pgv_to_page(&h.h1->tp_sec));
390 smp_wmb();
391
392 return ts_status;
393}
394
342static void *packet_lookup_frame(struct packet_sock *po, 395static void *packet_lookup_frame(struct packet_sock *po,
343 struct packet_ring_buffer *rb, 396 struct packet_ring_buffer *rb,
344 unsigned int position, 397 unsigned int position,
@@ -1657,26 +1710,6 @@ drop:
1657 return 0; 1710 return 0;
1658} 1711}
1659 1712
1660static void tpacket_get_timestamp(struct sk_buff *skb, struct timespec *ts,
1661 unsigned int flags)
1662{
1663 struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
1664
1665 if (shhwtstamps) {
1666 if ((flags & SOF_TIMESTAMPING_SYS_HARDWARE) &&
1667 ktime_to_timespec_cond(shhwtstamps->syststamp, ts))
1668 return;
1669 if ((flags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
1670 ktime_to_timespec_cond(shhwtstamps->hwtstamp, ts))
1671 return;
1672 }
1673
1674 if (ktime_to_timespec_cond(skb->tstamp, ts))
1675 return;
1676
1677 getnstimeofday(ts);
1678}
1679
1680static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, 1713static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
1681 struct packet_type *pt, struct net_device *orig_dev) 1714 struct packet_type *pt, struct net_device *orig_dev)
1682{ 1715{
@@ -1691,6 +1724,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
1691 unsigned short macoff, netoff, hdrlen; 1724 unsigned short macoff, netoff, hdrlen;
1692 struct sk_buff *copy_skb = NULL; 1725 struct sk_buff *copy_skb = NULL;
1693 struct timespec ts; 1726 struct timespec ts;
1727 __u32 ts_status;
1694 1728
1695 if (skb->pkt_type == PACKET_LOOPBACK) 1729 if (skb->pkt_type == PACKET_LOOPBACK)
1696 goto drop; 1730 goto drop;
@@ -1773,7 +1807,11 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
1773 spin_unlock(&sk->sk_receive_queue.lock); 1807 spin_unlock(&sk->sk_receive_queue.lock);
1774 1808
1775 skb_copy_bits(skb, 0, h.raw + macoff, snaplen); 1809 skb_copy_bits(skb, 0, h.raw + macoff, snaplen);
1776 tpacket_get_timestamp(skb, &ts, po->tp_tstamp); 1810
1811 if (!(ts_status = tpacket_get_timestamp(skb, &ts, po->tp_tstamp)))
1812 getnstimeofday(&ts);
1813
1814 status |= ts_status;
1777 1815
1778 switch (po->tp_version) { 1816 switch (po->tp_version) {
1779 case TPACKET_V1: 1817 case TPACKET_V1:
@@ -1874,10 +1912,14 @@ static void tpacket_destruct_skb(struct sk_buff *skb)
1874 void *ph; 1912 void *ph;
1875 1913
1876 if (likely(po->tx_ring.pg_vec)) { 1914 if (likely(po->tx_ring.pg_vec)) {
1915 __u32 ts;
1916
1877 ph = skb_shinfo(skb)->destructor_arg; 1917 ph = skb_shinfo(skb)->destructor_arg;
1878 BUG_ON(atomic_read(&po->tx_ring.pending) == 0); 1918 BUG_ON(atomic_read(&po->tx_ring.pending) == 0);
1879 atomic_dec(&po->tx_ring.pending); 1919 atomic_dec(&po->tx_ring.pending);
1880 __packet_set_status(po, ph, TP_STATUS_AVAILABLE); 1920
1921 ts = __packet_set_timestamp(po, ph, skb);
1922 __packet_set_status(po, ph, TP_STATUS_AVAILABLE | ts);
1881 } 1923 }
1882 1924
1883 sock_wfree(skb); 1925 sock_wfree(skb);
@@ -1900,6 +1942,7 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
1900 skb->dev = dev; 1942 skb->dev = dev;
1901 skb->priority = po->sk.sk_priority; 1943 skb->priority = po->sk.sk_priority;
1902 skb->mark = po->sk.sk_mark; 1944 skb->mark = po->sk.sk_mark;
1945 sock_tx_timestamp(&po->sk, &skb_shinfo(skb)->tx_flags);
1903 skb_shinfo(skb)->destructor_arg = ph.raw; 1946 skb_shinfo(skb)->destructor_arg = ph.raw;
1904 1947
1905 switch (po->tp_version) { 1948 switch (po->tp_version) {