aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/uapi/linux/if_packet.h5
-rw-r--r--net/packet/af_packet.c36
2 files changed, 28 insertions, 13 deletions
diff --git a/include/uapi/linux/if_packet.h b/include/uapi/linux/if_packet.h
index 4dfc234d80e5..b950c02030c0 100644
--- a/include/uapi/linux/if_packet.h
+++ b/include/uapi/linux/if_packet.h
@@ -100,6 +100,11 @@ struct tpacket_auxdata {
100#define TP_STATUS_SENDING (1 << 1) 100#define TP_STATUS_SENDING (1 << 1)
101#define TP_STATUS_WRONG_FORMAT (1 << 2) 101#define TP_STATUS_WRONG_FORMAT (1 << 2)
102 102
103/* Rx and Tx ring - header status */
104#define TP_STATUS_TS_SOFTWARE (1 << 29)
105#define TP_STATUS_TS_SYS_HARDWARE (1 << 30)
106#define TP_STATUS_TS_RAW_HARDWARE (1 << 31)
107
103/* Rx ring - feature request bits */ 108/* Rx ring - feature request bits */
104#define TP_FT_REQ_FILL_RXHASH 0x1 109#define TP_FT_REQ_FILL_RXHASH 0x1
105 110
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 9d46a07a15c0..ba8309a3e01b 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -339,34 +339,35 @@ 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, 342static __u32 tpacket_get_timestamp(struct sk_buff *skb, struct timespec *ts,
343 unsigned int flags) 343 unsigned int flags)
344{ 344{
345 struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb); 345 struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
346 346
347 if (shhwtstamps) { 347 if (shhwtstamps) {
348 if ((flags & SOF_TIMESTAMPING_SYS_HARDWARE) && 348 if ((flags & SOF_TIMESTAMPING_SYS_HARDWARE) &&
349 ktime_to_timespec_cond(shhwtstamps->syststamp, ts)) 349 ktime_to_timespec_cond(shhwtstamps->syststamp, ts))
350 return true; 350 return TP_STATUS_TS_SYS_HARDWARE;
351 if ((flags & SOF_TIMESTAMPING_RAW_HARDWARE) && 351 if ((flags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
352 ktime_to_timespec_cond(shhwtstamps->hwtstamp, ts)) 352 ktime_to_timespec_cond(shhwtstamps->hwtstamp, ts))
353 return true; 353 return TP_STATUS_TS_RAW_HARDWARE;
354 } 354 }
355 355
356 if (ktime_to_timespec_cond(skb->tstamp, ts)) 356 if (ktime_to_timespec_cond(skb->tstamp, ts))
357 return true; 357 return TP_STATUS_TS_SOFTWARE;
358 358
359 return false; 359 return 0;
360} 360}
361 361
362static void __packet_set_timestamp(struct packet_sock *po, void *frame, 362static __u32 __packet_set_timestamp(struct packet_sock *po, void *frame,
363 struct sk_buff *skb) 363 struct sk_buff *skb)
364{ 364{
365 union tpacket_uhdr h; 365 union tpacket_uhdr h;
366 struct timespec ts; 366 struct timespec ts;
367 __u32 ts_status;
367 368
368 if (!tpacket_get_timestamp(skb, &ts, po->tp_tstamp)) 369 if (!(ts_status = tpacket_get_timestamp(skb, &ts, po->tp_tstamp)))
369 return; 370 return 0;
370 371
371 h.raw = frame; 372 h.raw = frame;
372 switch (po->tp_version) { 373 switch (po->tp_version) {
@@ -387,6 +388,8 @@ static void __packet_set_timestamp(struct packet_sock *po, void *frame,
387 /* one flush is safe, as both fields always lie on the same cacheline */ 388 /* one flush is safe, as both fields always lie on the same cacheline */
388 flush_dcache_page(pgv_to_page(&h.h1->tp_sec)); 389 flush_dcache_page(pgv_to_page(&h.h1->tp_sec));
389 smp_wmb(); 390 smp_wmb();
391
392 return ts_status;
390} 393}
391 394
392static void *packet_lookup_frame(struct packet_sock *po, 395static void *packet_lookup_frame(struct packet_sock *po,
@@ -1721,6 +1724,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
1721 unsigned short macoff, netoff, hdrlen; 1724 unsigned short macoff, netoff, hdrlen;
1722 struct sk_buff *copy_skb = NULL; 1725 struct sk_buff *copy_skb = NULL;
1723 struct timespec ts; 1726 struct timespec ts;
1727 __u32 ts_status;
1724 1728
1725 if (skb->pkt_type == PACKET_LOOPBACK) 1729 if (skb->pkt_type == PACKET_LOOPBACK)
1726 goto drop; 1730 goto drop;
@@ -1803,9 +1807,12 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
1803 spin_unlock(&sk->sk_receive_queue.lock); 1807 spin_unlock(&sk->sk_receive_queue.lock);
1804 1808
1805 skb_copy_bits(skb, 0, h.raw + macoff, snaplen); 1809 skb_copy_bits(skb, 0, h.raw + macoff, snaplen);
1806 if (!tpacket_get_timestamp(skb, &ts, po->tp_tstamp)) 1810
1811 if (!(ts_status = tpacket_get_timestamp(skb, &ts, po->tp_tstamp)))
1807 getnstimeofday(&ts); 1812 getnstimeofday(&ts);
1808 1813
1814 status |= ts_status;
1815
1809 switch (po->tp_version) { 1816 switch (po->tp_version) {
1810 case TPACKET_V1: 1817 case TPACKET_V1:
1811 h.h1->tp_len = skb->len; 1818 h.h1->tp_len = skb->len;
@@ -1905,11 +1912,14 @@ static void tpacket_destruct_skb(struct sk_buff *skb)
1905 void *ph; 1912 void *ph;
1906 1913
1907 if (likely(po->tx_ring.pg_vec)) { 1914 if (likely(po->tx_ring.pg_vec)) {
1915 __u32 ts;
1916
1908 ph = skb_shinfo(skb)->destructor_arg; 1917 ph = skb_shinfo(skb)->destructor_arg;
1909 BUG_ON(atomic_read(&po->tx_ring.pending) == 0); 1918 BUG_ON(atomic_read(&po->tx_ring.pending) == 0);
1910 atomic_dec(&po->tx_ring.pending); 1919 atomic_dec(&po->tx_ring.pending);
1911 __packet_set_timestamp(po, ph, skb); 1920
1912 __packet_set_status(po, ph, TP_STATUS_AVAILABLE); 1921 ts = __packet_set_timestamp(po, ph, skb);
1922 __packet_set_status(po, ph, TP_STATUS_AVAILABLE | ts);
1913 } 1923 }
1914 1924
1915 sock_wfree(skb); 1925 sock_wfree(skb);