Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 19 Nov 2012 19:14:25 +0000 (UTC)
From:      Ed Maste <emaste@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org
Subject:   svn commit: r243299 - stable/9/tools/tools/netmap
Message-ID:  <201211191914.qAJJEPAk026303@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: emaste
Date: Mon Nov 19 19:14:25 2012
New Revision: 243299
URL: http://svnweb.freebsd.org/changeset/base/243299

Log:
  Sync netmap pkt-gen with HEAD.
  
  MFC r238081, r238165, r238170, r238175, r239139, r239145, r240103,
      r238081:
  
  r238165: Allow threads to finish up when terminated by user
  
    Set a flag and allow worker threads to finish upon ^C, instead of
    immediately cancelling them, so that final packet count and rate
    stats can be displayed.
  
  r238170: Also report tx bandwidth with Ethernet overhead
  
  r238175: Allow continuous packet transmission (via -t 0)
  
    Also add a missing check for the cancel flag while waiting for the first
    packet in receive mode.
  
  r239139: Round displayed pps (instead of truncating)
  
  r239145: Be more descriptive about poll error / timeout when transmitting.
  
  r240103: Failure to open netmap device is unrecoverable.
  
    There's no reason to "fail later" since there's nothing this tool can do
    in netmap mode without /dev/netmap open.
  
  Sponsored by: ADARA Networks

Modified:
  stable/9/tools/tools/netmap/pkt-gen.c
Directory Properties:
  stable/9/tools/tools/netmap/   (props changed)

Modified: stable/9/tools/tools/netmap/pkt-gen.c
==============================================================================
--- stable/9/tools/tools/netmap/pkt-gen.c	Mon Nov 19 18:54:37 2012	(r243298)
+++ stable/9/tools/tools/netmap/pkt-gen.c	Mon Nov 19 19:14:25 2012	(r243299)
@@ -95,7 +95,7 @@ inline void prefetch (const void *x)
         __asm volatile("prefetcht0 %0" :: "m" (*(const unsigned long *)x));
 }
 
