diff options
| author | Daniel Borkmann <dborkman@redhat.com> | 2013-04-02 13:00:51 +0000 | 
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2013-04-07 17:02:24 -0400 | 
| commit | 23a9544206dd91dfe048fcf67abec3f3104c42b9 (patch) | |
| tree | 144beb514dd0a62c106732a403061f8dc7791508 /tools/testing/selftests/net/psock_lib.h | |
| parent | 9dcc71e1fdbb7aa10d92a3d35e8a201adc84abd0 (diff) | |
| download | olio-linux-3.10-23a9544206dd91dfe048fcf67abec3f3104c42b9.tar.xz olio-linux-3.10-23a9544206dd91dfe048fcf67abec3f3104c42b9.zip | |
selftests: net: add PF_PACKET TPACKET v1/v2/v3 selftests
This patch adds a simple test case that probes the packet socket's
TPACKET_V1, TPACKET_V2 and TPACKET_V3 behavior regarding mmap(2)'ed
I/O for a small burst of 100 packets. The test currently runs for ...
  TPACKET_V1: RX_RING, TX_RING
  TPACKET_V2: RX_RING, TX_RING
  TPACKET_V3: RX_RING
... and will output on success:
  test: TPACKET_V1 with PACKET_RX_RING .................... 100 pkts (9600 bytes)
  test: TPACKET_V1 with PACKET_TX_RING .................... 100 pkts (9600 bytes)
  test: TPACKET_V2 with PACKET_RX_RING .................... 100 pkts (9600 bytes)
  test: TPACKET_V2 with PACKET_TX_RING .................... 100 pkts (9600 bytes)
  test: TPACKET_V3 with PACKET_RX_RING .................... 100 pkts (9600 bytes)
  OK. All tests passed
Reusable parts of psock_fanout.c have been put into a psock_lib.h
file for common usage. Test case successfully tested on x86_64.
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'tools/testing/selftests/net/psock_lib.h')
| -rw-r--r-- | tools/testing/selftests/net/psock_lib.h | 127 | 
1 files changed, 127 insertions, 0 deletions
| diff --git a/tools/testing/selftests/net/psock_lib.h b/tools/testing/selftests/net/psock_lib.h new file mode 100644 index 00000000000..37da54ac85a --- /dev/null +++ b/tools/testing/selftests/net/psock_lib.h @@ -0,0 +1,127 @@ +/* + * Copyright 2013 Google Inc. + * Author: Willem de Bruijn <willemb@google.com> + *         Daniel Borkmann <dborkman@redhat.com> + * + * License (GPLv2): + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef PSOCK_LIB_H +#define PSOCK_LIB_H + +#include <sys/types.h> +#include <sys/socket.h> +#include <string.h> +#include <arpa/inet.h> +#include <unistd.h> + +#define DATA_LEN			100 +#define DATA_CHAR			'a' + +#define PORT_BASE			8000 + +#ifndef __maybe_unused +# define __maybe_unused		__attribute__ ((__unused__)) +#endif + +static __maybe_unused void pair_udp_setfilter(int fd) +{ +	struct sock_filter bpf_filter[] = { +		{ 0x80, 0, 0, 0x00000000 },  /* LD  pktlen		      */ +		{ 0x35, 0, 5, DATA_LEN   },  /* JGE DATA_LEN  [f goto nomatch]*/ +		{ 0x30, 0, 0, 0x00000050 },  /* LD  ip[80]		      */ +		{ 0x15, 0, 3, DATA_CHAR  },  /* JEQ DATA_CHAR [f goto nomatch]*/ +		{ 0x30, 0, 0, 0x00000051 },  /* LD  ip[81]		      */ +		{ 0x15, 0, 1, DATA_CHAR  },  /* JEQ DATA_CHAR [f goto nomatch]*/ +		{ 0x06, 0, 0, 0x00000060 },  /* RET match	              */ +		{ 0x06, 0, 0, 0x00000000 },  /* RET no match		      */ +	}; +	struct sock_fprog bpf_prog; + +	bpf_prog.filter = bpf_filter; +	bpf_prog.len = sizeof(bpf_filter) / sizeof(struct sock_filter); +	if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &bpf_prog, +		       sizeof(bpf_prog))) { +		perror("setsockopt SO_ATTACH_FILTER"); +		exit(1); +	} +} + +static __maybe_unused void pair_udp_open(int fds[], uint16_t port) +{ +	struct sockaddr_in saddr, daddr; + +	fds[0] = socket(PF_INET, SOCK_DGRAM, 0); +	fds[1] = socket(PF_INET, SOCK_DGRAM, 0); +	if (fds[0] == -1 || fds[1] == -1) { +		fprintf(stderr, "ERROR: socket dgram\n"); +		exit(1); +	} + +	memset(&saddr, 0, sizeof(saddr)); +	saddr.sin_family = AF_INET; +	saddr.sin_port = htons(port); +	saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + +	memset(&daddr, 0, sizeof(daddr)); +	daddr.sin_family = AF_INET; +	daddr.sin_port = htons(port + 1); +	daddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + +	/* must bind both to get consistent hash result */ +	if (bind(fds[1], (void *) &daddr, sizeof(daddr))) { +		perror("bind"); +		exit(1); +	} +	if (bind(fds[0], (void *) &saddr, sizeof(saddr))) { +		perror("bind"); +		exit(1); +	} +	if (connect(fds[0], (void *) &daddr, sizeof(daddr))) { +		perror("connect"); +		exit(1); +	} +} + +static __maybe_unused void pair_udp_send(int fds[], int num) +{ +	char buf[DATA_LEN], rbuf[DATA_LEN]; + +	memset(buf, DATA_CHAR, sizeof(buf)); +	while (num--) { +		/* Should really handle EINTR and EAGAIN */ +		if (write(fds[0], buf, sizeof(buf)) != sizeof(buf)) { +			fprintf(stderr, "ERROR: send failed left=%d\n", num); +			exit(1); +		} +		if (read(fds[1], rbuf, sizeof(rbuf)) != sizeof(rbuf)) { +			fprintf(stderr, "ERROR: recv failed left=%d\n", num); +			exit(1); +		} +		if (memcmp(buf, rbuf, sizeof(buf))) { +			fprintf(stderr, "ERROR: data failed left=%d\n", num); +			exit(1); +		} +	} +} + +static __maybe_unused void pair_udp_close(int fds[]) +{ +	close(fds[0]); +	close(fds[1]); +} + +#endif /* PSOCK_LIB_H */ |