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;
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to