/* aagen.c */

/* Generate traffic on a particular vci using the */
/* atm sockets interface.                         */

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/time.h>
#include <fcntl.h>
#include <sys/times.h>
#include <signal.h>

#ifdef GLIBC_PATCH
#include <stdint.h>
#undef __GLIBC__
#include <linux/socket.h>
#include <linux/atm.h>
#else
#include <sys/socket.h>
#include <linux/types.h>
#endif

static struct timezone dummy = {0,0};
struct tms timeb;

static int            frames = 0;
static struct timeval time1;
static struct timeval time2;
static double         tu1;
static double         tu2;
static int    count = 0;
static int    fsize;

static void sigintx(
int  dummyp)
{
   int fc;

   fc = frames;

   gettimeofday(&time2,&dummy);

   tu1 = 1000000 * time1.tv_sec;
   tu1 += time1.tv_usec;

   tu2 = 1000000 * time2.tv_sec;
   tu2 += time2.tv_usec;

   printf("Frames sent = %8d    \n", fc);
   printf("MBits / sec = %8.3lf \n", 8.0 * fc * fsize / (tu2 - tu1));
   printf("Frames/msec = %8.3lf \n", 1000 * fc / (tu2 - tu1));
   exit(1);
}

char buf[16 * 1024];

void aa_send(
int s,                  /* socket handle */
int blk,                /* Block size    */
int count)              /* Total count.  */
{
   int rc;
   int fc = 0;
   int sent = count;

   fsize = blk;
   signal(SIGINT, sigintx);
   rc = 0;
   memset(buf, 'a', sizeof(buf));
   gettimeofday(&time1,&dummy);

   while ((sent > 0) || (count <= 0))
   {
      long *loc;

      loc = (long *)buf;
     *loc = fc;
      rc = write(s, buf, blk);

      if (rc < 0)
         break;

      sent -= rc;
      fc += 1;
      frames += 1;
   }
}

main(
int argc,
char **argv)
{
   int  in;
   int  fd;
   int  len;
   int  vci;
   int  rc;
   int  fc;
   int  psr;
   int  blk;
   int  sent  = 0;
   struct sockaddr_atmpvc addr;
   struct atm_qos         qos;
   int    s,size,offset;


   blk = 1024 - 40;

   if (argc < 2)
   {
      printf("This sends stdin to the vci specified.              \n");
      printf("You must give vci number in decimal as parm 1.      \n");
      printf("You may  give blk size   in decimal as parm 2.      \n");
      printf("You may  give byte count in decimal as parm 2.      \n");
      printf("You may  give the psr    in decimal as parm 4.      \n");
      exit(1);
   }

   sscanf(argv[1], "%d", &vci);

   if (argc > 2)
      sscanf(argv[2], "%d", &blk);

   if (argc > 3)
      sscanf(argv[3], "%d", &count);

   if (argc > 4)
      sscanf(argv[4], "%d", &psr);

   printf("Sending to vci %d \n", vci);
   printf("Frame size %d bytes \n", blk);

   s = socket(PF_ATMPVC,SOCK_DGRAM,ATM_AAL5);
   printf("Socket call returned %d \n", s);

   qos.aal = 5;
   qos.txtp.traffic_class = ATM_UBR;
   qos.txtp.max_sdu = 9600;
   qos.txtp.max_pcr = 25 * 1024 * 1024;
   qos.txtp.min_pcr = 25 * 1024 * 1024;
   qos.txtp.max_cdv = 25 * 1024 * 1024;

   qos.rxtp.traffic_class = ATM_UBR;
   qos.rxtp.max_sdu = 9600;
   qos.rxtp.max_pcr = 25 * 1024 * 1024;
   qos.rxtp.min_pcr = 25 * 1024 * 1024;
   qos.rxtp.max_cdv = 25 * 1024 * 1024;

   rc = setsockopt(s, SOL_ATM, SO_ATMQOS, &qos, sizeof(qos));
   printf("Return from setsock is %d \n", rc);

   addr.sap_family   = AF_ATMPVC;
   addr.sap_addr.itf = 0;
   addr.sap_addr.vpi = 0;
   addr.sap_addr.vci = vci;

   while (rc = connect(s,(struct sockaddr *) &addr,sizeof(addr)))
   {
      sleep(1);
   }

   printf("Return from connect is %d \n", rc);

   memset(buf, 'A', sizeof(buf));

   aa_send(s, blk, count);

   times(&timeb);
   gettimeofday(&time2,&dummy);

   printf("time 1: %d %d\n",time1.tv_sec, time1.tv_usec);
   printf("time 2: %d %d\n",time2.tv_sec, time2.tv_usec);

   tu1 = 1000000 * time1.tv_sec;
   tu1 += time1.tv_usec;

   tu2 = 1000000 * time2.tv_sec;
   tu2 += time2.tv_usec;

   fc = frames;

   printf("Frames sent = %8d    \n", fc);
   printf("MBits / sec = %8.3lf \n", 8.0 * fc * fsize / (tu2 - tu1));
   printf("Frames/msec = %8.3lf \n", 1000 * fc / (tu2 - tu1));

   fprintf(stderr,
      "%6d \t %6d.%02d \t %6d.%02d \t %8.2lf \t %8.3lf \t %8d \t %8.3lf \n",
       blk,
       timeb.tms_utime / 100, timeb.tms_utime % 100,
       timeb.tms_stime / 100, timeb.tms_stime % 100,
       (tu2 - tu1)/ 1000000,
       8 * count / (tu2 - tu1),
       fc,
       fc / (tu2 - tu1));

   sleep(2);

}

