pass settings rather than using a global
Этот коммит содержится в:
родитель
bc495fb9f7
Коммит
56cb7ca790
167
src/main.c
167
src/main.c
@ -48,7 +48,7 @@ enum {
|
|||||||
};
|
};
|
||||||
#define SEC_TO_NS 1000000000 /* too big for enum on some platforms */
|
#define SEC_TO_NS 1000000000 /* too big for enum on some platforms */
|
||||||
|
|
||||||
struct stream
|
struct iperf_stream
|
||||||
{
|
{
|
||||||
int sock; /* local socket */
|
int sock; /* local socket */
|
||||||
struct sockaddr_in local; /* local address */
|
struct sockaddr_in local; /* local address */
|
||||||
@ -66,13 +66,15 @@ struct stream
|
|||||||
void *(*server)(void *sp);
|
void *(*server)(void *sp);
|
||||||
void *(*client)(void *sp);
|
void *(*client)(void *sp);
|
||||||
|
|
||||||
struct stream *next;
|
struct iperf_settings *settings;
|
||||||
|
|
||||||
|
struct iperf_stream *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
void *udp_client_thread(struct stream *sp);
|
void *udp_client_thread(struct iperf_stream *sp);
|
||||||
void *udp_server_thread(struct stream *sp);
|
void *udp_server_thread(struct iperf_stream *sp);
|
||||||
void *tcp_client_thread(struct stream *sp);
|
void *tcp_client_thread(struct iperf_stream *sp);
|
||||||
void *tcp_server_thread(struct stream *sp);
|
void *tcp_server_thread(struct iperf_stream *sp);
|
||||||
|
|
||||||
static struct option longopts[] =
|
static struct option longopts[] =
|
||||||
{
|
{
|
||||||
@ -88,7 +90,7 @@ static struct option longopts[] =
|
|||||||
{ NULL, 0, NULL, 0 }
|
{ NULL, 0, NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct settings
|
struct iperf_settings
|
||||||
{
|
{
|
||||||
char mode;
|
char mode;
|
||||||
char proto;
|
char proto;
|
||||||
@ -103,37 +105,41 @@ struct settings
|
|||||||
struct sockaddr_in sa;
|
struct sockaddr_in sa;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct settings settings =
|
void
|
||||||
|
default_settings(struct iperf_settings *settings)
|
||||||
{
|
{
|
||||||
Mundef,
|
settings->mode = Mundef;
|
||||||
Ptcp,
|
settings->proto = Ptcp;
|
||||||
NULL,
|
settings->client = NULL;
|
||||||
5001,
|
settings->port = 5001;
|
||||||
-1,
|
settings->sock = -1;
|
||||||
1000000,
|
settings->bw = 1000000;
|
||||||
10,
|
settings->duration = 10;
|
||||||
1,
|
settings->threads = 1;
|
||||||
DEFAULT_UDP_BUFSIZE,
|
settings->bufsize = DEFAULT_UDP_BUFSIZE;
|
||||||
1024*1024
|
settings->window = 1024*1024;
|
||||||
};
|
memset(&settings->sa, 0, sizeof(struct sockaddr_in));
|
||||||
|
}
|
||||||
|
|
||||||
struct stream *streams; /* head of list of streams */
|
struct iperf_stream *streams; /* head of list of streams */
|
||||||
int done = 0;
|
int done = 0;
|
||||||
|
|
||||||
struct stream *
|
struct iperf_stream *
|
||||||
new_stream(int s)
|
new_stream(int s, struct iperf_settings *settings)
|
||||||
{
|
{
|
||||||
struct stream *sp;
|
struct iperf_stream *sp;
|
||||||
socklen_t len;
|
socklen_t len;
|
||||||
|
|
||||||
sp = (struct stream *) malloc(sizeof(struct 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 stream));
|
|
||||||
|
|
||||||
|
memset(sp, 0, sizeof(struct iperf_stream));
|
||||||
|
|
||||||
|
sp->settings = settings;
|
||||||
sp->sock = s;
|
sp->sock = s;
|
||||||
|
|
||||||
len = sizeof sp->local;
|
len = sizeof sp->local;
|
||||||
@ -159,7 +165,7 @@ new_stream(int s)
|
|||||||
perror("inet_pton");
|
perror("inet_pton");
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (settings.proto) {
|
switch (settings->proto) {
|
||||||
case Ptcp:
|
case Ptcp:
|
||||||
sp->client = (void *) tcp_client_thread;
|
sp->client = (void *) tcp_client_thread;
|
||||||
sp->server = (void *) tcp_server_thread;
|
sp->server = (void *) tcp_server_thread;
|
||||||
@ -173,8 +179,8 @@ new_stream(int s)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(set_tcp_windowsize(sp->sock, settings.window,
|
if(set_tcp_windowsize(sp->sock, settings->window,
|
||||||
settings.mode == Mserver ? SO_RCVBUF : SO_SNDBUF) < 0)
|
settings->mode == Mserver ? SO_RCVBUF : SO_SNDBUF) < 0)
|
||||||
fprintf(stderr, "unable to set window size\n");
|
fprintf(stderr, "unable to set window size\n");
|
||||||
|
|
||||||
int x;
|
int x;
|
||||||
@ -194,9 +200,9 @@ new_stream(int s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
add_stream(struct stream *sp)
|
add_stream(struct iperf_stream *sp)
|
||||||
{
|
{
|
||||||
struct stream *n;
|
struct iperf_stream *n;
|
||||||
|
|
||||||
if(!streams)
|
if(!streams)
|
||||||
streams = sp;
|
streams = sp;
|
||||||
@ -209,12 +215,12 @@ add_stream(struct stream *sp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
free_stream(struct stream *sp)
|
free_stream(struct iperf_stream *sp)
|
||||||
{
|
{
|
||||||
free(sp);
|
free(sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void connect_msg(struct stream *sp)
|
void connect_msg(struct iperf_stream *sp)
|
||||||
{
|
{
|
||||||
char *ipl, *ipr;
|
char *ipl, *ipr;
|
||||||
|
|
||||||
@ -228,24 +234,24 @@ void connect_msg(struct stream *sp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
udp_client_thread(struct stream *sp)
|
udp_client_thread(struct iperf_stream *sp)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int64_t delayns, adjustns, dtargns;
|
int64_t delayns, adjustns, dtargns;
|
||||||
char *buf;
|
char *buf;
|
||||||
struct timeval before, after;
|
struct timeval before, after;
|
||||||
|
|
||||||
buf = (char *) malloc(settings.bufsize);
|
buf = (char *) malloc(sp->settings->bufsize);
|
||||||
if(!buf) {
|
if(!buf) {
|
||||||
perror("malloc: unable to allocate transmit buffer");
|
perror("malloc: unable to allocate transmit buffer");
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i=0; i < settings.bufsize; i++)
|
for(i=0; i < sp->settings->bufsize; i++)
|
||||||
buf[i] = i % 37;
|
buf[i] = i % 37;
|
||||||
|
|
||||||
dtargns = (int64_t) settings.bufsize * SEC_TO_NS * 8;
|
dtargns = (int64_t) sp->settings->bufsize * SEC_TO_NS * 8;
|
||||||
dtargns /= settings.bw;
|
dtargns /= sp->settings->bw;
|
||||||
|
|
||||||
assert(dtargns != 0);
|
assert(dtargns != 0);
|
||||||
|
|
||||||
@ -257,8 +263,8 @@ udp_client_thread(struct stream *sp)
|
|||||||
adjustns = 0;
|
adjustns = 0;
|
||||||
printf("%lld adj %lld delay\n", adjustns, delayns);
|
printf("%lld adj %lld delay\n", adjustns, delayns);
|
||||||
while(!done) {
|
while(!done) {
|
||||||
send(sp->sock, buf, settings.bufsize, 0);
|
send(sp->sock, buf, sp->settings->bufsize, 0);
|
||||||
sp->bytes_out += settings.bufsize;
|
sp->bytes_out += sp->settings->bufsize;
|
||||||
|
|
||||||
if(delayns > 0)
|
if(delayns > 0)
|
||||||
delay(delayns);
|
delay(delayns);
|
||||||
@ -291,23 +297,24 @@ udp_client_thread(struct stream *sp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
udp_server_thread(struct stream *sp)
|
udp_server_thread(struct iperf_stream *sp)
|
||||||
{
|
{
|
||||||
char *buf;
|
char *buf, ubuf[UNIT_LEN];
|
||||||
ssize_t sz;
|
ssize_t sz;
|
||||||
|
|
||||||
buf = (char *) malloc(settings.bufsize);
|
buf = (char *) malloc(sp->settings->bufsize);
|
||||||
if(!buf) {
|
if(!buf) {
|
||||||
perror("malloc: unable to allocate receive buffer");
|
perror("malloc: unable to allocate receive buffer");
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
while((sz = recv(sp->sock, buf, settings.bufsize, 0)) > 0) {
|
while((sz = recv(sp->sock, buf, sp->settings->bufsize, 0)) > 0) {
|
||||||
sp->bytes_in += sz;
|
sp->bytes_in += sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
close(sp->sock);
|
close(sp->sock);
|
||||||
printf("%llu bytes received %g\n", sp->bytes_in, (sp->bytes_in * 8.0)/(settings.duration*1000.0*1000.0));
|
unit_snprintf(ubuf, UNIT_LEN, (double) sp->bytes_in / sp->settings->duration, 'a');
|
||||||
|
printf("%llu bytes received %s/sec\n", sp->bytes_in, ubuf);
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -322,12 +329,12 @@ tcp_report(int final)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
tcp_client_thread(struct stream *sp)
|
tcp_client_thread(struct iperf_stream *sp)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
char *buf;
|
char *buf;
|
||||||
|
|
||||||
buf = (char *) malloc(settings.bufsize);
|
buf = (char *) malloc(sp->settings->bufsize);
|
||||||
if(!buf) {
|
if(!buf) {
|
||||||
perror("malloc: unable to allocate transmit buffer");
|
perror("malloc: unable to allocate transmit buffer");
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
@ -335,12 +342,12 @@ tcp_client_thread(struct stream *sp)
|
|||||||
|
|
||||||
printf("window: %d\n", getsock_tcp_windowsize(sp->sock, SO_SNDBUF));
|
printf("window: %d\n", getsock_tcp_windowsize(sp->sock, SO_SNDBUF));
|
||||||
|
|
||||||
for(i=0; i < settings.bufsize; i++)
|
for(i=0; i < sp->settings->bufsize; i++)
|
||||||
buf[i] = i % 37;
|
buf[i] = i % 37;
|
||||||
|
|
||||||
while(!done) {
|
while(!done) {
|
||||||
send(sp->sock, buf, settings.bufsize, 0);
|
send(sp->sock, buf, sp->settings->bufsize, 0);
|
||||||
sp->bytes_out += settings.bufsize;
|
sp->bytes_out += sp->settings->bufsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* a 0 byte packet is the server's cue that we're done */
|
/* a 0 byte packet is the server's cue that we're done */
|
||||||
@ -355,12 +362,12 @@ tcp_client_thread(struct stream *sp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
tcp_server_thread(struct stream *sp)
|
tcp_server_thread(struct iperf_stream *sp)
|
||||||
{
|
{
|
||||||
char *buf;
|
char *buf, ubuf[UNIT_LEN];
|
||||||
ssize_t sz;
|
ssize_t sz;
|
||||||
|
|
||||||
buf = (char *) malloc(settings.bufsize);
|
buf = (char *) malloc(sp->settings->bufsize);
|
||||||
if(!buf) {
|
if(!buf) {
|
||||||
perror("malloc: unable to allocate receive buffer");
|
perror("malloc: unable to allocate receive buffer");
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
@ -368,44 +375,45 @@ tcp_server_thread(struct stream *sp)
|
|||||||
|
|
||||||
printf("window: %d\n", getsock_tcp_windowsize(sp->sock, SO_RCVBUF));
|
printf("window: %d\n", getsock_tcp_windowsize(sp->sock, SO_RCVBUF));
|
||||||
|
|
||||||
while( (sz = recv(sp->sock, buf, settings.bufsize, 0)) > 0) {
|
while( (sz = recv(sp->sock, buf, sp->settings->bufsize, 0)) > 0) {
|
||||||
sp->bytes_in += sz;
|
sp->bytes_in += sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
close(sp->sock);
|
close(sp->sock);
|
||||||
printf("%llu bytes received %g\n", sp->bytes_in, (sp->bytes_in * 8.0)/(settings.duration*1000.0*1000.0));
|
unit_snprintf(ubuf, UNIT_LEN, (double) sp->bytes_in / sp->settings->duration, 'a');
|
||||||
|
printf("%llu bytes received %s/sec\n", sp->bytes_in, ubuf);
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
client(void)
|
client(struct iperf_settings *settings)
|
||||||
{
|
{
|
||||||
int s, i;
|
int s, i;
|
||||||
struct stream *sp;
|
struct iperf_stream *sp;
|
||||||
struct timer *timer;
|
struct timer *timer;
|
||||||
|
|
||||||
for(i = 0; i < settings.threads; i++) {
|
for(i = 0; i < settings->threads; i++) {
|
||||||
s = netdial(settings.proto, settings.client, settings.port);
|
s = netdial(settings->proto, settings->client, settings->port);
|
||||||
if(s < 0) {
|
if(s < 0) {
|
||||||
fprintf(stderr, "netdial failed\n");
|
fprintf(stderr, "netdial failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_tcp_windowsize(s, settings.window, SO_SNDBUF);
|
set_tcp_windowsize(s, settings->window, SO_SNDBUF);
|
||||||
|
|
||||||
if(s < 0)
|
if(s < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
sp = new_stream(s);
|
sp = new_stream(s, settings);
|
||||||
add_stream(sp);
|
add_stream(sp);
|
||||||
connect_msg(sp);
|
connect_msg(sp);
|
||||||
pthread_create(&sp->thread, NULL, sp->client, (void *) sp);
|
pthread_create(&sp->thread, NULL, sp->client, (void *) sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
timer = new_timer(settings.duration, 0);
|
timer = new_timer(settings->duration, 0);
|
||||||
|
|
||||||
while(!timer->expired(timer))
|
while(!timer->expired(timer))
|
||||||
sleep(settings.duration);
|
sleep(settings->duration);
|
||||||
|
|
||||||
done = 1;
|
done = 1;
|
||||||
|
|
||||||
@ -420,44 +428,44 @@ client(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
server()
|
server(struct iperf_settings *settings)
|
||||||
{
|
{
|
||||||
int s, cs, sz;
|
int s, cs, sz;
|
||||||
struct stream *sp;
|
struct iperf_stream *sp;
|
||||||
struct sockaddr_in sa_peer;
|
struct sockaddr_in sa_peer;
|
||||||
socklen_t len;
|
socklen_t len;
|
||||||
char buf[settings.bufsize], ubuf[11];
|
char buf[settings->bufsize], ubuf[UNIT_LEN];
|
||||||
|
|
||||||
s = netannounce(settings.proto, NULL, settings.port);
|
s = netannounce(settings->proto, NULL, settings->port);
|
||||||
if(s < 0)
|
if(s < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if(set_tcp_windowsize(s, settings.window, SO_RCVBUF) < 0) {
|
if(set_tcp_windowsize(s, settings->window, SO_RCVBUF) < 0) {
|
||||||
perror("unable to set window");
|
perror("unable to set window");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("-----------------------------------------------------------\n");
|
printf("-----------------------------------------------------------\n");
|
||||||
printf("Server listening on %d\n", settings.port);
|
printf("Server listening on %d\n", settings->port);
|
||||||
int x;
|
int x;
|
||||||
if((x = getsock_tcp_windowsize(s, SO_RCVBUF)) < 0)
|
if((x = getsock_tcp_windowsize(s, SO_RCVBUF)) < 0)
|
||||||
perror("SO_RCVBUF");
|
perror("SO_RCVBUF");
|
||||||
|
|
||||||
unit_snprintf(ubuf, 11, (double) x, 'A');
|
unit_snprintf(ubuf, UNIT_LEN, (double) x, 'A');
|
||||||
printf("%s: %s\n",
|
printf("%s: %s\n",
|
||||||
settings.proto == Ptcp ? "TCP window size" : "UDP buffer size", ubuf);
|
settings->proto == Ptcp ? "TCP window size" : "UDP buffer size", ubuf);
|
||||||
printf("-----------------------------------------------------------\n");
|
printf("-----------------------------------------------------------\n");
|
||||||
|
|
||||||
len = sizeof sa_peer;
|
len = sizeof sa_peer;
|
||||||
while(1) {
|
while(1) {
|
||||||
if (Ptcp == settings.proto) {
|
if (Ptcp == settings->proto) {
|
||||||
if( (cs = accept(s, (struct sockaddr *) &sa_peer, &len)) < 0) {
|
if( (cs = accept(s, (struct sockaddr *) &sa_peer, &len)) < 0) {
|
||||||
perror("accept");
|
perror("accept");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
sp = new_stream(cs);
|
sp = new_stream(cs, settings);
|
||||||
} else if (Pudp == settings.proto) {
|
} else if (Pudp == settings->proto) {
|
||||||
sz = recvfrom(s, buf, settings.bufsize, 0, (struct sockaddr *) &sa_peer, &len);
|
sz = recvfrom(s, buf, settings->bufsize, 0, (struct sockaddr *) &sa_peer, &len);
|
||||||
if(!sz)
|
if(!sz)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -466,10 +474,10 @@ server()
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sp = new_stream(s);
|
sp = new_stream(s, settings);
|
||||||
sp->bytes_in += sz;
|
sp->bytes_in += sz;
|
||||||
|
|
||||||
s = netannounce(settings.proto, NULL, settings.port);
|
s = netannounce(settings->proto, NULL, settings->port);
|
||||||
if(s < 0) {
|
if(s < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -487,6 +495,9 @@ main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
char ch;
|
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 )
|
while( (ch = getopt_long(argc, argv, "c:p:st:uP:b:l:w:", longopts, NULL)) != -1 )
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
@ -526,10 +537,10 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
switch (settings.mode) {
|
switch (settings.mode) {
|
||||||
case Mclient:
|
case Mclient:
|
||||||
rc = client();
|
rc = client(&settings);
|
||||||
break;
|
break;
|
||||||
case Mserver:
|
case Mserver:
|
||||||
rc = server();
|
rc = server(&settings);
|
||||||
break;
|
break;
|
||||||
case Mundef:
|
case Mundef:
|
||||||
/* FALLTHRU */
|
/* FALLTHRU */
|
||||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user