PERFORCE change 197135 for review

Takuya ASADA syuu at FreeBSD.org
Wed Aug 3 14:00:58 UTC 2011


http://p4web.freebsd.org/@@197135?ac=10

Change 197135 by syuu at kikurage on 2011/08/03 14:00:09

	test_mqbpf, test_sqbpf replaced with 'bpfnull' based code, from zcopybpf repository.

Affected files ...

.. //depot/projects/soc2011/mq_bpf/src/tools/regression/bpf/mq_bpf/test_mqbpf/test_mqbpf.c#2 edit
.. //depot/projects/soc2011/mq_bpf/src/tools/regression/bpf/mq_bpf/test_sqbpf/Makefile#2 edit
.. //depot/projects/soc2011/mq_bpf/src/tools/regression/bpf/mq_bpf/test_sqbpf/test_sqbpf.c#2 edit

Differences ...

==== //depot/projects/soc2011/mq_bpf/src/tools/regression/bpf/mq_bpf/test_mqbpf/test_mqbpf.c#2 (text+ko) ====

@@ -1,183 +1,459 @@
-/*	$OpenBSD: bpf.c,v 1.13 2004/05/05 14:28:58 deraadt Exp $	*/
-
-/* BPF socket interface code, originally contributed by Archie Cobbs. */
-
-/*
- * Copyright (c) 1995, 1996, 1998, 1999
- * The Internet Software Consortium.    All rights reserved.
+/*-
+ * Copyright (c) 2007 Seccuris Inc.
+ * Copyright (c) 2007 Christian S.J. Peron
+ * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
- *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of The Internet Software Consortium nor the names
- *    of its contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
- * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * This software has been written for the Internet Software Consortium
- * by Ted Lemon <mellon at fugue.com> in cooperation with Vixie
- * Enterprises.  To learn more about the Internet Software Consortium,
- * see ``http://www.vix.com/isc''.  To learn more about Vixie
- * Enterprises, see ``http://www.vix.com''.
  */
-
 #include <sys/types.h>
-#include <sys/cdefs.h>
+#include <sys/time.h>
 #include <sys/ioctl.h>
-#include <sys/uio.h>
+#include <sys/select.h>
 #include <sys/socket.h>
-#include <sys/time.h>
+#include <sys/mman.h>
 #include <sys/param.h>
 #include <sys/cpuset.h>
-#include <sys/sysctl.h>
+
 #include <net/bpf.h>
-#include <net/if.h>
 #include <netinet/in_systm.h>
 #include <netinet/in.h>
 #include <netinet/ip.h>
-#include <netinet/udp.h>
-#include <netinet/if_ether.h>
+#include <net/if.h>
+#include <net/ethernet.h>
 
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
 #include <fcntl.h>
 #include <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
+#include <signal.h>
 #include <err.h>
+#include <assert.h>
 #include <pthread.h>
-#include <signal.h>
-
-#define CAP_FORMAT "cap.dat.%d"
-#define BPF_FORMAT "/dev/bpf%d"
-
-#define QUEUE_TYPE_RX		0
-#define QUEUE_TYPE_TX		1
-#define QUEUE_TYPE_OTHER	2
 
 struct bpf_thread_instance {
-	pthread_t thread;
-	int rxqueue;
-	int txqueue;
-	int other;
-	int cpu;
-	cpuset_t cpuset;
-	int fd;
-	uint32_t wrote;
+	pthread_t	thread;
+	int 		rxqueue;
+	int		txqueue;
+	int		other;
+	int		cpu;
+	cpuset_t	cpuset;
+	int		bpffd;
+	u_int64_t	sum;	/* cycles spent processing packet data */
+	u_int64_t	rsum;	/* cycles spent in syscalls after wakeup */
+	u_int64_t	ssum;	/* cycles spent not sleep in event  loop */
+	u_int64_t	psum;	/* cycles spent before buffer can be reclaimed */
+	u_char		*bufa, *bufb;
+	unsigned long	count;
+	unsigned long	wrote;
 };
 
 static char *ifname = NULL;
 static struct bpf_thread_instance *instances;
 static int rxqlen, txqlen;
