Annotation of elwix/patches/freebsd.netblast.PR179085.patch, revision 1.2

1.2     ! misho       1: Index: tools/tools/netrate/netblast/Makefile
        !             2: ===================================================================
        !             3: --- tools/tools/netrate/netblast/Makefile      (revision 258293)
        !             4: +++ tools/tools/netrate/netblast/Makefile      (working copy)
        !             5: @@ -4,5 +4,8 @@
        !             6:  
        !             7:  PROG= netblast
        !             8:  MAN=
        !             9: +LDFLAGS += -lpthread
        !            10:  
        !            11: +WARNS?= 3
        !            12: +
        !            13:  .include <bsd.prog.mk>
        !            14: Index: tools/tools/netrate/netblast/netblast.c
        !            15: ===================================================================
        !            16: --- tools/tools/netrate/netblast/netblast.c    (revision 258293)
        !            17: +++ tools/tools/netrate/netblast/netblast.c    (working copy)
        !            18: @@ -36,19 +36,29 @@
        !            19:  
        !            20:  #include <signal.h>
        !            21:  #include <stdio.h>
        !            22: +#include <inttypes.h>
        !            23:  #include <stdlib.h>
        !            24:  #include <string.h>
        !            25:  #include <unistd.h>                   /* close */
        !            26:  
        !            27: +#include <pthread.h>
        !            28: +#include <fcntl.h>
        !            29: +#include <time.h>   /* clock_getres() */
        !            30: +
        !            31: +static int round_to(int n, int l)
        !            32: +{
        !            33: +    return ((n + l - 1)/l)*l;
        !            34: +}
        !            35: +
        !            36:  static void
        !            37:  usage(void)
        !            38:  {
        !            39:  
        !            40: -      fprintf(stderr, "netblast [ip] [port] [payloadsize] [duration]\n");
        !            41: +      fprintf(stderr, "netblast [ip] [port] [payloadsize] [duration] [nthreads]\n");
        !            42:        exit(-1);
        !            43:  }
        !            44:  
        !            45: -static int    global_stop_flag;
        !            46: +static int    global_stop_flag=0;
        !            47:  
        !            48:  static void
        !            49:  signal_handler(int signum __unused)
        !            50: @@ -57,48 +67,28 @@
        !            51:        global_stop_flag = 1;
        !            52:  }
        !            53:  
        !            54: +
        !            55:  /*
        !            56: - * Loop that blasts packets: begin by recording time information, resetting
        !            57: - * stats.  Set the interval timer for when we want to wake up.  Then go.
        !            58: - * SIGALRM will set a flag indicating it's time to stop.  Note that there's
        !            59: - * some overhead to the signal and timer setup, so the smaller the duration,
        !            60: - * the higher the relative overhead.
        !            61: + * Each socket uses multiple threads so the generator is
        !            62: + * more efficient. A collector thread runs the stats.
        !            63:   */
        !            64: -static int
        !            65: -blast_loop(int s, long duration, u_char *packet, u_int packet_len)
        !            66: +struct td_desc {
        !            67: +      pthread_t td_id;
        !            68: +      uint64_t counter; /* tx counter */
        !            69: +      uint64_t send_errors; /* tx send errors */
        !            70: +      uint64_t send_calls;    /* tx send calls */
        !            71: +      int s;
        !            72: +      u_char *packet;
        !            73: +      u_int packet_len;
        !            74: +};
        !            75: +
        !            76: +static void *
        !            77: +blast(void *data)
        !            78:  {
        !            79: -      struct timespec starttime, tmptime;
        !            80: -      struct itimerval it;
        !            81: -      u_int32_t counter;
        !            82: -      int send_errors, send_calls;
        !            83: -
        !            84: -      if (signal(SIGALRM, signal_handler) == SIG_ERR) {
        !            85: -              perror("signal");
        !            86: -              return (-1);
        !            87: -      }
        !            88: -
        !            89: -      if (clock_getres(CLOCK_REALTIME, &tmptime) == -1) {
        !            90: -              perror("clock_getres");
        !            91: -              return (-1);
        !            92: -      }
        !            93: -
        !            94: -      if (clock_gettime(CLOCK_REALTIME, &starttime) == -1) {
        !            95: -              perror("clock_gettime");
        !            96: -              return (-1);
        !            97: -      }
        !            98: -
        !            99: -      it.it_interval.tv_sec = 0;
        !           100: -      it.it_interval.tv_usec = 0;
        !           101: -      it.it_value.tv_sec = duration;
        !           102: -      it.it_value.tv_usec = 0;
        !           103: -
        !           104: -      if (setitimer(ITIMER_REAL, &it, NULL) < 0) {
        !           105: -              perror("setitimer");
        !           106: -              return (-1);
        !           107: -      }
        !           108: -
        !           109: -      send_errors = send_calls = 0;
        !           110: -      counter = 0;
        !           111: +    struct td_desc *t = data;
        !           112: +      t->counter=0;
        !           113: +      t->send_errors=0;
        !           114: +      t->send_calls=0;
        !           115:        while (global_stop_flag == 0) {
        !           116:                /*
        !           117:                 * We maintain and, if there's room, send a counter.  Note
        !           118: @@ -110,32 +100,84 @@
        !           119:                 * operation, causing the current sequence number also to be
        !           120:                 * skipped.
        !           121:                 */
        !           122: -              if (packet_len >= 4) {
        !           123: -                      be32enc(packet, counter);
        !           124: -                      counter++;
        !           125: +              if (t->packet_len >= 4) {
        !           126: +                      be32enc(t->packet, t->counter);
        !           127: +                      t->counter++;
        !           128:                }
        !           129: -              if (send(s, packet, packet_len, 0) < 0)
        !           130: -                      send_errors++;
        !           131: -              send_calls++;
        !           132: +              if (send(t->s, t->packet, t->packet_len, 0) < 0)
        !           133: +                      t->send_errors++;
        !           134: +              t->send_calls++;
        !           135:        }
        !           136: +    return NULL;
        !           137: +}
        !           138:  
        !           139: +static struct td_desc **
        !           140: +make_threads(int s, u_char *packet, u_int packet_len, int nthreads)
        !           141: +{
        !           142: +    int i;
        !           143: +    int lb = round_to(nthreads * sizeof (struct td_desc *), 64);
        !           144: +    int td_len = round_to(sizeof(struct td_desc), 64); // cache align
        !           145: +    char *m = calloc(1, lb + td_len * nthreads);
        !           146: +    struct td_desc **tp;
        !           147: +
        !           148: +    /* pointers plus the structs */
        !           149: +    if (m == NULL) {
        !           150: +        perror("no room for pointers!");
        !           151: +        exit(1);
        !           152: +    }
        !           153: +    tp = (struct td_desc **)m;
        !           154: +    m += lb;    /* skip the pointers */
        !           155: +    for (i = 0; i < nthreads; i++, m += td_len) {
        !           156: +        tp[i] = (struct td_desc *)m;
        !           157: +        tp[i]->s = s;
        !           158: +        tp[i]->packet = packet;
        !           159: +        tp[i]->packet_len = packet_len;
        !           160: +        if (pthread_create(&tp[i]->td_id, NULL, blast, tp[i])) {
        !           161: +            perror("unable to create thread");
        !           162: +            exit(1);
        !           163: +        }
        !           164: +    }
        !           165: +    return tp;
        !           166: +}
        !           167: +
        !           168: +
        !           169: +static void
        !           170: +main_thread(struct td_desc **tp, long duration, struct timespec starttime, struct timespec tmptime, long payloadsize, int family, int nthreads)
        !           171: +{
        !           172: +      uint64_t send_errors=0, send_calls=0;
        !           173: +      int i;
        !           174:        if (clock_gettime(CLOCK_REALTIME, &tmptime) == -1) {
        !           175:                perror("clock_gettime");
        !           176: -              return (-1);
        !           177:        }
        !           178:  
        !           179: +      for (i = 0; i < nthreads; i++) {
        !           180: +              /* Wait for thread end */
        !           181: +              pthread_join( tp[i]->td_id, NULL);
        !           182: +              send_calls+=tp[i]->send_calls;
        !           183: +              send_errors+=tp[i]->send_errors;
        !           184: +    }
        !           185: +
        !           186:        printf("\n");
        !           187: -      printf("start:             %zd.%09lu\n", starttime.tv_sec,
        !           188: +      printf("start:                      %zd.%09lu\n", starttime.tv_sec,
        !           189:            starttime.tv_nsec);
        !           190: -      printf("finish:            %zd.%09lu\n", tmptime.tv_sec,
        !           191: +      printf("finish:                     %zd.%09lu\n", tmptime.tv_sec,
        !           192:            tmptime.tv_nsec);
        !           193: -      printf("send calls:        %d\n", send_calls);
        !           194: -      printf("send errors:       %d\n", send_errors);
        !           195: -      printf("approx send rate:  %ld\n", (send_calls - send_errors) /
        !           196: +      printf("send calls:                 %" PRIu64 "\n", send_calls);
        !           197: +      printf("send errors:                %" PRIu64 "\n", send_errors);
        !           198: +      printf("send success:               %" PRIu64 "\n", send_calls - send_errors);
        !           199: +      printf("approx send rate:           %" PRIu64 "\n", (send_calls - send_errors) /
        !           200:            duration);
        !           201: -      printf("approx error rate: %d\n", (send_errors / send_calls));
        !           202: -
        !           203: -      return (0);
        !           204: +      printf("approx error rate:          %" PRIu64 "\n", (send_errors / send_calls));
        !           205: +      printf("approx Ethernet throughput: ");
        !           206: +      if (family == AF_INET)
        !           207: +              printf("%" PRIu64 " Mib/s\n", ((send_calls - send_errors) / duration ) *
        !           208: +              (payloadsize + 8 + 20 + 14 ) * 8 / 1000 / 1000);
        !           209: +      else if (family == AF_INET6)
        !           210: +              printf("%" PRIu64 " Mib/s\n", ((send_calls - send_errors) / duration ) *
        !           211: +              (payloadsize + 8 + 40 + 14 ) * 8 / 1000 / 1000);
        !           212: +      else printf("CAN 'T DETERMINE family type %i\n",family);
        !           213: +      printf("approx payload throughput:  %" PRIu64 " Mib/s\n", ((send_calls - send_errors) / 
        !           214: +              duration ) * payloadsize * 8 / 1000 / 1000);
        !           215:  }
        !           216:  
        !           217:  int
        !           218: @@ -143,11 +185,15 @@
        !           219:  {
        !           220:        long payloadsize, duration;
        !           221:        struct addrinfo hints, *res, *res0;
        !           222: -      char *dummy, *packet;
        !           223: -      int port, s, error;
        !           224: +      char *dummy;
        !           225: +      u_char *packet;
        !           226: +      int family, port, s, error, nthreads = 1;
        !           227: +      struct td_desc **tp;    
        !           228:        const char *cause = NULL;
        !           229: +      struct timespec starttime, tmptime;
        !           230: +      struct itimerval it;
        !           231:  
        !           232: -      if (argc != 5)
        !           233: +      if (argc < 5)
        !           234:                usage();
        !           235:  
        !           236:        memset(&hints, 0, sizeof(hints));
        !           237: @@ -177,6 +223,11 @@
        !           238:                /*NOTREACHED*/
        !           239:        }
        !           240:  
        !           241: +      if (argc > 5)
        !           242: +        nthreads = strtoul(argv[5], &dummy, 10);
        !           243: +    if (nthreads < 1 || nthreads > 64)
        !           244: +        usage();
        !           245: +
        !           246:        packet = malloc(payloadsize);
        !           247:        if (packet == NULL) {
        !           248:                perror("malloc");
        !           249: @@ -213,9 +264,46 @@
        !           250:                return (-1);
        !           251:                /*NOTREACHED*/
        !           252:        }
        !           253: -
        !           254: +      family=res->ai_family;
        !           255:        freeaddrinfo(res0);
        !           256:  
        !           257: -      return (blast_loop(s, duration, packet, payloadsize));
        !           258: +      printf("netblast %d threads sending on UDP port %d\n",
        !           259: +    nthreads, (u_short)port);
        !           260:  
        !           261: +      /*
        !           262: +       * Begin by recording time information stats.
        !           263: +       * Set the interval timer for when we want to wake up.
        !           264: +       * SIGALRM will set a flag indicating it's time to stop.  Note that there's
        !           265: +       * some overhead to the signal and timer setup, so the smaller the duration,
        !           266: +       * the higher the relative overhead.
        !           267: +       */
        !           268: +
        !           269: +      if (signal(SIGALRM, signal_handler) == SIG_ERR) {
        !           270: +              perror("signal");
        !           271: +              return (-1);
        !           272: +      }
        !           273: +
        !           274: +      if (clock_getres(CLOCK_REALTIME, &tmptime) == -1) {
        !           275: +              perror("clock_getres");
        !           276: +              return (-1);
        !           277: +      }
        !           278: +
        !           279: +      if (clock_gettime(CLOCK_REALTIME, &starttime) == -1) {
        !           280: +              perror("clock_gettime");
        !           281: +              return (-1);
        !           282: +      }
        !           283: +
        !           284: +      it.it_interval.tv_sec = 0;
        !           285: +      it.it_interval.tv_usec = 0;
        !           286: +      it.it_value.tv_sec = duration;
        !           287: +      it.it_value.tv_usec = 0;
        !           288: +
        !           289: +      if (setitimer(ITIMER_REAL, &it, NULL) < 0) {
        !           290: +              perror("setitimer");
        !           291: +              return (-1);
        !           292: +      }
        !           293: +
        !           294: +    tp = make_threads(s, packet, payloadsize, nthreads);
        !           295: +    main_thread(tp, duration, starttime,  tmptime, payloadsize, family, nthreads);
        !           296: +
        !           297:  }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>