home *** CD-ROM | disk | FTP | other *** search
/ ftp.ee.lbl.gov / 2014.05.ftp.ee.lbl.gov.tar / ftp.ee.lbl.gov / stdload.c < prev    next >
C/C++ Source or Header  |  1993-07-07  |  6KB  |  233 lines

  1. /*
  2.  * stdload - a mulitcast traffic generator designed to mimic an IETF broadcast.
  3.  * 
  4.  * (c) Pittsburgh Supercomputing Center, Matthew B Mathis, 1993.
  5.  * All rights reserved.   See COPYRIGHT.h for additional information.
  6.  *
  7.  * This program is very dangerous!
  8.  
  9.  
  10. The command I am using to generate the IETF load is 
  11.  
  12. %  stdload -s 7 -c
  13.  
  14. --Jamshid
  15.  */
  16. #include <stdio.h>
  17. #include <errno.h>
  18. #include <netdb.h>
  19. #include <time.h>
  20.  
  21. #include <sys/types.h>
  22. #include <sys/param.h>
  23. #include <sys/socket.h>
  24. #include <sys/time.h>
  25. #include <sys/ioctl.h>
  26.  
  27. #include <netinet/in_systm.h>
  28. #include <netinet/in.h>
  29.  
  30. #define MAXSES    10 /* maximum number of sessions */
  31. #define DEFG    "224.2.200.68"    /* default group (UGH!) */
  32. #define DEFP    12341        /* default port */
  33. #define TIMEBASE 20000        /* 20 mS = 50 Hz */
  34.  
  35. #define NOERROR(val,msg) {if (((int)(val)) < 0) {perror(msg);exit(1);}}
  36. #define NOTNULL(val,msg) {if (!(val)) {fprintf(stderr,msg);exit(1);}}
  37. #define MEG 1000000
  38. #define TIMEADJ(tv) \
  39. { if ((tv)->tv_usec >= MEG) {(tv)->tv_usec -= MEG; (tv)->tv_sec++;} \
  40.   else if ((tv)->tv_usec < 0) {(tv)->tv_usec += MEG; (tv)->tv_sec--;};}
  41. #define deltaU(start,stop) \
  42.         (((stop).tv_sec - (start).tv_sec) * MEG + \
  43.         ((stop).tv_usec - (start).tv_usec))
  44.  
  45. #define TV2TS(tv) ((((tv)->tv_usec*0x431C) >> 15) + ((tv)->tv_sec << 16))
  46.  
  47. char usage[] =
  48. "Usage: stdload [-s <sess>] [-t <ttl>] [-m] [-c] [<group>]\n\
  49.     -s <n>       Use only selected sessions\n\
  50.     -t <ttl>     Clamp all signals to <ttl>\n\
  51.     -m           Margin test, raise rates by 5%% for each -m\n\
  52.     -c           Chop mode,  5 sec on/off (sync to GMT)\n\
  53.     <group>      Multicast group, defaults to %s\n";
  54.  
  55. struct rtp_head {
  56. /*  int ver:2, flow:6, P:1, S:1, for:6, seq16; */
  57.   int unsigned bits:16, seq:16;
  58.   long tstamp;
  59. };
  60. /*
  61.  * No - we must not fragment on tunnels either....
  62.  * #define MPAY (1500 - 20 - 8 - sizeof(struct rtp_head))
  63.  */
  64. #define MPAY 1400
  65.  
  66. struct session {
  67.   /* parameters */
  68.   int ttl, payload;
  69.   int raten, rated;
  70.   char *name;
  71.  
  72.   /* state */
  73.   int seq;
  74.   int ratediv;
  75.   int port;
  76. } s[] = {
  77.   {255, 320, 1, 4, "GSM Audio 1"},
  78.   {223, 320, 1, 4, "GSM Audio 2"},
  79.   {191, 160, 1, 1, "PCM Audio 1"},
  80.   {159, 160, 1, 1, "PCM Audio 2"},
  81.   {191,  50, 1, 1, "Assorted control and listener messages"},
  82.   {127, 512, 1, 2, "Video 1"},
  83.   { 95, 512, 1, 2, "Video 2"},
  84.   { 63,MPAY, 1, 1, "Test Application1"},
  85.   { 63,MPAY, 1, 1, "Test Application2"}
  86. };
  87. #define NSES (sizeof(s)/sizeof(struct session))
  88. #define DNS 4
  89. int ns=DNS;
  90.  
  91. void ring();
  92. int ttlclamp=255, margin=0, chop=0;
  93. struct sockaddr_in grsin;
  94. struct itimerval timebase;
  95. struct timeval now;
  96. int os;
  97. int pkts, bytes, errors;
  98. int tick, silent;
  99.  
  100. struct {
  101.   struct rtp_head h;
  102.   char data[MPAY];
  103. } outbuf;
  104.  
  105. main(argc, argv)
  106. char *argv[];
  107. {
  108.   char *sv, **av = argv, *name = DEFG;
  109.   struct hostent *hp;
  110.   int i, port = DEFP;
  111.   int r, sz, Tr, Tbw;
  112.   int sockbuf=32767;
  113.  
  114.   argc--, av++;
  115.   while (argc > 0 && *av[0] == '-') {
  116.     sv = *av++; argc--;
  117.     while (*++sv) switch (*sv) {
  118.     case 's':
  119.       if ((argc > 0) &&
  120.       ((ns = atoi(*av++)) > 0) &&
  121.       (ns <= NSES)) {
  122.     argc--;
  123.         break;
  124.       }
  125.       printf("  -s <n> to include sessions 1 through <n> of:\n");
  126. /*           "d)  ddd  ddd  dddd   ddd   dddd   dddd nnnnnnnn"  */
  127.       printf("    ttl  pps  size  kb/S  T pps T kb/S\n");
  128.       Tr = Tbw = 0;
  129.       for (i=0; i<NSES; i++) {
  130.     r = 5000*s[i].raten/s[i].rated;        /* pay attention to roundoff */
  131.     sz = 20+8+sizeof(struct rtp_head)+s[i].payload;
  132.     Tr += r; Tbw += r*sz;
  133.     printf("%d)  %3d  %3d  %4d %4d   %4d   %4d %s\n",
  134.            i+1, s[i].ttl, r/100, sz, r*sz*8/100000, Tr/100, Tbw*8/100000,
  135.            s[i].name);
  136.       }
  137.       printf("(Defaults to 1 through %d)\n", DNS);
  138.       exit(1);
  139.     case 't':
  140.       if ((argc > 0) &&
  141.           ((ttlclamp = atoi(*av++)) >= 0) &&
  142.       (ttlclamp < 256)) {
  143.         argc--;
  144.         break;
  145.       }
  146. punt:
  147.       printf(usage, DEFG);
  148.       printf("Invalid argument to -%c\n", *sv);
  149.       exit(1);
  150.     case 'm':
  151.       margin++;
  152.       break;
  153.     case 'c':
  154.       chop++;
  155.       break;
  156.     default:
  157.       printf(usage, DEFG);
  158.       printf("Unknown switch: -%c\n", *sv);
  159.       exit(1);
  160.     }
  161.   }
  162.   if (*av) name = *av; 
  163.   if (isdigit(*name)) {
  164.     grsin.sin_addr.s_addr = inet_addr(name);
  165.   } else if (hp = gethostbyname(name)) {
  166.     bcopy(hp->h_addr, (char *)&grsin.sin_addr, hp->h_length);
  167.   } else {
  168.     printf("I Don't understand name %s\n",name);
  169.     exit(1);
  170.   }
  171.   grsin.sin_family = AF_INET;
  172.   NOERROR(os = socket(AF_INET, SOCK_DGRAM, 0), "socket");
  173.   NOERROR(setsockopt(os, SOL_SOCKET, SO_SNDBUF, &sockbuf, sizeof(int)),
  174.       "SO_SNDBUF");
  175.   for (i=0; i<NSES; i++) {
  176.     s[i].port = htons(port++);
  177.   }
  178.  
  179.   gettimeofday(&now, 0);
  180.   tick = now.tv_sec-1;
  181.   silent = chop;
  182.   NOERROR(signal(SIGALRM, ring), "signal");
  183.   bzero(&timebase, sizeof(timebase));
  184.   timebase.it_value.tv_usec = timebase.it_interval.tv_usec =
  185.     TIMEBASE-(TIMEBASE*margin/20);
  186.   NOERROR(setitimer(ITIMER_REAL, &timebase, 0), "setitimer");
  187.   printf("pkts kb/S errors\n");
  188.   for (;;) pause();
  189. }
  190.  
  191. void ring()
  192. {
  193.   int tsnow;
  194.   int i;
  195.  
  196.   NOERROR(signal(SIGALRM, ring), "signal");
  197.   gettimeofday(&now, 0);
  198.   if (tick != now.tv_sec) {
  199.     if (silent) {
  200.      putc('.', stdout);
  201.      if ((tick%10) == 9) printf("\n");
  202.      fflush(stdout);
  203.     } else
  204.       printf("%3d %5d %d\n", pkts, bytes*8/1000, errors);
  205.     pkts = bytes = errors =0;
  206.     tick++;
  207.     if (chop) silent = (tick%10) >= 5;
  208.   }
  209.   if (silent) return;
  210.   tsnow = TV2TS(&now);
  211.  
  212.   for (i=0; i<ns; i++) {
  213.     unsigned char ttl;
  214.     s[i].ratediv += s[i].raten;
  215.     while (s[i].ratediv >= s[i].rated) {
  216.       s[i].ratediv -= s[i].rated;
  217.  
  218.       outbuf.h.bits = htons(0x4040);
  219.       outbuf.h.seq = htons(s[i].seq++);
  220.       outbuf.h.tstamp = htonl(tsnow);
  221.       ttl = (s[i].ttl > ttlclamp)?ttlclamp:s[i].ttl;
  222.       NOERROR(setsockopt(os, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, 1), "ttl");
  223.       grsin.sin_port = s[i].port;
  224.       if (sendto(os, (char *)&outbuf, sizeof(struct rtp_head)+s[i].payload, 0,
  225.          &grsin, sizeof(grsin)) > 0) {
  226.     pkts++;
  227.     bytes += 20 + 8 + sizeof(struct rtp_head)+s[i].payload;
  228.       } else
  229.     errors++;
  230.     }
  231.   }
  232. }
  233.