Updated reporter callback, interval report, and the tcp info report to print out its message rather than allocating memory.

This commit is contained in:
sethdelliott 2010-06-16 20:32:01 +00:00
parent ccb086576f
commit 3e402adeb7
4 changed files with 199 additions and 247 deletions

View File

@ -1,5 +1,3 @@
/*
Copyright (c) 2009, The Regents of the University of California, through
Lawrence Berkeley National Laboratory (subject to receipt of any required

View File

@ -410,6 +410,8 @@ iperf_connect(struct iperf_test *test)
struct iperf_stream *sp;
int i, s = 0;
printf("Connecting to host %s, port %d\n", test->server_hostname, test->server_port);
/* For Select: Set the test->write_set select set to zero, then set the s fd */
FD_ZERO(&test->write_set);
@ -473,35 +475,34 @@ iperf_stats_callback(struct iperf_test * test)
//printf("in stats_callback: num_streams = %d role = %c\n", test->num_streams, test->role);
while (sp != NULL)
{
rp = sp->result;
while (sp != NULL) {
rp = sp->result;
if (test->role == 'c')
temp.bytes_transferred = rp->bytes_sent_this_interval;
else
temp.bytes_transferred = rp->bytes_received_this_interval;
if (test->role == 'c')
temp.bytes_transferred = rp->bytes_sent_this_interval;
else
temp.bytes_transferred = rp->bytes_received_this_interval;
ip = sp->result->interval_results;
/* result->end_time contains timestamp of previous interval */
ip = sp->result->interval_results;
/* result->end_time contains timestamp of previous interval */
if ( ip != NULL ) /* not the 1st interval */
memcpy(&temp.interval_start_time, &sp->result->end_time, sizeof(struct timeval));
memcpy(&temp.interval_start_time, &sp->result->end_time, sizeof(struct timeval));
else /* or use timestamp from beginning */
memcpy(&temp.interval_start_time, &sp->result->start_time, sizeof(struct timeval));
/* now save time of end of this interval */
gettimeofday(&sp->result->end_time, NULL);
memcpy(&temp.interval_end_time, &sp->result->end_time, sizeof(struct timeval));
temp.interval_duration = timeval_diff(&temp.interval_start_time, &temp.interval_end_time);
//temp.interval_duration = timeval_diff(&temp.interval_start_time, &temp.interval_end_time);
if (test->tcp_info)
get_tcpinfo(test, &temp);
/* now save time of end of this interval */
gettimeofday(&sp->result->end_time, NULL);
memcpy(&temp.interval_end_time, &sp->result->end_time, sizeof(struct timeval));
temp.interval_duration = timeval_diff(&temp.interval_start_time, &temp.interval_end_time);
//temp.interval_duration = timeval_diff(&temp.interval_start_time, &temp.interval_end_time);
if (test->tcp_info)
get_tcpinfo(test, &temp);
//printf(" iperf_stats_callback: adding to interval list: \n");
add_to_interval_list(rp, &temp);
add_to_interval_list(rp, &temp);
rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0;
/* for debugging */
//display_interval_list(rp, test->tcp_info);
sp = sp->next;
/* for debugging */
//display_interval_list(rp, test->tcp_info);
sp = sp->next;
} /* for each stream */
return 0;
@ -519,9 +520,7 @@ iperf_stats_callback(struct iperf_test * test)
void
iperf_reporter_callback(struct iperf_test * test)
{
int total_packets = 0, lost_packets = 0, curr_state = 0;
char *message = NULL;
char *message_final = NULL;
int total_packets = 0, lost_packets = 0, iperf_state;
char ubuf[UNIT_LEN];
char nbuf[UNIT_LEN];
struct iperf_stream *sp = NULL;
@ -529,53 +528,47 @@ iperf_reporter_callback(struct iperf_test * test)
double start_time, end_time;
struct iperf_interval_results *ip = NULL;
message = (char *)calloc(MAX_RESULT_STRING, sizeof(char));
message_final = (char *)calloc(MAX_RESULT_STRING, sizeof(char));
sp = test->streams;
curr_state = sp->settings->state;
iperf_state = sp->settings->state;
switch (curr_state) {
switch (iperf_state) {
case TEST_RUNNING:
case STREAM_RUNNING:
/* print interval results for each stream */
while (sp) {
message_final = print_interval_results(test, sp, message_final);
for (sp = test->streams; sp != NULL; sp = sp->next) {
print_interval_results(test, sp);
bytes += sp->result->interval_results->bytes_transferred; /* sum up all streams */
sp = sp->next;
}
if (bytes <=0 ) { /* this can happen if timer goes off just when client exits */
fprintf(stderr, "error: bytes <= 0!\n");
break;
}
/* next build string with sum of all streams */
sp = test->streams; /* reset back to 1st stream */
if (test->num_streams > 1) {
sp = test->streams; /* reset back to 1st stream */
ip = test->streams->result->last_interval_results; /* use 1st stream for timing info */
unit_snprintf(ubuf, UNIT_LEN, (double) (bytes), 'A');
unit_snprintf(nbuf, UNIT_LEN, (double) (bytes / ip->interval_duration),
test->default_settings->unit_format);
start_time = timeval_diff(&sp->result->start_time,&ip->interval_start_time);
end_time = timeval_diff(&sp->result->start_time,&ip->interval_end_time);
unit_snprintf(nbuf, UNIT_LEN, (double) (bytes / ip->interval_duration),
test->default_settings->unit_format);
sprintf(message, report_sum_bw_format, start_time, end_time, ubuf, nbuf);
safe_strcat(message_final, message);
printf(report_sum_bw_format, start_time, end_time, ubuf, nbuf);
#ifdef NOT_DONE /* is it usful to figure out a way so sum * TCP_info acrross multiple streams? */
if (test->tcp_info) {
build_tcpinfo_message(ip, message);
safe_strcat(message_final, message);
}
#if defined(linux) || defined(__FreeBSD__) /* is it usful to figure out a way so sum * TCP_info acrross multiple streams? */
if (test->tcp_info)
print_tcpinfo(ip);
#endif
}
break;
case ALL_STREAMS_END:
case RESULT_REQUEST:
/* print final summary for all intervals */
sp = test->streams;
start_time = 0.;
end_time = timeval_diff(&sp->result->start_time, &sp->result->end_time);
while (sp) {
for (sp = test->streams; sp != NULL; sp = sp->next) {
if (test->role == 'c')
bytes = sp->result->bytes_sent;
else
@ -588,101 +581,79 @@ iperf_reporter_callback(struct iperf_test * test)
if (bytes > 0 ) {
unit_snprintf(ubuf, UNIT_LEN, (double) (bytes), 'A');
unit_snprintf(nbuf, UNIT_LEN, (double) (bytes / end_time), test->default_settings->unit_format);
if (test->protocol == Ptcp) { // TCP mode
sprintf(message, report_bw_format, sp->socket, start_time, end_time, ubuf, nbuf);
safe_strcat(message_final, message);
if (test->protocol == Ptcp) {
printf(report_bw_format, sp->socket, start_time, end_time, ubuf, nbuf);
#if defined(linux) || defined(__FreeBSD__)
if (test->tcp_info) {
ip = sp->result->last_interval_results;
build_tcpinfo_message(ip, message);
safe_strcat(message_final, message);
print_tcpinfo(ip);
}
#endif
} else { // UDP mode
sprintf(message, report_bw_jitter_loss_format, sp->socket, start_time,
end_time, ubuf, nbuf, sp->jitter * 1000, sp->cnt_error,
sp->packet_count, (double) (100.0 * sp->cnt_error / sp->packet_count));
safe_strcat(message_final, message);
} else {
printf(report_bw_jitter_loss_format, sp->socket, start_time,
end_time, ubuf, nbuf, sp->jitter * 1000, sp->cnt_error,
sp->packet_count, (double) (100.0 * sp->cnt_error / sp->packet_count));
if (test->role == 'c') {
sprintf(message, report_datagrams, sp->socket, sp->packet_count);
safe_strcat(message_final, message);
printf(report_datagrams, sp->socket, sp->packet_count);
}
if (sp->outoforder_packets > 0)
printf(report_sum_outoforder, start_time, end_time, sp->cnt_error);
}
}
sp = sp->next;
}
unit_snprintf(ubuf, UNIT_LEN, (double) total_bytes, 'A');
unit_snprintf(nbuf, UNIT_LEN, (double) total_bytes / end_time, test->default_settings->unit_format);
if (test->num_streams > 1) {
if (test->protocol == Ptcp) {
sprintf(message, report_sum_bw_format, start_time, end_time, ubuf, nbuf);
safe_strcat(message_final, message);
printf(report_sum_bw_format, start_time, end_time, ubuf, nbuf);
} else {
sprintf(message, report_sum_bw_jitter_loss_format, start_time, end_time, ubuf, nbuf, sp->jitter,
printf(report_sum_bw_jitter_loss_format, start_time, end_time, ubuf, nbuf, sp->jitter,
lost_packets, total_packets, (double) (100.0 * lost_packets / total_packets));
safe_strcat(message_final, message);
}
if ((test->print_mss != 0) && (test->role == 'c')) {
sprintf(message, "\nThe TCP maximum segment size mss = %d \n", getsock_tcp_mss(sp->socket));
safe_strcat(message_final, message);
printf("The TCP maximum segment size mss = %d\n", getsock_tcp_mss(sp->socket));
}
}
break;
} // end switch
}
free(message);
printf("%s\n", message_final);
free(message_final);
}
/**************************************************************************/
char *
print_interval_results(struct iperf_test * test, struct iperf_stream * sp, char *message_final)
void
print_interval_results(struct iperf_test * test, struct iperf_stream * sp)
{
static int first_stream = 1;
char ubuf[UNIT_LEN];
char nbuf[UNIT_LEN];
double st = 0., et = 0.;
char ubuf[UNIT_LEN];
char nbuf[UNIT_LEN];
double st = 0., et = 0.;
struct iperf_interval_results *ir = NULL;
char *message = (char *) malloc(MAX_RESULT_STRING);
//printf("in print_interval_results for stream %d \n", sp->socket);
ir = sp->result->last_interval_results; /* get last entry in linked list */
if (ir == NULL)
{
printf("print_interval_results Error: interval_results = NULL \n");
return NULL;
if (ir == NULL) {
printf("print_interval_results Error: interval_results = NULL \n");
return;
}
if (first_stream) /* only print header for 1st stream */
{
sprintf(message, report_bw_header);
safe_strcat(message_final, message);
first_stream = 0;
if (sp == test->streams) {
printf(report_bw_header);
}
unit_snprintf(ubuf, UNIT_LEN, (double) (ir->bytes_transferred), 'A');
unit_snprintf(nbuf, UNIT_LEN,
(double) (ir->bytes_transferred / ir->interval_duration), test->default_settings->unit_format);
unit_snprintf(ubuf, UNIT_LEN, (double) (ir->bytes_transferred), 'A');
unit_snprintf(nbuf, UNIT_LEN, (double) (ir->bytes_transferred / ir->interval_duration),
test->default_settings->unit_format);
st = timeval_diff(&sp->result->start_time,&ir->interval_start_time);
et = timeval_diff(&sp->result->start_time,&ir->interval_end_time);
sprintf(message, report_bw_format, sp->socket, st, et, ubuf, nbuf);
//printf("print_interval_results 1: message = %s \n", message);
safe_strcat(message_final, message);
printf(report_bw_format, sp->socket, st, et, ubuf, nbuf);
#if defined(linux) || defined(__FreeBSD__)
if (test->tcp_info)
{
build_tcpinfo_message(ir, message);
safe_strcat(message_final, message);
}
print_tcpinfo(ir);
#endif
//printf("reporter_callback: built interval string: %s \n", message_final);
free(message);
return message_final;
}
/**************************************************************************/

View File

@ -139,7 +139,7 @@ void get_tcpinfo(struct iperf_test *test, struct iperf_interval_results *rp);
void print_tcpinfo(struct iperf_interval_results *);
void build_tcpinfo_message(struct iperf_interval_results *r, char *message);
void safe_strcat(char *s1, char *s2);
char * print_interval_results(struct iperf_test * test, struct iperf_stream *sp, char *m);
void print_interval_results(struct iperf_test * test, struct iperf_stream *sp);
int iperf_connect(struct iperf_test *);
int iperf_client_start(struct iperf_test *);
int iperf_client_end(struct iperf_test *);

View File

@ -29,7 +29,7 @@
#include "locale.h"
int iperf_run(struct iperf_test * test);
int iperf_run(struct iperf_test *);
/**************************************************************************/
@ -72,15 +72,9 @@ static struct option longopts[] =
int
main(int argc, char **argv)
{
char ch, role;
char ch, role;
struct iperf_test *test;
int port = PORT;
// The following lines need to be removed and moved to somewhere else!!!
const char *usage_long1 = "this is usage_long1";
const char *usage_long2 = "this is usage_long2";
int port = PORT;
#ifdef TEST_PROC_AFFINITY
/* didnt seem to work.... */
@ -88,167 +82,155 @@ main(int argc, char **argv)
* increasing the priority of the process to minimise packet generation
* delay
*/
int rc = setpriority(PRIO_PROCESS, 0, -15);
int rc = setpriority(PRIO_PROCESS, 0, -15);
if (rc < 0)
{
perror("setpriority:");
printf("setting priority to valid level\n");
rc = setpriority(PRIO_PROCESS, 0, 0);
if (rc < 0) {
perror("setpriority:");
printf("setting priority to valid level\n");
rc = setpriority(PRIO_PROCESS, 0, 0);
}
/* setting the affinity of the process */
cpu_set_t cpu_set;
int affinity = -1;
int ncores = 1;
int affinity = -1;
int ncores = 1;
sched_getaffinity(0, sizeof(cpu_set_t), &cpu_set);
if (errno)
perror("couldn't get affinity:");
perror("couldn't get affinity:");
if ((ncores = sysconf(_SC_NPROCESSORS_CONF)) <= 0)
err("sysconf: couldn't get _SC_NPROCESSORS_CONF");
err("sysconf: couldn't get _SC_NPROCESSORS_CONF");
CPU_ZERO(&cpu_set);
CPU_SET(affinity, &cpu_set);
if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set) != 0)
err("couldn't change CPU affinity");
err("couldn't change CPU affinity");
#endif
test = iperf_new_test();
iperf_defaults(test); /* sets defaults */
while ((ch = getopt_long(argc, argv, "c:p:st:uP:b:l:w:i:n:mNTvhVdM:f:", longopts, NULL)) != -1)
{
switch (ch)
{
case 'c':
test->role = 'c';
role = test->role;
test->server_hostname = (char *) malloc(strlen(optarg)+1);
strncpy(test->server_hostname, optarg, strlen(optarg));
break;
case 'p':
test->server_port = atoi(optarg);
port = test->server_port;
break;
case 's':
test->role = 's';
role = test->role;
break;
case 't':
test->duration = atoi(optarg);
if (test->duration > MAX_TIME)
{
fprintf(stderr, "\n Error: test duration too long. Maximum value = %d \n\n", (int)MAX_TIME);
fprintf(stderr, usage_long1);
fprintf(stderr, usage_long2);
exit(1);
}
break;
case 'u':
test->protocol = Pudp;
test->default_settings->blksize = DEFAULT_UDP_BLKSIZE;
test->new_stream = iperf_new_udp_stream;
break;
case 'P':
test->num_streams = atoi(optarg);
if (test->num_streams > MAX_STREAMS)
{
fprintf(stderr, "\n Error: Number of parallel streams too large. Maximum value = %d \n\n", MAX_STREAMS);
fprintf(stderr, usage_long1);
fprintf(stderr, usage_long2);
exit(1);
}
break;
case 'b':
test->default_settings->rate = unit_atof(optarg);
break;
case 'l':
test->default_settings->blksize = unit_atoi(optarg);
if (test->default_settings->blksize > MAX_BLOCKSIZE)
{
fprintf(stderr, "\n Error: Block size too large. Maximum value = %d \n\n", MAX_BLOCKSIZE);
fprintf(stderr, usage_long1);
fprintf(stderr, usage_long2);
exit(1);
}
break;
case 'w':
test->default_settings->socket_bufsize = unit_atof(optarg);
if (test->default_settings->socket_bufsize > MAX_TCP_BUFFER)
{
fprintf(stderr, "\n Error: TCP buffer too large. Maximum value = %d \n\n", MAX_TCP_BUFFER);
fprintf(stderr, usage_long1);
fprintf(stderr, usage_long2);
exit(1);
}
break;
case 'i':
/* could potentially want separate stat collection and reporting intervals,
but just set them to be the same for now */
test->stats_interval = atoi(optarg);
test->reporter_interval = atoi(optarg);
if (test->stats_interval > MAX_INTERVAL)
{
fprintf(stderr, "\n Error: Report interval too large. Maximum value = %d \n\n", MAX_INTERVAL);
fprintf(stderr, usage_long1);
fprintf(stderr, usage_long2);
exit(1);
}
break;
case 'n':
test->default_settings->bytes = unit_atoi(optarg);
printf("total bytes to be transferred = %llu\n", test->default_settings->bytes);
break;
case 'm':
test->print_mss = 1;
break;
case 'N':
test->no_delay = 1;
break;
case 'M':
test->default_settings->mss = atoi(optarg);
if (test->default_settings->mss > MAX_MSS)
{
fprintf(stderr, "\n Error: MSS too large. Maximum value = %d \n\n", MAX_MSS);
fprintf(stderr, usage_long1);
fprintf(stderr, usage_long2);
exit(1);
}
break;
case 'f':
test->default_settings->unit_format = *optarg;
break;
case 'T':
test->tcp_info = 1;
break;
case 'V':
test->verbose = 1;
break;
case 'd':
test->debug = 1;
break;
case 'v': // print version and exit
fprintf( stderr, version );
exit(1);
case 'h':
default:
fprintf(stderr, usage_long1);
fprintf(stderr, usage_long2);
exit(1);
}
while ((ch = getopt_long(argc, argv, "c:p:st:uP:b:l:w:i:n:mNTvhVdM:f:", longopts, NULL)) != -1) {
switch (ch) {
case 'c':
test->role = 'c';
role = test->role;
test->server_hostname = (char *) malloc(strlen(optarg)+1);
strncpy(test->server_hostname, optarg, strlen(optarg));
break;
case 'p':
test->server_port = atoi(optarg);
port = test->server_port;
break;
case 's':
test->role = 's';
role = test->role;
break;
case 't':
test->duration = atoi(optarg);
if (test->duration > MAX_TIME) {
fprintf(stderr, "\n Error: test duration too long. Maximum value = %d \n\n", (int)MAX_TIME);
fprintf(stderr, usage_long1);
fprintf(stderr, usage_long2);
exit(1);
}
break;
case 'u':
test->protocol = Pudp;
test->default_settings->blksize = DEFAULT_UDP_BLKSIZE;
test->new_stream = iperf_new_udp_stream;
break;
case 'P':
test->num_streams = atoi(optarg);
if (test->num_streams > MAX_STREAMS) {
fprintf(stderr, "\n Error: Number of parallel streams too large. Maximum value = %d \n\n", MAX_STREAMS);
fprintf(stderr, usage_long1);
fprintf(stderr, usage_long2);
exit(1);
}
break;
case 'b':
test->default_settings->rate = unit_atof(optarg);
break;
case 'l':
test->default_settings->blksize = unit_atoi(optarg);
if (test->default_settings->blksize > MAX_BLOCKSIZE) {
fprintf(stderr, "\n Error: Block size too large. Maximum value = %d \n\n", MAX_BLOCKSIZE);
fprintf(stderr, usage_long1);
fprintf(stderr, usage_long2);
exit(1);
}
break;
case 'w':
test->default_settings->socket_bufsize = unit_atof(optarg);
if (test->default_settings->socket_bufsize > MAX_TCP_BUFFER) {
fprintf(stderr, "\n Error: TCP buffer too large. Maximum value = %d \n\n", MAX_TCP_BUFFER);
fprintf(stderr, usage_long1);
fprintf(stderr, usage_long2);
exit(1);
}
break;
case 'i':
/* could potentially want separate stat collection and reporting intervals,
but just set them to be the same for now */
test->stats_interval = atoi(optarg);
test->reporter_interval = atoi(optarg);
if (test->stats_interval > MAX_INTERVAL) {
fprintf(stderr, "\n Error: Report interval too large. Maximum value = %d \n\n", MAX_INTERVAL);
fprintf(stderr, usage_long1);
fprintf(stderr, usage_long2);
exit(1);
}
break;
case 'n':
test->default_settings->bytes = unit_atoi(optarg);
printf("total bytes to be transferred = %llu\n", test->default_settings->bytes);
break;
case 'm':
test->print_mss = 1;
break;
case 'N':
test->no_delay = 1;
break;
case 'M':
test->default_settings->mss = atoi(optarg);
if (test->default_settings->mss > MAX_MSS) {
fprintf(stderr, "\n Error: MSS too large. Maximum value = %d \n\n", MAX_MSS);
fprintf(stderr, usage_long1);
fprintf(stderr, usage_long2);
exit(1);
}
break;
case 'f':
test->default_settings->unit_format = *optarg;
break;
case 'T':
test->tcp_info = 1;
break;
case 'V':
test->verbose = 1;
break;
case 'd':
test->debug = 1;
break;
case 'v': // print version and exit
fprintf( stderr, version );
exit(1);
case 'h':
default:
fprintf(stderr, usage_long1);
fprintf(stderr, usage_long2);
exit(1);
}
}
/* exit until this is done.... */
if (test->protocol == Pudp) {
printf("UDP mode not yet supported. Exiting. \n");
exit(0);
printf("UDP mode not yet supported. Exiting. \n");
exit(0);
}
//printf("in main: calling iperf_init_test \n");
if (test->role == 'c')
printf("Connecting to port %d on host %s \n", test->server_port, test->server_hostname);
iperf_init_test(test);
//printf("in main: calling iperf_run \n");
@ -256,7 +238,8 @@ main(int argc, char **argv)
iperf_free_test(test);
printf("\niperf Done.\n");
exit(0);
return 0;
}
/**************************************************************************/