#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <netinet/in.h>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>
#include <fcntl.h>
#include <math.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <string.h>
#include <pcap.h>
#include <assert.h>
#define TRAFFICSOURCE_VERSION "$Revision: 1.13 $ $Date: 2000/01/21 15:48:10 $"
extern const char trafficsource_version[]; /* version string */
extern int optind, opterr;
#define OUTPUT_BUFFER_SIZE 2000 /* Big enough for largest payload+header*/
#define BURST_DEFAULT 0.352 /* secs */
#define IDLE_DEFAULT 0.620 /* secs */
#define PEAK_DEFAULT 32000 /* bits/sec (32Kbits/sec) */
#define INVERSE_M ((double) 4.6566128200e-10) /* (1.0/(double)M) */
#define DEBUG 0
#define DEFAULT_PACKETSIZE 64 /* payload */
#define DEFAULT_SOURCES 10
#define DEFAULT_PORT 4000 /* discard port */
#define DEFAULT_HOST "10.3.1.2"
#define DEFAULT_SNAPLEN 68
#define DEFAULT_INTERVAL 16 /* ms */
#define DEFAULT_LENGTH 98 /* packet length */
#define DEFAULT_TCPDUMP "/tmp/tcpdump"
#define TEXT_TRACE "/tmp/trace_file"
#define BIN_TRACE "/tmp/bin_trace_file"
/*
* From bitindex to int index.
*/
#define BITS2INT32(B) ((B)/(sizeof(u_int32_t)*8))
#define REMAIN(B) ((B)%(sizeof(u_int32_t)*8))
#define GETBIT(d, i) ((((d)[BITS2INT32(i)]) & (1 << REMAIN(i))) ? 1 : 0)
struct
data_pattern {
double burst_time;
double idle_time;
double peak_rate;
double interval;
int packet_size;
int burstlen;
int idlelen;
char dst_hostname[64];
short dst_port;
int nsources;
char tcpdump_filename[64];
char text_trace[64];
char bin_trace[64];
unsigned int running_time;
unsigned int nsteps;
int stats;
int tcpdump;
int senddata;
int bindata;
int readwritetrace;
};
enum wise_hdr_type_t {
WISE_HDR_NULL, /* Illegal */
WISE_HDR_DATA, /* User defined payload */
WISE_HDR_PING, /* No payload */
WISE_HDR_ECHO /* Echo on PINGs seq, timestamp */
};
static void usage();
void generate_packets(struct data_pattern *d);
int calc_length(double burstlen);
void send_packet(FILE *);
void idle_cycle(FILE *);
void zero_cycle(FILE *);
struct timeval gettimestamp(void);
struct timeval timevaladd(struct timeval t1, struct timeval t2);
struct timeval timevalsub(struct timeval t1, struct timeval t2);
char * timevalprint(struct timeval t1);
int write_trace(int rtime, struct data_pattern *d, int *rem, char *trace_file, int nsources);
void show_source_statistics(int *data, int nelements);
/*int send_data(struct data_pattern *d, FILE *, int i, struct sockaddr_in *addr, int sockfd, int nsources, pcap_dumper_t *pcap_file);*/
void delay(double);
int initialise(struct data_pattern *d, struct sockaddr_in *addr);
void get_arguments(int argc, char *argv[], struct data_pattern *d);
int calc_interval(struct data_pattern *d, int source, int rtime, FILE *, int *rem, int sources);
void dodots(int j);
void calc_burstlength(struct data_pattern *d, int sources, int *rem);
int
write_tcpdump_file(pcap_dumper_t *pcap_file, int noelements, struct data_pattern *d, int nsources);
int
produce_trace(struct data_pattern *d, int rtime, int **data, char *text_trace, char *bin_trace, int nsources, int *rem);
int make_bitmap(int **data, int l, int this);
int read_tracefile(char *tracefile, int nsources, int *nelements, int **data);
/*
* gprof
* calc packet size, hold constant rate and interval
*/
#include "trafficsource.h"
#include "rtp.h"
#define DBG 0
const char trafficsource_version[] = TRAFFICSOURCE_VERSION;
#if 0
static struct pcap *pd;
#endif
char dst_str[128], *pstr;
int snaplen = DEFAULT_SNAPLEN;
struct timeval T0; /* Start time */
void
calc_burstlength(struct data_pattern *d, int nsources, int rem[]) {
int i, temp;
d->interval = ((double)DEFAULT_INTERVAL)/1000.0;
d->burstlen = (d->burst_time/d->interval);
d->idlelen = (d->idle_time/d->interval);
d->nsteps = (int)(d->running_time/d->interval);
for (i = 0; i < nsources; i++){
do {
temp = calc_length(d->burstlen);
if (i % 2)
rem[i] = -temp; /* just make 50% start with idle i.e. -ve values */
else
rem[i] = temp; /* other 50% +ve, hence busrt */
} while (rem[i] == 0); /* We don't want a burstlen of 0 */
}
}
int
calc_length(double burstlen) {
double rand, logvalue;
rand = INVERSE_M * random();
logvalue = burstlen * -log(rand);
return ((int)(logvalue + 0.5));
}
int
calc_interval(struct data_pattern *d, int source, int rtime, FILE *trace_file, int *rem, int nsources) {
int temp;
/*
* burst time
*/
if (rem[source] > 0) {
send_packet(trace_file);
if (--rem[source] == 0) {
do {
temp = calc_length(d->idlelen);
} while (temp == 0);
rem[source] = -temp;
}
return 1;
}
/*
* Idle time
*/
else if (rem[source] < 0) {
idle_cycle(trace_file);
if(++rem[source] == 0) {
do {
temp = calc_length(d->burstlen);
} while (temp == 0);
rem[source] = temp;
}
return -1;
}
/*
* Shouldn't come here but bugs you know...
*/
else {
zero_cycle(trace_file);
}
return 0;
}
/*
* Executes the loops making exponential sources.
*
*/
int
write_trace(int rtime, struct data_pattern *d, int *rem, char *trace_file, int sources) {
int i,j;
FILE *f;
/*
* Open trace file.
*/
if ((f = fopen(trace_file, "w")) == NULL){
perror("fopen");
return -1;
}
for (j = 0; j < rtime; j++) {
/* dodots(j);*/
/* fprintf(f, "\n%d\t", j);*/
for(i = 0; i < sources; i++) {
calc_interval(d, i, j, f, rem, sources);
}
}
fclose(f);
return 0;
}
void
dodots(int j) {
if (j % 100 == 0) {
printf(".");
fflush(stdout);
}
}
void
send_packet(FILE *trace_file) {
fprintf(trace_file, " %s ", "1");
fflush(trace_file);
}
void
idle_cycle(FILE *trace_file) {
fprintf(trace_file, " %s ", "0");
fflush(trace_file);
}
void
zero_cycle(FILE *trace_file) {
fprintf(trace_file, " %s ", "-1");
fflush(trace_file);
}
void
new_line(FILE *trace_file) {
fprintf(trace_file, "\n");
}
static void
usage ()
{
fprintf(stderr, "\nusage: ");
fprintf(stderr, "trafficsource \n\n"
"[-h]\t\t\t\t# Print this text\n"
"[-v]\t\t\t\t# Print version\n"
"[-b burstsize]\t\t\t# Burstsize (def: 0.325)\n"
"[-i idletime]\t\t\t# Idletime (def: 0.625)\n"
"[-p peak rate]\t\t\t# Peak rate (def: 20480 bits/sec) \n"
"[-s packet size]\t\t# Packet Size (def:%d)\n"
"[-n number of sources]\t\t# Number of Sources (def:10)\n"
"[-t tcpdump filename]\t\t# Tcpdump filename (def/tmp/tcpdump)\n"
"[-f trace filename]\t\t# Trace filename text (def:/tmp/trace_file)\n"
"[-d destination host:port]\t# ipv4addr:port (def 10.3.1.2:4000)\n"
"[-l running time]\t\t# Duration of trace (seconds) (def:512)\n"
"[-c stats]\t\t\t# Statistics on trace generated (def:none)\n"
"[-r]\t\t\t\t# Write & read file /tmp/trace_file (def:on)\n\n"
"e.g. ./trafficsource -t /tmp/tcpfile -f /tmp/tracefile -d 193.10.66.193:9 -n 10\n\n",
DEFAULT_PACKETSIZE
);
exit(0);
}
int
initialise(struct data_pattern *d, struct sockaddr_in *addr) {
/*
* initialise with default values
*/
d->burst_time = BURST_DEFAULT;
d->idle_time = IDLE_DEFAULT;
d->peak_rate = PEAK_DEFAULT;
d->packet_size = DEFAULT_PACKETSIZE;
d->nsources = DEFAULT_SOURCES;
d->running_time = 100 * BURST_DEFAULT;
d->packet_size = DEFAULT_PACKETSIZE;
strcpy(d->tcpdump_filename, DEFAULT_TCPDUMP);
strcpy(d->text_trace, TEXT_TRACE);
strcpy(d->bin_trace, BIN_TRACE);
d->stats = 0;
d->tcpdump = 0;
d->senddata = 1;
d->readwritetrace = 1;
if (!addr)
return -1;
addr->sin_family = AF_INET;
addr->sin_port = htons(DEFAULT_PORT);
addr->sin_addr.s_addr = inet_addr(DEFAULT_HOST);
return 0;
}
void
get_arguments(int argc, char *argv[], struct data_pattern *d ) {
char dst_str[128], *pstr;
int ppos;
argv++;argc--;
for (;(argc>0)&& *argv; argc--, argv++){
if (**argv != '-')
break;
(*argv)++;
if (strlen(*argv)==0)
usage();
switch(**argv) {
case 'h': /* help */
usage(); /* usage exits */
break;
case 'v': /* version */
printf("%s\n", trafficsource_version);
exit(0);
break;
case 'b': /* burst rate */
argc--;argv++;
if (!*argv || sscanf(*argv, "%lf", &d->burst_time) != 1)
usage();
break;
case 'i': /* idle time */
argc--;argv++;
if (!*argv || sscanf(*argv, "%lf", &d->idle_time) != 1)
usage();
break;
case 'p': /* peak rate */
argc--;argv++;
if (!*argv || sscanf(*argv, "%lf", &d->peak_rate) != 1)
usage();
break;
case 's': /* packet size (bytes) */
argc--;argv++;
if (!*argv || sscanf(*argv, "%d", &d->packet_size) != 1)
usage();
break;
case 'd': /* destination */
argc--;argv++;
strcpy(dst_str, *argv);
if ((pstr = (char*)strrchr(dst_str, ':')) != NULL){
ppos = pstr-dst_str;
d->dst_port = (short)atoi(pstr+1);
*pstr = '\0';
}
strcpy(d->dst_hostname, dst_str);
break;
case 'n': /* number of sources */
argc--;argv++;
if (!*argv || sscanf(*argv, "%d", &d->nsources) != 1)
usage();
break;
case 't': /* tcpdump filename */
argc--;argv++;
if (!*argv || sscanf(*argv, "%s", d->tcpdump_filename) != 1)
usage();
break;
case 'f': /* text filename */
argc--;argv++;
if (!*argv || sscanf(*argv, "%s", d->text_trace) != 1)
usage();
break;
case 'l': /* running time (seconds) */
argc--;argv++;
if (!*argv || sscanf(*argv, "%d", &d->running_time) != 1)
usage();
break;
case 'c': /* stats */
argc--;argv++;
if (!*argv || sscanf(*argv, "%d", &d->stats) != 1)
usage();
break;
case 'u': /* tcpdump */
argc--;argv++;
if (!*argv || sscanf(*argv, "%d", &d->tcpdump) != 1)
usage();
break;
case 'r': /* readfile */
argc--;argv++;
if (!*argv || sscanf(*argv, "%d", &d->readwritetrace) != 1)
usage();
break;
default:
fprintf(stderr, "-%s - unrecognized option\n", *argv);
usage();
break;
}
}
if (argc != 0)
usage();
}
int
write_tcpdump_file_bitmap(pcap_dumper_t *pcap_file, struct data_pattern *d, int nsources, int nelements, int *data) {
struct pcap_pkthdr h;
static char outbuf[0];
static struct timeval now;
int i = 0;
for(i = 0; i < nelements; i++) {
/*
* Wait until the next slot
*/
if (i && ((i % nsources) == 0)){
delay(d->interval);
}
/*
* For each source, see if there is a packet to send
*/
if (GETBIT(data, i)) {
now = gettimestamp();
h.caplen = DEFAULT_SNAPLEN;
h.len = DEFAULT_LENGTH;
bcopy(&now, &h.ts, sizeof(struct timeval));
pcap_dump((u_char *)pcap_file, &h, outbuf);
}
} /* for elements */
return 0;
}
int
write_tcpdump_file(pcap_dumper_t *pcap_file, int noelements, struct data_pattern *d, int nsources) {
struct pcap_pkthdr h;
static char outbuf[0];
static struct timeval now;
int i = 0, j = 0;
int *ptr;
FILE *f;
/*
* Open trace file (again)
*/
if ((f = fopen(d->text_trace, "r")) == NULL){
perror("fopen");
return -1;
}
ptr = malloc((nsources + 1) * sizeof(int) * d->nsteps);
if (ptr == NULL) {
fprintf(stderr, "Not enough memory to load table Megs\n");
exit(0);
}
/*
* Small section of code below reads the ascii trace file really it
* should read the binary version, we have that and it's faster.
*/
while (fscanf(f, "%d", &ptr[i]) != EOF) {
/* printf("%d ", ptr[i]);*/
i++;
if (i % (nsources + 1) == 0)
;
/* printf(" \n"); */
}
fclose(f);
noelements = i;
for(i = 0; i < noelements; i++) {
/*
* Wait until the next slot
*/
if ((i % (nsources + 1)) == 0)
delay(d->interval);
/*
* For each source, see if there is a packet to send
*/
if ( (ptr[i] == 1) && (i != 4)) {
/*
* Write the tcpdump file
*/
now = gettimestamp();
h.caplen = DEFAULT_SNAPLEN;
h.len = DEFAULT_LENGTH;
bcopy(&now, &h.ts, sizeof(struct timeval));
pcap_dump((u_char *)pcap_file, &h, outbuf);
j++;
}
}
free(ptr);
return j;
}
void
delay(double waittime) {
int ret = 0;
static struct timeval wait_tv, now, start, future, diff;
now = start = gettimestamp();
wait_tv.tv_sec = (int)waittime;
wait_tv.tv_usec = abs((waittime - wait_tv.tv_sec) * 1000000);
future = timevaladd(wait_tv, start);
diff = timevalsub(future, now);
while ((diff.tv_usec > 0) && (diff.tv_sec >= 0)) {
ret = gettimeofday(&now, NULL);
diff = timevalsub(future, now);
}
}
void
show_source_statistics(int *data, int nelements) {
FILE *fd_stats;
fd_stats = fopen("/tmp/trace_file", "w");
#if 0
for (i=1; i < 200; i++) {
}
for (i=1; i < 200; i++) {
}
#endif
fflush(fd_stats);
fclose(fd_stats);
}
struct timeval gettimestamp() {
struct timeval t;
gettimeofday(&t, NULL);
return t;
}
void timevalfix(struct timeval *t1)
{
if (t1->tv_usec < 0) {
t1->tv_sec--;
t1->tv_usec += 1000000;
}
if (t1->tv_usec >= 1000000) {
t1->tv_sec++;
t1->tv_usec -= 1000000;
}
}
struct timeval timevaladd(struct timeval t1, struct timeval t2)
{
struct timeval t = t1;
t.tv_sec += t2.tv_sec;
t.tv_usec += t2.tv_usec;
timevalfix(&t);
return t;
}
struct timeval timevalsub(struct timeval t1, struct timeval t2)
{
struct timeval t = t1;
t.tv_sec -= t2.tv_sec;
t.tv_usec -= t2.tv_usec;
timevalfix(&t);
return t;
}
char *timevalprint(struct timeval t1)
{
static char s[64];
if (t1.tv_sec < 0 && t1.tv_usec > 0){
if (t1.tv_sec == -1)
sprintf(s, "-%ld.%06ld", t1.tv_sec+1, 1000000-t1.tv_usec);
else
sprintf(s, "%ld.%06ld", t1.tv_sec+1, 1000000-t1.tv_usec);
}
else
sprintf(s, "%ld.%06ld", t1.tv_sec, t1.tv_usec);
return s;
}
char *timevalprintms(struct timeval t1)
{
static char s[64];
if (t1.tv_sec < 0 && t1.tv_usec > 0){
if (t1.tv_sec == -1)
sprintf(s, "-%ld.%06ld", t1.tv_sec+1, 1000000-t1.tv_usec);
else
sprintf(s, "%ld.%06ld", t1.tv_sec+1, 1000000-t1.tv_usec);
}
else
sprintf(s, "%ld", t1.tv_sec*1000+t1.tv_usec/1000);
return s;
}
void rtp_set_hdr(rtp_header *hdr, struct timeval *T0, u_int32_t ssrc)
{
struct timeval T;
/* Fill in RTP v2 information */
hdr->flags = 0x0;
rtp_set_v(hdr->flags, RTP_VERSION);
rtp_set_pt(hdr->flags, RTP_PT_WISE); /* payload type */
if (T0)
T = *T0;
else
T = gettimestamp();
TV2NTP(&T, &hdr->ts);
hdr->ssrc = ssrc;
}
void NTP2TV(struct NTP_timestamp *NTP, struct timeval *TV)
{
static struct timeval T;
T = gettimestamp(); /* Need only be done every 18 hours :-> */
TV->tv_sec = NTP->sec | (T.tv_sec & 0xffff0000);
TV->tv_usec = ((NTP->frac*15625)>>10);
}
/* struct timeval to NTP 32-bit timestamp */
void TV2NTP(struct timeval *TV, struct NTP_timestamp *NTP)
{
/* u-seconds to 16 bit fraction 1024=2^10. Coneversion is x*65536/1000000*/
NTP->sec = TV->tv_sec & 0xffff;
NTP->frac = (TV->tv_usec<<10)/15625;
}
/* struct timeval to NTP 32-bit timestamp */
void TV2NTP_64(struct timeval *TV, struct NTP_timestamp_64 *NTP)
{
NTP->sec = TV->tv_sec;
/* conversion factor is 4294967296/1000000 */
NTP->frac = (u_int32_t)((double)TV->tv_usec*4294.967296);
}
/* Translate NTP timestamp to floating point seconds */
double NTP2sec(struct NTP_timestamp *NTP)
{
return (double)NTP->sec + ((double)NTP->frac)/65536.0;
}
/* Encode RTP header: generated from from Assar Ws ydr */
char *marshal_rtp_hdr(rtp_header *o, char *ptr)
{
rtp_header *p = (rtp_header *)ptr;
p->flags = htons(o->flags);
p->seq = htons(o->seq);
p->ts.sec = htons(o->ts.sec);
p->ts.frac = htons(o->ts.frac);
p->ssrc = htonl(o->ssrc);
return ptr;
}
int
make_bitmap(int **data, int l, int this) {
int k, a = 0;
k = BITS2INT32(l);
a = this << REMAIN(l);
(*data)[k] |= a;
return 0;
}
int
produce_trace(struct data_pattern *d, int rtime, int **data, char *text_trace, char *bin_trace, int source, int *rem) {
int j, l, i = 0, temp, written = 0, tot, pkts = 0;
double pkts_on, pkts_src, interval;
FILE *f = NULL, *bf = NULL;
int tot_elements;
double myinterval;
int *textfile;
myinterval = ((double)DEFAULT_INTERVAL)/1000.0;
tot_elements = d->nsources * d->running_time / myinterval;
/*
* Open trace file for writing specified
*/
if (d->readwritetrace) {
if (text_trace != NULL) {
if ((f = fopen(text_trace, "w")) == NULL){
fprintf(stderr, "fopen text trace file");
return -1;
}
}
}
/*
* read pre written trace file
*/
else {
printf("\nReading trace files %s\n", (TEXT_TRACE));
textfile = malloc((sizeof(int) * tot_elements));
if ((f = fopen(text_trace, "r")) == NULL){
fprintf(stderr, "fopen reading text trace file");
return -1;
}
i = 0;
while ((fscanf(f, "%d", &textfile[i]) != EOF) || i > tot_elements) {
if (i > tot_elements) {
printf("over tot_elements %d\n", tot_elements);
}
if (textfile[i] == 1)
pkts++;
i++;
}
fclose(f);
printf("Read %d elements (%d 1's) from %d sources time running_time %d\n", tot_elements, pkts, d->nsources, d->running_time);
for(i = 0; i < tot_elements; i++) {
make_bitmap(data, i, textfile[i]);
}
free(textfile);
return 0;
}
if (bin_trace != NULL) {
if ((bf = fopen(bin_trace, "w")) == NULL){
fprintf(stderr, "fopen binary trace file");
return -1;
}
}
/*
* Print info for user
*
* rtime = running time
* source = number of sources
* pkts_on = approx number of packets
*
* BURST_DEFAULT = 0.352 probability source is on
* DEFAULT_INTERVAL = space between packets in ms
*/
interval = ((double)DEFAULT_INTERVAL)/1000.0;
tot = rtime * d->nsources;
pkts_on = tot * BURST_DEFAULT;
pkts_src = pkts_on / d->nsources;
printf("\nProducing trace files %s\n", (TEXT_TRACE));
printf("\nrunning time %d, interval %f\n", d->running_time, d->interval);
printf ("sources %d total 1's 0's %d\n", d->nsources, tot);
printf ("packets on (approx)= %f pkts/source %f\n", pkts_on, pkts_src);
/*
* Number of elements
*/
l = -1;
for (j = 0; j < rtime; j++) {
for(i = 0; i < source; i++) {
l++;
/*
* burst time
*/
if (rem[i] > 0) {
make_bitmap(data, l, 1);
send_packet(f);
if (--rem[i] == 0) {
do {
temp = calc_length(d->idlelen);
} while (temp == 0);
rem[i] = -temp;
}
continue;
}
/*
* Idle time
*/
else if (rem[i] < 0) {
make_bitmap(data, l, 0);
idle_cycle(f);
if(++rem[i] == 0) {
do {
temp = calc_length(d->burstlen);
} while (temp == 0);
rem[i] = temp;
}
continue;
}
/*
* Shouldn't come here but bugs you know...
*/
else {
make_bitmap(data, l, -1);
zero_cycle(f);
}
} /* sources */
new_line(f);
} /* rtime */
/*
* Write binary file
*/
written = fwrite(*data, sizeof(int), rtime * source, bf);
if (text_trace != NULL) {
fclose(f);
}
if (bf != NULL) {
fclose(bf);
}
return 0;
}
/*
* Just spin loop til gettimeofday is T.
* return -1 if time had already passed.
*/
static int
delay_til(struct timeval T, struct timeval *max)
{
static struct timeval now;
struct timeval diff;
now = gettimestamp();
if (timercmp(&now, &T, >)){
#if DBG
/* printf(" miss "); */
#endif
diff = timevalsub(now, T);
if (timercmp(&diff, max, >))
*max = diff;
return -1;
}
while (timercmp(&now, &T, <))
now = gettimestamp();
return 0;
}
static int
send_it(int source, struct sockaddr_in *addr, int sockfd, unsigned short *seqs, unsigned timestamp, int packet_size)
{
static char outbuf[OUTPUT_BUFFER_SIZE];
static rtp_header hdr;
static int first = 1;
int sent;
int len = 0;
char *p = outbuf;
if(first) {
first = 0;
/*
* set the source from which this packet came
*/
hdr.flags = 0x0;
rtp_set_v(hdr.flags, RTP_VERSION);
rtp_set_pt(hdr.flags, RTP_PT_WISE); /* payload type */
}
hdr.ts.sec = (timestamp&0xffff0000)>>16;
hdr.ts.frac = timestamp&0xffff;
hdr.seq = seqs[source];
hdr.ssrc = source;
/*
* Translate header into network byte order
*/
marshal_rtp_hdr(&hdr, p);
len += sizeof(rtp_header);
p += sizeof(rtp_header);
len += packet_size;
p += packet_size;
if ((sent = sendto(sockfd, outbuf, len, 0x0,
(struct sockaddr*)addr, sizeof(*addr))) < 0)
perror("sendto");
fflush(NULL);
return (sent);
}
/*
* Send all data.
* Send it within a loop.
* Packets are sent in rounds: src 0, src 1,..., src n-1.
* Each round should take TP time (<1 sec).
* Distance between packets within a round is dP (= TP/nsources).
*/
static int
send_data(struct sockaddr_in *addr, int nsources, int nelements, double interval_s, int packet_size, int *data)
{
unsigned int i=0, j;
int sockfd, src;
struct timeval TP; /* Periodic interval */
struct timeval TP0; /* Start of Periodic interval */
struct timeval dT; /* increment within interval */
struct timeval T;
#if DBG
struct timeval diff;
#endif
struct timeval max_missed; /* max missed time */
unsigned short *seqs; /* Vector of sequence #: one for each src. */
u_int32_t timestep = 0;
u_int32_t missed = 0; /* # of missed deadlines */
u_int32_t sent_bytes = 0; /* # of succesfully sent bytes */
u_int32_t sent_packets = 0; /* # of succesfully sent packets */
u_int32_t notsent_packets = 0; /* # of succesfully sent packets */
if ((seqs = (unsigned short*)calloc(nsources, sizeof(unsigned short))) == NULL){
perror("malloc");
return -1;
}
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){
perror("socket");
return -1;
}
/*
*
*/
assert(interval_s < 1.0);
TP.tv_sec = 0;
TP.tv_usec = (u_int32_t)(interval_s*1000000);
dT.tv_sec = 0;
dT.tv_usec = TP.tv_usec/nsources;
/*
* Wait 1 sec til start.
*/
T0 = gettimestamp();
T0.tv_sec += 1;
TP0 = T = T0;
#if DBG
printf("T0: %s\n", timevalprint(T0));
printf("TP: %s\n", timevalprint(TP));
printf("dT: %s\n", timevalprint(dT));
#endif
for(i=0; i < nelements; i++) {
src = i % nsources;
/*
* Wait until the next slot
*/
/*
* Check if new sending round: timestep is plus one.
*/
if (i && (src == 0)){
timestep++; /* eq i/nsources */
assert(timestep == i/nsources);
T = TP0 = timevaladd(TP0, TP);
}
if (src != 0)
T = timevaladd(T, dT);
/*
* For each source, see if there is a packet to send
*/
#if DBG
printf("%d ", GETBIT(data, i));
diff = timevalsub(T, T0);
printf("%s\n", timevalprint(diff));
/* printf("%s %d\n", timevalprint(diff), src);*/
#endif
if (GETBIT(data, i)){
if (delay_til(T, &max_missed) < 0)
missed++;
j = send_it(src, addr, sockfd, seqs, timestep, packet_size);
if (j==0)
notsent_packets++;
else
sent_packets++;
sent_bytes += j;
seqs[src]++;
}
#if DBG
if ((i+1)%nsources == 0)
;
#endif
} /* for() */
#if 0
printf("\n");
#endif
printf("Successfully sent: \t%8d [packets]\n", sent_packets);
printf("Successfully sent: \t%8d [bytes]\n", sent_bytes);
printf("Missed deadlines: \t%8d", missed);
if (missed)
printf(" (max: %s)", timevalprint(max_missed));
printf("\nFailed sendto:s: \t%8d\n", notsent_packets);
free(seqs);
return 0;
}
int
main(int argc, char *argv[]) {
int sent = 0, nelements = 0;
struct data_pattern *d;
struct sockaddr_in addr;
int *rem, *data;
#if 0
char ebuf[PCAP_ERRBUF_SIZE];
char *device = NULL;
pcap_dumper_t *pcap_file;
#endif
double interval;
interval = ((double)DEFAULT_INTERVAL)/1000.0;
d = malloc(sizeof(struct data_pattern));
if (d == NULL)
exit(0);
#if 0
if (device == NULL) {
device = pcap_lookupdev(ebuf);
if (device == NULL)
printf("%s", ebuf);
}
pd = pcap_open_live(device, snaplen, 0, 1000, ebuf); /* 0 !promiscous mode */
#endif
initialise(d, &addr);
get_arguments(argc, argv, d);
#if 0
pcap_file = pcap_dump_open(pd, d->tcpdump_filename);
#endif
rem = malloc(d->nsources * sizeof(int));
if (rem == NULL) {
perror("malloc");
exit(0);
}
calc_burstlength(d, d->nsources, rem);
nelements = d->nsources * d->nsteps;
if ((data = (u_int32_t*)malloc(nelements/8)) == NULL){
perror("malloc");
exit(0);
}
produce_trace(d, d->nsteps, &data, d->text_trace, d->bin_trace, d->nsources, rem);
if (d->stats) {
printf("Producing statistics, well er\n");
show_source_statistics(data, nelements);
}
if (d->tcpdump) {
printf("writing tcpdump file\n");
#if 0
lines = write_tcpdump_file_bitmap(pcap_file, d, d->nsources, nelements, data);
#endif
}
if (d->senddata) {
printf("sending data\n");
sent = send_data(&addr, d->nsources, nelements, interval, d->packet_size, data);
}
/*
* Clean up, close files and exit
*/
#if 0
pcap_dump_close(pcap_file);
pcap_close(pd);
#endif
free(data);
free(rem);
if (d->senddata) {
/* printf("%d bytes sent\n", sent); */
}
free(d);
return 0;
}