Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 3 May 2012 15:37:06 +0000 (UTC)
From:      Luigi Rizzo <luigi@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r234956 - head/tools/tools/netmap
Message-ID:  <201205031537.q43Fb6Op049335@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: luigi
Date: Thu May  3 15:37:05 2012
New Revision: 234956
URL: http://svn.freebsd.org/changeset/base/234956

Log:
  - add code to run pkt-gen on top of libpcap so we can see the
    difference from a native API
  
  - add some testing options, such as conditional prefetching and
    packet copy.

Modified:
  head/tools/tools/netmap/pkt-gen.c

Modified: head/tools/tools/netmap/pkt-gen.c
==============================================================================
--- head/tools/tools/netmap/pkt-gen.c	Thu May  3 15:34:44 2012	(r234955)
+++ head/tools/tools/netmap/pkt-gen.c	Thu May  3 15:37:05 2012	(r234956)
@@ -25,7 +25,7 @@
 
 /*
  * $FreeBSD$
- * $Id: pkt-gen.c 10637 2012-02-24 16:36:25Z luigi $
+ * $Id: pkt-gen.c 10967 2012-05-03 11:29:23Z luigi $
  *
  * Example program to show how to build a multithreaded packet
  * source/sink using the netmap device.
@@ -90,6 +90,36 @@ int verbose = 0;
 
 #define SKIP_PAYLOAD 1 /* do not check payload. */
 
+inline void prefetch (const void *x)
+{
+        __asm volatile("prefetcht0 %0" :: "m" (*(const unsigned long *)x));
+}
+
+// XXX only for multiples of 32 bytes, non overlapped.
+static inline void
+pkt_copy(void *_src, void *_dst, int l)
+{
+	uint64_t *src = _src;
+	uint64_t *dst = _dst;
+#define likely(x)       __builtin_expect(!!(x), 1)
+#define unlikely(x)       __builtin_expect(!!(x), 0)
+	if (unlikely(l >= 1024)) {
+		bcopy(src, dst, l);
+		return;
+	}
+	for (; l > 0; l-=64) {
+		*dst++ = *src++;
+		*dst++ = *src++;
+		*dst++ = *src++;
+		*dst++ = *src++;
+		*dst++ = *src++;
+		*dst++ = *src++;
+		*dst++ = *src++;
+		*dst++ = *src++;
+	}
+}
+
+
 #if EXPERIMENTAL
 /* Wrapper around `rdtsc' to take reliable timestamps flushing the pipeline */ 
 #define netmap_rdtsc(t) \
@@ -140,6 +170,11 @@ struct glob_arg {
 	int npackets;	/* total packets to send */
 	int nthreads;
 	int cpus;
+	int options;	/* testing */
+#define OPT_PREFETCH	1
+#define OPT_ACCESS	2
+#define OPT_COPY	4
+#define OPT_MEMCPY	8
 	int use_pcap;
 	pcap_t *p;
 };
