tcpdump mailing list archives

Re: libpcap timeout weirdness


From: Robert Monaghan <bob () gluetools com>
Date: Sun, 24 Mar 2013 20:18:43 +0100

Ok,

So I just stumbled into a "sort of" solution. I have to do a wide-spread test, first, to see if this is really a fix:

I just set my timeout to 1ms using pcap_set_timeout,
I then added the following to my callback:

void processSingleImage(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
{
        GT_DataOperation *dataOp = (GT_DataOperation *)args;
        static int count = 0;
        count++;

        if (count == rtoDataOp->totalBlockCount) {
                count = 0;
                pcap_breakloop(dataOp->handle);
        }
}

Basically, I count blocks until I get everything that I need. At that point, I do a breakloop.
This seems to eliminate the timeout issue I saw.

Now, however, I am concerned that the timeout is going to have to be adjusted to some value that at is "One Size Fits 
All". Naturally a number that degrades performance for all of my users.
I tried a timeout of 0, using pcap_set_timeout. But this ever called my callback.

I am curious to know if anyone has any thoughts..

Thanks!

bob.


On Mar 24, 2013, at 7:51 PM, Robert Monaghan wrote:

Hi Everyone!

I am using the built in Libpcap library that comes with MacOSX. (MacOSX 10.8.3)

I have set up a background GCD dispatch queue, where the libpcap is set up and waits for packets to arrive on my 
10Gig card.

The code is very trivial, and appears as if it should works well..
Here is the problem.

I am using "pcap_loop" to grab a specific number of packets. This is set up using a snap size of 1504  (To match the 
packet size from my hardware device.)
The buffer is large, about 1Mb in size. I have the "pcap_loop" code in "blocking" mode, so that I can wait for all of 
the packets to finish, before triggering a semaphore.

When I start the pcap_loop to do its work, which grabs exactly 1879 packets.  (Precisely the number I am asking for.) 
I end up with a timeout being called. (I know this is a timeout, because if I change the timeout value in  
"pcap_open_live", the timeout matches the duration that I set.) As a test, I decide to trim the number of packets 
used in pcap_loop by 160, and everything speeds up dramatically! Absolutely no timeouts. Anything less that 159 
packets (determined by trial & error), the time out occurs.

This isn't the only size, either.

Now I download another (smaller) set of data, this time I download only 782 packets. This download starts to timeout, 
as well! (Even though the 1700 or so, packet downloaded just fine!)  If I trim it by about 97 packet, the system no 
longer times out.

Weird.

Just for fun, I tried an really large data set, at 3130 packets. As expected it stalls. But again, trimming about 200 
packets removes the stall, and it moves the data extremely quickly.

If I use pcap_stats immediately after the pcap_loop, I see that in both fast and timed out situations, that I don't 
drop any packets.
The only issue seems to be that the timeout is triggered.

I am at a loss on this one. I have tried changing the 'snaplen' size, and altered the timeout, but i can't seem to 
see where the problem is.
This works if I trim the number of packets read, but slows down dramatically, if I do the full amount of packets 
requested.
I have also switched over to pcap_create and the assorted pcap_set commands to try to noodle with settings.
I have even set different buffersizes with sysctl debug.bpf_bufsize and maxbufsize. No luck there, either.

Can anyone make a suggestion?

Should I ditch the built in MacOSX libpcap and compile the one available from the tcpdump repository?


Attached is the relevant code:

      char filter_exp[] = "ether proto 0x7777";
      
      char errbuf[PCAP_ERRBUF_SIZE] = {0};
      int buffersize = (int)(1048576);
      //handle = pcap_open_live([ethernetInterface cStringUsingEncoding:NSASCIIStringEncoding], 65536 * 2, 0, 1000, 
errbuf);

      handle = pcap_create([ethernetInterface cStringUsingEncoding:NSASCIIStringEncoding], errbuf);
      
      if (handle != NULL) {
              //pcap_set_promisc(handle, 0);
              pcap_set_timeout(handle, 1000);
              //pcap_setdirection(handle,  PCAP_D_IN);
              pcap_set_snaplen(handle, 1504);
              pcap_set_buffer_size(handle, buffersize);
              //pcap_set_rfmon(handle, 0);
              pcap_activate(handle);
              
              /* compile the filter expression */
              bpf_u_int32 mask = 0xffff0000;
              if (pcap_compile(handle, &fp, filter_exp, 1, mask) == -1) {
                      fprintf(stderr, "Couldn't parse filter %s: %s\n",
                                      filter_exp, pcap_geterr(handle));
                      exit(EXIT_FAILURE);
              }
              
              /* apply the compiled filter */
              if (pcap_setfilter(handle, &fp) == -1) {
                      fprintf(stderr, "Couldn't install filter %s: %s\n",
                                      filter_exp, pcap_geterr(handle));
                      exit(EXIT_FAILURE);
              }
              
              return true;
      }

---
      int err = pcap_loop(handle, blockCount, processSingleImage, (u_char *)&dataOp);
and


void processSingleImage(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
{
      GT_DataOperation *dataOp = (GT_DataOperation *)args;
      static int count = 0;
      count++;
}

Thanks!

bob.
_______________________________________________
tcpdump-workers mailing list
tcpdump-workers () lists tcpdump org
https://lists.sandelman.ca/mailman/listinfo/tcpdump-workers

_______________________________________________
tcpdump-workers mailing list
tcpdump-workers () lists tcpdump org
https://lists.sandelman.ca/mailman/listinfo/tcpdump-workers


Current thread: