0

I'm programming for a network program using libevent.

In this program, I want to capture packets using libpcap, modify these packets and then sends them out. These steps should be in real time.

So I create a live capture, use pcap_get_selectable_fd to get a file descriptor pcap_fd for the live capture and add a READ_EV event for pcap_fd to a libevent loop. Anyway, it is like select() or epoll() polling the file descriptor.

But I notice the program doesn't work as expected, so I use tcpdump and some debugging logs to check the problem. I notice that sometimes, the polling on pcap_fd is not working correctly, for example, at the begining, it seems to work fine. Some time later, the READ_EV event for pcap_fd is triggered 2 seconds later, which is really a big delay.

I read the mannual, it says:

   pcap_get_selectable_fd(3) will return a file descriptor. But simple select() 
   or poll() will not indicate that the  descriptor  is  readable
   until  a  full  buffer's worth of packets is received, even if the read
   timeout expires before then.  

It seems to me that the live capture has captured around 15 packets (each of which is 66 bytes), but the READ_EV event is not triggered until 2 seconds later. But at the very beginning, even 1 packet arrival can trigger a READ_EV event. This means it is very unstable.

   To work around this, an application  that
   uses  select()  or  poll()  to  wait for packets to arrive must put the
   pcap_t in non-blocking mode, and must  arrange  that  the  select()  or
   poll()  have a timeout less than or equal to the read timeout, and must
   try to read packets after that timeout expires, regardless  of  whether
   select() or poll() indicated that the file descriptor for the pcap_t is
   ready to be read or not.

My question is for the paragraph above:

1 it seems to me that there are 2 timeouts, a read timeout and a timeout defined by myself, so what is the read timeout?

2 it seems to me that I need to set a very small timeout and poll the live capture using pcap_next() or pcap_dispatch, is it right? then my polling could be very CPU consuming?

thanks!

misteryes
  • 2,167
  • 4
  • 32
  • 58

1 Answers1

1

The paragraph in question is probably

Note that on most versions of most BSDs (including Mac OS X) select() and poll() do not work correctly on BPF devices; pcap_get_selectable_fd() will return a file descriptor on most of those versions (the exceptions being FreeBSD 4.3 and 4.4), a simple select() or poll() will not return even after a timeout specified in pcap_open_live() expires. To work around this, an application that uses select() or poll() to wait for packets to arrive must put the pcap_t in non‐blocking mode, and must arrange that the select() or poll() have a timeout less than or equal to the timeout specified in pcap_open_live(), and must try to read packets after that timeout expires, regardless of whether select() or poll() indicated that the file descriptor for the pcap_t is ready to be read or not. (That work‐ around will not work in FreeBSD 4.3 and later; however, in FreeBSD 4.6 and later, select() and poll() work correctly on BPF devices, so the workaround isn’t necessary, although it does no harm.)

You didn't quote the first sentence, which is important here - you said "epoll()", which is a Linux system call; that paragraph does not apply on Linux.

(The current version of that paragraph, which is in the pcap_get_selectable_fd man page, is

   Note that in:

          FreeBSD prior to FreeBSD 4.6;

          NetBSD prior to NetBSD 3.0;

          OpenBSD prior to OpenBSD 2.4;

          Mac OS X prior to Mac OS X 10.7;

   select()   and   poll()   do   not   work  correctly  on  BPF  devices;
   pcap_get_selectable_fd() will return a file descriptor on most of those
   versions  (the  exceptions  being  FreeBSD  4.3  and 4.4), but a simple
   select() or poll() will not indicate that the  descriptor  is  readable
   until  a  full  buffer’s worth of packets is received, even if the read
   timeout expires before then.  To work around this, an application  that
   uses  select()  or  poll()  to  wait for packets to arrive must put the
   pcap_t in non‐blocking mode, and must  arrange  that  the  select()  or
   poll()  have a timeout less than or equal to the read timeout, and must
   try to read packets after that timeout expires, regardless  of  whether
   select() or poll() indicated that the file descriptor for the pcap_t is
   ready to be read or not.  (That workaround will not work in FreeBSD 4.3
   and  later; however, in FreeBSD 4.6 and later, select() and poll() work
   correctly on BPF devices, so the workaround isn’t  necessary,  although
   it does no harm.)

which is more correct. Note, however, that, due to a bug in Mac OS X 10.6's BPF, non-blocking mode doesn't work correctly, so the workaround also won't work on OS X 10.6. It's not necessary in 10.7 and later.)

If you're using libevent, you should put the pcap_fd into non-blocking mode, using pcap_setnonblock() (NOT an fcntl()!) and, if you get a READ_EV event, use pcap_dispatch() to process the packets.