libpcap VLAN accel support
Subsystems (2)
In case someone is interested, I just sent these patches for VLAN accel support to the libpcap maintainers.
The latest CVS version includes support for mmaped packet sockets, so I also added support for this (this was missing from the example patch I posted earlier since it was based on an old Debian version).
Also the payload is not moved anymore when reconstructing the VLAN headers, only the ethernet addresses are moved further to the front to make room for the VLAN header.
pcap-linux: fix invalid rcvbuf size
From: Patrick McHardy <[email protected]>
Libpcap issues a SO_RCVBUF when the buffer size if unspecified (zero). The intention appears to be to set it when its *not* zero.
---
pcap-linux.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
pcap-linux.c +1 -1
@@ -557,7 +557,7 @@ pcap_activate_linux(pcap_t *handle) goto fail; } -if (handle->opt.buffer_size ==0 ) { +if (handle->opt.buffer_size !=0 ) {/* * Set the socket buffer size to the specified value. */
pcap-linux: convert to recvmsg()
From: Patrick McHardy <[email protected]>
Convert pcap-linux to use recvmsg() as preparation for using PACKET_AUXDATA cmsgs.
---
pcap-linux.c | 23 ++++++++++++++++------- 1 files changed, 16 insertions(+), 7 deletions(-)
pcap-linux.c +16 -7
@@ -625,10 +625,10 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)#else struct sockaddr from;#endif -socklen_t fromlen;int packet_len, caplen;struct pcap_pkthdr pcap_header; - +struct iovec iov; +struct msghdr msg;#ifdef HAVE_PF_PACKET_SOCKETS /* * If this is a cooked device, leave extra room for a
@@ -662,6 +662,18 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)* get notified of "network down" events. */ bp = handle->buffer + handle->offset; + + msg.msg_name = &from; + msg.msg_namelen =sizeof (from); + msg.msg_iov = &iov; + msg.msg_iovlen =1 ; + msg.msg_control =NULL ; + msg.msg_controllen =0 ; + msg.msg_flags =0 ; + + iov.iov_len = handle->bufsize - offset; + iov.iov_base = bp + offset; + do { /* * Has "pcap_breakloop()" been called?
@@ -675,11 +687,8 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) handle->break_loop =0 ;return -2 ; } - fromlen =sizeof (from); - packet_len =recvfrom ( - handle->fd, bp + offset, - handle->bufsize - offset,MSG_TRUNC , - (struct sockaddr *) &from, &fromlen); + + packet_len =recvmsg (handle->fd, &msg,MSG_TRUNC ); }while (packet_len ==-1 && (errno ==EINTR || errno ==ENETDOWN ));/* Check if an error occured */
pcap-linux: reconstruct VLAN header from PACKET_AUXDATA
From: Patrick McHardy <[email protected]>
VLAN packets sent over devices supporting VLAN tagging/stripping in hardwaredon't have a VLAN header when they are received on packet sockets. The VLAN TCI is available through the PACKET_AUXDATA cmsg, reconstruct the entire header when necessary.
---
pcap-linux.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- pcap/vlan.h | 11 +++++++++++ 2 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 pcap/vlan.h
pcap-linux.c +56 -3
101 lines not on this page · raw message
pcap/vlan.h new file +11 -0
@@ -0,0 +1,11 @@ +#ifndef lib_pcap_vlan_h +#define lib_pcap_vlan_h + +struct vlan_tag { +u_int16_t vlan_tpid;/* ETH_P_8021Q */ +u_int16_t vlan_tci;/* VLAN TCI */ +}; + +#define VLAN_TAG_LEN 4 + +#endif
pcap-linux: support new tpacket frame header format
From: Patrick McHardy <[email protected]>
The tpacket_hdr is not clean for 64 bit kernel/32 bit userspace and is not extendable because the struct sockaddr_ll following it is expected at a fixed offset.
Linux 2.6.27-rc supports a new tpacket frame header that removes these two limitations. Convert the mmap ring support to support both formats and probe for availability of the new version.
---
pcap-int.h | 2 + pcap-linux.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 134 insertions(+), 20 deletions(-)
pcap-int.h +2 -0
@@ -132,6 +132,8 @@ struct pcap_md {int lo_ifindex;/* interface index of the loopback device */ u_int packets_read;/* count of packets read with recvfrom() */ bpf_u_int32 oldmode;/* mode to restore when turning monitor mode off */ +u_int tp_version;/* version of tpacket_hdr for mmaped ring */ +u_int tp_hdrlen;/* hdrlen of tpacket_hdr for mmaped ring */ #endif /* linux */ #ifdef HAVE_DAG_API
pcap-linux.c +132 -20
259 lines not on this page · raw message
pcap-linux: reconstruct VLAN headers from tpacket2_hdr
From: Patrick McHardy <[email protected]>
Similar to PACKET_AUXDATA for non-mmaped sockets, the VLAN TCI is present in a new member of struct tpacket2_hdr. Use it to reconstruct the VLAN header when necessary.
---
pcap-linux.c | 28 ++++++++++++++++++++++++++++ 1 files changed, 28 insertions(+), 0 deletions(-)
pcap-linux.c +28 -0
@@ -1965,6 +1965,17 @@ prepare_tpacket_socket(pcap_t *handle) return 0; } handle->md.tp_version =TPACKET_V2 ; + +/* Reserve space for VLAN tag reconstruction */ + val =VLAN_TAG_LEN ; +if (setsockopt (handle->fd,SOL_PACKET ,PACKET_RESERVE , &val, +sizeof (val)) <0 ) { +snprintf (handle->errbuf,PCAP_ERRBUF_SIZE , +"can't set up reserve on socket %d: %d-%s" , + handle->fd, errno,pcap_strerror (errno)); +return 0 ; + } +#endif /* HAVE_TPACKET2 */ return 1 ; }
@@ -2281,6 +2292,23 @@ pcap_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, pcaphdr.len +=SLL_HDR_LEN ; } +#ifdef HAVE_TPACKET2 +if (handle->md.tp_version ==TPACKET_V2 && h.h2->tp_vlan_tci && + tp_snaplen >=2 *ETH_ALEN ) { +struct vlan_tag *tag; + + bp -=VLAN_TAG_LEN ; +memmove (bp, bp +VLAN_TAG_LEN ,2 *ETH_ALEN ); + + tag = (struct vlan_tag *)(bp +2 *ETH_ALEN ); + tag->vlan_tpid =htons (ETH_P_8021Q ); + tag->vlan_tci =htons (h.h2->tp_vlan_tci); + + pcaphdr.caplen +=VLAN_TAG_LEN ; + pcaphdr.len +=VLAN_TAG_LEN ; + } +#endif +/* pass the packet to the user */ pkts++;callback (user, &pcaphdr, bp);