-static struct timeval start;
+
+int		bpf_open(void);
+void		usage(void);
+
+static struct ifreq	 ifr;
+static int		 Iflag;
+static char		*iflag;
+static int		 bflag = 32768;
+static int		 vflag;
+static int		 zflag;
+static int		 Tflag;
+static int		 pflag;
+static int		 Pflag;
+
+#ifndef BPF_BUFMODE_ZBUF
+/*
+ * bpfnull uses certain constructs that depend on zero-copy definitions being
+ * present in bpf.h even when running in normal buffer mode.  If the system
+ * doesn't have these constructs, define them locally.
+ */
+struct bpf_zbuf {
+	void	*bz_bufa;
+	void	*bz_bufb;
+	size_t	 bz_buflen;
+};
+#warning "BPF_BUFMODE_ZBUF not present, building without zero-copy support"
+#endif
+
+static int
+handle_int(int sig __unused)
+{
+	int i;
+	struct bpf_stat bs;
+	double wrote = 0, throughput;
+	u_int64_t	sum = 0;	/* cycles spent processing packet data */
+	u_int64_t	rsum = 0;	/* cycles spent in syscalls after wakeup */
+	u_int64_t	ssum = 0;	/* cycles spent not sleep in event  loop */
+	u_int64_t	psum = 0;	/* cycles spent before buffer can be reclaimed */
+	unsigned long	count = 0;
+#if 0
+	u_int		recv = 0;
+	u_int		drop = 0;
+#endif
+
+	for (i = 0; i < (rxqlen + txqlen + 1); i++) {
+		pthread_cancel(instances[i].thread);
+		pthread_join(instances[i].thread, NULL);
+		wrote += (double)instances[i].wrote / (double)(1024 * 1024);
+		sum += instances[i].sum;
+		rsum += instances[i].rsum;
+		ssum += instances[i].ssum;
+		psum += instances[i].psum;
+		count += instances[i].count;
+#if 0
+		if (ioctl(instances[i].bpffd, BIOCGSTATS, &bs) < 0)
+			err(-1, "BIOCGSTATS");
+		recv += bs.bs_recv;
+		drop += bs.bs_drop;
+#endif
+	}
+
+	putchar('\n');
+	printf("%lu cycles spent processing packets\n", sum);
+	printf("%lu cycles spent in a syscall after wakeup\n", rsum);
+	printf("%lu cycles spent not sleeping\n", ssum);
+	printf("%lu cycles spent before buffer reclaims\n", psum);
+	printf("%lu packets processed\n", count);
+	throughput = (wrote * 8) / 60;
+	printf("wrote:%f MB throughput:%f Mbps\n",
+		wrote, throughput);
+
+#if 0
+	printf("%u packets received (BPF)\n", recv);
+	printf("%u packets dropped (BPF)\n", drop);
+#endif
+
+	exit(0);
+}
 
-int bpf_thread(struct bpf_thread_instance *instance)
+u_int64_t
+rdtsc(void)
 {
-	char filename[50];
-	int bpf, b;
-	int flag = 1, sz;
-	char *rbuf;
-	int rbuf_offset = 0;
-	int rbuf_len = 0;
-	int length = 0;
-	struct bpf_hdr *hdr;
-	struct ifreq ifr;
+	u_int32_t high, low;
+
+	__asm __volatile("rdtsc" : "=a" (low), "=d" (high));
+	return (low | ((u_int64_t) high << 32));
+}
 
-	ifr.ifr_addr.sa_family = AF_LOCAL;
-	strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+/*
+#define CACHE_LINE_SIZE 32
+*/
 
