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>