tcpdump mailing list archives

Re: Portable way to "block" on pcap_next_ex()


From: Guy Harris <guy () alum mit edu>
Date: Sun, 15 Jan 2012 14:28:03 -0800


On Jan 15, 2012, at 9:36 AM, Fernando Gont wrote:

I'd like a call to pcap_next_ex() to block, waiting for a single packet,
with no timeout.

So far, the only portable way to do it I've found is to select() on the
underlying descriptor.

The reason is that if I pcap_open_live() with a "to_ms" of 0, in some
systems pcap_next_ex() will remain blocked even if a packet is received
(i.e., it will wait for *many* packets).

At least on systems with BPF, it'll block until the BPF buffer fills up, so it could wait indefinitely.

On the other hand, if I use a
non-zero "to_ms" in pcap_open_live(), that will mean that my app will be
awaken every "to_ms" milliseconds, because of the timeout

"May be awakened", not "will be awakened"; on Solaris, at least when using DLPI, the timer for the timeout is started 
when the first packet arrives, not when the read is done:

        http://docs.oracle.com/cd/E23824_01/html/821-1475/bufmod-7m.html

"To ensure that messages do not languish forever in an accumulating chunk, bufmod maintains a read timeout. Whenever 
this timeout expires, the module closes off the current chunk and passes it upward. The module restarts the timeout 
period when it receives a read side data message and a timeout is not currently active. These two rules insure that 
bufmod minimizes the number of chunks it produces during periods of intense message activity and that it periodically 
disposes of all messages during slack intervals, but avoids any timeout overhead when there is no activity."

Solaris 11 also implements BPF:

        http://docs.oracle.com/cd/E23824_01/html/821-1475/bpf-7d.html

and its timer works the way other BPF timers work - it starts when the read is done.

On Linux, either the memory-mapped mechanism isn't being used, in which case each recvfrom() returns a single packet, 
with no timeout, or it is being used, in which case the timeout is done with an internal poll() call (if the pcap_t 
isn't in non-blocking mode), so you have a timeout that expires even if no packet has arrived.  I haven't looked at 
TPACKET_V3 in detail, but I suspect, from something I read, that it has a BPF-like timeout, i.e. the timer can expire 
if no packets are available.

No BPF-based platform offers an API to allow libpcap to choose how the timer works.

(which is undesirable).

Is that "undesirable" as in "I have to be able to handle pcap_next_ex() not returning a packet" (which may be annoying 
but can be dealt with) or "undesirable" as in "causes significant performance problems"?

Any other way of doing the same without relying on select()?

No portable way.  Some systems (those with BPF) start the timer when you do a read(), so the timer goes off even if no 
packets have arrived.  Solaris's bufmod starts the timer when the first packet arrives.

BPF offers BIOCIMMEDIATE mode, which means that packets are *not* buffered (i.e., each read() returns a single packet) 
and there's no timeout.  The bufmod equivalent would be to set the read timeout to 0.  There's currently no API in 
libpcap to request that, so turning it on would currently have to be done in a platform-dependent fashion.-
This is the tcpdump-workers list.
Visit https://cod.sandelman.ca/ to unsubscribe.


Current thread: