svn commit: r251426 - head/tools/tools/netmap

Luigi Rizzo luigi at FreeBSD.org
Wed Jun 5 17:38:00 UTC 2013


Author: luigi
Date: Wed Jun  5 17:37:59 2013
New Revision: 251426
URL: http://svnweb.freebsd.org/changeset/base/251426

Log:
  new features (mostly for testing netmap capabilities)
  
  + pkt-gen -f rx now remains active even when traffic stops
    Previous behaviour (exit after 1 second of silence) can be
    restored with the -W option
  
  + the -X option does a hexdump of the content of a packet (both tx and rx).
    This can be useful to check what goes in and out.
  
  + the -I option instructs the sender to use indirect buffers
    (not really useful other than to test the kernel module in the
    VALE switch)

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

Modified: head/tools/tools/netmap/pkt-gen.c
==============================================================================
--- head/tools/tools/netmap/pkt-gen.c	Wed Jun  5 17:27:59 2013	(r251425)
+++ head/tools/tools/netmap/pkt-gen.c	Wed Jun  5 17:37:59 2013	(r251426)
@@ -38,6 +38,8 @@
 
 #include "nm_util.h"
 
+#include <ctype.h>	// isprint()
+
 const char *default_payload="netmap pkt-gen payload\n"
 	"http://info.iet.unipi.it/~luigi/netmap/ ";
 
@@ -86,6 +88,8 @@ struct glob_arg {
 #define OPT_COPY	4
 #define OPT_MEMCPY	8
 #define OPT_TS		16	/* add a timestamp */
+#define OPT_INDIRECT	32	/* use indirect buffers, tx only */
+#define OPT_DUMP	64	/* dump rx/tx traffic */
 	int dev_type;
 	pcap_t *p;
 
@@ -346,6 +350,33 @@ wrapsum(u_int32_t sum)
 	return (htons(sum));
 }
 
+/* Check the payload of the packet for errors (use it for debug).
+ * Look for consecutive ascii representations of the size of the packet.
+ */
+static void
+dump_payload(char *p, int len, struct netmap_ring *ring, int cur)
+{
+	char buf[128];
+	int i, j, i0;
+
+	/* get the length in ASCII of the length of the packet. */
+	
+	printf("ring %p cur %5d len %5d buf %p\n", ring, cur, len, p);
+	/* hexdump routine */
+	for (i = 0; i < len; ) {
+		memset(buf, sizeof(buf), ' ');
+		sprintf(buf, "%5d: ", i);
+		i0 = i;
+		for (j=0; j < 16 && i < len; i++, j++)
+			sprintf(buf+7+j*3, "%02x ", (uint8_t)(p[i]));
+		i = i0;
+		for (j=0; j < 16 && i < len; i++, j++)
+			sprintf(buf+7+j + 48, "%c",
+				isprint(p[i]) ? p[i] : '.');
+		printf("%s\n", buf);
+	}
+}
+
 /*
  * Fill a packet with some payload.
  * We create a UDP packet so the payload starts at
@@ -357,6 +388,7 @@ wrapsum(u_int32_t sum)
 #define uh_ulen len
 #define uh_sum check
 #endif /* linux */
+
 static void
 initialize_packet(struct targ *targ)
 {
@@ -365,11 +397,13 @@ initialize_packet(struct targ *targ)
 	struct ip *ip;
 	struct udphdr *udp;
 	uint16_t paylen = targ->g->pkt_size - sizeof(*eh) - sizeof(struct ip);
-	int i, l, l0 = strlen(default_payload);
+	const char *payload = targ->g->options & OPT_INDIRECT ?
+		"XXXXXXXXXXXXXXXXXXXXXX" : default_payload;
+	int i, l, l0 = strlen(payload);
 
 	for (i = 0; i < paylen;) {
 		l = min(l0, paylen - i);
-		bcopy(default_payload, pkt->body + i, l);
+		bcopy(payload, pkt->body + i, l);
 		i += l;
 	}
 	pkt->body[i-1] = '\0';
@@ -415,34 +449,9 @@ initialize_packet(struct targ *targ)
 	bcopy(&targ->g->src_mac.start, eh->ether_shost, 6);
 	bcopy(&targ->g->dst_mac.start, eh->ether_dhost, 6);
 	eh->ether_type = htons(ETHERTYPE_IP);
+	// dump_payload((void *)pkt, targ->g->pkt_size, NULL, 0);
 }
 
