diff options
author | Guy Harris <guy@alum.mit.edu> | 2013-12-10 15:59:16 -0800 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2013-12-10 15:59:16 -0800 |
commit | ee4085152260466ea845d9e9109a251a39ded93b (patch) | |
tree | 517d3481765d7fa76fc279fb19b07345df7f54b3 /pcap-linux.c | |
parent | 7eb0a94dd54e77c6fb885654418287f3aa6f3ce0 (diff) |
Work around a TPACKET_V3 issue with a timeout of 0.
See https://github.com/the-tcpdump-group/libpcap/issues/335 for details.
Diffstat (limited to 'pcap-linux.c')
-rw-r--r-- | pcap-linux.c | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/pcap-linux.c b/pcap-linux.c index 7c077931..764ad012 100644 --- a/pcap-linux.c +++ b/pcap-linux.c @@ -4073,9 +4073,29 @@ static int pcap_wait_for_frames_mmap(pcap_t *handle) pollinfo.fd = handle->fd; pollinfo.events = POLLIN; - if (handlep->timeout == 0) - timeout = -1; /* block forever */ - else if (handlep->timeout > 0) + if (handlep->timeout == 0) { + /* + * XXX - due to a set of (mis)features in the + * TPACKET_V3 kernel code, blocking forever with + * a TPACKET_V3 socket can, if few packets + * are arriving and passing the socket filter, + * cause most packets to be dropped. See + * libpcap issue #335 for the full painful + * story. The workaround is to have poll() + * time out very quickly, so we grab the + * frames handed to us, and return them to + * the kernel, ASAP. + * + * If those issues are ever fixed, we might + * want to check the kernel version and block + * forever with TPACKET_V3 if we're running + * with a kernel that has the fix. + */ + if (handlep->tp_version == TPACKET_V3) + timeout = 1; /* don't block for very long */ + else + timeout = -1; /* block forever */ + } else if (handlep->timeout > 0) timeout = handlep->timeout; /* block for that amount of time */ else timeout = 0; /* non-blocking mode - poll to pick up errors */ |