diff options
author | Paolo Abeni <pabeni@redhat.com> | 2017-05-05 18:16:20 +0200 |
---|---|---|
committer | Paolo Abeni <pabeni@redhat.com> | 2017-05-11 10:18:11 +0200 |
commit | 5409b7ab378be997c0d26ba41a6ca18795e0b581 (patch) | |
tree | 4042a031340b4b627b9af0c4e45b79d2999898f3 /pcap-linux.c | |
parent | 8a072ceeca867c23985b6ead7bed7003c43b0a96 (diff) |
bound snaplen for linux tpacket_v2 to ~64k
The aggregated ethernet packets produced by the linux kernel
can't exceed 65535 (plus eth overhead), so we can bound
accordingly the snaplen for tpacket_v2 on such devices.
This allows a more efficient usage of the receive buffer;
tcpdump has increased the default snaplen up to 256K in recent
versions, to cope better with USB data, and that leads to
tpacket_v2 rx ring being configured by default with tp_frame_nr
equal to 7, which is very bad for most use-case.
With this change the default tpacket_v2 layout has tp_frame_nr
equal to 32, which is still quite low, but works much better
and is consistent with the previous tcpdump behavior.
v1 -> v2:
update the comment to better reflect the current status,
code cleanup
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Diffstat (limited to 'pcap-linux.c')
-rw-r--r-- | pcap-linux.c | 42 |
1 files changed, 25 insertions, 17 deletions
diff --git a/pcap-linux.c b/pcap-linux.c index b077ba30..1ee10ddb 100644 --- a/pcap-linux.c +++ b/pcap-linux.c @@ -3999,6 +3999,8 @@ prepare_tpacket_socket(pcap_t *handle) return 1; } +#define MAX(a,b) ((a)>(b)?(a):(b)) + /* * Attempt to set up memory-mapped access. * @@ -4042,10 +4044,10 @@ create_ring(pcap_t *handle, int *status) #ifdef HAVE_TPACKET2 case TPACKET_V2: #endif - /* Note that with large snapshot length (say 64K, which is - * the default for recent versions of tcpdump, the value that - * "-s 0" has given for a long time with tcpdump, and the - * default in Wireshark/TShark/dumpcap), if we use the snapshot + /* Note that with large snapshot length (say 256K, which is + * the default for recent versions of tcpdump, Wireshark, + * TShark, dumpcap or 64K, the value that "-s 0" has given for + * a long time with tcpdump), if we use the snapshot * length to calculate the frame length, only a few frames * will be available in the ring even with pretty * large ring size (and a lot of memory will be unused). @@ -4069,29 +4071,35 @@ create_ring(pcap_t *handle, int *status) * based on the MTU, so that the MTU limits the maximum size * of packets that we can receive.) * - * We don't do that if segmentation/fragmentation or receive - * offload are enabled, so we don't get rudely surprised by - * "packets" bigger than the MTU. */ + * If segmentation/fragmentation or receive offload are + * enabled, we can get reassembled/aggregated packets larger + * than MTU, but bounded to 65535 plus the Ethernet overhead, + * due to kernel and protocol constraints */ frame_size = handle->snapshot; if (handle->linktype == DLT_EN10MB) { + unsigned int max_frame_len; int mtu; int offload; + mtu = iface_get_mtu(handle->fd, handle->opt.device, + handle->errbuf); + if (mtu == -1) { + *status = PCAP_ERROR; + return -1; + } offload = iface_get_offload(handle); if (offload == -1) { *status = PCAP_ERROR; return -1; } - if (!offload) { - mtu = iface_get_mtu(handle->fd, handle->opt.device, - handle->errbuf); - if (mtu == -1) { - *status = PCAP_ERROR; - return -1; - } - if (frame_size > (unsigned int)mtu + 18) - frame_size = (unsigned int)mtu + 18; - } + if (offload) + max_frame_len = MAX(mtu, 65535); + else + max_frame_len = mtu; + max_frame_len += 18; + + if (frame_size > max_frame_len) + frame_size = max_frame_len; } /* NOTE: calculus matching those in tpacket_rcv() |