-	CPU_ZERO(&instance->cpuset);
-	CPU_SET(instance->cpu, &instance->cpuset);
-	cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1,
-			   sizeof(cpuset_t), &instance->cpuset);
+static void
+bpf_process_packets(struct bpf_thread_instance *instance, struct bpf_zbuf *bz, char *bufname)
+{
+	int clen, hlen, i;
+	u_char *b,*bp, *ep, *p, by;
+#define bhp ((struct bpf_hdr *)bp)
 
-	snprintf(filename, sizeof(filename), CAP_FORMAT, instance->cpu);
-	instance->fd = open(filename, O_RDWR | O_CREAT);
-	if (instance->fd < 0) {
-		perror("open");
-		return instance->fd;
+	b = bp = bz->bz_bufa;
+	ep = bp + bz->bz_buflen;
+	while (bp < ep) {
+		instance->count++;
+		if (pflag) {
+			/*
+			 * XXXCSJP this prefetch method needs to be
+			 * re-visted
+			 */
+			__builtin_prefetch(bp + bhp->bh_datalen, 0, 3);
+		}
+		clen = bhp->bh_caplen;
+		hlen = bhp->bh_hdrlen;
+		if (Tflag) {
+			for (i = 0; i < bhp->bh_datalen; i++)
+				by = p[i];
+			bp += BPF_WORDALIGN(clen + hlen);
+			continue;
+		}
+		instance->wrote += bhp->bh_caplen;
+		bp += BPF_WORDALIGN(clen + hlen);
 	}
-	/* Open a BPF device */
-	for (b = 0; 1; b++) {
-		snprintf(filename, sizeof(filename), BPF_FORMAT, b);
-		bpf = open(filename, O_RDWR, 0);
-		if (bpf < 0) {
-			if (errno == EBUSY)
-				continue;
-			else {
-				perror("open");
-				return bpf;
+}
+
+static void
+bpf_wait_for_fullbuf(struct bpf_thread_instance *instance)
+{
+	fd_set s_set, r_set;
+	struct bpf_zbuf bz;
+	char *pbuf;
+	int n;
+	struct bpf_zbuf_header *bzha, *bzhb;
+	struct timeval tv;
+	void *prev2, *prev;
+	u_int64_t b, a, c, d, e, f;
+
+	prev2 = prev = NULL;
+	pbuf = malloc(bflag + 1);
+	if (pbuf == NULL)
+		err(1, "malloc");
+	tv.tv_sec = 1;
+	tv.tv_usec = 0;
+	FD_SET(instance->bpffd, &s_set);
+        for (;;) {
+		r_set = s_set;
+		n = select(instance->bpffd + 1, &r_set, NULL, NULL, &tv);
+		e = rdtsc();
+		if (n < 0) {
+			fprintf(stderr,"owned by select\n");
+			err(1, "select failed");
+		}
+		if (vflag)
+			(void) fprintf(stderr, "select wakeup\n");
+		if (n != 0 && !FD_ISSET(instance->bpffd, &r_set) && vflag)
+			printf("No timeout and fd is not ready!\n");
+#ifdef BPF_BUFMODE_ZBUF
+		if (zflag == 0) {
+#endif
+			c = rdtsc();
+			n = read(instance->bpffd, pbuf, bflag);
+			d = rdtsc();
+			if (n < 0)
+//				err(1, "read failed");
+				fprintf(stderr, "read failed");
+			instance->psum += d - e;
+			instance->rsum += d - c;
+			bz.bz_bufa = pbuf;
+			bz.bz_buflen = n;
+			b = rdtsc();
+			bpf_process_packets(instance, &bz, "W");
+			a = rdtsc();
+			instance->sum += a - b;
+#ifdef BPF_BUFMODE_ZBUF
+		} else {
+			bzha = (struct bpf_zbuf_header *)instance->bufa;
+			bzhb = (struct bpf_zbuf_header *)instance->bufb;
+			if (n == 0) {
+				c = rdtsc();
+				if (ioctl(instance->bpffd, BIOCROTZBUF, &bz) < 0)
+					err(1, "ioctl");
+				d = rdtsc();
+				instance->rsum += d - c;
+				if (bz.bz_bufa == NULL) {
+					if (vflag)
+					printf("timeout no data\n");
+					continue;
+				}
+			}
+			assert(bzha->bzh_kernel_gen > bzha->bzh_user_gen ||
+			    bzhb->bzh_kernel_gen > bzhb->bzh_user_gen);
+			if (bzha->bzh_kernel_gen > bzha->bzh_user_gen) {
+				bz.bz_bufa = instance->bufa;
+				bz.bz_bufa += sizeof(struct bpf_zbuf_header);
+				bz.bz_buflen = bzha->bzh_kernel_len;
+				b = rdtsc();
+				bpf_process_packets(instance, &bz, "A");
+				a = rdtsc();
+				instance->sum += a - b;
+				instance->psum += a - e;
+				bzha->bzh_user_gen++;
+			} else if (bzhb->bzh_kernel_gen > bzhb->bzh_user_gen) {
+				bz.bz_bufa = instance->bufb;
+				bz.bz_bufa += sizeof(struct bpf_zbuf_header);
+				bz.bz_buflen = bzhb->bzh_kernel_len;
+				b = rdtsc();
+				bpf_process_packets(instance, &bz, "B");
+				a = rdtsc();
+				instance->sum += a - b;
+				instance->psum += a - e;
+				bzhb->bzh_user_gen++;
 			}
-		} else
+		}
+#endif
+		f = rdtsc();
+		instance->ssum += f - e;
+        }
+}
+
+int
+bpf_open(void)
+{
+	char buf[32];
+	int i, ret;
+
+	for (i = 0; i < 8; i++) {
+		snprintf(buf, sizeof(buf), "/dev/bpf%d", i);
+		ret = open(buf, O_RDWR);
+		if (ret != -1)
 			break;
+		else if (errno != EBUSY)
+			(void) fprintf(stderr, "open %s: %s\n",
+			    buf, strerror(errno));
 	}
+	return (ret);
+}
+
+void
+usage()
+{
+
+	(void) fprintf(stderr, "usage: bpfnull [-ipPTwvz] [-b bufsize] "
+	    "[-c limit] [-f file] -i interface\n");
+	exit(0);
+}
+
+#ifdef BPF_BUFMODE_ZBUF
+static int
+bpf_zbuf_init(struct bpf_thread_instance *instance, struct bpf_zbuf *bz)
+{
+	int bmode;
+	u_int zbufmax;
 
-	/* Set the BPF device to point at this interface. */
-	if (ioctl(bpf, BIOCSETIF, &ifr) < 0) {
-		perror("SETIF");
-		return -1;
+	if ((bflag % getpagesize()) != 0)
+		errx(1, "-b must be multiple of system page size");
+	bz->bz_buflen = bflag;
+	instance->bufa = mmap(NULL, bz->bz_buflen, PROT_READ | PROT_WRITE,
+	    MAP_ANON, -1, 0);
+	if (instance->bufa == MAP_FAILED)
+		err(1, "mmap(bufa)");
+	instance->bufb = mmap(NULL, bz->bz_buflen, PROT_READ | PROT_WRITE,
+	    MAP_ANON, -1, 0);
+	if (instance->bufb == MAP_FAILED)
+		err(1, "mmap(bufb)");
+	bz->bz_bufa = instance->bufa;
+	bz->bz_bufb = instance->bufb;
+	bmode = BPF_BUFMODE_ZBUF;
+	if (ioctl(instance->bpffd, BIOCSETBUFMODE, &bmode) < 0)
+		err(1, "ioctl(BIOCGSETBUFMODE)");
+	if (ioctl(instance->bpffd, BIOCGETZMAX, (caddr_t)&zbufmax) < 0) {
+		err(1, "ioctl(BIOCGETZMAX)");
+	}
+	if (bz->bz_buflen > zbufmax) {
+		printf("zbufmax is smaller than buflen:%d\n", zbufmax);
 	}
+	if (ioctl(instance->bpffd, BIOCSETZBUF, bz) < 0)
+		err(1, "ioctl(BIOCSETZBUF)");
+	if (vflag)
+		(void) fprintf(stderr,
+		    "DEBUG: bufa=%p bufb=%p\n", instance->bufa, instance->bufb);
+	return (0);
+}
+#endif
+
+static int
+bpf_rbuf_init(struct bpf_thread_instance *instance)
+{
+	int v, bmode;
 
-	/*
-	 * Set immediate mode so that reads return as soon as a packet
-	 * comes in, rather than waiting for the input buffer to fill
-	 * with packets.
-	 */
-	if (ioctl(bpf, BIOCIMMEDIATE, &flag) < 0) {
-		perror("IMMEDIATE");
-		return -1;
+#ifdef BPF_BUFMODE_ZBUF
+	bmode = BPF_BUFMODE_BUFFER;
+
+	if (ioctl(instance->bpffd, BIOCGETBUFMODE, &bmode) < 0)
+		err(1, "ioctl(BIOCGETBUFMODE)");
+#endif
+	for (v = bflag; v != 0; v >>= 1) {
+		(void) ioctl(instance->bpffd, BIOCSBLEN, &v);
+		if (ioctl(instance->bpffd, BIOCSETIF, &ifr) == 0)
+			break;
 	}
+	if (ioctl(instance->bpffd, BIOCFLUSH, NULL) < 0)
+		err(1, "ioctl(BIOCFLUSH)");
+	return (0);
+}
 
-	/* Get the required BPF buffer length from the kernel. */
-	if (ioctl(bpf, BIOCGBLEN, &sz) < 0) {
-		perror("BLEN");
-		return -1;
+int bpf_thread(struct bpf_thread_instance *instance)
+{
+	struct bpf_zbuf bz;
+	struct ifreq ifr;
+	int opt;
+
+	CPU_ZERO(&instance->cpuset);
+	CPU_SET(instance->cpu, &instance->cpuset);
+	cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1,
+			   sizeof(cpuset_t), &instance->cpuset);
+
+	bzero(&ifr, sizeof(ifr));
+	strlcpy(ifr.ifr_name, iflag, sizeof(ifr.ifr_name));
+	instance->bpffd = bpf_open();
+	if (instance->bpffd == -1) {
+		(void) fprintf(stderr, "bpfnull: no bpf device available\n");
+		exit(1);
+	}
+	if (vflag)
+		(void) fprintf(stderr,
+		    "DEBUG: obtained bpf fd=%d\n", instance->bpffd);
+#ifdef BPF_BUFMODE_ZBUF
+	if (zflag) {
+		if (vflag)
+			(void) fprintf(stderr,
+			    "DEBUG: bufmode=zerocopy\n");
+		bzero(&bz, sizeof(bz));
+		bpf_zbuf_init(instance, &bz);
+		if (ioctl(instance->bpffd, BIOCSETIF, &ifr) < 0)
+			err(1, "ioctl(BIOCSETIF)");
+	} else {
+#endif
+		if (vflag)
+			(void) fprintf(stderr,
+			    "DEBUG: bufmode=buffer\n");
+		bpf_rbuf_init(instance);
+#ifdef BPF_BUFMODE_ZBUF
+	}
+#endif
+	if (Iflag) {
+		if (vflag)
+			(void) fprintf(stderr,
+			    "DEBUG: setting BIOCIMMEDIATE\n");
+		opt = 1;
+		if (ioctl(instance->bpffd, BIOCIMMEDIATE, &opt) < 0)
+			err(1, "BIOCIMMEDIATE");
 	}
-	rbuf = malloc(sz);
-	if (!rbuf) {
-		perror("malloc");
-		return -1;
+	if (Pflag) {
+		if (vflag)
+			(void) fprintf(stderr,
+			    "DEBUG: putting card into promiscuous "
+			    "mode\n");
+		if (ioctl(instance->bpffd, BIOCPROMISC, NULL) < 0)
+			err(1, "BIOCPROMISC");
 	}
+	if (vflag)
+		(void) fprintf(stderr,
+		    "DEBUG: attaching to %s\n", iflag);
 
-	if (ioctl(bpf, BIOCENAQMASK, NULL) < 0) {
+	if (ioctl(instance->bpffd, BIOCENAQMASK, NULL) < 0) {
 		perror("enable qmask");
 		return -1;
 	}
 
 	if (instance->rxqueue > -1) {
-		if (ioctl(bpf, BIOCSTRXQMASK, &instance->rxqueue) < 0) {
+		if (ioctl(instance->bpffd, BIOCSTRXQMASK, &instance->rxqueue) < 0) {
 			perror("rx qmask");
 			return -1;
 		}
 	}
 
 	if (instance->txqueue > -1) {
-		if (ioctl(bpf, BIOCSTTXQMASK, &instance->txqueue) < 0) {
+		if (ioctl(instance->bpffd, BIOCSTTXQMASK, &instance->txqueue) < 0) {
 			perror("tx qmask");
 			return -1;
 		}
 	}
 	if (instance->other > -1) {
-		if (ioctl(bpf, BIOCSTOTHERMASK, &instance->other) < 0) {
+		if (ioctl(instance->bpffd, BIOCSTOTHERMASK, &instance->other) < 0) {
 			perror("other qmask");
 			return -1;
 		}
@@ -185,96 +461,18 @@
 
 	instance->wrote = 0;
 
-	while(1) {
-		/* If the buffer is empty, fill it. */
-		if (rbuf_offset >= rbuf_len) {
-			length = read(bpf, rbuf,
-			    sz);
-			if (length < 0) {
-				perror("read");
-				return length;
-			}
-			rbuf_offset = 0;
-			rbuf_len = length;
-		}
 
-		/*
-		 * If there isn't room for a whole bpf header, something
-		 * went wrong, but we'll ignore it and hope it goes
-		 * away... XXX
-		 */
-		if (rbuf_len - rbuf_offset <
-		    sizeof(struct bpf_hdr)) {
-			rbuf_offset = rbuf_len;
-			printf("rbuf_len - rbuf_offset < sizeof(struct bpf_hdr)\n");
-			continue;
-		}
-
-		hdr = (struct bpf_hdr *)&rbuf[rbuf_offset];
-
-		/*
-		 * If the bpf header plus data doesn't fit in what's
-		 * left of the buffer, stick head in sand yet again...
-		 */
-		if (rbuf_offset + hdr->bh_hdrlen + hdr->bh_caplen >
-		    rbuf_len) {
-			rbuf_offset = rbuf_len;
-			printf("rbuf_offset + hdr->bh_hdrlen + hdr->bh_caplen > rbuf_len\n");
-			continue;
-		}
-
-		/* Skip over the BPF header... */
-		rbuf_offset += hdr->bh_hdrlen;
-
-		/*
-		 * If the captured data wasn't the whole packet, or if
-		 * the packet won't fit in the input buffer, all we can
-		 * do is drop it.
-		 */
-		if (hdr->bh_caplen != hdr->bh_datalen) {
-			rbuf_offset =
-			    BPF_WORDALIGN(rbuf_offset +
-			    hdr->bh_caplen);
-			printf("hdr->bh_caplen != hdr->bh_datalen\n");
-			continue;
-		}
-
-		/* Copy out the data in the packet... */
-		write(instance->fd, rbuf + rbuf_offset, hdr->bh_caplen);
-		instance->wrote += hdr->bh_caplen;
-		rbuf_offset =
-		    BPF_WORDALIGN(rbuf_offset +
-		    hdr->bh_caplen);
-	}
+	bpf_wait_for_fullbuf(instance);
 	return 0;
 }
 
-static void timer_handler(int arg)
+int
+main(int argc, char *argv[])
 {
-	struct timeval curr;
-	time_t sec;
-	int i, ret;
-	uint32_t wrote = 0;
-
-	for (i = 0; i < (rxqlen + txqlen + 1); i++) {
-		pthread_cancel(instances[i].thread);
-		pthread_join(instances[i].thread, (void **)&ret);
-		wrote += instances[i].wrote;
-	}
-	gettimeofday(&curr, NULL);
-	sec = curr.tv_sec - start.tv_sec;
-	wrote /= (1024 * 1024);
-	printf("sec:%ld  wrote:%d MB  thoughput:%f MB/s\n",
-		sec, wrote, (double)wrote / (double)sec);
-	exit(0);
-}
-
-int main(int argc, char **argv)
-{
-	struct	ifreq ifr;
-	int i, s, ret, maxcpus;
+	char ch;
+	int i, s, maxcpus;
 	struct sigaction action = {
-		.sa_handler = timer_handler,
+		.sa_handler = (void (*)(int))handle_int,
 		.sa_flags = 0
 	};
 	struct itimerval timer = {
@@ -288,14 +486,53 @@
 		}
 	};
 
-	if (argc < 2) {
-		printf("usage: %s [ifname]\n", argv[0]);
+	sigemptyset(&action.sa_mask);
+	if (sigaction(SIGALRM, &action, NULL) < 0) {
+		perror("sigaction");
+		return -1;
+	}
+	if (setitimer(ITIMER_REAL, &timer, NULL) < 0) {
+		perror("setitimer");
 		return -1;
 	}
-
-	ifname = argv[1];
+	signal(SIGINT, (void *)handle_int);
+	while ((ch = getopt(argc, argv, "b:c:f:hIi:pPTwvz")) != -1) {
+		switch (ch) {
+		case 'b':
+			bflag = atoi(optarg);
+			break;
+		case 'i':
+			iflag = optarg;
+			break;
+		case 'I':
+			Iflag = 1;
+			break;
+		case 'p':
+			pflag = 1;
+			break;
+		case 'P':
+			Pflag = 1;
+			break;
+		case 'T':
+			Tflag = 1;
+			break;
+		case 'v':
+			vflag++;
+			break;
+#ifdef BPF_BUFMODE_ZBUF
+		case 'z':
+			zflag++;
+			break;
+#endif
+		default:
+			usage();
+		}
+	}
+	if (iflag == NULL)
+		usage();
+	
 	ifr.ifr_addr.sa_family = AF_LOCAL;
-	strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+	strncpy(ifr.ifr_name, iflag, sizeof(ifr.ifr_name));
 	s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0);
 	if (s < 0) {
 		perror("socket");
@@ -314,18 +551,6 @@
 	instances = (struct bpf_thread_instance *)
 		calloc(maxcpus, sizeof(struct bpf_thread_instance));
 
-	sigemptyset(&action.sa_mask);
-	if (sigaction(SIGALRM, &action, NULL) < 0) {
-		perror("sigaction");
-		return -1;
-	}
-	if (setitimer(ITIMER_REAL, &timer, NULL) < 0) {
-		perror("setitimer");
-		return -1;
-	}
-
-	gettimeofday(&start, NULL);
-
 	for (i = 0; i < maxcpus; i++) {
 		instances[i].cpu = i;
 		instances[i].rxqueue = -1;
@@ -358,7 +583,7 @@
 			(void *(*)(void *))bpf_thread, &instances[i]);
 
 	for (i = 0; i < maxcpus; i++)
-		pthread_join(instances[i].thread, (void **)&ret);
+		pthread_join(instances[i].thread, NULL);
 
-	return 0;
+	return (0);
 }

==== //depot/projects/soc2011/mq_bpf/src/tools/regression/bpf/mq_bpf/test_sqbpf/Makefile#2 (text+ko) ====

@@ -1,5 +1,7 @@
 PROG=	test_sqbpf
 SRCS+=	test_sqbpf.c
+DPADD=	${LIBPCAP}
+LDADD=	-lpcap
 NO_MAN=
 
 .include <bsd.prog.mk>

==== //depot/projects/soc2011/mq_bpf/src/tools/regression/bpf/mq_bpf/test_sqbpf/test_sqbpf.c#2 (text+ko) ====

@@ -1,101 +1,377 @@
-/*	$OpenBSD: bpf.c,v 1.13 2004/05/05 14:28:58 deraadt Exp $	*/
-
-/* BPF socket interface code, originally contributed by Archie Cobbs. */
-
-/*
- * Copyright (c) 1995, 1996, 1998, 1999
- * The Internet Software Consortium.    All rights reserved.
+/*-
+ * Copyright (c) 2007 Seccuris Inc.
+ * Copyright (c) 2007 Christian S.J. Peron
+ * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
- *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of The Internet Software Consortium nor the names
- *    of its contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
- * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * This software has been written for the Internet Software Consortium
- * by Ted Lemon <mellon at fugue.com> in cooperation with Vixie
- * Enterprises.  To learn more about the Internet Software Consortium,
- * see ``http://www.vix.com/isc''.  To learn more about Vixie
- * Enterprises, see ``http://www.vix.com''.
  */
-
 #include <sys/types.h>
-#include <sys/cdefs.h>
+#include <sys/time.h>
 #include <sys/ioctl.h>
-#include <sys/uio.h>
+#include <sys/select.h>
 #include <sys/socket.h>
-#include <sys/time.h>
+#include <sys/mman.h>
+
 #include <net/bpf.h>
-#include <net/if.h>
 #include <netinet/in_systm.h>
 #include <netinet/in.h>
 #include <netinet/ip.h>
-#include <netinet/udp.h>
-#include <netinet/if_ether.h>
+#include <net/if.h>
+#include <net/ethernet.h>
 
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
 #include <fcntl.h>
 #include <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
+#include <signal.h>
 #include <err.h>
-#include <signal.h>
+#include <pcap.h>
+#include <assert.h>
+
+int		bpf_open(void);
+void		usage(void);
+u_int64_t	sum;	/* cycles spent processing packet data */
+u_int64_t	rsum;	/* cycles spent in syscalls after wakeup */
+u_int64_t	ssum;	/* cycles spent not sleep in event  loop */
+u_int64_t	psum;	/* cycles spent before buffer can be reclaimed */
+
+static struct ifreq	 ifr;
+static pcap_dumper_t	*dp;
+static pcap_t		*p;
+static int		 bpffd = -1;
+static char		*fflag = "-";
+static unsigned long	 cflag;
+static int		 Iflag;
+static char		*iflag;
+static int		 bflag = 32768;
+static int		 wflag;
+static int		 vflag;
+static int		 zflag;
+static int		 Tflag;
+static int		 pflag;
+static int		 Pflag;
+
+static u_char		*bufa, *bufb;
+static unsigned long		 packet_count;
+static unsigned long		packet_wrote;
+
+#ifndef BPF_BUFMODE_ZBUF
+/*
+ * bpfnull uses certain constructs that depend on zero-copy definitions being
+ * present in bpf.h even when running in normal buffer mode.  If the system
+ * doesn't have these constructs, define them locally.
+ */
+struct bpf_zbuf {
+	void	*bz_bufa;
+	void	*bz_bufb;
+	size_t	 bz_buflen;
+};
+#warning "BPF_BUFMODE_ZBUF not present, building without zero-copy support"
+#endif
+
+static int
+handle_int(int sig __unused)
+{
+	struct bpf_stat bs;
+	double wrote, throughput;
+
+	putchar('\n');
+	printf("%lu cycles spent processing packets\n", sum);
+	printf("%lu cycles spent in a syscall after wakeup\n", rsum);
+	printf("%lu cycles spent not sleeping\n", ssum);
+	printf("%lu cycles spent before buffer reclaims\n", psum);
+	printf("%lu packets processed\n", packet_count);
+	wrote = (double)packet_wrote / (double)(1024 * 1024);
+	throughput = (wrote * 8) / 60;
+	printf("wrote:%f MB throughput:%f Mbps\n",
+		wrote, throughput);
+	if (ioctl(bpffd, BIOCGSTATS, &bs) < 0)
+		err(-1, "BIOCGSTATS");
+
+	printf("%u packets received (BPF)\n", bs.bs_recv);
+	printf("%u packets dropped (BPF)\n", bs.bs_drop);
+
+	exit(0);
+}
+
+u_int64_t
+rdtsc(void)
+{
+	u_int32_t high, low;
+
+	__asm __volatile("rdtsc" : "=a" (low), "=d" (high));
+	return (low | ((u_int64_t) high << 32));
+}
+
+static void
+bpf_init_dumpfile(void)
+{
+
+	if (wflag == 0)
+		return;
+	p = pcap_open_dead(DLT_EN10MB, 0xffffU);
+	dp = pcap_dump_open(p, fflag);
+	if (dp == NULL) {
+		pcap_perror(p, fflag);
+		exit(1);
+	}
+}
+
+#define CACHE_LINE_SIZE 32
+
+static void
+bpf_process_packets(struct bpf_zbuf *bz, char *bufname)
+{
+	struct pcap_pkthdr phd;
+	int clen, hlen, i;
+	u_char *b,*bp, *ep, *p, by;
+#define bhp ((struct bpf_hdr *)bp)
+
+	b = bp = bz->bz_bufa;
+	ep = bp + bz->bz_buflen;
+	while (bp < ep) {
+		packet_count++;
+		if (cflag > 0 && packet_count > cflag)
+			exit(0);
+		if (pflag) {
+			/*
+			 * XXXCSJP this prefetch method needs to be
+			 * re-visted
+			 */
+			__builtin_prefetch(bp + bhp->bh_datalen, 0, 3);
+		}
+		clen = bhp->bh_caplen;
+		hlen = bhp->bh_hdrlen;
+		p = (u_char *)bp + hlen;
+		phd.ts.tv_sec = bhp->bh_tstamp.tv_sec;
+		phd.ts.tv_usec = bhp->bh_tstamp.tv_usec;

>>> TRUNCATED FOR MAIL (1000 lines) <<<


More information about the p4-projects mailing list