-/* Check the payload of the packet for errors (use it for debug).
- * Look for consecutive ascii representations of the size of the packet.
- */
-static void
-check_payload(char *p, int psize)
-{
-	char temp[64];
-	int n_read, size, sizelen;
-
-	/* get the length in ASCII of the length of the packet. */
-	sizelen = sprintf(temp, "%d", psize) + 1; // include a whitespace
-
-	/* dummy payload. */
-	p += 14; /* skip packet header. */
-	n_read = 14;
-	while (psize - n_read >= sizelen) {
-		sscanf(p, "%d", &size);
-		if (size != psize) {
-			D("Read %d instead of %d", size, psize);
-			break;
-		}
-
-		p += sizelen;
-		n_read += sizelen;
-	}
-}
 
 
 /*
@@ -475,7 +484,13 @@ send_packets(struct netmap_ring *ring, s
 		struct netmap_slot *slot = &ring->slot[cur];
 		char *p = NETMAP_BUF(ring, slot->buf_idx);
 
-		if (options & OPT_COPY)
+		slot->flags = 0;
+		if (options & OPT_DUMP)
+			dump_payload(p, size, ring, cur);
+		if (options & OPT_INDIRECT) {
+			slot->flags |= NS_INDIRECT;
+			*((struct pkt **)(void *)p) = pkt;
+		} else if (options & OPT_COPY)
 			pkt_copy(pkt, p, size);
 		else if (options & OPT_MEMCPY)
 			memcpy(p, pkt, size);
@@ -756,6 +771,7 @@ sender_body(void *data)
 	struct timespec tmptime, nexttime = { 0, 0}; // XXX silence compiler
 	int rate_limit = targ->g->tx_rate;
 	long long waited = 0;
+
 	D("start");
 	if (setaffinity(targ->thread, targ->affinity))
 		goto quit;
@@ -882,7 +898,7 @@ receive_pcap(u_char *user, const struct 
 }
 
 static int
-receive_packets(struct netmap_ring *ring, u_int limit, int skip_payload)
+receive_packets(struct netmap_ring *ring, u_int limit, int dump)
 {
 	u_int cur, rx;
 
@@ -893,8 +909,9 @@ receive_packets(struct netmap_ring *ring
 		struct netmap_slot *slot = &ring->slot[cur];
 		char *p = NETMAP_BUF(ring, slot->buf_idx);
 
-		if (!skip_payload)
-			check_payload(p, slot->len);
+		slot->flags = OPT_INDIRECT; // XXX
+		if (dump)
+			dump_payload(p, slot->len, ring, cur);
 
 		cur = NETMAP_RING_NEXT(ring, cur);
 	}
@@ -946,6 +963,7 @@ receiver_body(void *data)
 			targ->count++;
 	}
     } else {
+	int dump = targ->g->options & OPT_DUMP;
 	while (!targ->cancel) {
 		/* Once we started to receive packets, wait at most 1 seconds
 		   before quitting. */
@@ -962,8 +980,7 @@ receiver_body(void *data)
 			if (rxring->avail == 0)
 				continue;
 
-			m = receive_packets(rxring, targ->g->burst,
-					SKIP_PAYLOAD);
+			m = receive_packets(rxring, targ->g->burst, dump);
 			received += m;
 		}
 		targ->count = received;
@@ -1324,10 +1341,11 @@ main(int arc, char **argv)
 	g.burst = 512;		// default
 	g.nthreads = 1;
 	g.cpus = 1;
+	g.forever = 1;
 	g.tx_rate = 0;
 
 	while ( (ch = getopt(arc, argv,
-			"a:f:n:i:t:r:l:d:s:D:S:b:c:o:p:PT:w:WvR:")) != -1) {
+			"a:f:n:i:It:r:l:d:s:D:S:b:c:o:p:PT:w:WvR:X")) != -1) {
 		struct sf *fn;
 
 		switch(ch) {
@@ -1367,6 +1385,10 @@ main(int arc, char **argv)
 				g.dev_type = DEV_NETMAP;
 			break;
 
+		case 'I':
+			g.options |= OPT_INDIRECT;	/* XXX use indirect buffer */
+			break;
+
 		case 't':	/* send, deprecated */
 			D("-t deprecated, please use -f tx -n %s", optarg);
 			g.td_body = sender_body;
@@ -1399,8 +1421,8 @@ main(int arc, char **argv)
 			wait_link = atoi(optarg);
 			break;
 
-		case 'W':
-			g.forever = 1; /* do not exit rx even with no traffic */
+		case 'W': /* XXX changed default */
+			g.forever = 0; /* do not exit rx even with no traffic */
 			break;
 
 		case 'b':	/* burst */
@@ -1430,6 +1452,8 @@ main(int arc, char **argv)
 		case 'R':
 			g.tx_rate = atoi(optarg);
 			break;
+		case 'X':
+			g.options |= OPT_DUMP;
 		}
 	}
 
@@ -1572,10 +1596,11 @@ main(int arc, char **argv)
     }
 
 	if (g.options) {
-		D("special options:%s%s%s%s\n",
+		D("--- SPECIAL OPTIONS:%s%s%s%s%s\n",
 			g.options & OPT_PREFETCH ? " prefetch" : "",
 			g.options & OPT_ACCESS ? " access" : "",
 			g.options & OPT_MEMCPY ? " memcpy" : "",
+			g.options & OPT_INDIRECT ? " indirect" : "",
 			g.options & OPT_COPY ? " copy" : "");
 	}
 	


More information about the svn-src-head mailing list