aboutsummaryrefslogtreecommitdiff
path: root/pcap-linux.c
diff options
context:
space:
mode:
authorPaolo Abeni <pabeni@redhat.com>2017-05-05 18:16:20 +0200
committerPaolo Abeni <pabeni@redhat.com>2017-05-11 10:18:11 +0200
commit5409b7ab378be997c0d26ba41a6ca18795e0b581 (patch)
tree4042a031340b4b627b9af0c4e45b79d2999898f3 /pcap-linux.c
parent8a072ceeca867c23985b6ead7bed7003c43b0a96 (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.c42
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()