summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMario J. Rugiero <mrugiero@gmail.com>2020-02-16 20:47:40 -0300
committerMario Rugiero <mario.rugiero@wildlifestudios.com>2020-06-15 20:44:21 -0300
commita1119a18874410d4d51a61d2e582d25b7c578a54 (patch)
tree622aa4874b0e49d903f8dd1fc4fbb8d45d17fb77
parent0b5dba664659779c2533bffa1355ff964af10853 (diff)
downloadlibpcap-test-rc.tar.gz
Linux: proper memory sync for PACKET_MMAP.test-rc
Release and acquire packets using GCC builtins (compatible with many other common-place compilers). Should fix #898.
-rw-r--r--pcap-linux.c27
1 files changed, 18 insertions, 9 deletions
diff --git a/pcap-linux.c b/pcap-linux.c
index 546d0369..3ba8f710 100644
--- a/pcap-linux.c
+++ b/pcap-linux.c
@@ -117,6 +117,15 @@
# define HAVE_TPACKET3
#endif /* TPACKET3_HDRLEN */
+#define packet_mmap_acquire(pkt) \
+ (__atomic_load_n(&pkt->tp_status, __ATOMIC_ACQUIRE) != TP_STATUS_KERNEL)
+#define packet_mmap_release(pkt) \
+ (__atomic_store_n(&pkt->tp_status, TP_STATUS_KERNEL, __ATOMIC_RELEASE))
+#define packet_mmap_v3_acquire(pkt) \
+ (__atomic_load_n(&pkt->hdr.bh1.block_status, __ATOMIC_ACQUIRE) != TP_STATUS_KERNEL)
+#define packet_mmap_v3_release(pkt) \
+ (__atomic_store_n(&pkt->hdr.bh1.block_status, TP_STATUS_KERNEL, __ATOMIC_RELEASE))
+
#include <linux/types.h>
#include <linux/filter.h>
@@ -3680,11 +3689,11 @@ pcap_get_ring_frame_status(pcap_t *handle, int offset)
h.raw = RING_GET_FRAME_AT(handle, offset);
switch (handlep->tp_version) {
case TPACKET_V2:
- return (h.h2->tp_status);
+ return __atomic_load_n(&h.h2->tp_status, __ATOMIC_ACQUIRE);
break;
#ifdef HAVE_TPACKET3
case TPACKET_V3:
- return (h.h3->hdr.bh1.block_status);
+ return __atomic_load_n(&h.h3->hdr.bh1.block_status, __ATOMIC_ACQUIRE);
break;
#endif
}
@@ -4264,7 +4273,7 @@ pcap_read_linux_mmap_v2(pcap_t *handle, int max_packets, pcap_handler callback,
/* wait for frames availability.*/
h.raw = RING_GET_CURRENT_FRAME(handle);
- if (h.h2->tp_status == TP_STATUS_KERNEL) {
+ if (!packet_mmap_acquire(h.h2)) {
/*
* The current frame is owned by the kernel; wait for
* a frame to be handed to us.
@@ -4283,7 +4292,7 @@ pcap_read_linux_mmap_v2(pcap_t *handle, int max_packets, pcap_handler callback,
* it's still owned by the kernel.
*/
h.raw = RING_GET_CURRENT_FRAME(handle);
- if (h.h2->tp_status == TP_STATUS_KERNEL)
+ if (!packet_mmap_acquire(h.h2))
break;
ret = pcap_handle_packet_mmap(
@@ -4311,7 +4320,7 @@ pcap_read_linux_mmap_v2(pcap_t *handle, int max_packets, pcap_handler callback,
* after having been filtered by the kernel, count
* the one we've just processed.
*/
- h.h2->tp_status = TP_STATUS_KERNEL;
+ packet_mmap_release(h.h2);
if (handlep->blocks_to_filter_in_userland > 0) {
handlep->blocks_to_filter_in_userland--;
if (handlep->blocks_to_filter_in_userland == 0) {
@@ -4350,7 +4359,7 @@ again:
if (handlep->current_packet == NULL) {
/* wait for frames availability.*/
h.raw = RING_GET_CURRENT_FRAME(handle);
- if (h.h3->hdr.bh1.block_status == TP_STATUS_KERNEL) {
+ if (!packet_mmap_v3_acquire(h.h3)) {
/*
* The current frame is owned by the kernel; wait
* for a frame to be handed to us.
@@ -4362,7 +4371,7 @@ again:
}
}
h.raw = RING_GET_CURRENT_FRAME(handle);
- if (h.h3->hdr.bh1.block_status == TP_STATUS_KERNEL) {
+ if (!packet_mmap_v3_acquire(h.h3)) {
if (pkts == 0 && handlep->timeout == 0) {
/* Block until we see a packet. */
goto again;
@@ -4377,7 +4386,7 @@ again:
if (handlep->current_packet == NULL) {
h.raw = RING_GET_CURRENT_FRAME(handle);
- if (h.h3->hdr.bh1.block_status == TP_STATUS_KERNEL)
+ if (!packet_mmap_v3_acquire(h.h3))
break;
handlep->current_packet = h.raw + h.h3->hdr.bh1.offset_to_first_pkt;
@@ -4429,7 +4438,7 @@ again:
* filtered by the kernel, count the one we've
* just processed.
*/
- h.h3->hdr.bh1.block_status = TP_STATUS_KERNEL;
+ packet_mmap_v3_release(h.h3);
if (handlep->blocks_to_filter_in_userland > 0) {
handlep->blocks_to_filter_in_userland--;
if (handlep->blocks_to_filter_in_userland == 0) {