3

What I currently do is the following:

struct pcap_pkthdr *phdr;
const u_char *data;

pcap_next_ex(descriptor, &phdr, &data);
memcpy((void*)mybuf, phdr, sizeof(*phdr));
memcpy((void*)mybuf + sizeof(*phdr), data, phdr->len);

But what I'd like to do is the following, that is, providing a preallocated buffer.

u_char mybuf[2048];

pcap_next_ex(descriptor, mybuf, mybuf + 16); // 16 is size of pkthdr

The second example wouldn't compile anyway because of wrong pointer types, but I think my question is better understandable this way. I am reading from a 10G interface and speed is extremely important. I'd like to benchmarks certain parts of the code, for example, using own preallocated packet buffers instead of the hidden allocations/buffers in libpcap.

Is there a way or API to make libpcap take preallocated buffers to write the results of pcap_next_ex into?

flowit
  • 1,382
  • 1
  • 10
  • 36

1 Answers1

3

From glancing at the libpcap source code there does not appear to be a way to pass a pre-allocated buffer. However, chances are it's already using an internally preallocated buffer. For example, for live captures on Linux, pcap_next_ex() drills down into a call to pcap_read_packet() in pcap-linux.c. Here you can see that the pointer being returned is just an offset into a larger read buffer that belongs to the capture handle. I haven't looked at the implementations for other OS's but I suspect they are similar.

Allowing you to pass in your own buffers would either require the platform implementations to copy data from their own internal buffers into your buffer (very inefficient), or severely limit their ability to manage their own buffering for system calls and such (memory mapping, receiving multiple packets per system call, etc.). Either way, it's very likely that this is not a source of potential optimization for you.

See also this mailing list thread where the relative performance of pcap_next_ex() and the older pcap_loop() interface are discussed.

Edit

interjay points out that the Linux live capture implementation makes a copy anyway because of the requirement for the buffer contents to remain valid after the call (see line 4452 of pcap-linux.c). The comment in the code suggests that pcap_loop() may indeed be faster because the buffer is exposed only to the callback function and thus its contents aren't required to remain valid after the callback returns.

TypeIA
  • 16,916
  • 1
  • 38
  • 52
  • 2
    Regarding `pcap_next_ex` vs `pcap_loop`, [the code](https://github.com/the-tcpdump-group/libpcap/blob/8b65b39f26e93190e353e3b8d3178054e2d05af8/pcap-linux.c#L4464) says that `pcap_next_ex` needs to perform an extra copy. – interjay Jan 08 '18 at 19:02