diff options
-rw-r--r-- | include/uapi/linux/if_packet.h | 5 | ||||
-rw-r--r-- | net/packet/af_packet.c | 36 |
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 | ||
342 | static bool tpacket_get_timestamp(struct sk_buff *skb, struct timespec *ts, | 342 | static __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 | ||
362 | static void __packet_set_timestamp(struct packet_sock *po, void *frame, | 362 | static __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 | ||
392 | static void *packet_lookup_frame(struct packet_sock *po, | 395 | static 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); |