tcpdump mailing list archives

Re: linux pcap blocking and cpu utilization


From: Guy Harris <guy () alum mit edu>
Date: Mon, 28 Jun 2004 18:20:25 -0700


On Jun 28, 2004, at 12:10 PM, four wrote:

Here is the situation: I am trying to build a simple bridging program.
If I  use pcap_set_nonblock() the function call returns fine, but the
program ends up using 100% cpu utilization, presumably because it is
simply looping  and returning with no packets caught. So the other way
is to just have the call wait for a certain packet count.

No, the other way is to have *a* call wait until packets arrive.

On most UN*X platforms, the calls that can be used to do that are named "select()" and "poll()".

In libpcap 0.8 and later, the "pcap_get_selectable_fd()" call will return a descriptor on which you can do a "select()" or "poll()" - unless, on the platform on which you're running, you *can't* do a "select()" or "poll()" to wait for packets to arrive, in which case it returns -1.

The cases where it returns -1 are:

1) FreeBSD 4.3 and 4.4, where the workaround for the fact that "select()" and "poll()" don't work correctly on BPF devices doesn't work, either;

2) Linux and BSD, when capturing on a DAG card from Endace, because the drivers for DAG cards unfortunately don't support "select()" or "poll()".

If you're capturing on regular interfaces, "select()" and "poll()" should work just fine on the PF_PACKET sockets used for normal capturing.

Prior to libpcap 0.8, there is no "pcap_get_selectable_fd()" call - but, if you're not going to run on BSD or capture on DAG cards, you can just use "pcap_fileno()". (Ideally, you should, if you want to ensure portability, use autoconf to test whether "pcap_get_selectable_fd()" exists and, if it doesn't supply a substitute version that returns -1 on FreeBSD 4.3 and 4.4 and the result of "pcap_fileno()" otherwise, and use "pcap_get_selectable_fd()" in your program.)

But this doesn't work either because if no packets are coming one way down the
wire, but we have recieved some in the other direction, the (singly
threaded) program will block on the one direction. So I want to make a
simple program that listens and forwards on two interfaces... what is
the proper way to implement this on linux so that it doesn't use all
the CPU and doesn't require multiple threads?

Open both interfaces, use "pcap_get_selectable_fd()" (or "pcap_fileno()" if "pcap_get_selectable_fd()" isn't available, as per the above), and, in the main loop, "select()" or "poll()" on both FDs and process input if the "select()" or "poll()" call says it's readable.

(If the program is to run on BSD, put both pcap_t's into non-blocking mode, supply the timeout used in the "pcap_open_live()" call as the timeout for "select()" or "poll()", and read from the descriptor regardless of whether it's marked as readable or not; that's the workaround for "select()" and "poll()" not working correctly on BPF devices. As noted, that workaround probably doesn't work on FreeBSD 4.3 and 4.4, but it works on earlier releases, and "select()" and "poll()" should, I think, work correctly on BPF devices in 4.5 or later. On other BSDs, I think that, depending on the BSD and the release, either the workaround will work or won't be necessary - meaning that "select()" and "poll()" will work correctly, even if you *do* use the workaround - or both.)

-
This is the tcpdump-workers list.
Visit https://lists.sandelman.ca/ to unsubscribe.


Current thread: