now compiles on FreeBSD, and fixed -h option

This commit is contained in:
Brian Tierney 2009-10-20 03:33:50 +00:00
parent b25e5235cb
commit 371c23d833
4 changed files with 442 additions and 1458 deletions

View File

@ -10,7 +10,7 @@ endif
all: iperf
iperf: $(OBJS)
$(CC) $(LDFLAGS) -o iperf $(OBJS)
$(CC) $(LDFLAGS) -o iperf3 $(OBJS)
profile: iperf
$(CC) -pg -o iperf-profile $(OBJS)

File diff suppressed because it is too large Load Diff

View File

@ -71,15 +71,11 @@ Client/Server:\n\
-i, --interval # seconds between periodic bandwidth reports\n\
-l, --len #[KM] length of buffer to read or write (default 8 KB)\n\
-m, --print_mss print TCP maximum segment size (MTU - TCP/IP header)\n\
-o, --output <filename> output the report or error message to this specified file\n\
-p, --port # server port to listen on/connect to\n\
-u, --udp use UDP rather than TCP\n\
-w, --window #[KM] TCP window size (socket buffer size)\n\
-B, --bind <host> bind to <host>, an interface or multicast address\n\
-C, --compatibility for use with older versions does not sent extra msgs\n\
-M, --mss # set TCP maximum segment size (MTU - 40 bytes)\n\
-N, --nodelay set TCP no delay, disabling Nagle's Algorithm\n\
-V, --IPv6Version Set the domain to IPv6\n\
-T, --tcpinfo Output detailed TCP info\n\
Server specific:\n\
-s, --server run in server mode\n\
@ -90,38 +86,44 @@ Server specific:\n\
#endif
;
#ifdef OBSOLETE /* from old iperf: no longer supported. Add someday?? */
-o, --output <filename> output the report or error message to this specified file\n\
-B, --bind <host> bind to <host>, an interface or multicast address\n\
-V, --IPv6Version Set the domain to IPv6\n\
-C, --compatibility for use with older versions does not sent extra msgs
#endif
const char usage_long2[] = "\
\n\
Client specific:\n\
-b, --bandwidth #[KM] for UDP, bandwidth to send at in bits/sec\n\
(default 1 Mbit/sec, implies -u)\n\
-c, --client <host> run in client mode, connecting to <host>\n\
-d, --dualtest Do a bidirectional test simultaneously\n\
-n, --num #[KM] number of bytes to transmit (instead of -t)\n\
-r, --tradeoff Do a bidirectional test individually\n\
-t, --time # time in seconds to transmit for (default 10 secs)\n\
-F, --fileinput <name> input the data to be transmitted from a file\n\
-I, --stdin input the data to be transmitted from stdin\n\
-L, --listenport # port to recieve bidirectional tests back on\n\
-P, --parallel # number of parallel client threads to run\n\
-T, --ttl # time-to-live, for multicast (default 1)\n\
-Z, --linux-congestion <algo> set TCP congestion control algorithm (Linux only)\n\
-T, --tcpinfo Output detailed TCP info (Linux and FreeBSD only)\n\
\n\
Miscellaneous:\n\
-x, --reportexclude [CDMSV] exclude C(connection) D(data) M(multicast) S(settings) V(server) reports\n\
-y, --reportstyle C report as a Comma-Separated Values\n\
-h, --help print this message and quit\n\
-v, --version print version information and quit\n\
\n\
[KM] Indicates options that support a K or M suffix for kilo- or mega-\n\
\n\
The TCP window size option can be set by the environment variable\n\
TCP_WINDOW_SIZE. Most other options can be set by an environment variable\n\
IPERF_<long option name>, such as IPERF_BANDWIDTH.\n\
\n\
Report bugs to <iperf-users@lists.sourceforge.net>\n";
#ifdef OBSOLETE /* from old iperf: no longer supported. Add some of these back someday */
-v, --version print version information and quit\n\
-Z, --linux-congestion <algo> set TCP congestion control algorithm (Linux only)\n\
-d, --dualtest Do a bidirectional test simultaneously\n\
-L, --listenport # port to recieve bidirectional tests back on\n\
-I, --stdin input the data to be transmitted from stdin\n\
-F, --fileinput <name> input the data to be transmitted from a file\n\
-r, --tradeoff Do a bidirectional test individually\n\
-T, --ttl # time-to-live, for multicast (default 1)\n\
-x, --reportexclude [CDMSV] exclude C(connection) D(data) M(multicast) S(settings) V(server) reports\n\
-y, --reportstyle C report as a Comma-Separated Values
#endif
//const char version[] = "iperf version " IPERF_VERSION " (" IPERF_VERSION_DATE ") " IPERF_THREADS "\n";
/* -------------------------------------------------------------------
@ -225,6 +227,7 @@ const char report_tcpInfo[] =
"\t TCP Info: CWND=%u SND_SSTHRESH=%u RCV_SSTHRESH=%u UNACKED=%u SACK=%u LOST=%u RETRANS=%u FACK=%u";
#endif
#if defined(__FreeBSD__)
const char report_tcpInfo[] =
"\t TCP Info: CWND=%u SND_SSTHRESH=%u RCV_WIND=%u";
#endif

View File

@ -1,953 +0,0 @@
/*
* iperf3
*/
/*
Copyright (c) 2004, 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <assert.h>
#include<fcntl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <pthread.h>
#include <stdint.h>
#include <sys/time.h>
#include "iperf.h"
#include "timer.h"
#include "net.h"
#include "units.h"
#include "tcp_window_size.h"
enum
{
Mundef = 0,
Mclient,
Mserver,
Ptcp = SOCK_STREAM,
Pudp = SOCK_DGRAM,
uS_TO_NS = 1000,
MAX_BUFFER_SIZE = 10,
DEFAULT_UDP_BUFSIZE = 1470,
DEFAULT_TCP_BUFSIZE = 8192
};
#define SEC_TO_NS 1000000000 /* too big for enum on some platforms */
struct iperf_stream
{
int sock; /* local socket */
struct sockaddr_in local; /* local address */
struct sockaddr_in peer; /* peer address */
uint64_t bytes_in;
uint64_t bytes_out;
pthread_t thread;
char local_addr[512], peer_addr[512];
void *stats; /* ptr to protocol specific stats */
void *(*server) (void *sp);
void *(*client) (void *sp);
struct iperf_settings *settings;
struct iperf_stream *next;
};
void *udp_client_thread(struct iperf_stream * sp);
void *udp_server_thread(int maxfd, fd_set * temp_set, fd_set * read_set);
int udp_server_accept(int *s, int maxfd, fd_set * read_set, struct iperf_settings * settings);
void *tcp_client_thread(struct iperf_stream * sp);
void *tcp_server_thread(int maxfd, fd_set * temp_set, fd_set * read_set);
int tcp_server_accept(int s, int maxfd, fd_set * read_set, struct iperf_settings * settings);
static struct option longopts[] =
{
{"client", required_argument, NULL, 'c'},
{"server", no_argument, NULL, 's'},
{"time", required_argument, NULL, 't'},
{"port", required_argument, NULL, 'p'},
{"parallel", required_argument, NULL, 'P'},
{"udp", no_argument, NULL, 'u'},
{"bandwidth", required_argument, NULL, 'b'},
{"length", required_argument, NULL, 'l'},
{"window", required_argument, NULL, 'w'},
{NULL, 0, NULL, 0}
};
struct iperf_settings
{
char mode;
char proto;
char *client;
int port;
int sock;
iperf_size_t bw;
int duration;
int threads;
iperf_size_t bufsize;
iperf_size_t window;
struct sockaddr_in sa;
};
void
default_settings(struct iperf_settings * settings)
{
settings->mode = Mundef;
settings->proto = Ptcp;
settings->client = NULL;
settings->port = 5001;
settings->sock = -1;
settings->bw = 1000000;
settings->duration = 10;
settings->threads = 1;
settings->bufsize = DEFAULT_UDP_BUFSIZE;
settings->window = 1024 * 1024;
memset(&settings->sa, 0, sizeof(struct sockaddr_in));
}
struct iperf_stream *streams; /* head of list of streams */
int done = 0;
/*--------------------------------------------------------
* Displays the current list of streams
-------------------------------------------------------*/
void
Display()
{
struct iperf_stream *n;
n = streams;
int count = 1;
printf("===============DISPLAY==================\n");
while (1)
{
if (n)
{
if (n->settings->mode == Mclient)
printf("position-%d\tsp=%d\tsocket=%d\tbytes sent=%llu\n", count++, (int) n, n->sock, n->bytes_out);
else
printf("position-%d\tsp=%d\tsocket=%d\tbytes received=%llu\n", count++, (int) n, n->sock, n->bytes_in);
if (n->next == NULL)
{
printf("=================END====================\n");
fflush(stdout);
break;
}
n = n->next;
}
}
}
/*--------------------------------------------------------
* sets the parameters for the new stream created
-------------------------------------------------------*/
struct iperf_stream *
new_stream(int s, struct iperf_settings * settings)
{
struct iperf_stream *sp;
socklen_t len;
sp = (struct iperf_stream *) malloc(sizeof(struct iperf_stream));
if (!sp)
{
perror("malloc");
return (NULL);
}
memset(sp, 0, sizeof(struct iperf_stream));
sp->settings = settings;
sp->sock = s;
len = sizeof sp->local;
if (getsockname(sp->sock, (struct sockaddr *) & sp->local, &len) < 0)
{
perror("getsockname");
free(sp);
return (NULL);
}
/* converts the local ip into string address */
if (inet_ntop(AF_INET, (void *) &sp->local.sin_addr,
(void *) &sp->local_addr, 512) == NULL)
{
perror("inet_pton");
}
/* stores the socket id. */
if (getpeername(sp->sock, (struct sockaddr *) & sp->peer, &len) < 0)
{
perror("getpeername");
free(sp);
return (NULL);
}
/* converts the remote ip into string address */
if (inet_ntop(AF_INET, (void *) &sp->peer.sin_addr,
(void *) &sp->peer_addr, 512) == NULL)
{
perror("inet_pton");
}
/* not needed now */
switch (settings->proto)
{
case Ptcp:
sp->client = (void *) tcp_client_thread;
sp->server = (void *) tcp_server_thread;
break;
case Pudp:
sp->client = (void *) udp_client_thread;
sp->server = (void *) udp_server_thread;
break;
default:
assert(0);
break;
}
if (set_tcp_windowsize(sp->sock, settings->window,
settings->mode == Mserver ? SO_RCVBUF : SO_SNDBUF) < 0)
fprintf(stderr, "unable to set window size\n");
int x;
x = getsock_tcp_windowsize(sp->sock, SO_RCVBUF);
if (x < 0)
perror("SO_RCVBUF");
printf("RCV: %d\n", x);
x = getsock_tcp_windowsize(sp->sock, SO_SNDBUF);
if (x < 0)
perror("SO_SNDBUF");
printf("SND: %d\n", x);
return (sp);
}
/*--------------------------------------------------------
* add a stream into stream_list linked list
-------------------------------------------------------*/
void
add_stream(struct iperf_stream * sp)
{
struct iperf_stream *n;
if (!streams)
streams = sp;
else
{
n = streams;
while (n->next)
n = n->next;
n->next = sp;
}
}
/*--------------------------------------------------------
* delete the stream
-------------------------------------------------------*/
int
free_stream(struct iperf_stream * sp)
{
struct iperf_stream *prev, *start;
prev = streams;
start = streams;
if (streams->sock == sp->sock)
{
streams = streams->next;
return 0;
} else
{
start = streams->next;
while (1)
{
if (start->sock == sp->sock)
{
prev->next = sp->next;
free(sp);
return 0;
}
if (start->next != NULL)
{
start = start->next;
prev = prev->next;
}
}
return -1;
}
}
/*--------------------------------------------------------
* update the stream
-------------------------------------------------------*/
struct iperf_stream *
update_stream(int j, int result)
{
struct iperf_stream *n;
n = streams;
/* find the correct stream for update */
while (1)
{
if (n->sock == j)
{
n->bytes_in = n->bytes_in + result;
break;
}
if (n->next == NULL)
break;
n = n->next;
}
return n;
}
/*--------------------------------------------------------
* Display connected message
-------------------------------------------------------*/
void
connect_msg(struct iperf_stream * sp)
{
char *ipl, *ipr;
ipl = (char *) &sp->local.sin_addr;
ipr = (char *) &sp->peer.sin_addr;
printf("[%3d] local %s port %d connected with %s port %d\n",
sp->sock,
sp->local_addr, htons(sp->local.sin_port),
sp->peer_addr, htons(sp->peer.sin_port));
}
/*--------------------------------------------------------
* Make socket non-blocking
* -------------------------------------------------------*/
void
setnonblocking(int sock)
{
int opts;
/*
opts = fcntl(sock,F_GETFL);
if (opts < 0) {
perror("fcntl(F_GETFL)");
exit(EXIT_FAILURE);
}
*/
opts = (opts | O_NONBLOCK);
if (fcntl(sock, F_SETFL, opts) < 0)
{
perror("fcntl(F_SETFL)");
exit(EXIT_FAILURE);
}
return;
}
/*--------------------------------------------------------
* UDP client functionality. - NOT USED
-------------------------------------------------------*/
void *
udp_client_thread(struct iperf_stream * sp)
{
int i;
int64_t delayns, adjustns, dtargns;
char *buf;
struct timeval before, after;
buf = (char *) malloc(sp->settings->bufsize);
if (!buf)
{
perror("malloc: unable to allocate transmit buffer");
pthread_exit(NULL);
}
for (i = 0; i < sp->settings->bufsize; i++)
buf[i] = i % 37;
dtargns = (int64_t) sp->settings->bufsize * SEC_TO_NS * 8;
dtargns /= sp->settings->bw;
assert(dtargns != 0);
if (gettimeofday(&before, 0) < 0)
{
perror("gettimeofday");
}
delayns = dtargns;
adjustns = 0;
printf("%lld adj %lld delay\n", adjustns, delayns);
while (!done)
{
send(sp->sock, buf, sp->settings->bufsize, 0);
sp->bytes_out += sp->settings->bufsize;
if (delayns > 0)
delay(delayns);
if (gettimeofday(&after, 0) < 0)
{
perror("gettimeofday");
}
adjustns = dtargns;
adjustns += (before.tv_sec - after.tv_sec) * SEC_TO_NS;
adjustns += (before.tv_usec - after.tv_usec) * uS_TO_NS;
if (adjustns > 0 || delayns > 0)
{
//printf("%lld adj %lld delay\n", adjustns, delayns);
delayns += adjustns;
}
memcpy(&before, &after, sizeof before);
}
/* a 0 byte packet is the server's cue that we're done */
send(sp->sock, buf, 0, 0);
/* XXX: wait for response with server counts */
printf("%llu bytes sent\n", sp->bytes_out);
close(sp->sock);
pthread_exit(NULL);
}
/*--------------------------------------------------------
* UDP Server functionality
-------------------------------------------------------*/
void *
udp_server_thread(int maxfd, fd_set * temp_set, fd_set * read_set)
{
char buffer[DEFAULT_UDP_BUFSIZE], ubuf[UNIT_LEN];
int j, result;
struct iperf_stream *n;
for (j = 0; j < maxfd + 1; j++)
{
n = streams;
if (FD_ISSET(j, temp_set))
{
do
{
result = recv(j, buffer, DEFAULT_UDP_BUFSIZE, 0);
} while (result == -1 && errno == EINTR);
if (result > 0)
{
update_stream(j, result);
} else if (result == 0)
{
/* just find the stream with zero update */
n = update_stream(j, 0);
unit_snprintf(ubuf, UNIT_LEN, (double) n->bytes_in / n->settings->duration, 'a');
printf("%llu bytes received %s/sec for stream %d\n\n", n->bytes_in, ubuf, (int) n);
close(j);
free_stream(n);
FD_CLR(j, read_set);
} else
{
printf("Error in recv(): %s\n", strerror(errno));
}
} /* end if (FD_ISSET(j, &temp_set)) */
} /* end for (j=0;...) */
return 0;
}
/*--------------------------------------------------------
* UDP Server new connection
-------------------------------------------------------*/
int
udp_server_accept(int *s, int maxfd, fd_set * read_set, struct iperf_settings * settings)
{
struct iperf_stream *sp;
struct sockaddr_in sa_peer;
char buf[settings->bufsize];
socklen_t len;
int sz;
len = sizeof sa_peer;
/* getting a new UDP packet */
sz = recvfrom(*s, buf, settings->bufsize, 0, (struct sockaddr *) & sa_peer, &len);
if (!sz)
return -1;
if (connect(*s, (struct sockaddr *) & sa_peer, len) < 0)
{
perror("connect");
return -1;
}
/* get a new socket to connect to client */
sp = new_stream(*s, settings);
sp->bytes_in += sz;
add_stream(sp);
*s = netannounce(settings->proto, NULL, settings->port);
if (*s < 0)
return -1;
FD_SET(*s, read_set);
maxfd = (maxfd < *s) ? *s : maxfd;
return maxfd;
}
/*--------------------------------------------------------
* UDP Reporting routine - NOT USED
-------------------------------------------------------*/
void
udp_report(int final)
{
}
/*--------------------------------------------------------
* TCP Reporting routine - NOT USED
-------------------------------------------------------*/
void
tcp_report(int final)
{
}
/*--------------------------------------------------------
* TCP client functionality
* -------------------------------------------------------*/
void *
tcp_client_thread(struct iperf_stream * sp)
{
int i;
char *buf;
buf = (char *) malloc(sp->settings->bufsize);
if (!buf)
{
perror("malloc: unable to allocate transmit buffer");
pthread_exit(NULL);
}
printf("window: %d\n", getsock_tcp_windowsize(sp->sock, SO_SNDBUF));
for (i = 0; i < sp->settings->bufsize; i++)
buf[i] = i % 37;
while (!done)
{
send(sp->sock, buf, sp->settings->bufsize, 0);
sp->bytes_out += sp->settings->bufsize;
}
/* a 0 byte packet is the server's cue that we're done */
send(sp->sock, buf, 0, 0);
/* XXX: wait for response with server counts */
printf("%llu bytes sent\n", sp->bytes_out);
close(sp->sock);
pthread_exit(NULL);
}
/*--------------------------------------------------------
* TCP Server functionality
* -------------------------------------------------------*/
void *
tcp_server_thread(int maxfd, fd_set * temp_set, fd_set * read_set)
{
int j, result;
char buffer[DEFAULT_TCP_BUFSIZE], ubuf[UNIT_LEN];
struct iperf_stream *n;
/* scanning all socket descriptors for read */
for (j = 0; j < maxfd + 1; j++)
{
if (FD_ISSET(j, temp_set))
{
do
{
result = recv(j, buffer, DEFAULT_TCP_BUFSIZE, 0);
} while (result == -1 && errno == EINTR);
if (result > 0)
{
update_stream(j, result);
} else if (result == 0)
{
n = update_stream(j, 0);
printf("window: %d\n", getsock_tcp_windowsize(n->sock, SO_RCVBUF));
unit_snprintf(ubuf, UNIT_LEN, (double) n->bytes_in / n->settings->duration, 'a');
printf("%llu bytes received %s/sec for stream %d\n\n", n->bytes_in, ubuf, (int) n);
close(j);
free_stream(n);
FD_CLR(j, read_set);
} else
{
printf("Error in recv(): %s\n", strerror(errno));
}
} /* end if (FD_ISSET(j, &temp_set)) */
} /* end for (j=0;...) */
return 0;
}
/*--------------------------------------------------------
* TCP new connection
* -------------------------------------------------------*/
int
tcp_server_accept(int s, int maxfd, fd_set * read_set, struct iperf_settings * settings)
{
socklen_t len;
struct sockaddr_in addr;
int peersock;
struct iperf_stream *sp;
len = sizeof(addr);
peersock = accept(s, (struct sockaddr *) & addr, &len);
if (peersock < 0)
{
printf("Error in accept(): %s\n", strerror(errno));
return 0;
} else
{
setnonblocking(peersock);
FD_SET(peersock, read_set);
maxfd = (maxfd < peersock) ? peersock : maxfd;
sp = new_stream(peersock, settings);
add_stream(sp);
connect_msg(sp);
return maxfd;
}
return -1;
}
/*--------------------------------------------------------
* This is code for Client
* -------------------------------------------------------*/
int
client(struct iperf_settings * settings)
{
int s, i;
struct iperf_stream *sp;
struct timer *timer;
char *buf;
int64_t delayns, adjustns, dtargns;
struct timeval before, after;
fd_set write_set;
struct timeval tv;
int maxfd, ret = 0;
FD_ZERO(&write_set);
FD_SET(s, &write_set);
tv.tv_sec = 15; /* timeout interval in seconds */
tv.tv_usec = 0;
for (i = 0; i < settings->threads; i++)
{
s = netdial(settings->proto, settings->client, settings->port);
if (s < 0)
{
fprintf(stderr, "netdial failed\n");
return -1;
}
FD_SET(s, &write_set);
maxfd = (maxfd < s) ? s : maxfd;
set_tcp_windowsize(s, settings->window, SO_SNDBUF);
if (s < 0)
return -1;
/* setting noblock causes error in byte count -kprabhu */
//setnonblocking(s);
sp = new_stream(s, settings);
add_stream(sp);
connect_msg(sp);
}
buf = (char *) malloc(sp->settings->bufsize);
if (!buf)
{
perror("malloc: unable to allocate transmit buffer");
}
printf("window: %d\n", getsock_tcp_windowsize(sp->sock, SO_SNDBUF));
for (i = 0; i < settings->bufsize; i++)
buf[i] = i % 37;
if (settings->proto == Pudp)
{
dtargns = (int64_t) settings->bufsize * SEC_TO_NS * 8;
dtargns /= settings->bw;
assert(dtargns != 0);
if (gettimeofday(&before, 0) < 0)
{
perror("gettimeofday");
}
delayns = dtargns;
adjustns = 0;
printf("%lld adj %lld delay\n", adjustns, delayns);
}
timer = new_timer(settings->duration, 0);
printf("calling select\n");
Display();
/* send data till the timer expires */
while (!timer->expired(timer))
{
ret = select(maxfd + 1, NULL, &write_set, NULL, &tv);
if (ret < 0)
continue;
sp = streams;
for (i = 0; i < settings->threads; i++)
{
if (FD_ISSET(sp->sock, &write_set))
{
send(sp->sock, buf, sp->settings->bufsize, 0);
sp->bytes_out += sp->settings->bufsize;
if (settings->proto == Pudp)
{
if (delayns > 0)
delay(delayns);
if (gettimeofday(&after, 0) < 0)
{
perror("gettimeofday");
}
adjustns = dtargns;
adjustns += (before.tv_sec - after.tv_sec) * SEC_TO_NS;
adjustns += (before.tv_usec - after.tv_usec) * uS_TO_NS;
if (adjustns > 0 || delayns > 0)
{
printf("%lld adj %lld delay\n", adjustns, delayns);
delayns += adjustns;
}
memcpy(&before, &after, sizeof before);
}
if (sp->next == NULL)
break;
sp = sp->next;
}
}
}
Display();
/* XXX: report */
sp = streams;
do
{
send(sp->sock, buf, 0, 0);
printf("%llu bytes sent\n", sp->bytes_out);
//close(sp->sock);
//free(sp);
sp = sp->next;
} while (sp);
return 0;
}
/*--------------------------------------------------------
* This is code for Server
* -------------------------------------------------------*/
int
server(struct iperf_settings * settings)
{
struct timeval tv;
char ubuf[UNIT_LEN];
fd_set read_set, temp_set;
int maxfd, result, s;
s = netannounce(settings->proto, NULL, settings->port);
if (s < 0)
return -1;
if (set_tcp_windowsize(s, settings->window, SO_RCVBUF) < 0)
{
perror("unable to set window");
return -1;
}
printf("-----------------------------------------------------------\n");
printf("Server listening on %d\n", settings->port);
int x;
if ((x = getsock_tcp_windowsize(s, SO_RCVBUF)) < 0)
perror("SO_RCVBUF");
unit_snprintf(ubuf, UNIT_LEN, (double) x, 'A');
printf("%s: %s\n",
settings->proto == Ptcp ? "TCP window size" : "UDP buffer size", ubuf);
printf("-----------------------------------------------------------\n");
FD_ZERO(&read_set);
FD_SET(s, &read_set);
maxfd = s;
do
{
memcpy(&temp_set, &read_set, sizeof(temp_set));
tv.tv_sec = 50; /* timeout interval in seconds */
tv.tv_usec = 0;
/* using select to check on multiple descriptors. */
result = select(maxfd + 1, &temp_set, NULL, NULL, &tv);
if (result == 0)
printf("select() timed out!\n");
else if (result < 0 && errno != EINTR)
printf("Error in select(): %s\n", strerror(errno));
else if (result > 0)
{
if (FD_ISSET(s, &temp_set))
{
if (settings->proto == Ptcp) /* New TCP Connection */
maxfd = tcp_server_accept(s, maxfd, &read_set, settings);
else if (settings->proto == Pudp) /* New UDP Connection */
maxfd = udp_server_accept(&s, maxfd, &read_set, settings);
FD_CLR(s, &temp_set);
Display();
}
if (settings->proto == Ptcp)
tcp_server_thread(maxfd, &temp_set, &read_set);
else if (settings->proto == Pudp)
udp_server_thread(maxfd, &temp_set, &read_set);
} /* end else if (result > 0) */
} while (1);
return 0;
}
int
main(int argc, char **argv)
{
int rc;
char ch;
struct iperf_settings settings;
default_settings(&settings);
while ((ch = getopt_long(argc, argv, "c:p:st:uP:b:l:w:", longopts, NULL)) != -1)
switch (ch)
{
case 'c':
settings.mode = Mclient;
settings.client = malloc(strlen(optarg));
strcpy(settings.client, optarg);
break;
case 'p':
settings.port = atoi(optarg);
break;
case 's':
settings.mode = Mserver;
break;
case 't':
settings.duration = atoi(optarg);
break;
case 'u':
settings.proto = Pudp;
break;
case 'P':
settings.threads = atoi(optarg);
break;
case 'b':
settings.bw = unit_atoi(optarg);
break;
case 'l':
settings.bufsize = atol(optarg);
break;
case 'w':
settings.window = unit_atoi(optarg);
break;
}
if (settings.proto == Ptcp && settings.bufsize == DEFAULT_UDP_BUFSIZE)
settings.bufsize = DEFAULT_TCP_BUFSIZE; /* XXX: this might be evil */
switch (settings.mode)
{
case Mclient:
rc = client(&settings);
break;
case Mserver:
rc = server(&settings);
break;
case Mundef:
/* FALLTHRU */
default:
printf("must specify one of -s or -c\n");
rc = -1;
break;
}
return rc;
}