Add -J flag to produce JSON output instead.
Этот коммит содержится в:
родитель
17666b94d9
Коммит
9bfb54c0cc
14
src/iperf.h
14
src/iperf.h
@ -17,6 +17,7 @@
|
|||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
|
#include "cjson.h"
|
||||||
|
|
||||||
typedef uint64_t iperf_size_t;
|
typedef uint64_t iperf_size_t;
|
||||||
|
|
||||||
@ -64,8 +65,12 @@ struct iperf_settings
|
|||||||
char unit_format; /* -f */
|
char unit_format; /* -f */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct iperf_test;
|
||||||
|
|
||||||
struct iperf_stream
|
struct iperf_stream
|
||||||
{
|
{
|
||||||
|
struct iperf_test* test;
|
||||||
|
|
||||||
/* configurable members */
|
/* configurable members */
|
||||||
int local_port;
|
int local_port;
|
||||||
int remote_port;
|
int remote_port;
|
||||||
@ -104,8 +109,6 @@ struct iperf_stream
|
|||||||
void *data;
|
void *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct iperf_test;
|
|
||||||
|
|
||||||
struct protocol {
|
struct protocol {
|
||||||
int id;
|
int id;
|
||||||
char *name;
|
char *name;
|
||||||
@ -140,6 +143,7 @@ struct iperf_test
|
|||||||
int reverse; /* -R option */
|
int reverse; /* -R option */
|
||||||
int v6domain; /* -6 option */
|
int v6domain; /* -6 option */
|
||||||
int verbose; /* -V option - verbose mode */
|
int verbose; /* -V option - verbose mode */
|
||||||
|
int json_output; /* -J option - JSON output */
|
||||||
|
|
||||||
/* Select related parameters */
|
/* Select related parameters */
|
||||||
int max_fd;
|
int max_fd;
|
||||||
@ -174,6 +178,12 @@ struct iperf_test
|
|||||||
void (*on_test_start)(struct iperf_test *);
|
void (*on_test_start)(struct iperf_test *);
|
||||||
void (*on_connect)(struct iperf_test *);
|
void (*on_connect)(struct iperf_test *);
|
||||||
void (*on_test_finish)(struct iperf_test *);
|
void (*on_test_finish)(struct iperf_test *);
|
||||||
|
|
||||||
|
/* cJSON handles for use when in -J mode */\
|
||||||
|
cJSON *json_top;
|
||||||
|
cJSON *json_start;
|
||||||
|
cJSON *json_intervals;
|
||||||
|
cJSON *json_end;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* default settings */
|
/* default settings */
|
||||||
|
@ -33,6 +33,9 @@ pause \fIn\fR seconds between periodic bandwidth reports
|
|||||||
.BR -V ", " --verbose " "
|
.BR -V ", " --verbose " "
|
||||||
give more detailed output
|
give more detailed output
|
||||||
.TP
|
.TP
|
||||||
|
.BR -J ", " --json " "
|
||||||
|
output in JSON format
|
||||||
|
.TP
|
||||||
.BR -d ", " --debug " "
|
.BR -d ", " --debug " "
|
||||||
debug mode
|
debug mode
|
||||||
.TP
|
.TP
|
||||||
|
499
src/iperf_api.c
499
src/iperf_api.c
@ -14,6 +14,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
@ -51,6 +52,7 @@ static int get_parameters(struct iperf_test *test);
|
|||||||
static int send_results(struct iperf_test *test);
|
static int send_results(struct iperf_test *test);
|
||||||
static int get_results(struct iperf_test *test);
|
static int get_results(struct iperf_test *test);
|
||||||
static int JSON_write(int fd, cJSON *json);
|
static int JSON_write(int fd, cJSON *json);
|
||||||
|
static void print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON *json_interval_streams);
|
||||||
static cJSON *JSON_read(int fd);
|
static cJSON *JSON_read(int fd);
|
||||||
|
|
||||||
|
|
||||||
@ -79,73 +81,73 @@ void warning(char *str)
|
|||||||
/************** Getter routines for some fields inside iperf_test *************/
|
/************** Getter routines for some fields inside iperf_test *************/
|
||||||
|
|
||||||
int
|
int
|
||||||
iperf_get_control_socket( struct iperf_test* ipt )
|
iperf_get_control_socket(struct iperf_test *ipt)
|
||||||
{
|
{
|
||||||
return ipt->ctrl_sck;
|
return ipt->ctrl_sck;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
iperf_get_test_duration( struct iperf_test* ipt )
|
iperf_get_test_duration(struct iperf_test *ipt)
|
||||||
{
|
{
|
||||||
return ipt->duration;
|
return ipt->duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
iperf_get_test_rate( struct iperf_test* ipt )
|
iperf_get_test_rate(struct iperf_test *ipt)
|
||||||
{
|
{
|
||||||
return ipt->settings->rate;
|
return ipt->settings->rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
char
|
char
|
||||||
iperf_get_test_role( struct iperf_test* ipt )
|
iperf_get_test_role(struct iperf_test *ipt)
|
||||||
{
|
{
|
||||||
return ipt->role;
|
return ipt->role;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
iperf_get_test_blksize( struct iperf_test* ipt )
|
iperf_get_test_blksize(struct iperf_test *ipt)
|
||||||
{
|
{
|
||||||
return ipt->settings->blksize;
|
return ipt->settings->blksize;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
iperf_get_test_socket_bufsize( struct iperf_test* ipt )
|
iperf_get_test_socket_bufsize(struct iperf_test *ipt)
|
||||||
{
|
{
|
||||||
return ipt->settings->socket_bufsize;
|
return ipt->settings->socket_bufsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
double
|
double
|
||||||
iperf_get_test_reporter_interval( struct iperf_test* ipt )
|
iperf_get_test_reporter_interval(struct iperf_test *ipt)
|
||||||
{
|
{
|
||||||
return ipt->reporter_interval;
|
return ipt->reporter_interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
double
|
double
|
||||||
iperf_get_test_stats_interval( struct iperf_test* ipt )
|
iperf_get_test_stats_interval(struct iperf_test *ipt)
|
||||||
{
|
{
|
||||||
return ipt->stats_interval;
|
return ipt->stats_interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
iperf_get_test_num_streams( struct iperf_test* ipt )
|
iperf_get_test_num_streams(struct iperf_test *ipt)
|
||||||
{
|
{
|
||||||
return ipt->num_streams;
|
return ipt->num_streams;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
iperf_get_test_server_port( struct iperf_test* ipt )
|
iperf_get_test_server_port(struct iperf_test *ipt)
|
||||||
{
|
{
|
||||||
return ipt->server_port;
|
return ipt->server_port;
|
||||||
}
|
}
|
||||||
|
|
||||||
char*
|
char*
|
||||||
iperf_get_test_server_hostname( struct iperf_test* ipt )
|
iperf_get_test_server_hostname(struct iperf_test *ipt)
|
||||||
{
|
{
|
||||||
return ipt->server_hostname;
|
return ipt->server_hostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
iperf_get_test_protocol_id( struct iperf_test* ipt )
|
iperf_get_test_protocol_id(struct iperf_test *ipt)
|
||||||
{
|
{
|
||||||
return ipt->protocol->id;
|
return ipt->protocol->id;
|
||||||
}
|
}
|
||||||
@ -153,73 +155,73 @@ iperf_get_test_protocol_id( struct iperf_test* ipt )
|
|||||||
/************** Setter routines for some fields inside iperf_test *************/
|
/************** Setter routines for some fields inside iperf_test *************/
|
||||||
|
|
||||||
void
|
void
|
||||||
iperf_set_control_socket( struct iperf_test* ipt, int ctrl_sck )
|
iperf_set_control_socket(struct iperf_test *ipt, int ctrl_sck)
|
||||||
{
|
{
|
||||||
ipt->ctrl_sck = ctrl_sck;
|
ipt->ctrl_sck = ctrl_sck;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
iperf_set_test_duration( struct iperf_test* ipt, int duration )
|
iperf_set_test_duration(struct iperf_test *ipt, int duration)
|
||||||
{
|
{
|
||||||
ipt->duration = duration;
|
ipt->duration = duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
iperf_set_test_reporter_interval( struct iperf_test* ipt, double reporter_interval )
|
iperf_set_test_reporter_interval(struct iperf_test *ipt, double reporter_interval)
|
||||||
{
|
{
|
||||||
ipt->reporter_interval = reporter_interval;
|
ipt->reporter_interval = reporter_interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
iperf_set_test_stats_interval( struct iperf_test* ipt, double stats_interval )
|
iperf_set_test_stats_interval(struct iperf_test *ipt, double stats_interval)
|
||||||
{
|
{
|
||||||
ipt->stats_interval = stats_interval;
|
ipt->stats_interval = stats_interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
iperf_set_test_state( struct iperf_test* ipt, char state )
|
iperf_set_test_state(struct iperf_test *ipt, char state)
|
||||||
{
|
{
|
||||||
ipt->state = state;
|
ipt->state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
iperf_set_test_blksize( struct iperf_test* ipt, int blksize )
|
iperf_set_test_blksize(struct iperf_test *ipt, int blksize)
|
||||||
{
|
{
|
||||||
ipt->settings->blksize = blksize;
|
ipt->settings->blksize = blksize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
iperf_set_test_rate( struct iperf_test* ipt, uint64_t rate )
|
iperf_set_test_rate(struct iperf_test *ipt, uint64_t rate)
|
||||||
{
|
{
|
||||||
ipt->settings->rate = rate;
|
ipt->settings->rate = rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
iperf_set_test_server_port( struct iperf_test* ipt, int server_port )
|
iperf_set_test_server_port(struct iperf_test *ipt, int server_port)
|
||||||
{
|
{
|
||||||
ipt->server_port = server_port;
|
ipt->server_port = server_port;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
iperf_set_test_socket_bufsize( struct iperf_test* ipt, int socket_bufsize )
|
iperf_set_test_socket_bufsize(struct iperf_test *ipt, int socket_bufsize)
|
||||||
{
|
{
|
||||||
ipt->settings->socket_bufsize = socket_bufsize;
|
ipt->settings->socket_bufsize = socket_bufsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
iperf_set_test_num_streams( struct iperf_test* ipt, int num_streams )
|
iperf_set_test_num_streams(struct iperf_test *ipt, int num_streams)
|
||||||
{
|
{
|
||||||
ipt->num_streams = num_streams;
|
ipt->num_streams = num_streams;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
iperf_set_test_role( struct iperf_test* ipt, char role )
|
iperf_set_test_role(struct iperf_test *ipt, char role)
|
||||||
{
|
{
|
||||||
ipt->role = role;
|
ipt->role = role;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
iperf_set_test_server_hostname( struct iperf_test* ipt, char* server_hostname )
|
iperf_set_test_server_hostname(struct iperf_test *ipt, char *server_hostname)
|
||||||
{
|
{
|
||||||
ipt->server_hostname = server_hostname;
|
ipt->server_hostname = server_hostname;
|
||||||
}
|
}
|
||||||
@ -271,14 +273,18 @@ iperf_on_new_stream(struct iperf_stream *sp)
|
|||||||
void
|
void
|
||||||
iperf_on_test_start(struct iperf_test *test)
|
iperf_on_test_start(struct iperf_test *test)
|
||||||
{
|
{
|
||||||
if (test->verbose) {
|
if (test->json_output) {
|
||||||
if (test->settings->bytes) {
|
if (test->settings->bytes)
|
||||||
printf(test_start_bytes, test->protocol->name, test->num_streams,
|
cJSON_AddItemToObject(test->json_start, "test_start", iperf_json_printf("protocol: %s num_streams: %d blksize: %d bytes: %d", test->protocol->name, (int64_t) test->num_streams, (int64_t) test->settings->blksize, (int64_t) test->settings->bytes));
|
||||||
test->settings->blksize, test->settings->bytes);
|
else
|
||||||
} else {
|
cJSON_AddItemToObject(test->json_start, "test_start", iperf_json_printf("protocol: %s num_streams: %d blksize: %d duration: %d", test->protocol->name, (int64_t) test->num_streams, (int64_t) test->settings->blksize, (int64_t) test->duration));
|
||||||
printf(test_start_time, test->protocol->name, test->num_streams,
|
} else {
|
||||||
test->settings->blksize, test->duration);
|
if (test->verbose) {
|
||||||
}
|
if (test->settings->bytes)
|
||||||
|
printf(test_start_bytes, test->protocol->name, test->num_streams, test->settings->blksize, test->settings->bytes);
|
||||||
|
else
|
||||||
|
printf(test_start_time, test->protocol->name, test->num_streams, test->settings->blksize, test->duration);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,31 +292,55 @@ void
|
|||||||
iperf_on_connect(struct iperf_test *test)
|
iperf_on_connect(struct iperf_test *test)
|
||||||
{
|
{
|
||||||
char ipr[INET6_ADDRSTRLEN];
|
char ipr[INET6_ADDRSTRLEN];
|
||||||
struct sockaddr_storage temp;
|
int port;
|
||||||
|
struct sockaddr_storage sa;
|
||||||
|
struct sockaddr_in *sa_inP;
|
||||||
|
struct sockaddr_in6 *sa_in6P;
|
||||||
socklen_t len;
|
socklen_t len;
|
||||||
int domain, opt;
|
int domain, opt;
|
||||||
|
|
||||||
if (test->role == 'c') {
|
if (test->role == 'c') {
|
||||||
printf("Connecting to host %s, port %d\n", test->server_hostname,
|
if (test->json_output)
|
||||||
test->server_port);
|
cJSON_AddItemToObject(test->json_start, "connecting_to", iperf_json_printf("host: %s port: %d", test->server_hostname, (int64_t) test->server_port));
|
||||||
|
else
|
||||||
|
printf("Connecting to host %s, port %d\n", test->server_hostname, test->server_port);
|
||||||
} else {
|
} else {
|
||||||
domain = test->settings->domain;
|
domain = test->settings->domain;
|
||||||
len = sizeof(temp);
|
len = sizeof(sa);
|
||||||
getpeername(test->ctrl_sck, (struct sockaddr *) &temp, &len);
|
getpeername(test->ctrl_sck, (struct sockaddr *) &sa, &len);
|
||||||
if (domain == AF_INET) {
|
if (domain == AF_INET) {
|
||||||
inet_ntop(domain, &((struct sockaddr_in *) &temp)->sin_addr, ipr, sizeof(ipr));
|
sa_inP = (struct sockaddr_in *) &sa;
|
||||||
printf("Accepted connection from %s, port %d\n", ipr, ntohs(((struct sockaddr_in *) &temp)->sin_port));
|
inet_ntop(domain, &sa_inP->sin_addr, ipr, sizeof(ipr));
|
||||||
|
port = ntohs(sa_inP->sin_port);
|
||||||
|
if (test->json_output)
|
||||||
|
cJSON_AddItemToObject(test->json_start, "accepted_connection", iperf_json_printf("host: %s port: %d", ipr, (int64_t) port));
|
||||||
|
else
|
||||||
|
printf("Accepted connection from %s, port %d\n", ipr, port);
|
||||||
} else {
|
} else {
|
||||||
inet_ntop(domain, &((struct sockaddr_in6 *) &temp)->sin6_addr, ipr, sizeof(ipr));
|
sa_in6P = (struct sockaddr_in6 *) &sa;
|
||||||
printf("Accepted connection from %s, port %d\n", ipr, ntohs(((struct sockaddr_in6 *) &temp)->sin6_port));
|
inet_ntop(domain, &sa_in6P->sin6_addr, ipr, sizeof(ipr));
|
||||||
|
port = ntohs(sa_in6P->sin6_port);
|
||||||
|
if (test->json_output)
|
||||||
|
cJSON_AddItemToObject(test->json_start, "accepted_connection", iperf_json_printf("host: %s port: %d", ipr, (int64_t) port));
|
||||||
|
else
|
||||||
|
printf("Accepted connection from %s, port %d\n", ipr, port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (test->verbose) {
|
if (test->json_output) {
|
||||||
|
cJSON_AddStringToObject(test->json_start, "cookie", test->cookie);
|
||||||
|
if (test->protocol->id == SOCK_STREAM)
|
||||||
|
cJSON_AddIntToObject(test->json_start, "tcp_mss", test->settings->mss);
|
||||||
|
else {
|
||||||
|
len = sizeof(opt);
|
||||||
|
getsockopt(test->ctrl_sck, IPPROTO_TCP, TCP_MAXSEG, &opt, &len);
|
||||||
|
cJSON_AddIntToObject(test->json_start, "tcp_mss_default", opt);
|
||||||
|
}
|
||||||
|
} else if (test->verbose) {
|
||||||
printf(" Cookie: %s\n", test->cookie);
|
printf(" Cookie: %s\n", test->cookie);
|
||||||
if (test->protocol->id == SOCK_STREAM) {
|
if (test->protocol->id == SOCK_STREAM) {
|
||||||
if (test->settings->mss) {
|
if (test->settings->mss)
|
||||||
printf(" TCP MSS: %d\n", test->settings->mss);
|
printf(" TCP MSS: %d\n", test->settings->mss);
|
||||||
} else {
|
else {
|
||||||
len = sizeof(opt);
|
len = sizeof(opt);
|
||||||
getsockopt(test->ctrl_sck, IPPROTO_TCP, TCP_MAXSEG, &opt, &len);
|
getsockopt(test->ctrl_sck, IPPROTO_TCP, TCP_MAXSEG, &opt, &len);
|
||||||
printf(" TCP MSS: %d (default)\n", opt);
|
printf(" TCP MSS: %d (default)\n", opt);
|
||||||
@ -338,6 +368,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
|
|||||||
{"interval", required_argument, NULL, 'i'},
|
{"interval", required_argument, NULL, 'i'},
|
||||||
{"daemon", no_argument, NULL, 'D'},
|
{"daemon", no_argument, NULL, 'D'},
|
||||||
{"verbose", no_argument, NULL, 'V'},
|
{"verbose", no_argument, NULL, 'V'},
|
||||||
|
{"json", no_argument, NULL, 'J'},
|
||||||
{"debug", no_argument, NULL, 'd'},
|
{"debug", no_argument, NULL, 'd'},
|
||||||
{"version", no_argument, NULL, 'v'},
|
{"version", no_argument, NULL, 'v'},
|
||||||
{"server", no_argument, NULL, 's'},
|
{"server", no_argument, NULL, 's'},
|
||||||
@ -370,7 +401,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
|
|||||||
int blksize;
|
int blksize;
|
||||||
|
|
||||||
blksize = 0;
|
blksize = 0;
|
||||||
while ((ch = getopt_long(argc, argv, "p:f:i:DVdvsc:ub:t:n:l:P:Rw:B:M:N6S:h", longopts, NULL)) != -1) {
|
while ((ch = getopt_long(argc, argv, "p:f:i:DVJdvsc:ub:t:n:l:P:Rw:B:M:N6S:h", longopts, NULL)) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'p':
|
case 'p':
|
||||||
test->server_port = atoi(optarg);
|
test->server_port = atoi(optarg);
|
||||||
@ -398,6 +429,9 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
|
|||||||
case 'V':
|
case 'V':
|
||||||
test->verbose = 1;
|
test->verbose = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'J':
|
||||||
|
test->json_output = 1;
|
||||||
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
test->debug = 1;
|
test->debug = 1;
|
||||||
break;
|
break;
|
||||||
@ -555,16 +589,12 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
|
|||||||
i_errno = IENOROLE;
|
i_errno = IENOROLE;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (test->verbose) {
|
|
||||||
fputs(version, stdout);
|
|
||||||
system("uname -a");
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
all_data_sent(struct iperf_test * test)
|
all_data_sent(struct iperf_test *test)
|
||||||
{
|
{
|
||||||
if (test->settings->bytes > 0) {
|
if (test->settings->bytes > 0) {
|
||||||
if (test->bytes_sent >= (test->num_streams * test->settings->bytes)) {
|
if (test->bytes_sent >= (test->num_streams * test->settings->bytes)) {
|
||||||
@ -616,7 +646,7 @@ iperf_recv(struct iperf_test *test, fd_set *read_setP)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_timer_proc(TimerClientData client_data, struct timeval* nowP)
|
test_timer_proc(TimerClientData client_data, struct timeval *nowP)
|
||||||
{
|
{
|
||||||
struct iperf_test *test = client_data.p;
|
struct iperf_test *test = client_data.p;
|
||||||
|
|
||||||
@ -625,7 +655,7 @@ test_timer_proc(TimerClientData client_data, struct timeval* nowP)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
stats_timer_proc(TimerClientData client_data, struct timeval* nowP)
|
stats_timer_proc(TimerClientData client_data, struct timeval *nowP)
|
||||||
{
|
{
|
||||||
struct iperf_test *test = client_data.p;
|
struct iperf_test *test = client_data.p;
|
||||||
|
|
||||||
@ -635,7 +665,7 @@ stats_timer_proc(TimerClientData client_data, struct timeval* nowP)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
reporter_timer_proc(TimerClientData client_data, struct timeval* nowP)
|
reporter_timer_proc(TimerClientData client_data, struct timeval *nowP)
|
||||||
{
|
{
|
||||||
struct iperf_test *test = client_data.p;
|
struct iperf_test *test = client_data.p;
|
||||||
|
|
||||||
@ -698,7 +728,7 @@ iperf_init_test(struct iperf_test *test)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
iperf_exchange_parameters(struct iperf_test * test)
|
iperf_exchange_parameters(struct iperf_test *test)
|
||||||
{
|
{
|
||||||
int s, msg;
|
int s, msg;
|
||||||
char state;
|
char state;
|
||||||
@ -1083,8 +1113,10 @@ connect_msg(struct iperf_stream *sp)
|
|||||||
rport = ntohs(((struct sockaddr_in6 *) &sp->remote_addr)->sin6_port);
|
rport = ntohs(((struct sockaddr_in6 *) &sp->remote_addr)->sin6_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("[%3d] local %s port %d connected to %s port %d\n",
|
if (sp->test->json_output)
|
||||||
sp->socket, ipl, lport, ipr, rport);
|
cJSON_AddItemToObject(sp->test->json_start, "connected", iperf_json_printf("socket: %d local_host: %s local_port: %d remote_host: %s remote_port: %d", (int64_t) sp->socket, ipl, (int64_t) lport, ipr, (int64_t) rport));
|
||||||
|
else
|
||||||
|
printf("[%3d] local %s port %d connected to %s port %d\n", sp->socket, ipl, lport, ipr, rport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1111,7 +1143,7 @@ iperf_new_test()
|
|||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
int
|
int
|
||||||
iperf_defaults(struct iperf_test * testp)
|
iperf_defaults(struct iperf_test *testp)
|
||||||
{
|
{
|
||||||
testp->duration = DURATION;
|
testp->duration = DURATION;
|
||||||
testp->server_port = PORT;
|
testp->server_port = PORT;
|
||||||
@ -1181,7 +1213,7 @@ iperf_defaults(struct iperf_test * testp)
|
|||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
void
|
void
|
||||||
iperf_free_test(struct iperf_test * test)
|
iperf_free_test(struct iperf_test *test)
|
||||||
{
|
{
|
||||||
struct protocol *prot;
|
struct protocol *prot;
|
||||||
struct iperf_stream *sp;
|
struct iperf_stream *sp;
|
||||||
@ -1280,7 +1312,7 @@ iperf_reset_test(struct iperf_test *test)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
iperf_stats_callback(struct iperf_test * test)
|
iperf_stats_callback(struct iperf_test *test)
|
||||||
{
|
{
|
||||||
struct iperf_stream *sp;
|
struct iperf_stream *sp;
|
||||||
struct iperf_stream_result *rp = NULL;
|
struct iperf_stream_result *rp = NULL;
|
||||||
@ -1330,15 +1362,32 @@ iperf_print_intermediate(struct iperf_test *test)
|
|||||||
struct iperf_stream *sp = NULL;
|
struct iperf_stream *sp = NULL;
|
||||||
struct iperf_interval_results *irp;
|
struct iperf_interval_results *irp;
|
||||||
iperf_size_t bytes = 0;
|
iperf_size_t bytes = 0;
|
||||||
|
double bandwidth;
|
||||||
long retransmits = 0;
|
long retransmits = 0;
|
||||||
double start_time, end_time;
|
double start_time, end_time;
|
||||||
|
cJSON *json_interval;
|
||||||
|
cJSON *json_interval_streams;
|
||||||
|
|
||||||
|
if (test->json_output) {
|
||||||
|
json_interval = cJSON_CreateObject();
|
||||||
|
if (json_interval == NULL)
|
||||||
|
return;
|
||||||
|
cJSON_AddItemToArray(test->json_intervals, json_interval);
|
||||||
|
json_interval_streams = cJSON_CreateArray();
|
||||||
|
if (json_interval_streams == NULL)
|
||||||
|
return;
|
||||||
|
cJSON_AddItemToObject(json_interval, "streams", json_interval_streams);
|
||||||
|
} else {
|
||||||
|
json_interval = NULL;
|
||||||
|
json_interval_streams = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
SLIST_FOREACH(sp, &test->streams, streams) {
|
SLIST_FOREACH(sp, &test->streams, streams) {
|
||||||
print_interval_results(test, sp);
|
print_interval_results(test, sp, json_interval_streams);
|
||||||
/* sum up all streams */
|
/* sum up all streams */
|
||||||
irp = TAILQ_LAST(&sp->result->interval_results, irlisthead);
|
irp = TAILQ_LAST(&sp->result->interval_results, irlisthead);
|
||||||
if (irp == NULL) {
|
if (irp == NULL) {
|
||||||
printf("iperf_print_intermediate Error: interval_results is NULL \n");
|
fprintf(stderr, "iperf_print_intermediate Error: interval_results is NULL\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bytes += irp->bytes_transferred;
|
bytes += irp->bytes_transferred;
|
||||||
@ -1354,16 +1403,23 @@ iperf_print_intermediate(struct iperf_test *test)
|
|||||||
sp = SLIST_FIRST(&test->streams); /* reset back to 1st stream */
|
sp = SLIST_FIRST(&test->streams); /* reset back to 1st stream */
|
||||||
irp = TAILQ_LAST(&sp->result->interval_results, irlisthead); /* use 1st stream for timing info */
|
irp = TAILQ_LAST(&sp->result->interval_results, irlisthead); /* use 1st stream for timing info */
|
||||||
|
|
||||||
unit_snprintf(ubuf, UNIT_LEN, (double) (bytes), 'A');
|
unit_snprintf(ubuf, UNIT_LEN, (double) bytes, 'A');
|
||||||
unit_snprintf(nbuf, UNIT_LEN, (double) (bytes / irp->interval_duration),
|
bandwidth = (double) bytes / (double) irp->interval_duration;
|
||||||
test->settings->unit_format);
|
unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
|
||||||
|
|
||||||
start_time = timeval_diff(&sp->result->start_time,&irp->interval_start_time);
|
start_time = timeval_diff(&sp->result->start_time,&irp->interval_start_time);
|
||||||
end_time = timeval_diff(&sp->result->start_time,&irp->interval_end_time);
|
end_time = timeval_diff(&sp->result->start_time,&irp->interval_end_time);
|
||||||
if (test->protocol->id == Ptcp && has_tcpinfo_retransmits())
|
if (test->protocol->id == Ptcp && has_tcpinfo_retransmits()) {
|
||||||
printf(report_sum_bw_retrans_format, start_time, end_time, ubuf, nbuf, retransmits);
|
if (test->json_output)
|
||||||
else
|
cJSON_AddItemToObject(json_interval, "sum", iperf_json_printf("start: %f end: %f seconds: %f bytes: %d bits_per_second: %f retransmits: %d", (double) start_time, (double) end_time, (double) irp->interval_duration, (int64_t) bytes, bandwidth * 8, (int64_t) retransmits));
|
||||||
printf(report_sum_bw_format, start_time, end_time, ubuf, nbuf);
|
else
|
||||||
|
printf(report_sum_bw_retrans_format, start_time, end_time, ubuf, nbuf, retransmits);
|
||||||
|
} else {
|
||||||
|
if (test->json_output)
|
||||||
|
cJSON_AddItemToObject(json_interval, "sum", iperf_json_printf("start: %f end: %f seconds: %f bytes: %d bits_per_second: %f", (double) start_time, (double) end_time, (double) irp->interval_duration, (int64_t) bytes, bandwidth * 8));
|
||||||
|
else
|
||||||
|
printf(report_sum_bw_format, start_time, end_time, ubuf, nbuf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1371,6 +1427,8 @@ static void
|
|||||||
iperf_print_results(struct iperf_test *test)
|
iperf_print_results(struct iperf_test *test)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
cJSON *json_summary_streams;
|
||||||
|
cJSON *json_summary_stream;
|
||||||
long retransmits = 0, total_retransmits = 0;
|
long retransmits = 0, total_retransmits = 0;
|
||||||
int total_packets = 0, lost_packets = 0;
|
int total_packets = 0, lost_packets = 0;
|
||||||
char ubuf[UNIT_LEN];
|
char ubuf[UNIT_LEN];
|
||||||
@ -1378,25 +1436,40 @@ iperf_print_results(struct iperf_test *test)
|
|||||||
struct iperf_stream *sp = NULL;
|
struct iperf_stream *sp = NULL;
|
||||||
iperf_size_t bytes_sent, total_sent = 0;
|
iperf_size_t bytes_sent, total_sent = 0;
|
||||||
iperf_size_t bytes_received, total_received = 0;
|
iperf_size_t bytes_received, total_received = 0;
|
||||||
double start_time, end_time, avg_jitter;
|
double start_time, end_time, avg_jitter, loss_percent;
|
||||||
|
double bandwidth, out_of_order_percent;
|
||||||
|
|
||||||
/* print final summary for all intervals */
|
/* print final summary for all intervals */
|
||||||
|
|
||||||
if (test->verbose)
|
if (test->json_output) {
|
||||||
printf("Test Complete. Summary Results:\n");
|
json_summary_streams = cJSON_CreateArray();
|
||||||
if (test->protocol->id == Ptcp)
|
if (json_summary_streams == NULL)
|
||||||
if (has_tcpinfo_retransmits())
|
return;
|
||||||
fputs(report_bw_retrans_header, stdout);
|
cJSON_AddItemToObject(test->json_end, "streams", json_summary_streams);
|
||||||
|
} else {
|
||||||
|
if (test->verbose)
|
||||||
|
printf("Test Complete. Summary Results:\n");
|
||||||
|
if (test->protocol->id == Ptcp)
|
||||||
|
if (has_tcpinfo_retransmits())
|
||||||
|
fputs(report_bw_retrans_header, stdout);
|
||||||
|
else
|
||||||
|
fputs(report_bw_header, stdout);
|
||||||
else
|
else
|
||||||
fputs(report_bw_header, stdout);
|
fputs(report_bw_udp_header, stdout);
|
||||||
else
|
}
|
||||||
fputs(report_bw_udp_header, stdout);
|
|
||||||
|
|
||||||
start_time = 0.;
|
start_time = 0.;
|
||||||
sp = SLIST_FIRST(&test->streams);
|
sp = SLIST_FIRST(&test->streams);
|
||||||
end_time = timeval_diff(&sp->result->start_time, &sp->result->end_time);
|
end_time = timeval_diff(&sp->result->start_time, &sp->result->end_time);
|
||||||
avg_jitter = 0;
|
avg_jitter = 0;
|
||||||
SLIST_FOREACH(sp, &test->streams, streams) {
|
SLIST_FOREACH(sp, &test->streams, streams) {
|
||||||
|
if (test->json_output) {
|
||||||
|
json_summary_stream = cJSON_CreateObject();
|
||||||
|
if (json_summary_stream == NULL)
|
||||||
|
return;
|
||||||
|
cJSON_AddItemToArray(json_summary_streams, json_summary_stream);
|
||||||
|
}
|
||||||
|
|
||||||
bytes_sent = sp->result->bytes_sent;
|
bytes_sent = sp->result->bytes_sent;
|
||||||
bytes_received = sp->result->bytes_received;
|
bytes_received = sp->result->bytes_received;
|
||||||
total_sent += bytes_sent;
|
total_sent += bytes_sent;
|
||||||
@ -1414,56 +1487,91 @@ iperf_print_results(struct iperf_test *test)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (bytes_sent > 0) {
|
if (bytes_sent > 0) {
|
||||||
unit_snprintf(ubuf, UNIT_LEN, (double) (bytes_sent), 'A');
|
unit_snprintf(ubuf, UNIT_LEN, (double) bytes_sent, 'A');
|
||||||
unit_snprintf(nbuf, UNIT_LEN, (double) (bytes_sent / end_time), test->settings->unit_format);
|
bandwidth = (double) bytes_sent / (double) end_time;
|
||||||
|
unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
|
||||||
if (test->protocol->id == Ptcp) {
|
if (test->protocol->id == Ptcp) {
|
||||||
fputs(" Sent\n", stdout);
|
if (!test->json_output)
|
||||||
if (has_tcpinfo_retransmits())
|
fputs(" Sent\n", stdout);
|
||||||
printf(report_bw_retrans_format, sp->socket, start_time, end_time, ubuf, nbuf, retransmits);
|
if (has_tcpinfo_retransmits()) {
|
||||||
else
|
if (test->json_output)
|
||||||
printf(report_bw_format, sp->socket, start_time, end_time, ubuf, nbuf);
|
cJSON_AddItemToObject(json_summary_stream, "sent", iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f retransmits: %d", (int64_t) sp->socket, (double) start_time, (double) end_time, (double) end_time, (int64_t) bytes_sent, bandwidth * 8, (int64_t) retransmits));
|
||||||
|
else
|
||||||
|
printf(report_bw_retrans_format, sp->socket, start_time, end_time, ubuf, nbuf, retransmits);
|
||||||
|
} else {
|
||||||
|
if (test->json_output)
|
||||||
|
cJSON_AddItemToObject(json_summary_stream, "sent", iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f", (int64_t) sp->socket, (double) start_time, (double) end_time, (double) end_time, (int64_t) bytes_sent, bandwidth * 8));
|
||||||
|
else
|
||||||
|
printf(report_bw_format, sp->socket, start_time, end_time, ubuf, nbuf);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
printf(report_bw_udp_format, sp->socket, start_time,
|
out_of_order_percent = 100.0 * sp->cnt_error / sp->packet_count;
|
||||||
end_time, ubuf, nbuf, sp->jitter * 1000, sp->cnt_error,
|
if (test->json_output)
|
||||||
sp->packet_count, (double) (100.0 * sp->cnt_error / sp->packet_count));
|
cJSON_AddItemToObject(json_summary_stream, "udp", iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f jitter_ms: %f outoforder: %d packets: %d percent: %f", (int64_t) sp->socket, (double) start_time, (double) end_time, (double) end_time, (int64_t) bytes_sent, bandwidth * 8, (double) sp->jitter * 1000.0, (int64_t) sp->cnt_error, (int64_t) sp->packet_count, out_of_order_percent));
|
||||||
if (test->role == 'c') {
|
else {
|
||||||
printf(report_datagrams, sp->socket, sp->packet_count);
|
printf(report_bw_udp_format, sp->socket, start_time, end_time, ubuf, nbuf, sp->jitter * 1000.0, sp->cnt_error, sp->packet_count, out_of_order_percent);
|
||||||
}
|
if (test->role == 'c')
|
||||||
if (sp->outoforder_packets > 0)
|
printf(report_datagrams, sp->socket, sp->packet_count);
|
||||||
printf(report_sum_outoforder, start_time, end_time, sp->cnt_error);
|
if (sp->outoforder_packets > 0)
|
||||||
|
printf(report_sum_outoforder, start_time, end_time, sp->cnt_error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (bytes_received > 0) {
|
if (bytes_received > 0) {
|
||||||
unit_snprintf(ubuf, UNIT_LEN, (double) bytes_received, 'A');
|
unit_snprintf(ubuf, UNIT_LEN, (double) bytes_received, 'A');
|
||||||
unit_snprintf(nbuf, UNIT_LEN, (double) (bytes_received / end_time), test->settings->unit_format);
|
bandwidth = (double) bytes_received / (double) end_time;
|
||||||
|
unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
|
||||||
if (test->protocol->id == Ptcp) {
|
if (test->protocol->id == Ptcp) {
|
||||||
printf(" Received\n");
|
if (!test->json_output)
|
||||||
printf(report_bw_format, sp->socket, start_time, end_time, ubuf, nbuf);
|
printf(" Received\n");
|
||||||
|
if (test->json_output)
|
||||||
|
cJSON_AddItemToObject(json_summary_stream, "received", iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f", (int64_t) sp->socket, (double) start_time, (double) end_time, (double) end_time, (int64_t) bytes_received, bandwidth * 8));
|
||||||
|
else
|
||||||
|
printf(report_bw_format, sp->socket, start_time, end_time, ubuf, nbuf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test->num_streams > 1) {
|
if (test->num_streams > 1) {
|
||||||
unit_snprintf(ubuf, UNIT_LEN, (double) total_sent, 'A');
|
unit_snprintf(ubuf, UNIT_LEN, (double) total_sent, 'A');
|
||||||
unit_snprintf(nbuf, UNIT_LEN, (double) total_sent / end_time, test->settings->unit_format);
|
bandwidth = (double) total_sent / (double) end_time;
|
||||||
|
unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
|
||||||
if (test->protocol->id == Ptcp) {
|
if (test->protocol->id == Ptcp) {
|
||||||
printf(" Total sent\n");
|
if (!test->json_output)
|
||||||
if (has_tcpinfo_retransmits())
|
printf(" Total sent\n");
|
||||||
printf(report_sum_bw_retrans_format, start_time, end_time, ubuf, nbuf, total_retransmits);
|
if (has_tcpinfo_retransmits()) {
|
||||||
|
if (test->json_output)
|
||||||
|
cJSON_AddItemToObject(test->json_end, "sum_sent", iperf_json_printf("start: %f end: %f seconds: %f bytes: %d bits_per_second: %f retransmits: %d", (double) start_time, (double) end_time, (double) end_time, (int64_t) total_sent, bandwidth * 8, (int64_t) total_retransmits));
|
||||||
|
else
|
||||||
|
printf(report_sum_bw_retrans_format, start_time, end_time, ubuf, nbuf, total_retransmits);
|
||||||
|
} else {
|
||||||
|
if (test->json_output)
|
||||||
|
cJSON_AddItemToObject(test->json_end, "sum_sent", iperf_json_printf("start: %f end: %f seconds: %f bytes: %d bits_per_second: %f", (double) start_time, (double) end_time, (double) end_time, (int64_t) total_sent, bandwidth * 8));
|
||||||
|
else
|
||||||
|
printf(report_sum_bw_format, start_time, end_time, ubuf, nbuf);
|
||||||
|
}
|
||||||
|
unit_snprintf(ubuf, UNIT_LEN, (double) total_received, 'A');
|
||||||
|
bandwidth = (double) total_received / (double) end_time;
|
||||||
|
unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
|
||||||
|
if (!test->json_output)
|
||||||
|
printf(" Total received\n");
|
||||||
|
if (test->json_output)
|
||||||
|
cJSON_AddItemToObject(test->json_end, "sum_received", iperf_json_printf("start: %f end: %f seconds: %f bytes: %d bits_per_second: %f", (double) start_time, (double) end_time, (double) end_time, (int64_t) total_received, bandwidth * 8));
|
||||||
else
|
else
|
||||||
printf(report_sum_bw_format, start_time, end_time, ubuf, nbuf);
|
printf(report_sum_bw_format, start_time, end_time, ubuf, nbuf);
|
||||||
unit_snprintf(ubuf, UNIT_LEN, (double) total_received, 'A');
|
|
||||||
unit_snprintf(nbuf, UNIT_LEN, (double) (total_received / end_time), test->settings->unit_format);
|
|
||||||
printf(" Total received\n");
|
|
||||||
printf(report_sum_bw_format, start_time, end_time, ubuf, nbuf);
|
|
||||||
} else {
|
} else {
|
||||||
avg_jitter /= test->num_streams;
|
avg_jitter /= test->num_streams;
|
||||||
printf(report_sum_bw_udp_format, start_time, end_time, ubuf, nbuf, avg_jitter,
|
loss_percent = 100.0 * lost_packets / total_packets;
|
||||||
lost_packets, total_packets, (double) (100.0 * lost_packets / total_packets));
|
if (test->json_output)
|
||||||
|
cJSON_AddItemToObject(test->json_end, "sum", iperf_json_printf("start: %f end: %f seconds: %f bytes: %d bits_per_second: %f jitter_ms: %f lost_packets: %d total_packets: %d loss_percent: %f", (double) start_time, (double) end_time, (double) end_time, (int64_t) total_sent, bandwidth * 8, avg_jitter, (int64_t) lost_packets, (int64_t) total_packets, loss_percent));
|
||||||
|
else
|
||||||
|
printf(report_sum_bw_udp_format, start_time, end_time, ubuf, nbuf, avg_jitter, lost_packets, total_packets, loss_percent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test->verbose) {
|
if (test->json_output)
|
||||||
|
cJSON_AddItemToObject(test->json_end, "cpu_utilization_percent", iperf_json_printf("host: %f remote: %f", (double) test->cpu_util, (double) test->remote_cpu_util));
|
||||||
|
else if (test->verbose) {
|
||||||
printf("Host CPU Utilization: %.1f%%\n", test->cpu_util);
|
printf("Host CPU Utilization: %.1f%%\n", test->cpu_util);
|
||||||
printf("Remote CPU Utilization: %.1f%%\n", test->remote_cpu_util);
|
printf("Remote CPU Utilization: %.1f%%\n", test->remote_cpu_util);
|
||||||
}
|
}
|
||||||
@ -1477,7 +1585,7 @@ iperf_print_results(struct iperf_test *test)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
iperf_reporter_callback(struct iperf_test * test)
|
iperf_reporter_callback(struct iperf_test *test)
|
||||||
{
|
{
|
||||||
switch (test->state) {
|
switch (test->state) {
|
||||||
case TEST_RUNNING:
|
case TEST_RUNNING:
|
||||||
@ -1494,50 +1602,60 @@ iperf_reporter_callback(struct iperf_test * test)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
void
|
static void
|
||||||
print_interval_results(struct iperf_test * test, struct iperf_stream * sp)
|
print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON *json_interval_streams)
|
||||||
{
|
{
|
||||||
char ubuf[UNIT_LEN];
|
char ubuf[UNIT_LEN];
|
||||||
char nbuf[UNIT_LEN];
|
char nbuf[UNIT_LEN];
|
||||||
double st = 0., et = 0.;
|
double st = 0., et = 0.;
|
||||||
struct iperf_interval_results *irp = NULL;
|
struct iperf_interval_results *irp = NULL;
|
||||||
|
double bandwidth;
|
||||||
|
|
||||||
irp = TAILQ_LAST(&sp->result->interval_results, irlisthead); /* get last entry in linked list */
|
irp = TAILQ_LAST(&sp->result->interval_results, irlisthead); /* get last entry in linked list */
|
||||||
if (irp == NULL) {
|
if (irp == NULL) {
|
||||||
printf("print_interval_results Error: interval_results is NULL \n");
|
fprintf(stderr, "print_interval_results Error: interval_results is NULL \n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* First stream? */
|
if (!test->json_output) {
|
||||||
if (sp == SLIST_FIRST(&test->streams)) {
|
/* First stream? */
|
||||||
/* It it's the first interval, print the header;
|
if (sp == SLIST_FIRST(&test->streams)) {
|
||||||
** else if there's more than one stream, print the separator;
|
/* It it's the first interval, print the header;
|
||||||
** else nothing.
|
** else if there's more than one stream, print the separator;
|
||||||
*/
|
** else nothing.
|
||||||
if (timeval_equals(&sp->result->start_time, &irp->interval_start_time))
|
*/
|
||||||
if (test->protocol->id == Ptcp && has_tcpinfo_retransmits())
|
if (timeval_equals(&sp->result->start_time, &irp->interval_start_time))
|
||||||
fputs(report_bw_retrans_header, stdout);
|
if (test->protocol->id == Ptcp && has_tcpinfo_retransmits())
|
||||||
else
|
fputs(report_bw_retrans_header, stdout);
|
||||||
fputs(report_bw_header, stdout);
|
else
|
||||||
else if (test->num_streams > 1)
|
fputs(report_bw_header, stdout);
|
||||||
fputs(report_bw_separator, stdout);
|
else if (test->num_streams > 1)
|
||||||
|
fputs(report_bw_separator, stdout);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unit_snprintf(ubuf, UNIT_LEN, (double) (irp->bytes_transferred), 'A');
|
unit_snprintf(ubuf, UNIT_LEN, (double) (irp->bytes_transferred), 'A');
|
||||||
unit_snprintf(nbuf, UNIT_LEN, (double) (irp->bytes_transferred / irp->interval_duration),
|
bandwidth = (double) irp->bytes_transferred / (double) irp->interval_duration;
|
||||||
test->settings->unit_format);
|
unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
|
||||||
|
|
||||||
st = timeval_diff(&sp->result->start_time,&irp->interval_start_time);
|
st = timeval_diff(&sp->result->start_time, &irp->interval_start_time);
|
||||||
et = timeval_diff(&sp->result->start_time,&irp->interval_end_time);
|
et = timeval_diff(&sp->result->start_time, &irp->interval_end_time);
|
||||||
|
|
||||||
if (test->protocol->id == Ptcp && has_tcpinfo_retransmits())
|
if (test->protocol->id == Ptcp && has_tcpinfo_retransmits()) {
|
||||||
printf(report_bw_retrans_format, sp->socket, st, et, ubuf, nbuf, irp->this_retrans);
|
if (test->json_output)
|
||||||
else
|
cJSON_AddItemToArray(json_interval_streams, iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f retransmits: %d", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, (int64_t) irp->this_retrans));
|
||||||
printf(report_bw_format, sp->socket, st, et, ubuf, nbuf);
|
else
|
||||||
|
printf(report_bw_retrans_format, sp->socket, st, et, ubuf, nbuf, irp->this_retrans);
|
||||||
|
} else {
|
||||||
|
if (test->json_output)
|
||||||
|
cJSON_AddItemToArray(json_interval_streams, iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8));
|
||||||
|
else
|
||||||
|
printf(report_bw_format, sp->socket, st, et, ubuf, nbuf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
void
|
void
|
||||||
iperf_free_stream(struct iperf_stream * sp)
|
iperf_free_stream(struct iperf_stream *sp)
|
||||||
{
|
{
|
||||||
struct iperf_interval_results *irp, *nirp;
|
struct iperf_interval_results *irp, *nirp;
|
||||||
|
|
||||||
@ -1568,6 +1686,7 @@ iperf_new_stream(struct iperf_test *test, int s)
|
|||||||
|
|
||||||
memset(sp, 0, sizeof(struct iperf_stream));
|
memset(sp, 0, sizeof(struct iperf_stream));
|
||||||
|
|
||||||
|
sp->test = test;
|
||||||
sp->buffer = (char *) malloc(test->settings->blksize);
|
sp->buffer = (char *) malloc(test->settings->blksize);
|
||||||
sp->result = (struct iperf_stream_result *) malloc(sizeof(struct iperf_stream_result));
|
sp->result = (struct iperf_stream_result *) malloc(sizeof(struct iperf_stream_result));
|
||||||
sp->settings = test->settings;
|
sp->settings = test->settings;
|
||||||
@ -1645,7 +1764,7 @@ iperf_init_stream(struct iperf_stream *sp, struct iperf_test *test)
|
|||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
void
|
void
|
||||||
iperf_add_stream(struct iperf_test * test, struct iperf_stream * sp)
|
iperf_add_stream(struct iperf_test *test, struct iperf_stream *sp)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct iperf_stream *n, *prev;
|
struct iperf_stream *n, *prev;
|
||||||
@ -1670,3 +1789,117 @@ sig_handler(int sig)
|
|||||||
{
|
{
|
||||||
longjmp(env, 1);
|
longjmp(env, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
iperf_json_start(struct iperf_test *test)
|
||||||
|
{
|
||||||
|
test->json_top = cJSON_CreateObject();
|
||||||
|
if (test->json_top == NULL)
|
||||||
|
return -1;
|
||||||
|
test->json_start = cJSON_CreateObject();
|
||||||
|
if (test->json_start == NULL)
|
||||||
|
return -1;
|
||||||
|
cJSON_AddItemToObject(test->json_top, "start", test->json_start);
|
||||||
|
test->json_intervals = cJSON_CreateArray();
|
||||||
|
if (test->json_intervals == NULL)
|
||||||
|
return -1;
|
||||||
|
cJSON_AddItemToObject(test->json_top, "intervals", test->json_intervals);
|
||||||
|
test->json_end = cJSON_CreateObject();
|
||||||
|
if (test->json_end == NULL)
|
||||||
|
return -1;
|
||||||
|
cJSON_AddItemToObject(test->json_top, "end", test->json_end);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
iperf_json_finish(struct iperf_test *test)
|
||||||
|
{
|
||||||
|
char *str;
|
||||||
|
|
||||||
|
str = cJSON_Print(test->json_top);
|
||||||
|
if (str == NULL)
|
||||||
|
return -1;
|
||||||
|
fputs(str, stdout);
|
||||||
|
putchar('\n');
|
||||||
|
free(str);
|
||||||
|
cJSON_Delete(test->json_top);
|
||||||
|
test->json_top = test->json_start = test->json_intervals = test->json_end = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Helper routine for building cJSON objects in a printf-like manner.
|
||||||
|
**
|
||||||
|
** Sample call:
|
||||||
|
** j = iperf_json_printf("foo: %b bar: %d bletch: %f eep: %s", b, i, f, s);
|
||||||
|
**
|
||||||
|
** The four formatting characters and the types they expect are:
|
||||||
|
** %b boolean int
|
||||||
|
** %d integer int64_t
|
||||||
|
** %f floating point double
|
||||||
|
** %s string char *
|
||||||
|
** If the values you're passing in are not these exact types, you must
|
||||||
|
** cast them, there is no automatic type coercion/widening here.
|
||||||
|
**
|
||||||
|
** The colons mark the end of field names, and blanks are ignored.
|
||||||
|
**
|
||||||
|
** This routine is not particularly robust, but it's not part of the API,
|
||||||
|
** it's just for internal iperf3 use.
|
||||||
|
**
|
||||||
|
** It currently lives in iperf_api.c, rather than iperf_util.c, because
|
||||||
|
** putting it in iperf_util.c would mean adding -lm to more executables,
|
||||||
|
** because the cJSON package uses libm/floor(). If I get around to fixing
|
||||||
|
** that, then this routine can move.
|
||||||
|
*/
|
||||||
|
cJSON*
|
||||||
|
iperf_json_printf(const char *format, ...)
|
||||||
|
{
|
||||||
|
cJSON* o;
|
||||||
|
va_list argp;
|
||||||
|
const char *cp;
|
||||||
|
char name[100];
|
||||||
|
char* np;
|
||||||
|
cJSON* j;
|
||||||
|
|
||||||
|
o = cJSON_CreateObject();
|
||||||
|
if (o == NULL)
|
||||||
|
return NULL;
|
||||||
|
va_start(argp, format);
|
||||||
|
np = name;
|
||||||
|
for (cp = format; *cp != '\0'; ++cp) {
|
||||||
|
switch (*cp) {
|
||||||
|
case ' ':
|
||||||
|
break;
|
||||||
|
case ':':
|
||||||
|
*np = '\0';
|
||||||
|
break;
|
||||||
|
case '%':
|
||||||
|
++cp;
|
||||||
|
switch (*cp) {
|
||||||
|
case 'b':
|
||||||
|
j = cJSON_CreateBool(va_arg(argp, int));
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
j = cJSON_CreateInt(va_arg(argp, int64_t));
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
j = cJSON_CreateFloat(va_arg(argp, double));
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
j = cJSON_CreateString(va_arg(argp, char *));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (j == NULL)
|
||||||
|
return NULL;
|
||||||
|
cJSON_AddItemToObject(o, name, j);
|
||||||
|
np = name;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
*np++ = *cp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
va_end(argp);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
@ -156,7 +156,6 @@ long get_tcpinfo_total_retransmits(struct iperf_interval_results *irp);
|
|||||||
void print_tcpinfo(struct iperf_test *test);
|
void print_tcpinfo(struct iperf_test *test);
|
||||||
void build_tcpinfo_message(struct iperf_interval_results *r, char *message);
|
void build_tcpinfo_message(struct iperf_interval_results *r, char *message);
|
||||||
|
|
||||||
void print_interval_results(struct iperf_test * test, struct iperf_stream *sp);
|
|
||||||
int iperf_send(struct iperf_test *, fd_set *);
|
int iperf_send(struct iperf_test *, fd_set *);
|
||||||
int iperf_recv(struct iperf_test *, fd_set *);
|
int iperf_recv(struct iperf_test *, fd_set *);
|
||||||
void sig_handler(int);
|
void sig_handler(int);
|
||||||
@ -193,6 +192,11 @@ int iperf_accept(struct iperf_test *);
|
|||||||
int iperf_handle_message_server(struct iperf_test *);
|
int iperf_handle_message_server(struct iperf_test *);
|
||||||
void iperf_test_reset(struct iperf_test *);
|
void iperf_test_reset(struct iperf_test *);
|
||||||
|
|
||||||
|
/* JSON output routines. */
|
||||||
|
int iperf_json_start(struct iperf_test *);
|
||||||
|
int iperf_json_finish(struct iperf_test *);
|
||||||
|
cJSON* iperf_json_printf(const char *format, ...);
|
||||||
|
|
||||||
/* Error routines. */
|
/* Error routines. */
|
||||||
void iperf_error(char *);
|
void iperf_error(char *);
|
||||||
char *iperf_strerror(int);
|
char *iperf_strerror(int);
|
||||||
|
@ -52,8 +52,10 @@ iperf_server_listen(struct iperf_test *test)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("-----------------------------------------------------------\n");
|
if (!test->json_output) {
|
||||||
printf("Server listening on %d\n", test->server_port);
|
printf("-----------------------------------------------------------\n");
|
||||||
|
printf("Server listening on %d\n", test->server_port);
|
||||||
|
}
|
||||||
|
|
||||||
// This needs to be changed to reflect if client has different window size
|
// This needs to be changed to reflect if client has different window size
|
||||||
// make sure we got what we asked for
|
// make sure we got what we asked for
|
||||||
@ -73,13 +75,16 @@ iperf_server_listen(struct iperf_test *test)
|
|||||||
if (test->protocol->id == Ptcp) {
|
if (test->protocol->id == Ptcp) {
|
||||||
if (test->settings->socket_bufsize > 0) {
|
if (test->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);
|
if (test->json_output)
|
||||||
|
printf("TCP window size: %s\n", ubuf);
|
||||||
} else {
|
} else {
|
||||||
printf("Using TCP Autotuning\n");
|
if (test->json_output)
|
||||||
|
printf("Using TCP Autotuning\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
printf("-----------------------------------------------------------\n");
|
if (!test->json_output)
|
||||||
|
printf("-----------------------------------------------------------\n");
|
||||||
|
|
||||||
FD_ZERO(&test->read_set);
|
FD_ZERO(&test->read_set);
|
||||||
FD_ZERO(&test->write_set);
|
FD_ZERO(&test->write_set);
|
||||||
|
@ -67,7 +67,7 @@ iperf_udp_recv(struct iperf_stream *sp)
|
|||||||
sp->packet_count = pcount;
|
sp->packet_count = pcount;
|
||||||
} else {
|
} else {
|
||||||
sp->outoforder_packets++;
|
sp->outoforder_packets++;
|
||||||
printf("OUT OF ORDER - incoming packet = %d and received packet = %d AND SP = %d\n", pcount, sp->packet_count, sp->socket);
|
fprintf(stderr, "OUT OF ORDER - incoming packet = %d and received packet = %d AND SP = %d\n", pcount, sp->packet_count, sp->socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* jitter measurement */
|
/* jitter measurement */
|
||||||
|
@ -67,10 +67,11 @@ const char usage_longstr[] = "Usage: iperf [-s|-c host] [options]\n"
|
|||||||
" -p, --port # server port to listen on/connect to\n"
|
" -p, --port # server port to listen on/connect to\n"
|
||||||
" -f, --format [kmgKMG] format to report: Kbits, Mbits, KBytes, MBytes\n"
|
" -f, --format [kmgKMG] format to report: Kbits, Mbits, KBytes, MBytes\n"
|
||||||
" -i, --interval # seconds between periodic bandwidth reports\n"
|
" -i, --interval # seconds between periodic bandwidth reports\n"
|
||||||
" -V, --verbose more verbose output\n"
|
" -V, --verbose more detailed output\n"
|
||||||
|
" -J, --json output in JSON format\n"
|
||||||
" -d, --debug debug mode\n"
|
" -d, --debug debug mode\n"
|
||||||
" -v, --version print version information and quit\n"
|
" -v, --version show version information and quit\n"
|
||||||
" -h, --help print this message and quit\n"
|
" -h, --help show this message and quit\n"
|
||||||
"Server specific:\n"
|
"Server specific:\n"
|
||||||
" -s, --server run in server mode\n"
|
" -s, --server run in server mode\n"
|
||||||
"Client specific:\n"
|
"Client specific:\n"
|
||||||
@ -110,7 +111,7 @@ const char usage_longstr[] = "Usage: iperf [-s|-c host] [options]\n"
|
|||||||
-y, --reportstyle C report as a Comma-Separated Values
|
-y, --reportstyle C report as a Comma-Separated Values
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const char version[] = "iperf version " IPERF_VERSION " (" IPERF_VERSION_DATE ") \n";
|
const char version[] = "iperf version " IPERF_VERSION " (" IPERF_VERSION_DATE ")";
|
||||||
|
|
||||||
/* -------------------------------------------------------------------
|
/* -------------------------------------------------------------------
|
||||||
* settings
|
* settings
|
||||||
|
39
src/main.c
39
src/main.c
@ -51,7 +51,7 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
perror("setpriority:");
|
perror("setpriority:");
|
||||||
printf("setting priority to valid level\n");
|
fprintf(stderr, "setting priority to valid level\n");
|
||||||
rc = setpriority(PRIO_PROCESS, 0, 0);
|
rc = setpriority(PRIO_PROCESS, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,21 +107,45 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
iperf_free_test(test);
|
iperf_free_test(test);
|
||||||
|
|
||||||
printf("\niperf Done.\n");
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char*
|
||||||
|
get_system_info(void)
|
||||||
|
{
|
||||||
|
FILE* fp;
|
||||||
|
static char buf[1000];
|
||||||
|
|
||||||
|
fp = popen("uname -a", "r");
|
||||||
|
if (fp == NULL)
|
||||||
|
return NULL;
|
||||||
|
fgets(buf, sizeof(buf), fp);
|
||||||
|
pclose(fp);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
int
|
int
|
||||||
iperf_run(struct iperf_test * test)
|
iperf_run(struct iperf_test * test)
|
||||||
{
|
{
|
||||||
|
if (test->json_output)
|
||||||
|
if (iperf_json_start(test) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (test->json_output) {
|
||||||
|
cJSON_AddItemToObject(test->json_start, "version", cJSON_CreateString(version));
|
||||||
|
cJSON_AddItemToObject(test->json_start, "system_info", cJSON_CreateString(get_system_info()));
|
||||||
|
} else if (test->verbose) {
|
||||||
|
printf("%s\n", version);
|
||||||
|
system("uname -a");
|
||||||
|
}
|
||||||
|
|
||||||
switch (test->role) {
|
switch (test->role) {
|
||||||
case 's':
|
case 's':
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (iperf_run_server(test) < 0) {
|
if (iperf_run_server(test) < 0) {
|
||||||
iperf_error("error");
|
iperf_error("error");
|
||||||
printf("\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
iperf_reset_test(test);
|
iperf_reset_test(test);
|
||||||
}
|
}
|
||||||
@ -137,5 +161,12 @@ iperf_run(struct iperf_test * test)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (test->json_output) {
|
||||||
|
if (iperf_json_finish(test) < 0)
|
||||||
|
return -1;
|
||||||
|
} else
|
||||||
|
printf("\niperf Done.\n");
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -99,6 +99,7 @@ get_tcpinfo_total_retransmits(struct iperf_interval_results *irp)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef notdef
|
||||||
/*************************************************************/
|
/*************************************************************/
|
||||||
//print_tcpinfo(struct iperf_interval_results *r)
|
//print_tcpinfo(struct iperf_interval_results *r)
|
||||||
void
|
void
|
||||||
@ -127,6 +128,7 @@ print_tcpinfo(struct iperf_test *test)
|
|||||||
*/
|
*/
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************/
|
/*************************************************************/
|
||||||
|
@ -8,4 +8,4 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define IPERF_VERSION "3.0-BETA5"
|
#define IPERF_VERSION "3.0-BETA5"
|
||||||
#define IPERF_VERSION_DATE "13 Dec 2012"
|
#define IPERF_VERSION_DATE "01 Feb 2013"
|
||||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user