diff --git a/src/iperf_api.c b/src/iperf_api.c index 05f881e..df6f3b2 100644 --- a/src/iperf_api.c +++ b/src/iperf_api.c @@ -595,19 +595,33 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) int iperf_send(struct iperf_test *test, fd_set *write_setP) { - iperf_size_t bytes_sent; - struct iperf_stream *sp; + int burst, r; + register struct iperf_stream *sp; - SLIST_FOREACH(sp, &test->streams, streams) { - if (FD_ISSET(sp->socket, write_setP)) { - if ((bytes_sent = sp->snd(sp)) < 0) { - i_errno = IESTREAMWRITE; - return -1; + /* Can we do burst mode? */ + if (test->protocol->id == Pudp && test->settings->rate != 0) + burst = 1; /* nope */ + else + burst = 20; /* arbitrary */ + + for (; burst > 0; --burst) { + SLIST_FOREACH(sp, &test->streams, streams) { + if (FD_ISSET(sp->socket, write_setP)) { + if ((r = sp->snd(sp)) < 0) { + if (r == NET_SOFTERROR) + break; + i_errno = IESTREAMWRITE; + return r; + } + test->bytes_sent += r; + if (burst > 1 && test->settings->bytes != 0 && test->bytes_sent >= test->settings->bytes) + break; } - test->bytes_sent += bytes_sent; - FD_CLR(sp->socket, write_setP); } } + SLIST_FOREACH(sp, &test->streams, streams) + if (FD_ISSET(sp->socket, write_setP)) + FD_CLR(sp->socket, write_setP); return 0; } @@ -615,16 +629,16 @@ iperf_send(struct iperf_test *test, fd_set *write_setP) int iperf_recv(struct iperf_test *test, fd_set *read_setP) { - iperf_size_t bytes_sent; + int r; struct iperf_stream *sp; SLIST_FOREACH(sp, &test->streams, streams) { if (FD_ISSET(sp->socket, read_setP)) { - if ((bytes_sent = sp->rcv(sp)) < 0) { + if ((r = sp->rcv(sp)) < 0) { i_errno = IESTREAMREAD; - return -1; + return r; } - test->bytes_sent += bytes_sent; + test->bytes_sent += r; FD_CLR(sp->socket, read_setP); } } diff --git a/src/iperf_tcp.c b/src/iperf_tcp.c index a14ee32..39d8713 100644 --- a/src/iperf_tcp.c +++ b/src/iperf_tcp.c @@ -33,19 +33,17 @@ int iperf_tcp_recv(struct iperf_stream *sp) { - int result = 0; - int size = sp->settings->blksize; + int r; - result = Nread(sp->socket, sp->buffer, size, Ptcp); + r = Nread(sp->socket, sp->buffer, sp->settings->blksize, Ptcp); - if (result < 0) { - return -1; - } + if (r < 0) + return r; - sp->result->bytes_received += result; - sp->result->bytes_received_this_interval += result; + sp->result->bytes_received += r; + sp->result->bytes_received_this_interval += r; - return result; + return r; } @@ -56,19 +54,17 @@ iperf_tcp_recv(struct iperf_stream *sp) int iperf_tcp_send(struct iperf_stream *sp) { - int result; - int size = sp->settings->blksize; + int r; - result = Nwrite(sp->socket, sp->buffer, size, Ptcp); + r = Nwrite(sp->socket, sp->buffer, sp->settings->blksize, Ptcp); - if (result < 0) { - return -1; - } + if (r < 0) + return r; - sp->result->bytes_sent += result; - sp->result->bytes_sent_this_interval += result; + sp->result->bytes_sent += r; + sp->result->bytes_sent_this_interval += r; - return result; + return r; } diff --git a/src/iperf_udp.c b/src/iperf_udp.c index 538b790..768992a 100644 --- a/src/iperf_udp.c +++ b/src/iperf_udp.c @@ -35,20 +35,19 @@ int iperf_udp_recv(struct iperf_stream *sp) { - int result; + int r; int size = sp->settings->blksize; int sec, usec, pcount; double transit = 0, d = 0; struct timeval sent_time, arrival_time; - result = Nread(sp->socket, sp->buffer, size, Pudp); + r = Nread(sp->socket, sp->buffer, size, Pudp); - if (result < 0) { - return -1; - } + if (r < 0) + return r; - sp->result->bytes_received += result; - sp->result->bytes_received_this_interval += result; + sp->result->bytes_received += r; + sp->result->bytes_received_this_interval += r; memcpy(&sec, sp->buffer, sizeof(sec)); memcpy(&usec, sp->buffer+4, sizeof(usec)); @@ -82,7 +81,7 @@ iperf_udp_recv(struct iperf_stream *sp) // J = |(R1 - S1) - (R0 - S0)| [/ number of packets, for average] sp->jitter += (d - sp->jitter) / 16.0; - return result; + return r; } @@ -107,7 +106,7 @@ send_timer_proc(TimerClientData client_data, struct timeval* nowP) int iperf_udp_send(struct iperf_stream *sp) { - ssize_t result = 0; + int r; int64_t dtargus; int64_t adjustus; uint64_t sec, usec, pcount; @@ -115,46 +114,47 @@ iperf_udp_send(struct iperf_stream *sp) struct timeval before, after; TimerClientData cd; - if (sp->udp_green_light) { - gettimeofday(&before, 0); + if (! sp->udp_green_light) + return 0; - ++sp->packet_count; - sec = htonl(before.tv_sec); - usec = htonl(before.tv_usec); - pcount = htonl(sp->packet_count); + gettimeofday(&before, 0); - memcpy(sp->buffer, &sec, sizeof(sec)); - memcpy(sp->buffer+4, &usec, sizeof(usec)); - memcpy(sp->buffer+8, &pcount, sizeof(pcount)); + ++sp->packet_count; + sec = htonl(before.tv_sec); + usec = htonl(before.tv_usec); + pcount = htonl(sp->packet_count); - result = Nwrite(sp->socket, sp->buffer, size, Pudp); + memcpy(sp->buffer, &sec, sizeof(sec)); + memcpy(sp->buffer+4, &usec, sizeof(usec)); + memcpy(sp->buffer+8, &pcount, sizeof(pcount)); - if (result < 0) - return -1; + r = Nwrite(sp->socket, sp->buffer, size, Pudp); - sp->result->bytes_sent += result; - sp->result->bytes_sent_this_interval += result; + if (r < 0) + return r; - if (sp->settings->rate != 0) { - gettimeofday(&after, 0); - dtargus = (int64_t) (sp->settings->blksize) * SEC_TO_US * 8; - dtargus /= sp->settings->rate; - assert(dtargus != 0); - adjustus = dtargus; - adjustus += (before.tv_sec - after.tv_sec) * SEC_TO_US; - adjustus += (before.tv_usec - after.tv_usec); - if (adjustus > 0) { - dtargus = adjustus; - } - cd.p = sp; - sp->udp_green_light = 0; - sp->send_timer = tmr_create((struct timeval*) 0, send_timer_proc, cd, dtargus, 0); - if (sp->send_timer == NULL) - return -1; + sp->result->bytes_sent += r; + sp->result->bytes_sent_this_interval += r; + + if (sp->settings->rate != 0) { + gettimeofday(&after, 0); + dtargus = (int64_t) (sp->settings->blksize) * SEC_TO_US * 8; + dtargus /= sp->settings->rate; + assert(dtargus != 0); + adjustus = dtargus; + adjustus += (before.tv_sec - after.tv_sec) * SEC_TO_US; + adjustus += (before.tv_usec - after.tv_usec); + if (adjustus > 0) { + dtargus = adjustus; } + cd.p = sp; + sp->udp_green_light = 0; + sp->send_timer = tmr_create((struct timeval*) 0, send_timer_proc, cd, dtargus, 0); + if (sp->send_timer == NULL) + return -1; } - return result; + return r; } diff --git a/src/net.c b/src/net.c index 03ca9f8..0dd6d82 100644 --- a/src/net.c +++ b/src/net.c @@ -131,7 +131,7 @@ Nread(int fd, void *buf, int count, int prot) if (errno == EINTR) n = 0; else - return -1; + return NET_HARDERROR; } else if (n == 0) break; @@ -144,9 +144,6 @@ Nread(int fd, void *buf, int count, int prot) /* * N W R I T E - * - * XXX: After updating this function to use read/write, the only difference between - * TCP and UDP is that udp handles ENOBUFS. Should we merge the two? */ int @@ -155,34 +152,22 @@ Nwrite(int fd, void *buf, int count, int prot) register int n; register int nleft = count; - if (prot == SOCK_DGRAM) { /* UDP mode */ - while (nleft > 0) { - if ((n = write(fd, buf, nleft)) < 0) { - if (errno == EINTR) { - n = 0; - } else if (errno == ENOBUFS) { - /* wait if run out of buffers */ - /* XXX: but how long to wait? Start shorter and increase delay each time?? */ - delay(18000); // XXX: Fixme! - n = 0; - } else { - return -1; - } - } - nleft -= n; - buf += n; - } - } else { - while (nleft > 0) { - if ((n = write(fd, buf, nleft)) < 0) { - if (errno == EINTR) - n = 0; - else - return -1; - } - nleft -= n; - buf += n; - } + while (nleft > 0) { + if ((n = write(fd, buf, nleft)) < 0) { + switch (errno) { + case EINTR: + return count - nleft; + + case EAGAIN: + case ENOBUFS: + return NET_SOFTERROR; + + default: + return NET_HARDERROR; + } + } + nleft -= n; + buf += n; } return count; } diff --git a/src/net.h b/src/net.h index cb14fc6..4a6129c 100644 --- a/src/net.h +++ b/src/net.h @@ -18,6 +18,9 @@ int getsock_tcp_mss(int); int set_tcp_options(int, int, int); int setnonblocking(int); +#define NET_SOFTERROR -1 +#define NET_HARDERROR -2 + unsigned long long htonll(unsigned long long); unsigned long long ntohll(unsigned long long);