-// XXX only for multiples of 32 bytes, non overlapped.
+// XXX only for multiples of 64 bytes, non overlapped.
 static inline void
 pkt_copy(void *_src, void *_dst, int l)
 {
@@ -191,6 +191,7 @@ struct targ {
 	struct glob_arg *g;
 	int used;
 	int completed;
+	int cancel;
 	int fd;
 	struct nmreq nmr;
 	struct netmap_if *nifp;
@@ -221,15 +222,8 @@ static int global_nthreads;
 static void
 sigint_h(__unused int sig)
 {
-	for (int i = 0; i < global_nthreads; i++) {
-		/* cancel active threads. */
-		if (targs[i].used == 0)
-			continue;
-
-		D("Cancelling thread #%d\n", i);
-		pthread_cancel(targs[i].thread);
-		targs[i].used = 0;
-	}
+	for (int i = 0; i < global_nthreads; i++)
+		targs[i].cancel = 1;
 
 	signal(SIGINT, SIG_DFL);
 }
@@ -474,13 +468,19 @@ static void *
 sender_body(void *data)
 {
 	struct targ *targ = (struct targ *) data;
-
 	struct pollfd fds[1];
 	struct netmap_if *nifp = targ->nifp;
 	struct netmap_ring *txring;
-	int i, n = targ->g->npackets / targ->g->nthreads, sent = 0;
+	int i, pkts_per_td = targ->g->npackets / targ->g->nthreads, sent = 0;
+	int continuous = 0;
 	int options = targ->g->options | OPT_COPY;
+	int retval;
+
 D("start");
+	if (pkts_per_td == 0) {
+		continuous = 1;
+		pkts_per_td = 100000;
+	}
 	if (setaffinity(targ->thread, targ->affinity))
 		goto quit;
 	/* setup poll(2) mechanism. */
@@ -495,7 +495,7 @@ D("start");
 	void *pkt = &targ->pkt;
 	pcap_t *p = targ->g->p;
 
-	for (i = 0; sent < n; i++) {
+	for (i = 0; (sent < pkts_per_td && !targ->cancel) || continuous; i++) {
 		if (pcap_inject(p, pkt, size) != -1)
 			sent++;
 		if (i > 10000) {
@@ -504,13 +504,19 @@ D("start");
 		}
 	}
     } else {
-	while (sent < n) {
+	while (sent < pkts_per_td || continuous) {
 
 		/*
 		 * wait for available room in the send queue(s)
 		 */
-		if (poll(fds, 1, 2000) <= 0) {
-			D("poll error/timeout on queue %d\n", targ->me);
+		if ((retval = poll(fds, 1, 2000)) <= 0) {
+			if (targ->cancel)
+				break;
+			if (retval == 0)
+				D("poll timeout on queue %d\n", targ->me);
+			else
+				D("poll error on queue %d: %s\n", targ->me,
+				    strerror(errno));
 			goto quit;
 		}
 		/*
@@ -518,8 +524,10 @@ D("start");
 		 */
 		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);
+		for (i = targ->qfirst; i < targ->qlast && !targ->cancel; i++) {
+			int m, limit = targ->g->burst;
+			if (!continuous && pkts_per_td - sent < limit)
+				limit = pkts_per_td - sent;
 
 			txring = NETMAP_TXRING(nifp, i);
 			if (txring->avail == 0)
@@ -529,6 +537,8 @@ D("start");
 			sent += m;
 			targ->count = sent;
 		}
+		if (targ->cancel)
+			break; 
 	}
 	/* flush any remaining packets */
 	ioctl(fds[0].fd, NIOCTXSYNC, NULL);
@@ -604,7 +614,7 @@ receiver_body(void *data)
 	fds[0].events = (POLLIN);
 
 	/* unbounded wait for the first packet. */
-	for (;;) {
+	while (!targ->cancel) {
 		i = poll(fds, 1, 1000);
 		if (i > 0 && !(fds[0].revents & POLLERR))
 			break;
@@ -614,11 +624,11 @@ receiver_body(void *data)
 	/* main loop, exit after 1s silence */
 	gettimeofday(&targ->tic, NULL);
     if (targ->g->use_pcap) {
-	for (;;) {
+	while (!targ->cancel) {
 		pcap_dispatch(targ->g->p, targ->g->burst, receive_pcap, NULL);
 	}
     } else {
-	while (1) {
+	while (!targ->cancel) {
 		/* Once we started to receive packets, wait at most 1 seconds
 		   before quitting. */
 		if (poll(fds, 1, 1 * 1000) <= 0) {
@@ -655,27 +665,41 @@ quit:
 	return (NULL);
 }
 
+static char *
+scaled_val(double val)
+{
+	static char buf[64];
+	const char *units[] = {"", "K", "M", "G"};
+	int i = 0;
+
+	while (val >= 1000 && i < 3) {
+		val /= 1000;
+		i++;
+	}
+	snprintf(buf, sizeof(buf), "%.2f%s", val, units[i]);
+	return (buf);
+}
+
 static void
 tx_output(uint64_t sent, int size, double delta)
 {
-	double amount = 8.0 * (1.0 * size * sent) / delta;
+	uint64_t bytes_sent = sent * size;
+	double bw = 8.0 * bytes_sent / delta;
 	double pps = sent / delta;
-	char units[4] = { '\0', 'K', 'M', 'G' };
-	int aunit = 0, punit = 0;
-
-	while (amount >= 1000) {
-		amount /= 1000;
-		aunit += 1;
-	}
-	while (pps >= 1000) {
-		pps /= 1000;
-		punit += 1;
-	}
+	/*
+	 * Assume Ethernet overhead of 24 bytes per packet excluding header:
+	 * FCS       4 bytes
+	 * Preamble  8 bytes
+	 * IFG      12 bytes
+	 */
+	double bw_with_overhead = 8.0 * (bytes_sent + sent * 24) / delta;
 
 	printf("Sent %" PRIu64 " packets, %d bytes each, in %.2f seconds.\n",
 	       sent, size, delta);
-	printf("Speed: %.2f%cpps. Bandwidth: %.2f%cbps.\n",
-	       pps, units[punit], amount, units[aunit]);
+	printf("Speed: %spps. ", scaled_val(pps));
+	printf("Bandwidth: %sbps ", scaled_val(bw));
+	printf("(%sbps with overhead).\n", scaled_val(bw_with_overhead));
+
 }
 
 
@@ -704,7 +728,7 @@ usage(void)
 		"Usage:\n"
 		"%s arguments\n"
 		"\t-i interface		interface name\n"
-		"\t-t pkts_to_send	also forces send mode\n"
+		"\t-t pkts_to_send	also forces send mode, 0 = continuous\n"
 		"\t-r pkts_to_receive	also forces receive mode\n"
 		"\t-l pkts_size		in bytes excluding CRC\n"
 		"\t-d dst-ip		end with %%n to sweep n addresses\n"
@@ -868,7 +892,7 @@ main(int arc, char **argv)
 	fd = open("/dev/netmap", O_RDWR);
 	if (fd == -1) {
 		D("Unable to open /dev/netmap");
-		// fail later
+		exit(1);
 	} else {
 		if ((ioctl(fd, NIOCGINFO, &nmr)) == -1) {
 			D("Unable to get if info without name");
@@ -1057,7 +1081,7 @@ main(int arc, char **argv)
 		pps = toc.tv_sec* 1000000 + toc.tv_usec;
 		if (pps < 10000)
 			continue;
-		pps = (my_count - prev)*1000000 / pps;
+		pps = ((my_count - prev) * 1000000 + pps / 2) / pps;
 		D("%" PRIu64 " pps", pps);
 		prev = my_count;
 		toc = now;



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