From: Patrick McHardy <kaber@trash.net>
To: davem@davemloft.net
Cc: netdev@vger.kernel.org
Subject: Re: [PATCH 00/08]: VLAN update
Date: Wed, 09 Jul 2008 14:12:26 +0200 [thread overview]
Message-ID: <4874AB2A.7000704@trash.net> (raw)
In-Reply-To: <20080709120945.11669.42790.sendpatchset@localhost.localdomain>
[-- Attachment #1: Type: text/plain, Size: 549 bytes --]
Patrick McHardy wrote:
> These patches include an updated set of the VLAN packet socket fixes,
> now also supporting VLAN TCI delivery to userspace using mmaped packet
> sockets, as well as a patch to add ->get_flags ethtool support and
> a few minor cleanup patches.
And for reference, attached is a patch for libpcap to reconstruct
the VLAN header from the auxdata, as well as a ugly small program
for testing the new mmaped packet socket protocol version (since I
couldn't find a version of libpcap that already supports this for
some reason).
[-- Attachment #2: libpcap.diff --]
[-- Type: text/x-diff, Size: 3176 bytes --]
diff --git a/pcap-linux.c b/pcap-linux.c
index e9db010..e877cd8 100644
--- a/pcap-linux.c
+++ b/pcap-linux.c
@@ -471,7 +471,13 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
socklen_t fromlen;
int packet_len, caplen;
struct pcap_pkthdr pcap_header;
-
+ struct iovec iov;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ union {
+ struct cmsghdr cmsg;
+ char buf[CMSG_SPACE(sizeof(struct tpacket_auxdata))];
+ } cmsg_buf;
#ifdef HAVE_PF_PACKET_SOCKETS
/*
* If this is a cooked device, leave extra room for a
@@ -492,6 +498,15 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
/* Receive a single packet from the kernel */
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 = &cmsg_buf;
+ msg.msg_controllen = sizeof(cmsg_buf);
+ msg.msg_flags = 0;
+
do {
/*
* Has "pcap_breakloop()" been called?
@@ -505,11 +520,11 @@ 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);
+
+ iov.iov_len = handle->bufsize - offset;
+ iov.iov_base = bp + offset;
+
+ packet_len = recvmsg(handle->fd, &msg, MSG_TRUNC);
} while (packet_len == -1 && errno == EINTR);
/* Check if an error occured */
@@ -524,6 +539,38 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
}
}
+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+ struct tpacket_auxdata *aux;
+ unsigned int len, copy;
+ unsigned short *ptr;
+
+ if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct tpacket_auxdata)) ||
+ cmsg->cmsg_level != SOL_PACKET ||
+ cmsg->cmsg_type != PACKET_AUXDATA)
+ continue;
+
+ aux = (struct tpacket_auxdata *)CMSG_DATA(cmsg);
+ if (aux->tp_vlan_tci == 0)
+ continue;
+
+ len = packet_len > iov.iov_len ? iov.iov_len : packet_len;
+ if (len > 2 * ETH_ALEN + 4) {
+ copy = len - 2 * ETH_ALEN - 4;
+ if (copy > iov.iov_len - 2 * ETH_ALEN - 4)
+ copy = iov.iov_len - 2 * ETH_ALEN - 4;
+
+ memmove(iov.iov_base + 2 * ETH_ALEN + 4,
+ iov.iov_base + 2 * ETH_ALEN, copy);
+ }
+
+ ptr = (unsigned short *)(iov.iov_base + 2 * ETH_ALEN);
+ if (len >= 2 * ETH_ALEN + 2)
+ *(ptr++) = htons(ETH_P_8021Q);
+ if (len >= 2 * ETH_ALEN + 4)
+ *(ptr++) = htons(aux->tp_vlan_tci);
+ packet_len += 4;
+ }
+
#ifdef HAVE_PF_PACKET_SOCKETS
if (!handle->md.sock_packet) {
/*
@@ -1631,6 +1678,7 @@ iface_bind(int fd, int ifindex, char *ebuf)
struct sockaddr_ll sll;
int err;
socklen_t errlen = sizeof(err);
+ int val;
memset(&sll, 0, sizeof(sll));
sll.sll_family = AF_PACKET;
@@ -1657,6 +1705,12 @@ iface_bind(int fd, int ifindex, char *ebuf)
return -2;
}
+ val = 1;
+ if (setsockopt(fd, SOL_PACKET, PACKET_AUXDATA, &val, sizeof(val)) == -1) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "setsockopt: %s", pcap_strerror(errno));
+ return -3;
+ }
return 0;
}
[-- Attachment #3: mmap-test.diff --]
[-- Type: text/x-diff, Size: 7535 bytes --]
diff -urN /tmp/null/if_packet.h mmap-test/if_packet.h
--- /tmp/null/if_packet.h 1970-01-01 01:00:00.000000000 +0100
+++ mmap-test/if_packet.h 2008-07-09 12:56:08.000000000 +0200
@@ -0,0 +1,144 @@
+#ifndef __LINUX_IF_PACKET_H
+#define __LINUX_IF_PACKET_H
+
+#include <linux/types.h>
+
+struct sockaddr_pkt
+{
+ unsigned short spkt_family;
+ unsigned char spkt_device[14];
+ __be16 spkt_protocol;
+};
+
+struct sockaddr_ll
+{
+ unsigned short sll_family;
+ __be16 sll_protocol;
+ int sll_ifindex;
+ unsigned short sll_hatype;
+ unsigned char sll_pkttype;
+ unsigned char sll_halen;
+ unsigned char sll_addr[8];
+};
+
+/* Packet types */
+
+#define PACKET_HOST 0 /* To us */
+#define PACKET_BROADCAST 1 /* To all */
+#define PACKET_MULTICAST 2 /* To group */
+#define PACKET_OTHERHOST 3 /* To someone else */
+#define PACKET_OUTGOING 4 /* Outgoing of any type */
+/* These ones are invisible by user level */
+#define PACKET_LOOPBACK 5 /* MC/BRD frame looped back */
+#define PACKET_FASTROUTE 6 /* Fastrouted frame */
+
+/* Packet socket options */
+
+#define PACKET_ADD_MEMBERSHIP 1
+#define PACKET_DROP_MEMBERSHIP 2
+#define PACKET_RECV_OUTPUT 3
+/* Value 4 is still used by obsolete turbo-packet. */
+#define PACKET_RX_RING 5
+#define PACKET_STATISTICS 6
+#define PACKET_COPY_THRESH 7
+#define PACKET_AUXDATA 8
+#define PACKET_ORIGDEV 9
+#define PACKET_VERSION 10
+#define PACKET_HDRLEN 11
+
+struct tpacket_stats
+{
+ unsigned int tp_packets;
+ unsigned int tp_drops;
+};
+
+struct tpacket_auxdata
+{
+ __u32 tp_status;
+ __u32 tp_len;
+ __u32 tp_snaplen;
+ __u16 tp_mac;
+ __u16 tp_net;
+ __u16 tp_vlan_tci;
+};
+
+struct tpacket_hdr
+{
+ unsigned long tp_status;
+#define TP_STATUS_KERNEL 0
+#define TP_STATUS_USER 1
+#define TP_STATUS_COPY 2
+#define TP_STATUS_LOSING 4
+#define TP_STATUS_CSUMNOTREADY 8
+ unsigned int tp_len;
+ unsigned int tp_snaplen;
+ unsigned short tp_mac;
+ unsigned short tp_net;
+ unsigned int tp_sec;
+ unsigned int tp_usec;
+};
+
+#define TPACKET_ALIGNMENT 16
+#define TPACKET_ALIGN(x) (((x)+TPACKET_ALIGNMENT-1)&~(TPACKET_ALIGNMENT-1))
+#define TPACKET_HDRLEN (TPACKET_ALIGN(sizeof(struct tpacket_hdr)) + sizeof(struct sockaddr_ll))
+
+struct tpacket2_hdr
+{
+ __u32 tp_status;
+ __u32 tp_len;
+ __u32 tp_snaplen;
+ __u16 tp_mac;
+ __u16 tp_net;
+ __u32 tp_sec;
+ __u32 tp_nsec;
+#ifdef TEST_VLAN_TCI
+ __u16 tp_vlan_tci;
+#endif
+};
+
+#ifdef __KERNEL__
+#define TPACKET2_HDRLEN (TPACKET_ALIGN(sizeof(struct tpacket2_hdr)) + sizeof(struct sockaddr_ll))
+#else
+#define TPACKET2_HDRLEN(x) (TPACKET_ALIGN(x) + sizeof(struct sockaddr_ll))
+#endif
+
+enum tpacket_versions
+{
+ TPACKET_V1,
+ TPACKET_V2,
+};
+
+/*
+ Frame structure:
+
+ - Start. Frame must be aligned to TPACKET_ALIGNMENT=16
+ - struct tpacket_hdr
+ - pad to TPACKET_ALIGNMENT=16
+ - struct sockaddr_ll
+ - Gap, chosen so that packet data (Start+tp_net) alignes to TPACKET_ALIGNMENT=16
+ - Start+tp_mac: [ Optional MAC header ]
+ - Start+tp_net: Packet data, aligned to TPACKET_ALIGNMENT=16.
+ - Pad to align to TPACKET_ALIGNMENT=16
+ */
+
+struct tpacket_req
+{
+ unsigned int tp_block_size; /* Minimal size of contiguous block */
+ unsigned int tp_block_nr; /* Number of blocks */
+ unsigned int tp_frame_size; /* Size of frame */
+ unsigned int tp_frame_nr; /* Total number of frames */
+};
+
+struct packet_mreq
+{
+ int mr_ifindex;
+ unsigned short mr_type;
+ unsigned short mr_alen;
+ unsigned char mr_address[8];
+};
+
+#define PACKET_MR_MULTICAST 0
+#define PACKET_MR_PROMISC 1
+#define PACKET_MR_ALLMULTI 2
+
+#endif
diff -urN /tmp/null/Makefile mmap-test/Makefile
--- /tmp/null/Makefile 1970-01-01 01:00:00.000000000 +0100
+++ mmap-test/Makefile 2008-07-09 03:21:21.000000000 +0200
@@ -0,0 +1,3 @@
+CFLAGS += -O2 -I. -Wall -g
+
+all: test
diff -urN /tmp/null/test.c mmap-test/test.c
--- /tmp/null/test.c 1970-01-01 01:00:00.000000000 +0100
+++ mmap-test/test.c 2008-07-09 12:56:40.000000000 +0200
@@ -0,0 +1,150 @@
+#include <unistd.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/mman.h>
+#include <poll.h>
+#include <arpa/inet.h>
+#include <linux/types.h>
+#include <linux/socket.h>
+#include <linux/if_ether.h>
+
+#define V2
+#ifdef V2
+#define TEST_VLAN_TCI 1
+#endif
+
+#include "if_packet.h"
+
+int main(int argc, char **argv)
+{
+ struct sockaddr_ll lladdr;
+ struct tpacket_req req;
+#ifdef V2
+ struct tpacket2_hdr *hdr;
+#else
+ struct tpacket_hdr *hdr;
+#endif
+ unsigned int hdrlen;
+ int val;
+ socklen_t len;
+ void *ring;
+ unsigned int head;
+ unsigned int total = 0;
+ int fd;
+
+ fd = socket(AF_PACKET, SOCK_RAW, 0);
+ if (fd < 0) {
+ perror("socket");
+ return 1;
+ }
+
+#ifdef V2
+ val = TPACKET_V2;
+ len = sizeof(val);
+ if (getsockopt(fd, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) {
+ perror("setsockopt(PACKET_HDRLEN)");
+ return 1;
+ }
+ hdrlen = val;
+
+ printf("hdrlen=%u sizeof(struct tpacket2_hdr)=%Zu\n",
+ hdrlen, sizeof(struct tpacket2_hdr));
+
+ val = TPACKET_V2;
+ if (setsockopt(fd, SOL_PACKET, PACKET_VERSION, &val, sizeof(val)) < 0) {
+ perror("setsockopt(PACKET_VERSION)");
+ return 1;
+ }
+#else
+ hdrlen = sizeof(struct tpacket_hdr);
+#endif
+
+ memset(&req, 0, sizeof(req));
+ req.tp_block_size = 16 * 4096;
+ req.tp_block_nr = 16;
+ req.tp_frame_size = 1024;
+ req.tp_frame_nr = 16 * 64;
+
+ if (setsockopt(fd, SOL_PACKET, PACKET_RX_RING, &req, sizeof(req)) < 0) {
+ perror("setsockopt");
+ return 1;
+ }
+
+ ring = mmap(NULL, req.tp_block_nr * req.tp_block_size,
+ PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if ((long)ring == -1L) {
+ perror("mmap");
+ return 1;
+ }
+
+ memset(&lladdr, 0, sizeof(lladdr));
+ lladdr.sll_family = AF_PACKET;
+ lladdr.sll_protocol = htons(ETH_P_ALL);
+ lladdr.sll_ifindex = 2;
+
+ if (bind(fd, (struct sockaddr *)&lladdr, sizeof(lladdr)) < 0) {
+ perror("bind");
+ return 1;
+ }
+
+ hdr = ring;
+ head = 0;
+
+ while (1) {
+ unsigned int cnt = 0;
+ struct pollfd pfds[1];
+
+ pfds[0].fd = fd;
+ pfds[0].events = POLLIN | POLLERR;
+ pfds[0].revents = 0;
+
+ if (poll(pfds, 1, -1) < 0 && errno != EINTR) {
+ perror("poll");
+ return 1;
+ }
+
+ if (pfds[0].revents & POLLERR) {
+ char buf[16384];
+ recv(fd, buf, sizeof(buf), MSG_DONTWAIT | MSG_ERRQUEUE);
+ printf("error %d\n", errno);
+ continue;
+ }
+
+ if (!(pfds[0].revents & POLLIN))
+ continue;
+
+ while (hdr->tp_status != TP_STATUS_KERNEL) {
+ struct sockaddr_ll *sll;
+ unsigned char *data = (void *)hdr + hdr->tp_mac;
+ unsigned int i;
+
+ printf("%.4u ring[%u]: tp_status=%u tp_len=%u "
+ "tp_snaplen=%u\n",
+ total, head, hdr->tp_status, hdr->tp_len, hdr->tp_snaplen);
+#ifdef TEST_VLAN_TCI
+ printf("tp_vlan_tci=%u id=%u\n",
+ hdr->tp_vlan_tci, hdr->tp_vlan_tci & 0xfff);
+#endif
+ for (i = 0; i < (hdr->tp_snaplen > 32 ? 32 : hdr->tp_snaplen); i++)
+ printf("%.2x ", data[i]);
+ printf("\n");
+
+ sll = (void *)hdr + TPACKET_ALIGN(hdrlen);
+ printf("sll_family=%u sll_protocol=%u sll_ifindex=%d sll_hatype=%u "
+ "sll_pkttype=%u sll_halen=%u\n",
+ sll->sll_family, ntohs(sll->sll_protocol),
+ sll->sll_ifindex, sll->sll_hatype,
+ sll->sll_pkttype, sll->sll_halen);
+ hdr->tp_status = TP_STATUS_KERNEL;
+
+ head = head == req.tp_frame_nr - 1 ? 0 : head + 1;
+ hdr = ring + head * req.tp_frame_size;
+ cnt++, total++;
+ }
+ printf("received %u consecutive entries, %u total\n\n", cnt, total);
+ }
+ return 0;
+}
next prev parent reply other threads:[~2008-07-09 12:12 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-07-09 12:09 [PATCH 00/08]: VLAN update Patrick McHardy
2008-07-09 12:09 ` [PATCH 01/08]: vlan: Don't store VLAN tag in cb Patrick McHardy
2008-07-09 12:09 ` [PATCH 02/08]: vlan: deliver packets received with VLAN acceleration to network taps Patrick McHardy
2008-07-09 12:35 ` Ben Hutchings
2008-07-09 12:37 ` Patrick McHardy
2008-07-09 12:09 ` [PATCH 03/08]: packet: support extensible, 64 bit clean mmaped ring structure Patrick McHardy
2008-07-09 12:09 ` [PATCH 04/08]: packet: deliver VLAN TCI to userspace Patrick McHardy
2008-07-09 12:09 ` [PATCH 05/08]: vlan: ethtool ->get_flags support Patrick McHardy
2008-07-09 12:09 ` [PATCH 06/08]: vlan: clean up vlan_dev_hard_header() Patrick McHardy
2008-07-09 12:09 ` [PATCH 07/08]: vlan: clean up hard_start_xmit functions Patrick McHardy
2008-07-09 12:09 ` [PATCH 08/08]: vlan: remove unnecessary include statements Patrick McHardy
2008-07-09 12:12 ` Patrick McHardy [this message]
2008-07-15 5:56 ` [PATCH 00/08]: VLAN update David Miller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4874AB2A.7000704@trash.net \
--to=kaber@trash.net \
--cc=davem@davemloft.net \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.