tag 623868 + patch thanks Robert Edmonds wrote: > this is fixed in upstream commit ea9432fabdf4b33cbc76d9437200e028f1c47c93, > "Fix the calculation of the frame size in memory-mapped captures."
attached is a backport of this commit to 1.1.1, and a patch to the debian package containing the fix. -- Robert Edmonds edmo...@debian.org
From cc4298babe767e394dc673c87ef3dbabe3fdb7c9 Mon Sep 17 00:00:00 2001 From: Julien Moutinho <j...@savines.alpes.fr.eu.org> Date: Tue, 22 Mar 2011 23:53:15 -0700 Subject: [PATCH] Fix the calculation of the frame size in memory-mapped captures. The old calculation truncated packets to a smaller value than the snapshot length. --- pcap-linux.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 46 insertions(+), 3 deletions(-) diff --git a/pcap-linux.c b/pcap-linux.c index af12543..74ac21f 100644 --- a/pcap-linux.c +++ b/pcap-linux.c @@ -3057,15 +3057,58 @@ create_ring(pcap_t *handle) { unsigned i, j, frames_per_block; struct tpacket_req req; + socklen_t len; + unsigned int sk_type, tp_reserve, maclen, tp_hdrlen, netoff, macoff; /* Note that with large snapshot (say 64K) only a few frames * will be available in the ring even with pretty large ring size * (and a lot of memory will be unused). * The snap len should be carefully chosen to achive best * performance */ - req.tp_frame_size = TPACKET_ALIGN(handle->snapshot + - TPACKET_ALIGN(handle->md.tp_hdrlen) + - sizeof(struct sockaddr_ll)); + + /* NOTE: calculus matching those in tpacket_rcv() + * in linux-2.6/net/packet/af_packet.c + */ + len = sizeof(sk_type); + if (getsockopt(handle->fd, SOL_SOCKET, SO_TYPE, &sk_type, &len) < 0) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "getsockopt: %s", pcap_strerror(errno)); + return -1; + } + len = sizeof(tp_reserve); + if (getsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE, &tp_reserve, &len) < 0) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "getsockopt: %s", pcap_strerror(errno)); + return -1; + } + maclen = (sk_type == SOCK_DGRAM) ? 0 : MAX_LINKHEADER_SIZE; + /* XXX: in the kernel maclen is calculated from + * LL_ALLOCATED_SPACE(dev) and vnet_hdr.hdr_len + * in: packet_snd() in linux-2.6/net/packet/af_packet.c + * then packet_alloc_skb() in linux-2.6/net/packet/af_packet.c + * then sock_alloc_send_pskb() in linux-2.6/net/core/sock.c + * but I see no way to get those sizes in userspace, + * like for instance with an ifreq ioctl(); + * the best thing I've found so far is MAX_HEADER in the kernel + * part of linux-2.6/include/linux/netdevice.h + * which goes up to 128+48=176; since pcap-linux.c defines + * a MAX_LINKHEADER_SIZE of 256 which is greater than that, + * let's use it.. maybe is it even large enough to directly + * replace macoff.. + */ + tp_hdrlen = TPACKET_ALIGN(handle->md.tp_hdrlen) + sizeof(struct sockaddr_ll) ; + netoff = TPACKET_ALIGN(tp_hdrlen + (maclen < 16 ? 16 : maclen)) + tp_reserve; + /* NOTE: AFAICS tp_reserve may break the TPACKET_ALIGN of + * netoff, which contradicts + * linux-2.6/Documentation/networking/packet_mmap.txt + * documenting that: + * "- Gap, chosen so that packet data (Start+tp_net) + * aligns to TPACKET_ALIGNMENT=16" + */ + /* NOTE: in linux-2.6/include/linux/skbuff.h: + * "CPUs often take a performance hit + * when accessing unaligned memory locations" + */ + macoff = netoff - maclen; + req.tp_frame_size = TPACKET_ALIGN(macoff + handle->snapshot); req.tp_frame_nr = handle->opt.buffer_size/req.tp_frame_size; /* compute the minumum block size that will handle this frame. -- 1.7.4.4
From 3e977e81063366e5634695f99afdd7a85f63a287 Mon Sep 17 00:00:00 2001 From: Robert S. Edmonds <edmo...@debian.org> Date: Sat, 23 Apr 2011 22:37:01 -0400 Subject: [PATCH] backport commit ea9432fabd from upstream for #623868 --- debian/changelog | 4 ++ debian/patches/60_tpacket_alignment.diff | 81 ++++++++++++++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 86 insertions(+), 0 deletions(-) create mode 100644 debian/patches/60_tpacket_alignment.diff diff --git a/debian/changelog b/debian/changelog index f99c8d1..dcd4fe5 100644 --- a/debian/changelog +++ b/debian/changelog @@ -4,6 +4,10 @@ libpcap (1.1.1-4) UNRELEASED; urgency=low when the bonding module is loaded (closes: #612803). * debian/patches/50_kfreebsd.diff: Enable zerocopy BPF again. + [ Robert S. Edmonds ] + * Backport commit ea9432fabd from upstream to fix corruption of snapshot + length on live captures (closes: #623868). + -- Romain Francoise <rfranco...@debian.org> Sat, 16 Apr 2011 15:49:38 +0200 libpcap (1.1.1-3) unstable; urgency=low diff --git a/debian/patches/60_tpacket_alignment.diff b/debian/patches/60_tpacket_alignment.diff new file mode 100644 index 0000000..e68e2e6 --- /dev/null +++ b/debian/patches/60_tpacket_alignment.diff @@ -0,0 +1,81 @@ +From cc4298babe767e394dc673c87ef3dbabe3fdb7c9 Mon Sep 17 00:00:00 2001 +From: Julien Moutinho <j...@savines.alpes.fr.eu.org> +Date: Tue, 22 Mar 2011 23:53:15 -0700 +Subject: [PATCH] Fix the calculation of the frame size in memory-mapped + captures. + +The old calculation truncated packets to a smaller value than the +snapshot length. +--- + pcap-linux.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++--- + 1 files changed, 46 insertions(+), 3 deletions(-) + +diff --git a/pcap-linux.c b/pcap-linux.c +index af12543..74ac21f 100644 +--- a/pcap-linux.c ++++ b/pcap-linux.c +@@ -3057,15 +3057,58 @@ create_ring(pcap_t *handle) + { + unsigned i, j, frames_per_block; + struct tpacket_req req; ++ socklen_t len; ++ unsigned int sk_type, tp_reserve, maclen, tp_hdrlen, netoff, macoff; + + /* Note that with large snapshot (say 64K) only a few frames + * will be available in the ring even with pretty large ring size + * (and a lot of memory will be unused). + * The snap len should be carefully chosen to achive best + * performance */ +- req.tp_frame_size = TPACKET_ALIGN(handle->snapshot + +- TPACKET_ALIGN(handle->md.tp_hdrlen) + +- sizeof(struct sockaddr_ll)); ++ ++ /* NOTE: calculus matching those in tpacket_rcv() ++ * in linux-2.6/net/packet/af_packet.c ++ */ ++ len = sizeof(sk_type); ++ if (getsockopt(handle->fd, SOL_SOCKET, SO_TYPE, &sk_type, &len) < 0) { ++ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "getsockopt: %s", pcap_strerror(errno)); ++ return -1; ++ } ++ len = sizeof(tp_reserve); ++ if (getsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE, &tp_reserve, &len) < 0) { ++ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "getsockopt: %s", pcap_strerror(errno)); ++ return -1; ++ } ++ maclen = (sk_type == SOCK_DGRAM) ? 0 : MAX_LINKHEADER_SIZE; ++ /* XXX: in the kernel maclen is calculated from ++ * LL_ALLOCATED_SPACE(dev) and vnet_hdr.hdr_len ++ * in: packet_snd() in linux-2.6/net/packet/af_packet.c ++ * then packet_alloc_skb() in linux-2.6/net/packet/af_packet.c ++ * then sock_alloc_send_pskb() in linux-2.6/net/core/sock.c ++ * but I see no way to get those sizes in userspace, ++ * like for instance with an ifreq ioctl(); ++ * the best thing I've found so far is MAX_HEADER in the kernel ++ * part of linux-2.6/include/linux/netdevice.h ++ * which goes up to 128+48=176; since pcap-linux.c defines ++ * a MAX_LINKHEADER_SIZE of 256 which is greater than that, ++ * let's use it.. maybe is it even large enough to directly ++ * replace macoff.. ++ */ ++ tp_hdrlen = TPACKET_ALIGN(handle->md.tp_hdrlen) + sizeof(struct sockaddr_ll) ; ++ netoff = TPACKET_ALIGN(tp_hdrlen + (maclen < 16 ? 16 : maclen)) + tp_reserve; ++ /* NOTE: AFAICS tp_reserve may break the TPACKET_ALIGN of ++ * netoff, which contradicts ++ * linux-2.6/Documentation/networking/packet_mmap.txt ++ * documenting that: ++ * "- Gap, chosen so that packet data (Start+tp_net) ++ * aligns to TPACKET_ALIGNMENT=16" ++ */ ++ /* NOTE: in linux-2.6/include/linux/skbuff.h: ++ * "CPUs often take a performance hit ++ * when accessing unaligned memory locations" ++ */ ++ macoff = netoff - maclen; ++ req.tp_frame_size = TPACKET_ALIGN(macoff + handle->snapshot); + req.tp_frame_nr = handle->opt.buffer_size/req.tp_frame_size; + + /* compute the minumum block size that will handle this frame. +-- +1.7.4.4 + diff --git a/debian/patches/series b/debian/patches/series index 4a9498b..80180e4 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -6,3 +6,4 @@ 50_kfreebsd.diff 55_hurd.diff 50_autotools-dev.diff +60_tpacket_alignment.diff -- 1.7.4.4
signature.asc
Description: Digital signature