# Performance difference between af\_packet/libpcap?

**URL:** <https://discuss.elastic.co/t/performance-difference-between-af-packet-libpcap/69766>\
**Category:** Beats\
**Tags:** packetbeat\
**Created:** [December 22, 2016, 10:14am UTC](https://discuss.elastic.co/t/performance-difference-between-af-packet-libpcap/69766 "2016-12-22T10:14:06Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![wofanli](https://avatars.discourse-cdn.com/v4/letter/w/22d042/32.png) [@wofanli](https://discuss.elastic.co/u/wofanli)\
**Post date:** [December 22, 2016, 10:14am UTC](https://discuss.elastic.co/t/performance-difference-between-af-packet-libpcap/69766/1 "2016-12-22T10:14:06Z")

</div>

Hi Guys,

I'm looking at the packetbeat [document](https://github.com/elastic/beats/blob/master/packetbeat/docs/capturing.asciidoc), and it declares af\_packet has better performance than pcap.

Do we have any number regarding this performance difference?  
As far as I know libpcap has leveraged af\_packet in Linux. I thought they should have similar performance before.

_pcap, which uses the libpcap library and works on most platforms, but it’s not the fastest option._  
_af\_\_packet, which uses memory mapped sniffing. This option is faster than libpcap and doesn’t require a kernel module, but it’s Linux-specific_

---

<div class="post-metadata">

**Author:** ![steffens](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/steffens/32/79630_2.png) [@steffens](https://discuss.elastic.co/u/steffens)\
**Post date:** [December 22, 2016, 1:10pm UTC](https://discuss.elastic.co/t/performance-difference-between-af-packet-libpcap/69766/2 "2016-12-22T13:10:35Z")

</div>

we don't have numbers and mileage might vary. Normally the performance difference is recognizable by packet loss.

But the libpcap based approach does add quite some overhead, as libpcap provides a callback based interface per packet, might enforce additional copies and most important, libpcap requires the CGO interface adding a function calling overhead per packet. af\_packet on the other hand is plain GO directly accessing the in shared memory (shared with kernel) + buffer sizes are somewhat tunable.

libpcap supports SOCK\_PACKET and SOCK\_RAW, but it depends on [compile-time flags which one is available](https://github.com/the-tcpdump-group/libpcap/blob/master/pcap-linux.c#L145). Plus, libpcap tries to use SOCK\_RAW/DGRAM, but might silently fallback to SOCK\_PACKET [reading package from socket](https://github.com/the-tcpdump-group/libpcap/blob/master/pcap-linux.c#L1683).

Using af\_packet you ensure SOCK\_PACKET is not used, buffers are configurable + you remove some go to C and C to go calling overhead.

---

<div class="post-metadata">

**Author:** ![wofanli](https://avatars.discourse-cdn.com/v4/letter/w/22d042/32.png) [@wofanli](https://discuss.elastic.co/u/wofanli)\
**Post date:** [December 22, 2016, 2:02pm UTC](https://discuss.elastic.co/t/performance-difference-between-af-packet-libpcap/69766/3 "2016-12-22T14:02:56Z")

</div>

Hi Steffens,

Thanks for your kindly reply.  
I forgot the overhead of CGO. It is the killer. In my quick test, GO call C is ~500 times slower than Go call Go.

After taking a quick look at the code of libpcap (Linux), I got some minor corrections.

Regarding the additional copies, it depends on how we use it.  
pcap\_loop does't require additional memory copy.

And the buffer can be configured in libpcap too (pcap\_set\_buffer\_size).

Thanks,  
Wenxian

---

<div class="post-metadata">

**Author:** ![steffens](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/steffens/32/79630_2.png) [@steffens](https://discuss.elastic.co/u/steffens)\
**Post date:** [December 22, 2016, 2:43pm UTC](https://discuss.elastic.co/t/performance-difference-between-af-packet-libpcap/69766/4 "2016-12-22T14:43:04Z")

</div>

> And the buffer can be configured in libpcap too (pcap\_set\_buffer\_size).

Right. I have had packetbeat configuration itself in mind. In packetbeat config file you can configure the buffer size for af\_packet only.

> Regarding the additional copies, it depends on how we use it.  
> pcap\_loop does't require additional memory copy.

packetbeat uses go-packet, which is not using `pcap_loop`, but [`pcap_next_ex`](https://github.com/tsg/gopacket/blob/master/pcap/pcap.go#L319). The [mmap callback](https://github.com/the-tcpdump-group/libpcap/blob/master/pcap-linux.c#L4431) requires a memcpy to copy the packet it's content into some temporary buffer.

In addition the sniffer in packetbeat uses ReadPacketData, which also copies the packet once again (required to hold on e.g. unordered TCP packets). That is af\_packet will copy the packet once, but using pcap will copy the packet twice (no matter if SOCK\_RAW or SOCK\_PACKET will be used).

---

<div class="post-metadata">

**Author:** ![wofanli](https://avatars.discourse-cdn.com/v4/letter/w/22d042/32.png) [@wofanli](https://discuss.elastic.co/u/wofanli)\
**Post date:** [December 23, 2016, 1:58am UTC](https://discuss.elastic.co/t/performance-difference-between-af-packet-libpcap/69766/5 "2016-12-23T01:58:59Z")

</div>

Hi Steffens,  
Thanks for your detailed explanation. You are quite helpful.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [January 20, 2017, 1:59am UTC](https://discuss.elastic.co/t/performance-difference-between-af-packet-libpcap/69766/6 "2017-01-20T01:59:12Z")

</div>

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.
