more cleanup and bug fixes

This commit is contained in:
Brian Tierney 2009-11-10 04:41:42 +00:00
parent a3281a3dc6
commit e99faeae86
9 changed files with 353 additions and 259 deletions

8
src/LICENSE.txt Normal file
View File

@ -0,0 +1,8 @@
/*
* Copyright (c) 2009, The Regents of the University of California, through
* Lawrence Berkeley National Laboratory (subject to receipt of any required
* approvals from the U.S. Dept. of Energy). All rights reserved.
*/

9
src/README.txt Normal file
View File

@ -0,0 +1,9 @@
iperf3 should work on Linux, FreeBSD, and Mac OSX
Prerequists:
libuuidgen
To build, just type 'make' (or 'gmake' on FreeBSD)

24
src/TODO.txt Normal file
View File

@ -0,0 +1,24 @@
Current list of things to fix/add to iperf 3.0
- finish/fix receive_result_from_server()
- also: should this be called for TCP too, or only UDP (currently its both,
but I think it should be UDP only, or maybe a command line option for TCP
- document and verify the 'state machine'. Is it an error to send messages in the wrong order?
- what is "STREAM_RUNNING" vs "TEST_RUNNING"??
- (-i N) mode on server does not work
- verify placment of all timing calls and total_bytes_sent computations
- break up into client/sever files and TCP/UDP files
- much better/standard error handling throughout
- better packaging/makefile, README, LICENCE, etc files
- cleanup/fix/test UDP mode
- IPV6
- add verbose and debug options
- add human readable vs machine readable output mode
(my idea on this is that "human readable" = compatable with old iperf,
and that "machine readable is all name=value pairs -blt )
- lots more testing
- look for 'XXX' in code and address
- deamon mode
- see issue tracker for other wish list items

View File

@ -110,9 +110,9 @@ struct iperf_test
/* Select related parameters */ /* Select related parameters */
int max_fd; int max_fd;
fd_set read_set; fd_set read_set; /* set of read sockets */
fd_set temp_set; fd_set temp_set; /* temp set for select */
fd_set write_set; fd_set write_set; /* set of write sockets */
int (*accept) (struct iperf_test *); int (*accept) (struct iperf_test *);
struct iperf_stream *(*new_stream) (struct iperf_test *); struct iperf_stream *(*new_stream) (struct iperf_test *);

View File

@ -39,7 +39,7 @@
#include "uuid.h" #include "uuid.h"
#include "locale.h" #include "locale.h"
jmp_buf env; /* to handle longjmp on signal */ jmp_buf env; /* to handle longjmp on signal */
/*************************************************************/ /*************************************************************/
@ -53,25 +53,27 @@ jmp_buf env; /* to handle longjmp on signal */
* iperf_test structure -blt * iperf_test structure -blt
*/ */
int int
all_data_sent(struct iperf_test *test) all_data_sent(struct iperf_test * test)
{ {
if (test->default_settings->bytes == 0) if (test->default_settings->bytes == 0)
return 0; return 0;
else { else
uint64_t total_bytes = 0; {
uint64_t total_bytes = 0;
struct iperf_stream *sp; struct iperf_stream *sp;
sp = test->streams; sp = test->streams;
while (sp) { while (sp)
{
total_bytes += sp->result->bytes_sent; total_bytes += sp->result->bytes_sent;
sp = sp->next; sp = sp->next;
} }
if (total_bytes >= (test->num_streams * test->default_settings->bytes)) { if (total_bytes >= (test->num_streams * test->default_settings->bytes))
{
return 1; return 1;
} } else
else
return 0; return 0;
} }
@ -85,16 +87,16 @@ all_data_sent(struct iperf_test *test)
*/ */
void void
exchange_parameters(struct iperf_test *test) exchange_parameters(struct iperf_test * test)
{ {
int result; int result;
struct iperf_stream *sp; struct iperf_stream *sp;
struct param_exchange *param; struct param_exchange *param;
//printf("in exchange_parameters \n"); printf("in exchange_parameters \n");
sp = test->streams; sp = test->streams;
sp->settings->state = PARAM_EXCHANGE; sp->settings->state = PARAM_EXCHANGE;
param = (struct param_exchange *)sp->buffer; param = (struct param_exchange *) sp->buffer;
get_uuid(test->default_settings->cookie); get_uuid(test->default_settings->cookie);
strncpy(param->cookie, test->default_settings->cookie, COOKIE_SIZE); strncpy(param->cookie, test->default_settings->cookie, COOKIE_SIZE);
@ -108,7 +110,7 @@ exchange_parameters(struct iperf_test *test)
param->format = test->default_settings->unit_format; param->format = test->default_settings->unit_format;
#ifdef OLD_WAY #ifdef OLD_WAY
//printf(" sending exchange params: size = %d \n", (int)sizeof(struct param_exchange)); //printf(" sending exchange params: size = %d \n", (int) sizeof(struct param_exchange));
/* XXX: can we use iperf_tcp_send for this? that would be cleaner */ /* XXX: can we use iperf_tcp_send for this? that would be cleaner */
result = send(sp->socket, sp->buffer, sizeof(struct param_exchange), 0); result = send(sp->socket, sp->buffer, sizeof(struct param_exchange), 0);
if (result < 0) if (result < 0)
@ -117,11 +119,13 @@ exchange_parameters(struct iperf_test *test)
//printf("result = %d state = %d, error = %d \n", result, sp->buffer[0], errno); //printf("result = %d state = %d, error = %d \n", result, sp->buffer[0], errno);
/* get answer back from server */ /* get answer back from server */
do { do
{
//printf("exchange_parameters: reading result from server .. \n"); //printf("exchange_parameters: reading result from server .. \n");
result = recv(sp->socket, sp->buffer, sizeof(struct param_exchange), 0); result = recv(sp->socket, sp->buffer, sizeof(struct param_exchange), 0);
} while (result == -1 && errno == EINTR); } while (result == -1 && errno == EINTR);
#else #else
printf(" sending exchange params: size = %d \n", (int) sizeof(struct param_exchange));
result = sp->snd(sp); result = sp->snd(sp);
if (result < 0) if (result < 0)
perror("Error sending exchange params to server"); perror("Error sending exchange params to server");
@ -130,7 +134,8 @@ exchange_parameters(struct iperf_test *test)
if (result < 0) if (result < 0)
perror("Error getting exchange params ack from server"); perror("Error getting exchange params ack from server");
if (result > 0 && sp->buffer[0] == ACCESS_DENIED) { if (result > 0 && sp->buffer[0] == ACCESS_DENIED)
{
fprintf(stderr, "Busy server Detected. Try again later. Exiting.\n"); fprintf(stderr, "Busy server Detected. Try again later. Exiting.\n");
exit(-1); exit(-1);
} }
@ -144,24 +149,25 @@ exchange_parameters(struct iperf_test *test)
*/ */
void void
add_interval_list(struct iperf_stream_result *rp, struct iperf_interval_results temp) add_interval_list(struct iperf_stream_result * rp, struct iperf_interval_results temp)
{ {
struct iperf_interval_results *n; struct iperf_interval_results *n;
struct iperf_interval_results *ip = (struct iperf_interval_results *)malloc(sizeof(struct iperf_interval_results)); struct iperf_interval_results *ip = (struct iperf_interval_results *) malloc(sizeof(struct iperf_interval_results));
ip->bytes_transferred = temp.bytes_transferred; ip->bytes_transferred = temp.bytes_transferred;
ip->interval_duration = temp.interval_duration; ip->interval_duration = temp.interval_duration;
ip->tcpInfo = temp.tcpInfo; ip->tcpInfo = temp.tcpInfo;
//printf("add_interval_list: Mbytes = %d, duration = %f \n", (int)(ip->bytes_transferred / 1000000), ip->interval_duration); //printf("add_interval_list: Mbytes = %d, duration = %f \n", (int) (ip->bytes_transferred / 1000000), ip->interval_duration);
if (!rp->interval_results) { if (!rp->interval_results)
{
rp->interval_results = ip; rp->interval_results = ip;
} } else
else { {
n = rp->interval_results; n = rp->interval_results;
while (n->next) /* find the end of the list */ while (n->next) /* find the end of the list */
n = n->next; n = n->next;
n->next = ip; n->next = ip;
@ -173,13 +179,14 @@ add_interval_list(struct iperf_stream_result *rp, struct iperf_interval_results
/* for debugging only */ /* for debugging only */
void void
display_interval_list(struct iperf_stream_result *rp, int tflag) display_interval_list(struct iperf_stream_result * rp, int tflag)
{ {
struct iperf_interval_results *n; struct iperf_interval_results *n;
n = rp->interval_results; n = rp->interval_results;
while (n) { while (n)
{
printf("Interval = %f\tBytes transferred = %llu\n", n->interval_duration, n->bytes_transferred); printf("Interval = %f\tBytes transferred = %llu\n", n->interval_duration, n->bytes_transferred);
if (tflag) if (tflag)
print_tcpinfo(n); print_tcpinfo(n);
@ -194,18 +201,18 @@ display_interval_list(struct iperf_stream_result *rp, int tflag)
*/ */
void void
receive_result_from_server(struct iperf_test *test) receive_result_from_server(struct iperf_test * test)
{ {
int result; int result;
struct iperf_stream *sp; struct iperf_stream *sp;
int size = 0; int size = 0;
char *buf = NULL; char *buf = NULL;
printf("in receive_result_from_server \n"); printf("in receive_result_from_server \n");
sp = test->streams; sp = test->streams;
size = MAX_RESULT_STRING; size = MAX_RESULT_STRING;
buf = (char *)malloc(size); buf = (char *) malloc(size);
printf("receive_result_from_server: send ALL_STREAMS_END to server \n"); printf("receive_result_from_server: send ALL_STREAMS_END to server \n");
sp->settings->state = ALL_STREAMS_END; sp->settings->state = ALL_STREAMS_END;
@ -218,7 +225,8 @@ receive_result_from_server(struct iperf_test *test)
/* receive from server */ /* receive from server */
printf("reading results (size=%d) back from server \n", size); printf("reading results (size=%d) back from server \n", size);
do { do
{
result = recv(sp->socket, buf, size, 0); result = recv(sp->socket, buf, size, 0);
} while (result == -1 && errno == EINTR); } while (result == -1 && errno == EINTR);
printf("Got size of results from server: %d \n", result); printf("Got size of results from server: %d \n", result);
@ -237,17 +245,17 @@ receive_result_from_server(struct iperf_test *test)
*/ */
void void
connect_msg(struct iperf_stream *sp) connect_msg(struct iperf_stream * sp)
{ {
char ipl [512], ipr[512]; char ipl[512], ipr[512];
inet_ntop(AF_INET, (void *)(&((struct sockaddr_in *)&sp->local_addr)->sin_addr), (void *)ipl, sizeof(ipl)); inet_ntop(AF_INET, (void *) (&((struct sockaddr_in *) & sp->local_addr)->sin_addr), (void *) ipl, sizeof(ipl));
inet_ntop(AF_INET, (void *)(&((struct sockaddr_in *)&sp->remote_addr)->sin_addr), (void *)ipr, sizeof(ipr)); inet_ntop(AF_INET, (void *) (&((struct sockaddr_in *) & sp->remote_addr)->sin_addr), (void *) ipr, sizeof(ipr));
printf("[%3d] local %s port %d connected to %s port %d\n", printf("[%3d] local %s port %d connected to %s port %d\n",
sp->socket, sp->socket,
ipl, ntohs(((struct sockaddr_in *)&sp->local_addr)->sin_port), ipl, ntohs(((struct sockaddr_in *) & sp->local_addr)->sin_port),
ipr, ntohs(((struct sockaddr_in *)&sp->remote_addr)->sin_port)); ipr, ntohs(((struct sockaddr_in *) & sp->remote_addr)->sin_port));
} }
/*************************************************************/ /*************************************************************/
@ -258,23 +266,26 @@ connect_msg(struct iperf_stream *sp)
*/ */
void void
Display(struct iperf_test *test) Display(struct iperf_test * test)
{ {
struct iperf_stream *n; struct iperf_stream *n;
n = test->streams; n = test->streams;
int count = 1; int count = 1;
printf("===============DISPLAY==================\n"); printf("===============DISPLAY==================\n");
while (1) { while (1)
if (n) { {
if (n)
{
if (test->role == 'c') if (test->role == 'c')
printf("position-%d\tsp=%d\tsocket=%d\tbytes sent=%llu\n", count++, (int)n, n->socket, n->result->bytes_sent); printf("position-%d\tsp=%d\tsocket=%d\tbytes sent=%llu\n", count++, (int) n, n->socket, n->result->bytes_sent);
else else
printf("position-%d\tsp=%d\tsocket=%d\tbytes received=%llu\n", count++, (int)n, n->socket, n->result->bytes_received); printf("position-%d\tsp=%d\tsocket=%d\tbytes received=%llu\n", count++, (int) n, n->socket, n->result->bytes_received);
if (n->next == NULL) { if (n->next == NULL)
{
printf("=================END====================\n"); printf("=================END====================\n");
fflush(stdout); fflush(stdout);
break; break;
@ -292,15 +303,16 @@ iperf_new_test()
struct iperf_test *testp; struct iperf_test *testp;
printf("in iperf_new_test: reinit default settings \n"); printf("in iperf_new_test: reinit default settings \n");
testp = (struct iperf_test *)malloc(sizeof(struct iperf_test)); testp = (struct iperf_test *) malloc(sizeof(struct iperf_test));
if (!testp) { if (!testp)
{
perror("malloc"); perror("malloc");
return (NULL); return (NULL);
} }
/* initialise everything to zero */ /* initialise everything to zero */
memset(testp, 0, sizeof(struct iperf_test)); memset(testp, 0, sizeof(struct iperf_test));
testp->default_settings = (struct iperf_settings *)malloc(sizeof(struct iperf_settings)); testp->default_settings = (struct iperf_settings *) malloc(sizeof(struct iperf_settings));
memset(testp->default_settings, 0, sizeof(struct iperf_settings)); memset(testp->default_settings, 0, sizeof(struct iperf_settings));
/* return an empty iperf_test* with memory alloted. */ /* return an empty iperf_test* with memory alloted. */
@ -309,7 +321,7 @@ iperf_new_test()
/**************************************************************************/ /**************************************************************************/
void void
iperf_defaults(struct iperf_test *testp) iperf_defaults(struct iperf_test * testp)
{ {
testp->protocol = Ptcp; testp->protocol = Ptcp;
testp->role = 's'; testp->role = 's';
@ -337,15 +349,17 @@ iperf_defaults(struct iperf_test *testp)
/**************************************************************************/ /**************************************************************************/
void void
iperf_init_test(struct iperf_test *test) iperf_init_test(struct iperf_test * test)
{ {
char ubuf [UNIT_LEN]; char ubuf[UNIT_LEN];
struct iperf_stream *sp; struct iperf_stream *sp;
int i , s = 0; int i, s = 0;
printf("in iperf_init_test \n"); printf("in iperf_init_test \n");
if (test->role == 's') { /* server */ if (test->role == 's')
if (test->protocol == Pudp) { { /* server */
if (test->protocol == Pudp)
{
test->listener_sock_udp = netannounce(Pudp, NULL, test->server_port); test->listener_sock_udp = netannounce(Pudp, NULL, test->server_port);
if (test->listener_sock_udp < 0) if (test->listener_sock_udp < 0)
exit(0); exit(0);
@ -355,7 +369,8 @@ iperf_init_test(struct iperf_test *test)
if (test->listener_sock_tcp < 0) if (test->listener_sock_tcp < 0)
exit(0); exit(0);
if (test->protocol == Ptcp) { if (test->protocol == Ptcp)
{
if (set_tcp_windowsize(test->listener_sock_tcp, test->default_settings->socket_bufsize, SO_RCVBUF) < 0) if (set_tcp_windowsize(test->listener_sock_tcp, test->default_settings->socket_bufsize, SO_RCVBUF) < 0)
perror("unable to set TCP window"); perror("unable to set TCP window");
} }
@ -365,27 +380,29 @@ iperf_init_test(struct iperf_test *test)
printf("-----------------------------------------------------------\n"); printf("-----------------------------------------------------------\n");
printf("Server listening on %d\n", test->server_port); printf("Server listening on %d\n", test->server_port);
int x; int x;
/* make sure we got what we asked for */ /* make sure we got what we asked for */
if ((x = get_tcp_windowsize(test->listener_sock_tcp, SO_RCVBUF)) < 0) if ((x = get_tcp_windowsize(test->listener_sock_tcp, SO_RCVBUF)) < 0)
perror("SO_RCVBUF"); perror("SO_RCVBUF");
if (test->protocol == Ptcp) { if (test->protocol == Ptcp)
{
{ {
if (test->default_settings->socket_bufsize > 0) { if (test->default_settings->socket_bufsize > 0)
unit_snprintf(ubuf, UNIT_LEN, (double)x, 'A'); {
unit_snprintf(ubuf, UNIT_LEN, (double) x, 'A');
printf("TCP window size: %s\n", ubuf); printf("TCP window size: %s\n", ubuf);
} } else
else { {
printf("Using TCP Autotuning \n"); printf("Using TCP Autotuning \n");
} }
} }
} }
printf("-----------------------------------------------------------\n"); printf("-----------------------------------------------------------\n");
} } else if (test->role == 'c')
else if (test->role == 'c') { /* Client */ { /* Client */
FD_ZERO(&test->write_set); FD_ZERO(&test->write_set);
FD_SET(s, &test->write_set); FD_SET(s, &test->write_set);
@ -393,9 +410,11 @@ iperf_init_test(struct iperf_test *test)
* XXX: I think we need to create a TCP control socket here too for * XXX: I think we need to create a TCP control socket here too for
* UDP mode -blt * UDP mode -blt
*/ */
for (i = 0; i < test->num_streams; i++) { for (i = 0; i < test->num_streams; i++)
{
s = netdial(test->protocol, test->server_hostname, test->server_port); s = netdial(test->protocol, test->server_hostname, test->server_port);
if (s < 0) { if (s < 0)
{
fprintf(stderr, "netdial failed\n"); fprintf(stderr, "netdial failed\n");
exit(0); exit(0);
} }
@ -414,7 +433,7 @@ iperf_init_test(struct iperf_test *test)
/**************************************************************************/ /**************************************************************************/
void void
iperf_free_test(struct iperf_test *test) iperf_free_test(struct iperf_test * test)
{ {
free(test->default_settings); free(test->default_settings);
@ -439,21 +458,23 @@ iperf_free_test(struct iperf_test *test)
*/ */
void * void *
iperf_stats_callback(struct iperf_test *test) iperf_stats_callback(struct iperf_test * test)
{ {
iperf_size_t cumulative_bytes = 0; iperf_size_t cumulative_bytes = 0;
int i; int i;
struct iperf_stream *sp = test->streams; struct iperf_stream *sp = test->streams;
struct iperf_stream_result *rp = test->streams->result; struct iperf_stream_result *rp = test->streams->result;
struct iperf_interval_results *ip, temp; struct iperf_interval_results *ip, temp;
//printf("in stats_callback: num_streams = %d \n", test->num_streams); //printf("in stats_callback: num_streams = %d \n", test->num_streams);
for (i = 0; i < test->num_streams; i++) { for (i = 0; i < test->num_streams; i++)
{
rp = sp->result; rp = sp->result;
if (!rp->interval_results) { if (!rp->interval_results)
{
if (test->role == 'c') if (test->role == 'c')
temp.bytes_transferred = rp->bytes_sent; temp.bytes_transferred = rp->bytes_sent;
else else
@ -465,10 +486,11 @@ iperf_stats_callback(struct iperf_test *test)
gettimeofday(&sp->result->end_time, NULL); gettimeofday(&sp->result->end_time, NULL);
add_interval_list(rp, temp); add_interval_list(rp, temp);
} } else
else { {
ip = sp->result->interval_results; ip = sp->result->interval_results;
while (1) { while (1)
{
cumulative_bytes += ip->bytes_transferred; cumulative_bytes += ip->bytes_transferred;
if (ip->next != NULL) if (ip->next != NULL)
ip = ip->next; ip = ip->next;
@ -508,17 +530,18 @@ iperf_stats_callback(struct iperf_test *test)
* *
*/ */
char * char *
iperf_reporter_callback(struct iperf_test *test) iperf_reporter_callback(struct iperf_test * test)
{ {
int total_packets = 0, lost_packets = 0, curr_state = 0; int total_packets = 0, lost_packets = 0, curr_state = 0;
char ubuf [UNIT_LEN]; int first_stream = 1;
char nbuf [UNIT_LEN]; char ubuf[UNIT_LEN];
char nbuf[UNIT_LEN];
struct iperf_stream *sp = NULL; struct iperf_stream *sp = NULL;
iperf_size_t bytes = 0; iperf_size_t bytes = 0;
double start_time, end_time; double start_time, end_time;
char *message = (char *)malloc(MAX_RESULT_STRING); char *message = (char *) malloc(MAX_RESULT_STRING);
char *message_final = (char *)malloc(MAX_RESULT_STRING); char *message_final = (char *) malloc(MAX_RESULT_STRING);
memset(message_final, 0, strlen(message_final)); memset(message_final, 0, strlen(message_final));
@ -529,136 +552,160 @@ iperf_reporter_callback(struct iperf_test *test)
curr_state = sp->settings->state; curr_state = sp->settings->state;
//printf("in iperf_reporter_callback: state = %d \n", curr_state); //printf("in iperf_reporter_callback: state = %d \n", curr_state);
if (curr_state == TEST_RUNNING) { if (curr_state == TEST_RUNNING || curr_state == STREAM_RUNNING)
{
/* print interval results */ /* print interval results */
while (sp) { /* for each stream */ while (sp)
{ /* for each stream */
ip = sp->result->interval_results; ip = sp->result->interval_results;
while (ip->next != NULL) { while (ip->next != NULL) /* find end of list. XXX: why not just keep track of this pointer?? */
{
ip_prev = ip; ip_prev = ip;
ip = ip->next; ip = ip->next;
} }
bytes += ip->bytes_transferred; bytes += ip->bytes_transferred;
unit_snprintf(ubuf, UNIT_LEN, (double)(ip->bytes_transferred), 'A'); unit_snprintf(ubuf, UNIT_LEN, (double) (ip->bytes_transferred), 'A');
if (test->streams->result->interval_results->next != NULL) { if (test->streams->result->interval_results->next != NULL)
{
unit_snprintf(nbuf, UNIT_LEN, unit_snprintf(nbuf, UNIT_LEN,
(double)(ip->bytes_transferred / (ip->interval_duration - ip_prev->interval_duration)), (double) (ip->bytes_transferred / (ip->interval_duration - ip_prev->interval_duration)),
test->default_settings->unit_format); test->default_settings->unit_format);
sprintf(message, report_bw_format, sp->socket, ip_prev->interval_duration, ip->interval_duration, ubuf, nbuf); sprintf(message, report_bw_format, sp->socket, ip_prev->interval_duration, ip->interval_duration, ubuf, nbuf);
} } else
else { {
sprintf(message, report_bw_header); if (first_stream) /* only print header for 1st stream */
safe_strcat(message_final, message); {
sprintf(message, report_bw_header);
safe_strcat(message_final, message);
first_stream = 0;
}
unit_snprintf(nbuf, UNIT_LEN, (double)(ip->bytes_transferred / ip->interval_duration), test->default_settings->unit_format); unit_snprintf(nbuf, UNIT_LEN, (double) (ip->bytes_transferred / ip->interval_duration), test->default_settings->unit_format);
sprintf(message, report_bw_format, sp->socket, 0.0, ip->interval_duration, ubuf, nbuf); sprintf(message, report_bw_format, sp->socket, 0.0, ip->interval_duration, ubuf, nbuf);
} }
if (strlen(message_final) + strlen(message) < MAX_RESULT_STRING) if (strlen(message_final) + strlen(message) < MAX_RESULT_STRING)
safe_strcat(message_final, message); safe_strcat(message_final, message);
else { else
{
printf("Error: results string too long \n"); printf("Error: results string too long \n");
return NULL; return NULL;
} }
if (test->tcp_info) { if (test->tcp_info)
{
build_tcpinfo_message(ip, message); build_tcpinfo_message(ip, message);
safe_strcat(message_final, message); safe_strcat(message_final, message);
} }
//printf("reporter_callback: built interval string: %s \n", message_final);
sp = sp->next; sp = sp->next;
} /* while (sp) */ } /* while (sp) */
if (test->num_streams > 1) { if (test->num_streams > 1) /* sum of all streams */
unit_snprintf(ubuf, UNIT_LEN, (double)(bytes), 'A'); {
unit_snprintf(ubuf, UNIT_LEN, (double) (bytes), 'A');
if (test->streams->result->interval_results->next != NULL) { if (test->streams->result->interval_results->next != NULL)
unit_snprintf(nbuf, UNIT_LEN, (double)(bytes / (ip->interval_duration - ip_prev->interval_duration)), {
unit_snprintf(nbuf, UNIT_LEN, (double) (bytes / (ip->interval_duration - ip_prev->interval_duration)),
test->default_settings->unit_format); test->default_settings->unit_format);
sprintf(message, report_sum_bw_format, ip_prev->interval_duration, ip->interval_duration, ubuf, nbuf); sprintf(message, report_sum_bw_format, ip_prev->interval_duration, ip->interval_duration, ubuf, nbuf);
} } else
else { {
unit_snprintf(nbuf, UNIT_LEN, (double)(bytes / ip->interval_duration), test->default_settings->unit_format); unit_snprintf(nbuf, UNIT_LEN, (double) (bytes / ip->interval_duration), test->default_settings->unit_format);
sprintf(message, report_sum_bw_format, 0.0, ip->interval_duration, ubuf, nbuf); sprintf(message, report_sum_bw_format, 0.0, ip->interval_duration, ubuf, nbuf);
} }
safe_strcat(message_final, message); safe_strcat(message_final, message);
if (test->tcp_info) { if (test->tcp_info)
{
build_tcpinfo_message(ip, message); build_tcpinfo_message(ip, message);
safe_strcat(message_final, message); safe_strcat(message_final, message);
} }
} }
} } else
else if (curr_state == ALL_STREAMS_END || curr_state == RESULT_REQUEST) { {
/* if TEST_RUNNING */ if (curr_state == ALL_STREAMS_END || curr_state == RESULT_REQUEST)
sp = test->streams; {
/* if TEST_RUNNING */
sp = test->streams;
while (sp) { while (sp)
if (test->role == 'c') {
bytes += sp->result->bytes_sent; if (test->role == 'c')
else bytes += sp->result->bytes_sent;
bytes += sp->result->bytes_received; else
bytes += sp->result->bytes_received;
if (test->protocol == Pudp) { if (test->protocol == Pudp)
total_packets += sp->packet_count; {
lost_packets += sp->cnt_error; total_packets += sp->packet_count;
} lost_packets += sp->cnt_error;
start_time = timeval_diff(&sp->result->start_time, &sp->result->start_time);
end_time = timeval_diff(&sp->result->start_time, &sp->result->end_time);
if (test->role == 'c') {
unit_snprintf(ubuf, UNIT_LEN, (double)(sp->result->bytes_sent), 'A');
unit_snprintf(nbuf, UNIT_LEN, (double)(sp->result->bytes_sent / end_time), test->default_settings->unit_format);
}
else {
unit_snprintf(ubuf, UNIT_LEN, (double)(sp->result->bytes_received), 'A');
unit_snprintf(nbuf, UNIT_LEN, (double)(sp->result->bytes_received / end_time), test->default_settings->unit_format);
}
if (test->protocol == Ptcp) {
sprintf(message, report_bw_format, sp->socket, start_time, end_time, ubuf, nbuf);
safe_strcat(message_final, message);
}
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);
if (test->role == 'c') {
sprintf(message, report_datagrams, sp->socket, sp->packet_count);
safe_strcat(message_final, message);
} }
if (sp->outoforder_packets > 0) start_time = timeval_diff(&sp->result->start_time, &sp->result->start_time);
printf(report_sum_outoforder, start_time, end_time, sp->cnt_error); end_time = timeval_diff(&sp->result->start_time, &sp->result->end_time);
}
/*
* XXX: we need to do something with any TCP_INFO results here
*/
sp = sp->next;
} /* while (sp) */
if (test->role == 'c')
{
unit_snprintf(ubuf, UNIT_LEN, (double) (sp->result->bytes_sent), 'A');
unit_snprintf(nbuf, UNIT_LEN, (double) (sp->result->bytes_sent / end_time), test->default_settings->unit_format);
} else
{
unit_snprintf(ubuf, UNIT_LEN, (double) (sp->result->bytes_received), 'A');
unit_snprintf(nbuf, UNIT_LEN, (double) (sp->result->bytes_received / end_time), test->default_settings->unit_format);
}
if (test->protocol == Ptcp)
{
sprintf(message, report_bw_format, sp->socket, start_time, end_time, ubuf, nbuf);
safe_strcat(message_final, message);
} 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);
if (test->role == 'c')
{
sprintf(message, report_datagrams, sp->socket, sp->packet_count);
safe_strcat(message_final, message);
}
if (sp->outoforder_packets > 0)
printf(report_sum_outoforder, start_time, end_time, sp->cnt_error);
}
/*
* XXX: we need to do something with any TCP_INFO results here
*/
sp = sp->next;
}
} /* while (sp) */
sp = test->streams; /* reset to first socket */ sp = test->streams; /* reset to first socket */
start_time = timeval_diff(&sp->result->start_time, &sp->result->start_time); start_time = timeval_diff(&sp->result->start_time, &sp->result->start_time);
end_time = timeval_diff(&sp->result->start_time, &sp->result->end_time); end_time = timeval_diff(&sp->result->start_time, &sp->result->end_time);
unit_snprintf(ubuf, UNIT_LEN, (double)bytes, 'A'); unit_snprintf(ubuf, UNIT_LEN, (double) bytes, 'A');
unit_snprintf(nbuf, UNIT_LEN, (double)bytes / end_time, test->default_settings->unit_format); unit_snprintf(nbuf, UNIT_LEN, (double) bytes / end_time, test->default_settings->unit_format);
if ((test->role == 'c' && test->num_streams > 1) || (test->role == 's')) { if ((test->role == 'c' && test->num_streams > 1) || (test->role == 's'))
if (test->protocol == Ptcp) { {
if (test->protocol == Ptcp)
{
sprintf(message, report_sum_bw_format, start_time, end_time, ubuf, nbuf); sprintf(message, report_sum_bw_format, start_time, end_time, ubuf, nbuf);
safe_strcat(message_final, message); safe_strcat(message_final, message);
} } else
else { {
sprintf(message, 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)); sprintf(message, 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); safe_strcat(message_final, message);
} }
if ((test->print_mss != 0) && (test->role == 'c')) { if ((test->print_mss != 0) && (test->role == 'c'))
{
sprintf(message, "\nThe TCP maximum segment size mss = %d \n", getsock_tcp_mss(sp->socket)); sprintf(message, "\nThe TCP maximum segment size mss = %d \n", getsock_tcp_mss(sp->socket));
safe_strcat(message_final, message); safe_strcat(message_final, message);
} }
@ -675,16 +722,17 @@ safe_strcat(char *s1, char *s2)
//printf(" adding string %s to end of string %s \n", s1, s1); //printf(" adding string %s to end of string %s \n", s1, s1);
if (strlen(s1) + strlen(s2) < MAX_RESULT_STRING) if (strlen(s1) + strlen(s2) < MAX_RESULT_STRING)
strcat(s1, s2); strcat(s1, s2);
else { else
{
printf("Error: results string too long \n"); printf("Error: results string too long \n");
exit(-1); /* XXX: should return an error instead! */ exit(-1); /* XXX: should return an error instead! */
//return -1; //return -1;
} }
} }
/**************************************************************************/ /**************************************************************************/
void void
iperf_free_stream(struct iperf_stream *sp) iperf_free_stream(struct iperf_stream * sp)
{ {
free(sp->buffer); free(sp->buffer);
free(sp->settings); free(sp->settings);
@ -695,25 +743,26 @@ iperf_free_stream(struct iperf_stream *sp)
/**************************************************************************/ /**************************************************************************/
struct iperf_stream * struct iperf_stream *
iperf_new_stream(struct iperf_test *testp) iperf_new_stream(struct iperf_test * testp)
{ {
int i = 0; int i = 0;
struct iperf_stream *sp; struct iperf_stream *sp;
//printf("in iperf_new_stream \n"); //printf("in iperf_new_stream \n");
sp = (struct iperf_stream *)malloc(sizeof(struct iperf_stream)); sp = (struct iperf_stream *) malloc(sizeof(struct iperf_stream));
if (!sp) { if (!sp)
{
perror("malloc"); perror("malloc");
return (NULL); return (NULL);
} }
memset(sp, 0, sizeof(struct iperf_stream)); memset(sp, 0, sizeof(struct iperf_stream));
printf("iperf_new_stream: Allocating new stream buffer: size = %d \n", testp->default_settings->blksize); printf("iperf_new_stream: Allocating new stream buffer: size = %d \n", testp->default_settings->blksize);
sp->buffer = (char *)malloc(testp->default_settings->blksize); sp->buffer = (char *) malloc(testp->default_settings->blksize);
sp->settings = (struct iperf_settings *)malloc(sizeof(struct iperf_settings)); sp->settings = (struct iperf_settings *) malloc(sizeof(struct iperf_settings));
/* make a per stream copy of default_settings in each stream structure */ /* make a per stream copy of default_settings in each stream structure */
memcpy(sp->settings, testp->default_settings, sizeof(struct iperf_settings)); memcpy(sp->settings, testp->default_settings, sizeof(struct iperf_settings));
sp->result = (struct iperf_stream_result *)malloc(sizeof(struct iperf_stream_result)); sp->result = (struct iperf_stream_result *) malloc(sizeof(struct iperf_stream_result));
/* fill in buffer with random stuff */ /* fill in buffer with random stuff */
/* XXX: probably better to use something truely random here */ /* XXX: probably better to use something truely random here */
@ -723,7 +772,7 @@ iperf_new_stream(struct iperf_test *testp)
sp->socket = -1; sp->socket = -1;
sp->packet_count = 0; sp->packet_count = 0;
sp->stream_id = (int)sp; sp->stream_id = (int) sp;
sp->jitter = 0.0; sp->jitter = 0.0;
sp->prev_transit = 0.0; sp->prev_transit = 0.0;
sp->outoforder_packets = 0; sp->outoforder_packets = 0;
@ -743,20 +792,23 @@ iperf_new_stream(struct iperf_test *testp)
/**************************************************************************/ /**************************************************************************/
void void
iperf_init_stream(struct iperf_stream *sp, struct iperf_test *testp) iperf_init_stream(struct iperf_stream * sp, struct iperf_test * testp)
{ {
socklen_t len; socklen_t len;
len = sizeof(struct sockaddr_in); len = sizeof(struct sockaddr_in);
if (getsockname(sp->socket, (struct sockaddr *)&sp->local_addr, &len) < 0) { if (getsockname(sp->socket, (struct sockaddr *) & sp->local_addr, &len) < 0)
{
perror("getsockname"); perror("getsockname");
} }
if (getpeername(sp->socket, (struct sockaddr *)&sp->remote_addr, &len) < 0) { if (getpeername(sp->socket, (struct sockaddr *) & sp->remote_addr, &len) < 0)
{
perror("getpeername"); perror("getpeername");
} }
//printf("in init_stream: calling set_tcp_windowsize: %d \n", testp->default_settings->socket_bufsize); //printf("in init_stream: calling set_tcp_windowsize: %d \n", testp->default_settings->socket_bufsize);
if (testp->protocol == Ptcp) { if (testp->protocol == Ptcp)
{
if (set_tcp_windowsize(sp->socket, testp->default_settings->socket_bufsize, if (set_tcp_windowsize(sp->socket, testp->default_settings->socket_bufsize,
testp->role == 's' ? SO_RCVBUF : SO_SNDBUF) < 0) testp->role == 's' ? SO_RCVBUF : SO_SNDBUF) < 0)
fprintf(stderr, "unable to set window size\n"); fprintf(stderr, "unable to set window size\n");
@ -768,15 +820,16 @@ iperf_init_stream(struct iperf_stream *sp, struct iperf_test *testp)
/**************************************************************************/ /**************************************************************************/
int int
iperf_add_stream(struct iperf_test *test, struct iperf_stream *sp) iperf_add_stream(struct iperf_test * test, struct iperf_stream * sp)
{ {
struct iperf_stream *n; struct iperf_stream *n;
if (!test->streams) { if (!test->streams)
{
test->streams = sp; test->streams = sp;
return 1; return 1;
} } else
else { {
n = test->streams; n = test->streams;
while (n->next) while (n->next)
n = n->next; n = n->next;
@ -797,13 +850,14 @@ iperf_add_stream(struct iperf_test *test, struct iperf_stream *sp)
*/ */
struct iperf_stream * struct iperf_stream *
find_stream_by_socket(struct iperf_test *test, int sock) find_stream_by_socket(struct iperf_test * test, int sock)
{ {
struct iperf_stream *n; struct iperf_stream *n;
n = test->streams; n = test->streams;
while (1) { while (1)
{
if (n->socket == sock) if (n->socket == sock)
break; break;
@ -826,19 +880,19 @@ catcher(int sig)
/**************************************************************************/ /**************************************************************************/
void void
iperf_run_client(struct iperf_test *test) iperf_run_client(struct iperf_test * test)
{ {
int i , result = 0; int i, result = 0;
struct iperf_stream *sp, *np; struct iperf_stream *sp, *np;
struct timer *timer, *stats_interval, *reporter_interval; struct timer *timer, *stats_interval, *reporter_interval;
char *result_string = NULL; char *result_string = NULL;
char *prot = NULL; char *prot = NULL;
int64_t delayus, adjustus, dtargus; int64_t delayus, adjustus, dtargus;
struct timeval tv; struct timeval tv;
int ret = 0; int ret = 0;
struct sigaction sact; struct sigaction sact;
//printf("in iperf_run_client \n"); printf("in iperf_run_client \n");
tv.tv_sec = 15; /* timeout interval in seconds */ tv.tv_sec = 15; /* timeout interval in seconds */
tv.tv_usec = 0; tv.tv_usec = 0;
@ -847,7 +901,8 @@ iperf_run_client(struct iperf_test *test)
sact.sa_handler = catcher; sact.sa_handler = catcher;
sigaction(SIGINT, &sact, NULL); sigaction(SIGINT, &sact, NULL);
if (test->protocol == Pudp) { if (test->protocol == Pudp)
{
dtargus = (int64_t) (test->default_settings->blksize) * SEC_TO_US * 8; dtargus = (int64_t) (test->default_settings->blksize) * SEC_TO_US * 8;
dtargus /= test->default_settings->rate; dtargus /= test->default_settings->rate;
@ -858,7 +913,8 @@ iperf_run_client(struct iperf_test *test)
printf("iperf_run_client: adjustus: %lld, delayus: %lld \n", adjustus, delayus); printf("iperf_run_client: adjustus: %lld, delayus: %lld \n", adjustus, delayus);
sp = test->streams; sp = test->streams;
for (i = 0; i < test->num_streams; i++) { for (i = 0; i < test->num_streams; i++)
{
sp->send_timer = new_timer(0, dtargus); sp->send_timer = new_timer(0, dtargus);
sp = sp->next; sp = sp->next;
} }
@ -884,10 +940,11 @@ iperf_run_client(struct iperf_test *test)
prot, test->num_streams, test->default_settings->blksize, test->duration); prot, test->num_streams, test->default_settings->blksize, test->duration);
else else
printf("Starting Test: protocol: %s, %d streams, %d byte blocks, %d bytes to send\n", printf("Starting Test: protocol: %s, %d streams, %d byte blocks, %d bytes to send\n",
prot, test->num_streams, test->default_settings->blksize, (int)test->default_settings->bytes); prot, test->num_streams, test->default_settings->blksize, (int) test->default_settings->bytes);
/* send data till the timer expires or bytes sent */ /* send data till the timer expires or bytes sent */
while (!all_data_sent(test) && !timer->expired(timer)) { while (!all_data_sent(test) && !timer->expired(timer))
{
#ifdef NEED_THIS /* not sure what this was for, so removed #ifdef NEED_THIS /* not sure what this was for, so removed
* -blt */ * -blt */
@ -899,7 +956,8 @@ iperf_run_client(struct iperf_test *test)
#endif #endif
sp = test->streams; sp = test->streams;
for (i = 0; i < test->num_streams; i++) { for (i = 0; i < test->num_streams; i++)
{
//printf("sending data to stream %d \n", i); //printf("sending data to stream %d \n", i);
result += sp->snd(sp); result += sp->snd(sp);
@ -909,12 +967,15 @@ iperf_run_client(struct iperf_test *test)
} }
if ((test->stats_interval != 0) && stats_interval->expired(stats_interval)) { if ((test->stats_interval != 0) && stats_interval->expired(stats_interval))
{
test->stats_callback(test); test->stats_callback(test);
update_timer(stats_interval, test->stats_interval, 0); update_timer(stats_interval, test->stats_interval, 0);
} }
if ((test->reporter_interval != 0) && reporter_interval->expired(reporter_interval)) { if ((test->reporter_interval != 0) && reporter_interval->expired(reporter_interval))
{
result_string = test->reporter_callback(test); result_string = test->reporter_callback(test);
//printf("interval expired: printing results: \n");
puts(result_string); puts(result_string);
update_timer(reporter_interval, test->reporter_interval, 0); update_timer(reporter_interval, test->reporter_interval, 0);
} }
@ -932,10 +993,11 @@ iperf_run_client(struct iperf_test *test)
printf("Test Complete. \n"); printf("Test Complete. \n");
/* send STREAM_END packets */ /* send STREAM_END packets */
np = test->streams; np = test->streams;
do { /* send STREAM_END to all sockets */ do
{ /* send STREAM_END to all sockets */
sp = np; sp = np;
sp->settings->state = STREAM_END; sp->settings->state = STREAM_END;
printf("sending state = STREAM_END to stream %d \n", sp->socket); printf("sending state = STREAM_END to stream %d \n", sp->socket);
sp->snd(sp); sp->snd(sp);
np = sp->next; np = sp->next;
} while (np); } while (np);
@ -968,7 +1030,8 @@ iperf_run_client(struct iperf_test *test)
/* Deleting all streams - CAN CHANGE FREE_STREAM FN */ /* Deleting all streams - CAN CHANGE FREE_STREAM FN */
sp = test->streams; sp = test->streams;
np = sp; np = sp;
do { do
{
sp = np; sp = np;
close(sp->socket); close(sp->socket);
np = sp->next; np = sp->next;

View File

@ -128,10 +128,18 @@ iperf_run_server(struct iperf_test * test)
printf("in iperf_run_server \n"); printf("in iperf_run_server \n");
FD_ZERO(&test->read_set); FD_ZERO(&test->read_set);
FD_SET(test->listener_sock_tcp, &test->read_set); FD_ZERO(&test->temp_set);
FD_SET(test->listener_sock_udp, &test->read_set); if (test->protocol == Ptcp)
{
/* add listener to the master set */
FD_SET(test->listener_sock_tcp, &test->read_set);
test->max_fd = test->listener_sock_tcp;
} else
{
FD_SET(test->listener_sock_udp, &test->read_set);
test->max_fd = test->listener_sock_udp;
}
test->max_fd = test->listener_sock_tcp > test->listener_sock_udp ? test->listener_sock_tcp : test->listener_sock_udp;
//printf("iperf_run_server: max_fd set to %d \n", test->max_fd); //printf("iperf_run_server: max_fd set to %d \n", test->max_fd);
test->num_streams = 0; test->num_streams = 0;
@ -158,37 +166,38 @@ iperf_run_server(struct iperf_test * test)
exit(0); exit(0);
} else if (result > 0) } else if (result > 0)
{ {
/* Accept a new TCP connection */ if (test->protocol == Ptcp)
if (FD_ISSET(test->listener_sock_tcp, &test->temp_set))
{ {
test->protocol = Ptcp; /* Accept a new TCP connection */
test->accept = iperf_tcp_accept; if (FD_ISSET(test->listener_sock_tcp, &test->temp_set))
if (test->accept < 0) {
return; test->protocol = Ptcp;
test->new_stream = iperf_new_tcp_stream; test->accept = iperf_tcp_accept;
test->accept(test); if (test->accept < 0)
test->default_settings->state = TEST_RUNNING; return;
FD_CLR(test->listener_sock_tcp, &test->temp_set); test->new_stream = iperf_new_tcp_stream;
printf("iperf_run_server: accepted TCP connection \n"); test->accept(test);
} test->default_settings->state = TEST_RUNNING;
/* Accept a new UDP connection */ FD_CLR(test->listener_sock_tcp, &test->temp_set);
else if (FD_ISSET(test->listener_sock_udp, &test->temp_set)) printf("iperf_run_server: accepted TCP connection \n");
}
} else
{ {
test->protocol = Pudp; /* Accept a new UDP connection */
test->accept = iperf_udp_accept; if (FD_ISSET(test->listener_sock_udp, &test->temp_set))
if (test->accept < 0) {
return; test->protocol = Pudp;
test->new_stream = iperf_new_udp_stream; test->accept = iperf_udp_accept;
test->accept(test); if (test->accept < 0)
test->default_settings->state = TEST_RUNNING; return;
FD_CLR(test->listener_sock_udp, &test->temp_set); test->new_stream = iperf_new_udp_stream;
test->accept(test);
test->default_settings->state = TEST_RUNNING;
FD_CLR(test->listener_sock_udp, &test->temp_set);
printf("iperf_run_server: accepted UDP connection \n");
}
} }
/* Process the sockets for read operation */ /* Process the sockets for read operation */
/*
* XXX: Need to try to read equal amounts from each socket, so
* keep track of last socket read from, and always start with the
* next socket
*/
nfd = test->max_fd + 1; nfd = test->max_fd + 1;
for (j = 0; j <= test->max_fd; j++) for (j = 0; j <= test->max_fd; j++)
{ {
@ -196,7 +205,7 @@ iperf_run_server(struct iperf_test * test)
if (FD_ISSET(j, &test->temp_set)) if (FD_ISSET(j, &test->temp_set))
{ {
//printf("iperf_run_server: data ready on socket %d \n", j); //printf("iperf_run_server: data ready on socket %d \n", j);
/* find the correct stream - possibly time consuming */ /* find the correct stream - possibly time consuming? */
np = find_stream_by_socket(test, j); np = find_stream_by_socket(test, j);
message = np->rcv(np); /* get data from client using message = np->rcv(np); /* get data from client using
* receiver callback */ * receiver callback */
@ -205,6 +214,7 @@ iperf_run_server(struct iperf_test * test)
handle_message(test, message, np); handle_message(test, message, np);
if (message == TEST_END) if (message == TEST_END)
break; /* test done, so break out of loop */ break; /* test done, so break out of loop */
} /* end if (FD_ISSET(j, &temp_set)) */ } /* end if (FD_ISSET(j, &temp_set)) */
} /* end for (j=0;...) */ } /* end for (j=0;...) */
} /* end else (result>0) */ } /* end else (result>0) */

View File

@ -282,10 +282,9 @@ iperf_tcp_accept(struct iperf_test * test)
} else } else
{ {
sp = test->new_stream(test); sp = test->new_stream(test);
/* XXX: what is this for? */ setnonblocking(peersock);
//setnonblocking(peersock);
FD_SET(peersock, &test->read_set); FD_SET(peersock, &test->read_set); /* add new socket to master set */
test->max_fd = (test->max_fd < peersock) ? peersock : test->max_fd; test->max_fd = (test->max_fd < peersock) ? peersock : test->max_fd;
//printf("iperf_tcp_accept: max_fd now set to: %d \n", test->max_fd ); //printf("iperf_tcp_accept: max_fd now set to: %d \n", test->max_fd );

View File

@ -1,33 +1,10 @@
/* /*
* Copyright (c) 2004, The Regents of the University of California, through * Copyright (c) 2009, The Regents of the University of California, through
* Lawrence Berkeley National Laboratory (subject to receipt of any required * Lawrence Berkeley National Laboratory (subject to receipt of any required
* approvals from the U.S. Dept. of Energy). All rights reserved. * approvals from the U.S. Dept. of Energy). All rights reserved.
*/ */
/*
* TO DO list:
* finish/fix receive_result_from_server()
* - also: should this be called for TCP too, or only UDP (currently its both,
* but I think it should be UDP only, or maybe a command line option for TCP
* (and related to this, check, test, document 'state machine' aspect of this.
* eg: are TEST_START and TEST_END, and STREAM_END / ALL_STREAMS_END all required?
* is it an error to get these in a strange order? etc. )
* verify placment of all timing calls and total_bytes_sent computations
* break up into client/sever files and TCP/UDP files
* much better/standard error handling throughout
* better packaging/makefile, README, LICENCE, etc files
* cleanup/fix/test UDP mode
* IPV6
* add verbose and debug options
* add human readable vs machine readable output mode
* (my idea on this is that "human readable" = compatable with old iperf,
* and that "machine readable is all name=value pairs -blt )
* lots more testing
* look for 'XXX' in code and address
* see issue tracker for other wish list items
*/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>

View File

@ -13,6 +13,10 @@
#include "net.h" #include "net.h"
#include "timer.h" #include "timer.h"
/* netdial and netannouce code comes from libtask: http://swtch.com/libtask/
* Copyright: http://swtch.com/libtask/COPYRIGHT
*/
/* make connection to server */ /* make connection to server */
int int
netdial(int proto, char *client, int port) netdial(int proto, char *client, int port)