@@ -394,19 +429,35 @@ check_payload(char *p, int psize)
  */
 static int
 send_packets(struct netmap_ring *ring, struct pkt *pkt, 
-		int size, u_int count, int fill_all)
+		int size, u_int count, int options)
 {
 	u_int sent, cur = ring->cur;
 
 	if (ring->avail < count)
 		count = ring->avail;
 
+#if 0
+	if (options & (OPT_COPY | OPT_PREFETCH) ) {
+		for (sent = 0; sent < count; sent++) {
+			struct netmap_slot *slot = &ring->slot[cur];
+			char *p = NETMAP_BUF(ring, slot->buf_idx);
+
+			prefetch(p);
+			cur = NETMAP_RING_NEXT(ring, cur);
+		}
+		cur = ring->cur;
+	}
+#endif
 	for (sent = 0; sent < count; sent++) {
 		struct netmap_slot *slot = &ring->slot[cur];
 		char *p = NETMAP_BUF(ring, slot->buf_idx);
 
-		if (fill_all)
+		if (options & OPT_COPY)
+			pkt_copy(pkt, p, size);
+		else if (options & OPT_MEMCPY)
 			memcpy(p, pkt, size);
+		else if (options & OPT_PREFETCH)
+			prefetch(p);
 
 		slot->len = size;
 		if (sent == count - 1)
@@ -428,8 +479,8 @@ sender_body(void *data)
 	struct netmap_if *nifp = targ->nifp;
 	struct netmap_ring *txring;
 	int i, n = targ->g->npackets / targ->g->nthreads, sent = 0;
-	int fill_all = 1;
-
+	int options = targ->g->options | OPT_COPY;
+D("start");
 	if (setaffinity(targ->thread, targ->affinity))
 		goto quit;
 	/* setup poll(2) mechanism. */
@@ -444,9 +495,13 @@ sender_body(void *data)
 	void *pkt = &targ->pkt;
 	pcap_t *p = targ->g->p;
 
-	for (; sent < n; sent++) {
-		if (pcap_inject(p, pkt, size) == -1)
-			break;
+	for (i = 0; sent < n; i++) {
+		if (pcap_inject(p, pkt, size) != -1)
+			sent++;
+		if (i > 10000) {
+			targ->count = sent;
+			i = 0;
+		}
 	}
     } else {
 	while (sent < n) {
@@ -461,8 +516,8 @@ sender_body(void *data)
 		/*
 		 * scan our queues and send on those with room
 		 */
-		if (sent > 100000)
-			fill_all = 0;
+		if (sent > 100000 && !(targ->g->options & OPT_COPY) )
+			options &= ~OPT_COPY;
 		for (i = targ->qfirst; i < targ->qlast; i++) {
 			int m, limit = MIN(n - sent, targ->g->burst);
 
@@ -470,12 +525,12 @@ sender_body(void *data)
 			if (txring->avail == 0)
 				continue;
 			m = send_packets(txring, &targ->pkt, targ->g->pkt_size,
-					 limit, fill_all);
+					 limit, options);
 			sent += m;
 			targ->count = sent;
 		}
 	}
-	/* Tell the interface that we have new packets. */
+	/* flush any remaining packets */
 	ioctl(fds[0].fd, NIOCTXSYNC, NULL);
 
 	/* final part: wait all the TX queues to be empty. */
@@ -672,6 +727,7 @@ int
 main(int arc, char **argv)
 {
 	int i, fd;
+	char pcap_errbuf[PCAP_ERRBUF_SIZE];
 
 	struct glob_arg g;
 
@@ -696,12 +752,15 @@ main(int arc, char **argv)
 	g.cpus = 1;
 
 	while ( (ch = getopt(arc, argv,
-			"i:t:r:l:d:s:D:S:b:c:p:T:w:v")) != -1) {
+			"i:t:r:l:d:s:D:S:b:c:o:p:PT:w:v")) != -1) {
 		switch(ch) {
 		default:
 			D("bad option %c %s", ch, optarg);
 			usage();
 			break;
+		case 'o':
+			g.options = atoi(optarg);
+			break;
 		case 'i':	/* interface */
 			ifname = optarg;
 			break;
@@ -775,6 +834,26 @@ main(int arc, char **argv)
 		usage();
 	}
 
+	if (td_body == sender_body && g.src_mac == NULL) {
+		static char mybuf[20] = "ff:ff:ff:ff:ff:ff";
+		/* retrieve source mac address. */
+		if (source_hwaddr(ifname, mybuf) == -1) {
+			D("Unable to retrieve source mac");
+			// continue, fail later
+		}
+		g.src_mac = mybuf;
+	}
+
+    if (g.use_pcap) {
+	D("using pcap on %s", ifname);
+	g.p = pcap_open_live(ifname, 0, 1, 100, pcap_errbuf);
+	if (g.p == NULL) {
+		D("cannot open pcap on %s", ifname);
+		usage();
+	}
+	mmap_addr = NULL;
+	fd = -1;
+    } else {
 	bzero(&nmr, sizeof(nmr));
 	nmr.nr_version = NETMAP_API;
 	/*
@@ -811,16 +890,6 @@ main(int arc, char **argv)
 		// continue, fail later
 	}
 
-	if (td_body == sender_body && g.src_mac == NULL) {
-		static char mybuf[20] = "ff:ff:ff:ff:ff:ff";
-		/* retrieve source mac address. */
-		if (source_hwaddr(ifname, mybuf) == -1) {
-			D("Unable to retrieve source mac");
-			// continue, fail later
-		}
-		g.src_mac = mybuf;
-	}
-
 	/*
 	 * Map the netmap shared memory: instead of issuing mmap()
 	 * inside the body of the threads, we prefer to keep this
@@ -869,8 +938,15 @@ main(int arc, char **argv)
 		D("aborting");
 		usage();
 	}
+    }
 
-
+	if (g.options) {
+		D("special options:%s%s%s%s\n",
+			g.options & OPT_PREFETCH ? " prefetch" : "",
+			g.options & OPT_ACCESS ? " access" : "",
+			g.options & OPT_MEMCPY ? " memcpy" : "",
+			g.options & OPT_COPY ? " copy" : "");
+	}
 	/* Wait for PHY reset. */
 	D("Wait %d secs for phy reset", wait_link);
 	sleep(wait_link);
@@ -881,7 +957,12 @@ main(int arc, char **argv)
 	signal(SIGINT, sigint_h);
 
 	if (g.use_pcap) {
-		// XXX g.p = pcap_open_live(..);
+		g.p = pcap_open_live(ifname, 0, 1, 100, NULL);
+		if (g.p == NULL) {
+			D("cannot open pcap on %s", ifname);
+			usage();
+		} else
+			D("using pcap %p on %s", g.p, ifname);
 	}
 
 	targs = calloc(g.nthreads, sizeof(*targs));
@@ -1018,9 +1099,11 @@ main(int arc, char **argv)
 		rx_output(count, delta_t);
     }
 
+    if (g.use_pcap == 0) {
 	ioctl(fd, NIOCUNREGIF, &nmr);
 	munmap(mmap_addr, nmr.nr_memsize);
 	close(fd);
+    }
 
 	return (0);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201205031537.q43Fb6Op049335>