Added support for UDP mode (-b mode not yet supported). Added htonll/ntohll functions. Cleaned up code.
This commit is contained in:
parent
b0b16b86cc
commit
8556db5d08
@ -1,5 +1,5 @@
|
||||
CFLAGS=-g -Wall
|
||||
OBJS=main.o iperf_api.o iperf_server_api.o iperf_tcp.o iperf_udp.o timer.o net.o tcp_window_size.o units.o uuid.o tcp_info.o locale.o
|
||||
OBJS=main.o iperf_api.o iperf_server_api.o iperf_tcp.o iperf_udp.o timer.o net.o tcp_window_size.o units.o iperf_util.o tcp_info.o locale.o
|
||||
LDFLAGS=
|
||||
|
||||
UNAME=$(shell uname)
|
||||
|
16
src/iperf.h
16
src/iperf.h
@ -80,7 +80,6 @@ struct iperf_stream
|
||||
* stream can have a pointer to this
|
||||
*/
|
||||
int packet_count;
|
||||
uint64_t stream_id; /* stream identity for UDP mode */
|
||||
double jitter;
|
||||
double prev_transit;
|
||||
int outoforder_packets;
|
||||
@ -108,16 +107,9 @@ struct iperf_test
|
||||
int server_port;
|
||||
int duration; /* total duration of test (-t flag) */
|
||||
|
||||
/* The following two members should be replaced by a single TCP control socket */
|
||||
int listener_sock_tcp;
|
||||
int listener_sock_udp;
|
||||
|
||||
int ctrl_sck;
|
||||
// Server is the only one that needs these
|
||||
int listener_tcp;
|
||||
int listener_udp;
|
||||
int prot_listener;
|
||||
|
||||
|
||||
/* boolen variables for Options */
|
||||
int daemon; /* -D option */
|
||||
@ -166,14 +158,6 @@ struct iperf_test
|
||||
struct iperf_settings *default_settings;
|
||||
};
|
||||
|
||||
struct udp_datagram
|
||||
{
|
||||
int state;
|
||||
int stream_id;
|
||||
int packet_count;
|
||||
struct timeval sent_time;
|
||||
};
|
||||
|
||||
struct param_exchange
|
||||
{
|
||||
int state;
|
||||
|
@ -300,6 +300,7 @@ parse_parameters(struct iperf_test *test)
|
||||
break;
|
||||
case 'u':
|
||||
test->protocol = Pudp;
|
||||
test->new_stream = iperf_new_udp_stream;
|
||||
break;
|
||||
case 'P':
|
||||
test->num_streams = atoi(optarg);
|
||||
@ -343,9 +344,9 @@ iperf_exchange_parameters(struct iperf_test * test)
|
||||
printf(" cookie: %s\n", test->default_settings->cookie);
|
||||
|
||||
if (test->protocol == Pudp) {
|
||||
test->prot_listener = netannounce(test->protocol, NULL, test->server_port);
|
||||
FD_SET(test->prot_listener, &test->read_set);
|
||||
test->max_fd = (test->prot_listener > test->max_fd) ? test->prot_listener : test->max_fd;
|
||||
test->listener_udp = netannounce(test->protocol, NULL, test->server_port);
|
||||
FD_SET(test->listener_udp, &test->read_set);
|
||||
test->max_fd = (test->listener_udp > test->max_fd) ? test->listener_udp : test->max_fd;
|
||||
}
|
||||
|
||||
// Send the control message to create streams and start the test
|
||||
@ -652,7 +653,7 @@ int
|
||||
iperf_create_streams(struct iperf_test *test)
|
||||
{
|
||||
struct iperf_stream *sp;
|
||||
int i, s;
|
||||
int i, s, buf;
|
||||
|
||||
for (i = 0; i < test->num_streams; ++i) {
|
||||
s = netdial(test->protocol, test->server_hostname, test->server_port);
|
||||
@ -666,6 +667,15 @@ iperf_create_streams(struct iperf_test *test)
|
||||
perror("Nwrite COOKIE\n");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (write(s, &buf, sizeof(i)) < 0) {
|
||||
perror("write data");
|
||||
return -1;
|
||||
}
|
||||
if (read(s, &buf, sizeof(i)) < 0) {
|
||||
perror("read data");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
FD_SET(s, &test->read_set);
|
||||
@ -746,7 +756,7 @@ iperf_connect(struct iperf_test *test)
|
||||
get_uuid(test->default_settings->cookie);
|
||||
|
||||
/* Create and connect the control channel */
|
||||
test->ctrl_sck = netdial(test->protocol, test->server_hostname, test->server_port);
|
||||
test->ctrl_sck = netdial(Ptcp, test->server_hostname, test->server_port);
|
||||
if (test->ctrl_sck < 0) {
|
||||
return -1;
|
||||
}
|
||||
@ -841,7 +851,7 @@ iperf_reporter_callback(struct iperf_test * test)
|
||||
struct iperf_stream *sp = NULL;
|
||||
iperf_size_t bytes = 0, bytes_sent = 0, bytes_received = 0;
|
||||
iperf_size_t total_sent = 0, total_received = 0;
|
||||
double start_time, end_time;
|
||||
double start_time, end_time, avg_jitter;
|
||||
struct iperf_interval_results *ip = NULL;
|
||||
|
||||
switch (test->state) {
|
||||
@ -892,6 +902,7 @@ iperf_reporter_callback(struct iperf_test * test)
|
||||
if (test->protocol == Pudp) {
|
||||
total_packets += sp->packet_count;
|
||||
lost_packets += sp->cnt_error;
|
||||
avg_jitter += sp->jitter;
|
||||
}
|
||||
|
||||
if (bytes_sent > 0) {
|
||||
@ -939,10 +950,12 @@ iperf_reporter_callback(struct iperf_test * test)
|
||||
printf(" Total received\n");
|
||||
printf(report_sum_bw_format, start_time, end_time, ubuf, nbuf);
|
||||
} else {
|
||||
printf(report_sum_bw_jitter_loss_format, start_time, end_time, ubuf, nbuf, sp->jitter,
|
||||
avg_jitter /= test->num_streams;
|
||||
printf(report_sum_bw_jitter_loss_format, start_time, end_time, ubuf, nbuf, avg_jitter,
|
||||
lost_packets, total_packets, (double) (100.0 * lost_packets / total_packets));
|
||||
}
|
||||
|
||||
// XXX: Why is this here?
|
||||
if ((test->print_mss != 0) && (test->role == 'c')) {
|
||||
printf("The TCP maximum segment size mss = %d\n", getsock_tcp_mss(sp->socket));
|
||||
}
|
||||
@ -1020,6 +1033,19 @@ iperf_new_stream(struct iperf_test *testp)
|
||||
sp->buffer = (char *) malloc(testp->default_settings->blksize);
|
||||
sp->settings = (struct iperf_settings *) malloc(sizeof(struct iperf_settings));
|
||||
sp->result = (struct iperf_stream_result *) malloc(sizeof(struct iperf_stream_result));
|
||||
|
||||
if (!sp->buffer) {
|
||||
perror("Malloc sp->buffer");
|
||||
return NULL;
|
||||
}
|
||||
if (!sp->settings) {
|
||||
perror("Malloc sp->settings");
|
||||
return NULL;
|
||||
}
|
||||
if (!sp->result) {
|
||||
perror("Malloc sp->result");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Make a per stream copy of default_settings in each stream structure */
|
||||
// XXX: These settings need to be moved to the test struct
|
||||
@ -1032,9 +1058,6 @@ iperf_new_stream(struct iperf_test *testp)
|
||||
|
||||
sp->socket = -1;
|
||||
|
||||
// XXX: Not entirely sure what this does
|
||||
sp->stream_id = (uint64_t) sp;
|
||||
|
||||
// XXX: Some of this code is needed, even though everything is already zero.
|
||||
sp->packet_count = 0;
|
||||
sp->jitter = 0.0;
|
||||
@ -1154,7 +1177,7 @@ iperf_run_client(struct iperf_test * test)
|
||||
fprintf(stderr, "Exiting...\n");
|
||||
test->state = CLIENT_TERMINATE;
|
||||
if (Nwrite(test->ctrl_sck, &test->state, sizeof(char), Ptcp) < 0) {
|
||||
fprintf(stderr, "Unable to send CLIENT_TERMINATE message to serer\n");
|
||||
fprintf(stderr, "Unable to send CLIENT_TERMINATE message to server\n");
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ iperf_server_listen(struct iperf_test *test)
|
||||
// This needs to be changed to reflect if client has different window size
|
||||
// make sure we got what we asked for
|
||||
/* XXX: This needs to be moved to the stream listener
|
||||
if ((x = get_tcp_windowsize(test->listener_sock_tcp, SO_RCVBUF)) < 0) {
|
||||
if ((x = get_tcp_windowsize(test->listener_tcp, SO_RCVBUF)) < 0) {
|
||||
// Needs to set some sort of error number/message
|
||||
perror("SO_RCVBUF");
|
||||
return -1;
|
||||
@ -312,9 +312,9 @@ iperf_test_reset(struct iperf_test *test)
|
||||
test->server_hostname = NULL;
|
||||
|
||||
test->ctrl_sck = -1;
|
||||
test->prot_listener = 0;
|
||||
|
||||
test->bytes_sent = 0;
|
||||
test->new_stream = iperf_new_tcp_stream;
|
||||
|
||||
test->reverse = 0;
|
||||
test->no_delay = 0;
|
||||
@ -336,7 +336,6 @@ int
|
||||
iperf_run_server(struct iperf_test *test)
|
||||
{
|
||||
int result;
|
||||
int streams_accepted;
|
||||
fd_set temp_read_set, temp_write_set;
|
||||
struct timeval tv;
|
||||
|
||||
@ -401,7 +400,7 @@ iperf_run_server(struct iperf_test *test)
|
||||
}
|
||||
} else {
|
||||
if (FD_ISSET(test->listener_udp, &temp_read_set)) {
|
||||
if (iperf_accept_udp_stream(test) < 0) {
|
||||
if (iperf_udp_accept(test) < 0) {
|
||||
fprintf(stderr, "iperf_accept_udp_stream: an error occurred.\n");
|
||||
exit(1);
|
||||
}
|
||||
@ -409,6 +408,11 @@ iperf_run_server(struct iperf_test *test)
|
||||
}
|
||||
}
|
||||
if (test->streams_accepted == test->num_streams) {
|
||||
if (test->protocol == Pudp) {
|
||||
FD_CLR(test->listener_udp, &test->read_set);
|
||||
close(test->listener_udp);
|
||||
test->listener_udp = -1;
|
||||
}
|
||||
test->state = TEST_START;
|
||||
if (Nwrite(test->ctrl_sck, &test->state, sizeof(char), Ptcp) < 0) {
|
||||
perror("Nwrite TEST_START");
|
||||
|
@ -105,7 +105,7 @@ iperf_tcp_send(struct iperf_stream * sp)
|
||||
result = Nwrite(sp->socket, sp->buffer, size, Ptcp);
|
||||
#endif
|
||||
if (result < 0)
|
||||
perror("Write error");
|
||||
perror("Nwrite error");
|
||||
|
||||
sp->result->bytes_sent += result;
|
||||
sp->result->bytes_sent_this_interval += result;
|
||||
@ -152,7 +152,7 @@ iperf_tcp_accept(struct iperf_test * test)
|
||||
struct iperf_stream *sp;
|
||||
|
||||
len = sizeof(addr);
|
||||
peersock = accept(test->prot_listener, (struct sockaddr *) & addr, &len);
|
||||
peersock = accept(test->listener_tcp, (struct sockaddr *) & addr, &len);
|
||||
if (peersock < 0) {
|
||||
// XXX: Needs to implement better error handling
|
||||
printf("Error in accept(): %s\n", strerror(errno));
|
||||
|
303
src/iperf_udp.c
303
src/iperf_udp.c
@ -51,177 +51,138 @@
|
||||
*/
|
||||
|
||||
int
|
||||
iperf_udp_recv(struct iperf_stream * sp)
|
||||
iperf_udp_recv(struct iperf_stream *sp)
|
||||
{
|
||||
int result, message;
|
||||
int result;
|
||||
int size = sp->settings->blksize;
|
||||
int sec, usec, pcount;
|
||||
double transit = 0, d = 0;
|
||||
struct udp_datagram *udp = (struct udp_datagram *) sp->buffer;
|
||||
struct timeval arrival_time;
|
||||
struct timeval sent_time, arrival_time;
|
||||
|
||||
printf("in iperf_udp_recv: reading %d bytes \n", size);
|
||||
if (!sp->buffer)
|
||||
{
|
||||
fprintf(stderr, "receive buffer not allocated \n");
|
||||
exit(0);
|
||||
// XXX: Is this necessary? We've already checked the buffer to see if it's allocated.
|
||||
if (!sp->buffer) {
|
||||
fprintf(stderr, "receive buffer not allocated \n");
|
||||
exit(0);
|
||||
}
|
||||
#ifdef USE_SEND
|
||||
do
|
||||
{
|
||||
result = recv(sp->socket, sp->buffer, size, 0);
|
||||
|
||||
do {
|
||||
result = recv(sp->socket, sp->buffer, size, 0);
|
||||
} while (result == -1 && errno == EINTR);
|
||||
#else
|
||||
result = Nread(sp->socket, sp->buffer, size, Pudp);
|
||||
#endif
|
||||
|
||||
/* interprete the type of message in packet */
|
||||
if (result > 0)
|
||||
{
|
||||
message = udp->state;
|
||||
if (result < 0) {
|
||||
perror("Nread udp result");
|
||||
return (-1);
|
||||
}
|
||||
if (message != 7)
|
||||
{
|
||||
//printf("result = %d state = %d, %d = error\n", result, sp->buffer[0], errno);
|
||||
sp->result->bytes_received += result;
|
||||
sp->result->bytes_received_this_interval += result;
|
||||
|
||||
memcpy(&sec, sp->buffer, sizeof(sec));
|
||||
memcpy(&usec, sp->buffer+4, sizeof(usec));
|
||||
memcpy(&pcount, sp->buffer+8, sizeof(pcount));
|
||||
sec = ntohl(sec);
|
||||
usec = ntohl(usec);
|
||||
pcount = ntohl(pcount);
|
||||
sent_time.tv_sec = sec;
|
||||
sent_time.tv_usec = usec;
|
||||
|
||||
/* Out of order packets */
|
||||
if (pcount >= sp->packet_count + 1) {
|
||||
if (pcount > sp->packet_count + 1) {
|
||||
sp->cnt_error += (pcount - 1) - sp->packet_count;
|
||||
}
|
||||
sp->packet_count = pcount;
|
||||
} else {
|
||||
sp->outoforder_packets++;
|
||||
printf("OUT OF ORDER - incoming packet = %d and received packet = %d AND SP = %d\n", pcount, sp->packet_count, sp->socket);
|
||||
}
|
||||
if (message == STREAM_RUNNING && (sp->stream_id == udp->stream_id))
|
||||
{
|
||||
sp->result->bytes_received += result;
|
||||
if (udp->packet_count == sp->packet_count + 1)
|
||||
sp->packet_count++;
|
||||
|
||||
/* jitter measurement */
|
||||
if (gettimeofday(&arrival_time, NULL) < 0)
|
||||
{
|
||||
perror("gettimeofday");
|
||||
}
|
||||
transit = timeval_diff(&udp->sent_time, &arrival_time);
|
||||
d = transit - sp->prev_transit;
|
||||
if (d < 0)
|
||||
d = -d;
|
||||
sp->prev_transit = transit;
|
||||
sp->jitter += (d - sp->jitter) / 16.0;
|
||||
|
||||
|
||||
/* OUT OF ORDER PACKETS */
|
||||
if (udp->packet_count != sp->packet_count)
|
||||
{
|
||||
if (udp->packet_count < sp->packet_count + 1)
|
||||
{
|
||||
sp->outoforder_packets++;
|
||||
printf("OUT OF ORDER - incoming packet = %d and received packet = %d AND SP = %d\n", udp->packet_count, sp->packet_count, sp->socket);
|
||||
} else
|
||||
sp->cnt_error += udp->packet_count - sp->packet_count;
|
||||
}
|
||||
/* store the latest packet id */
|
||||
if (udp->packet_count > sp->packet_count)
|
||||
sp->packet_count = udp->packet_count;
|
||||
|
||||
//printf("incoming packet = %d and received packet = %d AND SP = %d\n", udp->packet_count, sp->packet_count, sp->socket);
|
||||
|
||||
/* jitter measurement */
|
||||
if (gettimeofday(&arrival_time, NULL) < 0) {
|
||||
perror("gettimeofday");
|
||||
}
|
||||
return message;
|
||||
transit = timeval_diff(&sent_time, &arrival_time);
|
||||
d = transit - sp->prev_transit;
|
||||
if (d < 0)
|
||||
d = -d;
|
||||
sp->prev_transit = transit;
|
||||
// XXX: This is NOT the way to calculate jitter
|
||||
// J = |(R1 - S1) - (R0 - S0)| [/ number of packets, for average]
|
||||
sp->jitter += (d - sp->jitter) / 16.0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
int
|
||||
iperf_udp_send(struct iperf_stream * sp)
|
||||
iperf_udp_send(struct iperf_stream *sp)
|
||||
{
|
||||
int result = 0;
|
||||
struct timeval before, after;
|
||||
ssize_t result = 0;
|
||||
int64_t dtargus;
|
||||
int64_t adjustus = 0;
|
||||
uint64_t sec, usec, pcount;
|
||||
int size = sp->settings->blksize;
|
||||
struct timeval before, after;
|
||||
|
||||
//printf("in iperf_udp_send \n");
|
||||
/*
|
||||
* the || part ensures that last packet is sent to server - the
|
||||
* STREAM_END MESSAGE
|
||||
*/
|
||||
if (sp->send_timer->expired(sp->send_timer) || sp->settings->state == STREAM_END)
|
||||
{
|
||||
int size = sp->settings->blksize;
|
||||
// if (sp->send_timer->expired(sp->send_timer) || sp->settings->state == STREAM_END) {
|
||||
|
||||
/* this is for udp packet/jitter/lost packet measurements */
|
||||
struct udp_datagram *udp = (struct udp_datagram *) sp->buffer;
|
||||
struct param_exchange *param = NULL;
|
||||
/*
|
||||
dtargus = (int64_t) (sp->settings->blksize) * SEC_TO_US * 8;
|
||||
dtargus /= sp->settings->rate;
|
||||
|
||||
dtargus = (int64_t) (sp->settings->blksize) * SEC_TO_US * 8;
|
||||
dtargus /= sp->settings->rate;
|
||||
assert(dtargus != 0);
|
||||
*/
|
||||
if (gettimeofday(&before, 0) < 0)
|
||||
perror("gettimeofday");
|
||||
++sp->packet_count;
|
||||
sec = htonl(before.tv_sec);
|
||||
usec = htonl(before.tv_usec);
|
||||
pcount = htonl(sp->packet_count);
|
||||
|
||||
assert(dtargus != 0);
|
||||
memcpy(sp->buffer, &sec, sizeof(sec));
|
||||
memcpy(sp->buffer+4, &usec, sizeof(usec));
|
||||
memcpy(sp->buffer+8, &pcount, sizeof(pcount));
|
||||
|
||||
switch (sp->settings->state)
|
||||
{
|
||||
case STREAM_BEGIN:
|
||||
udp->state = STREAM_BEGIN;
|
||||
udp->stream_id = (uint64_t) sp;
|
||||
/* udp->packet_count = ++sp->packet_count; */
|
||||
break;
|
||||
|
||||
case STREAM_END:
|
||||
udp->state = STREAM_END;
|
||||
udp->stream_id = (uint64_t) sp;
|
||||
break;
|
||||
|
||||
case RESULT_REQUEST:
|
||||
udp->state = RESULT_REQUEST;
|
||||
udp->stream_id = (uint64_t) sp;
|
||||
break;
|
||||
|
||||
case ALL_STREAMS_END:
|
||||
udp->state = ALL_STREAMS_END;
|
||||
break;
|
||||
|
||||
case STREAM_RUNNING:
|
||||
udp->state = STREAM_RUNNING;
|
||||
udp->stream_id = (uint64_t) sp;
|
||||
udp->packet_count = ++sp->packet_count;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sp->settings->state == STREAM_BEGIN)
|
||||
{
|
||||
sp->settings->state = STREAM_RUNNING;
|
||||
}
|
||||
if (gettimeofday(&before, 0) < 0)
|
||||
perror("gettimeofday");
|
||||
|
||||
udp->sent_time = before;
|
||||
|
||||
printf("iperf_udp_send: writing %d bytes \n", size);
|
||||
#ifdef USE_SEND
|
||||
result = send(sp->socket, sp->buffer, size, 0);
|
||||
result = send(sp->socket, sp->buffer, size, 0);
|
||||
#else
|
||||
result = Nwrite(sp->socket, sp->buffer, size, Pudp);
|
||||
result = Nwrite(sp->socket, sp->buffer, size, Pudp);
|
||||
#endif
|
||||
|
||||
if (gettimeofday(&after, 0) < 0)
|
||||
perror("gettimeofday");
|
||||
if (result < 0)
|
||||
perror("Nwrite udp error");
|
||||
|
||||
/*
|
||||
* CHECK: Packet length and ID if(sp->settings->state ==
|
||||
* STREAM_RUNNING) printf("State = %d Outgoing packet = %d AND SP =
|
||||
* %d\n",sp->settings->state, sp->packet_count, sp->socket);
|
||||
*/
|
||||
sp->result->bytes_sent += result;
|
||||
sp->result->bytes_sent_this_interval += result;
|
||||
/*
|
||||
if (gettimeofday(&after, 0) < 0)
|
||||
perror("gettimeofday");
|
||||
|
||||
if (sp->settings->state == STREAM_RUNNING)
|
||||
sp->result->bytes_sent += result;
|
||||
//
|
||||
// CHECK: Packet length and ID if(sp->settings->state ==
|
||||
// STREAM_RUNNING) printf("State = %d Outgoing packet = %d AND SP =
|
||||
// %d\n",sp->settings->state, sp->packet_count, sp->socket);
|
||||
//
|
||||
|
||||
adjustus = dtargus;
|
||||
adjustus += (before.tv_sec - after.tv_sec) * SEC_TO_US;
|
||||
adjustus += (before.tv_usec - after.tv_usec);
|
||||
|
||||
if (adjustus > 0)
|
||||
{
|
||||
dtargus = adjustus;
|
||||
}
|
||||
/* RESET THE TIMER */
|
||||
update_timer(sp->send_timer, 0, dtargus);
|
||||
param = NULL;
|
||||
adjustus = dtargus;
|
||||
adjustus += (before.tv_sec - after.tv_sec) * SEC_TO_US;
|
||||
adjustus += (before.tv_usec - after.tv_usec);
|
||||
|
||||
} /* timer_expired_micro */
|
||||
if (adjustus > 0) {
|
||||
dtargus = adjustus;
|
||||
}
|
||||
// RESET THE TIMER
|
||||
update_timer(sp->send_timer, 0, dtargus);
|
||||
// } // timer_expired_micro
|
||||
*/
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -232,10 +193,9 @@ iperf_new_udp_stream(struct iperf_test * testp)
|
||||
struct iperf_stream *sp;
|
||||
|
||||
sp = (struct iperf_stream *) iperf_new_stream(testp);
|
||||
if (!sp)
|
||||
{
|
||||
perror("malloc");
|
||||
return (NULL);
|
||||
if (!sp) {
|
||||
perror("malloc");
|
||||
return (NULL);
|
||||
}
|
||||
sp->rcv = iperf_udp_recv;
|
||||
sp->snd = iperf_udp_send;
|
||||
@ -254,70 +214,53 @@ iperf_new_udp_stream(struct iperf_test * testp)
|
||||
|
||||
|
||||
int
|
||||
iperf_udp_accept(struct iperf_test * test)
|
||||
iperf_udp_accept(struct iperf_test *test)
|
||||
{
|
||||
|
||||
struct iperf_stream *sp;
|
||||
struct sockaddr_in sa_peer;
|
||||
char *buf;
|
||||
int buf;
|
||||
socklen_t len;
|
||||
int sz;
|
||||
int sz, s;
|
||||
|
||||
buf = (char *) malloc(test->default_settings->blksize);
|
||||
struct udp_datagram *udp = (struct udp_datagram *) buf;
|
||||
s = test->listener_udp;
|
||||
|
||||
len = sizeof sa_peer;
|
||||
|
||||
sz = recvfrom(test->listener_sock_udp, buf, test->default_settings->blksize, 0, (struct sockaddr *) & sa_peer, &len);
|
||||
|
||||
if (!sz)
|
||||
return -1;
|
||||
|
||||
if (connect(test->listener_sock_udp, (struct sockaddr *) & sa_peer, len) < 0)
|
||||
{
|
||||
perror("iperf_udp_accept: connect error");
|
||||
exit(-1); /* XXX: for debugging */
|
||||
return -1;
|
||||
if ((sz = recvfrom(test->listener_udp, &buf, sizeof(buf), 0, (struct sockaddr *) &sa_peer, &len)) < 0) {
|
||||
perror("recvfrom in udp accept");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (connect(s, (struct sockaddr *) &sa_peer, len) < 0) {
|
||||
perror("iperf_udp_accept: connect error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sp = test->new_stream(test);
|
||||
|
||||
sp->socket = test->listener_sock_udp;
|
||||
|
||||
setnonblocking(sp->socket);
|
||||
|
||||
if (!sp)
|
||||
return (-1);
|
||||
sp->socket = s;
|
||||
iperf_init_stream(sp, test);
|
||||
iperf_add_stream(test, sp);
|
||||
FD_SET(s, &test->read_set);
|
||||
FD_SET(s, &test->write_set);
|
||||
test->max_fd = (s > test->max_fd) ? s : test->max_fd;
|
||||
|
||||
test->listener_udp = netannounce(Pudp, NULL, test->server_port);
|
||||
if (test->listener_udp < 0)
|
||||
return -1;
|
||||
|
||||
test->listener_sock_udp = netannounce(Pudp, NULL, test->server_port);
|
||||
if (test->listener_sock_udp < 0)
|
||||
return -1;
|
||||
FD_SET(test->listener_udp, &test->read_set);
|
||||
test->max_fd = (test->max_fd < test->listener_udp) ? test->listener_udp : test->max_fd;
|
||||
|
||||
FD_SET(test->listener_sock_udp, &test->read_set);
|
||||
test->max_fd = (test->max_fd < test->listener_sock_udp) ? test->listener_sock_udp : test->max_fd;
|
||||
|
||||
if (test->default_settings->state != RESULT_REQUEST)
|
||||
connect_msg(sp);
|
||||
|
||||
printf("iperf_udp_accept: 1st UDP data packet for socket %d has arrived \n", sp->socket);
|
||||
sp->stream_id = udp->stream_id;
|
||||
sp->result->bytes_received += sz;
|
||||
|
||||
/* Count OUT OF ORDER PACKETS */
|
||||
if (udp->packet_count != 0)
|
||||
{
|
||||
if (udp->packet_count < sp->packet_count + 1)
|
||||
sp->outoforder_packets++;
|
||||
else
|
||||
sp->cnt_error += udp->packet_count - sp->packet_count;
|
||||
/* Let the client know we're ready "accept" another UDP "stream" */
|
||||
if (write(sp->socket, &buf, sizeof(buf)) < 0) {
|
||||
perror("write listen message");
|
||||
return -1;
|
||||
}
|
||||
/* store the latest packet id */
|
||||
if (udp->packet_count > sp->packet_count)
|
||||
sp->packet_count = udp->packet_count;
|
||||
|
||||
//printf("incoming packet = %d and received packet = %d AND SP = %d\n", udp->packet_count, sp->packet_count, sp->socket);
|
||||
connect_msg(sp);
|
||||
test->streams_accepted++;
|
||||
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -229,13 +229,6 @@ main(int argc, char **argv)
|
||||
optind = 0;
|
||||
|
||||
|
||||
/* exit until this is done.... */
|
||||
if (test->protocol == Pudp) {
|
||||
printf("UDP mode not yet supported. Exiting. \n");
|
||||
iperf_free_test(test);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (iperf_run(test) < 0) {
|
||||
fprintf(stderr, "An error occurred. Exiting...\n");
|
||||
return -1;
|
||||
|
42
src/net.c
42
src/net.c
@ -18,6 +18,7 @@
|
||||
*/
|
||||
|
||||
/* make connection to server */
|
||||
// XXX: Change client to server?
|
||||
int
|
||||
netdial(int proto, char *client, int port)
|
||||
{
|
||||
@ -49,13 +50,14 @@ netdial(int proto, char *client, int port)
|
||||
}
|
||||
|
||||
sn = sizeof sa;
|
||||
|
||||
if (getpeername(s, (struct sockaddr *) & sa, &sn) >= 0) {
|
||||
return (s);
|
||||
|
||||
// XXX: Is there a reason to call getpeername() if none of the return values are used?
|
||||
if (getpeername(s, (struct sockaddr *) & sa, &sn) < 0) {
|
||||
perror("getpeername error");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
perror("getpeername error");
|
||||
return (-1);
|
||||
return (s);
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@ -100,28 +102,20 @@ netannounce(int proto, char *local, int port)
|
||||
int
|
||||
Nread(int fd, void *buf, int count, int prot)
|
||||
{
|
||||
struct sockaddr from;
|
||||
socklen_t len = sizeof(from);
|
||||
register int n;
|
||||
register int nleft = count;
|
||||
|
||||
if (prot == SOCK_DGRAM) {
|
||||
// XXX: Does recvfrom guarantee all count bytes are sent at once?
|
||||
fprintf(stderr, "READING UDP DATA IN Nread SOCK_DGRAM\n");
|
||||
n = recvfrom(fd, buf, count, 0, &from, &len);
|
||||
} else {
|
||||
while (nleft > 0) {
|
||||
if ((n = read(fd, buf, nleft)) < 0) {
|
||||
if (errno == EINTR)
|
||||
n = 0;
|
||||
else
|
||||
return (-1);
|
||||
} else if (n == 0)
|
||||
break;
|
||||
|
||||
nleft -= n;
|
||||
buf += n;
|
||||
}
|
||||
while (nleft > 0) {
|
||||
if ((n = read(fd, buf, nleft)) < 0) {
|
||||
if (errno == EINTR)
|
||||
n = 0;
|
||||
else
|
||||
return (-1);
|
||||
} else if (n == 0)
|
||||
break;
|
||||
|
||||
nleft -= n;
|
||||
buf += n;
|
||||
}
|
||||
return (count - nleft);
|
||||
}
|
||||
|
30
src/net.h
30
src/net.h
@ -9,5 +9,35 @@ int getsock_tcp_mss(int);
|
||||
int set_tcp_options(int, int, int);
|
||||
int setnonblocking(int);
|
||||
|
||||
unsigned long long htonll(unsigned long long);
|
||||
unsigned long long ntohll(unsigned long long);
|
||||
|
||||
/* XXX: Need a better check for byte order */
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
#define HTONLL(n) (n)
|
||||
#define NTOHLL(n) (n)
|
||||
#else
|
||||
#define HTONLL(n) ((((unsigned long long)(n) & 0xFF) << 56) | \
|
||||
(((unsigned long long)(n) & 0xFF00) << 40) | \
|
||||
(((unsigned long long)(n) & 0xFF0000) << 24) | \
|
||||
(((unsigned long long)(n) & 0xFF000000) << 8) | \
|
||||
(((unsigned long long)(n) & 0xFF00000000) >> 8) | \
|
||||
(((unsigned long long)(n) & 0xFF0000000000) >> 24) | \
|
||||
(((unsigned long long)(n) & 0xFF000000000000) >> 40) | \
|
||||
(((unsigned long long)(n) & 0xFF00000000000000) >> 56))
|
||||
|
||||
#define NTOHLL(n) ((((unsigned long long)(n) & 0xFF) << 56) | \
|
||||
(((unsigned long long)(n) & 0xFF00) << 40) | \
|
||||
(((unsigned long long)(n) & 0xFF0000) << 24) | \
|
||||
(((unsigned long long)(n) & 0xFF000000) << 8) | \
|
||||
(((unsigned long long)(n) & 0xFF00000000) >> 8) | \
|
||||
(((unsigned long long)(n) & 0xFF0000000000) >> 24) | \
|
||||
(((unsigned long long)(n) & 0xFF000000000000) >> 40) | \
|
||||
(((unsigned long long)(n) & 0xFF00000000000000) >> 56))
|
||||
#endif
|
||||
|
||||
#define htonll(n) HTONLL(n)
|
||||
#define ntohll(n) NTOHLL(n)
|
||||
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user