Commit a version of the patch for #125 for testing.
Originally submitted by: @i2aaron
This commit is contained in:
parent
9ac254da7d
commit
081ba8e4e9
@ -36,9 +36,6 @@ main( int argc, char** argv )
|
|||||||
iperf_defaults( test );
|
iperf_defaults( test );
|
||||||
iperf_set_verbose( test, 1 );
|
iperf_set_verbose( test, 1 );
|
||||||
|
|
||||||
/* This main program doesn't use SIGALRM, so the iperf API may use it. */
|
|
||||||
iperf_set_test_may_use_sigalrm(test, 1);
|
|
||||||
|
|
||||||
iperf_set_test_role( test, 'c' );
|
iperf_set_test_role( test, 'c' );
|
||||||
iperf_set_test_server_hostname( test, host );
|
iperf_set_test_server_hostname( test, host );
|
||||||
iperf_set_test_server_port( test, port );
|
iperf_set_test_server_port( test, port );
|
||||||
|
@ -193,7 +193,6 @@ struct iperf_test
|
|||||||
int debug; /* -d option - enable debug */
|
int debug; /* -d option - enable debug */
|
||||||
|
|
||||||
int multisend;
|
int multisend;
|
||||||
int may_use_sigalrm;
|
|
||||||
|
|
||||||
char *json_output_string; /* rendered JSON output if json_output is set */
|
char *json_output_string; /* rendered JSON output if json_output is set */
|
||||||
/* Select related parameters */
|
/* Select related parameters */
|
||||||
|
@ -215,12 +215,6 @@ iperf_get_test_zerocopy(struct iperf_test *ipt)
|
|||||||
return ipt->zerocopy;
|
return ipt->zerocopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
iperf_get_test_may_use_sigalrm(struct iperf_test *ipt)
|
|
||||||
{
|
|
||||||
return ipt->may_use_sigalrm;
|
|
||||||
}
|
|
||||||
|
|
||||||
char
|
char
|
||||||
iperf_get_test_unit_format(struct iperf_test *ipt)
|
iperf_get_test_unit_format(struct iperf_test *ipt)
|
||||||
{
|
{
|
||||||
@ -362,12 +356,6 @@ iperf_set_test_zerocopy(struct iperf_test *ipt, int zerocopy)
|
|||||||
ipt->zerocopy = zerocopy;
|
ipt->zerocopy = zerocopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
iperf_set_test_may_use_sigalrm(struct iperf_test *ipt, int may_use_sigalrm)
|
|
||||||
{
|
|
||||||
ipt->may_use_sigalrm = may_use_sigalrm;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
iperf_set_test_unit_format(struct iperf_test *ipt, char unit_format)
|
iperf_set_test_unit_format(struct iperf_test *ipt, char unit_format)
|
||||||
{
|
{
|
||||||
@ -1604,7 +1592,6 @@ iperf_defaults(struct iperf_test *testp)
|
|||||||
memset(testp->cookie, 0, COOKIE_SIZE);
|
memset(testp->cookie, 0, COOKIE_SIZE);
|
||||||
|
|
||||||
testp->multisend = 10; /* arbitrary */
|
testp->multisend = 10; /* arbitrary */
|
||||||
testp->may_use_sigalrm = 0;
|
|
||||||
|
|
||||||
/* Set up protocol list */
|
/* Set up protocol list */
|
||||||
SLIST_INIT(&testp->streams);
|
SLIST_INIT(&testp->streams);
|
||||||
|
@ -70,7 +70,6 @@ int iperf_get_test_protocol_id( struct iperf_test* ipt );
|
|||||||
int iperf_get_test_json_output( struct iperf_test* ipt );
|
int iperf_get_test_json_output( struct iperf_test* ipt );
|
||||||
char* iperf_get_test_json_output_string ( struct iperf_test* ipt );
|
char* iperf_get_test_json_output_string ( struct iperf_test* ipt );
|
||||||
int iperf_get_test_zerocopy( struct iperf_test* ipt );
|
int iperf_get_test_zerocopy( struct iperf_test* ipt );
|
||||||
int iperf_get_test_may_use_sigalrm( struct iperf_test* ipt );
|
|
||||||
|
|
||||||
/* Setter routines for some fields inside iperf_test. */
|
/* Setter routines for some fields inside iperf_test. */
|
||||||
void iperf_set_verbose( struct iperf_test* ipt, int verbose );
|
void iperf_set_verbose( struct iperf_test* ipt, int verbose );
|
||||||
@ -92,7 +91,6 @@ void iperf_set_test_reverse( struct iperf_test* ipt, int reverse );
|
|||||||
void iperf_set_test_json_output( struct iperf_test* ipt, int json_output );
|
void iperf_set_test_json_output( struct iperf_test* ipt, int json_output );
|
||||||
int iperf_has_zerocopy( void );
|
int iperf_has_zerocopy( void );
|
||||||
void iperf_set_test_zerocopy( struct iperf_test* ipt, int zerocopy );
|
void iperf_set_test_zerocopy( struct iperf_test* ipt, int zerocopy );
|
||||||
void iperf_set_test_may_use_sigalrm( struct iperf_test* ipt, int may_use_sigalrm );
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* exchange_parameters - handles the param_Exchange part for client
|
* exchange_parameters - handles the param_Exchange part for client
|
||||||
|
@ -315,26 +315,15 @@ sigend_handler(int sig)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
typedef enum { cm_select, cm_itimer } cm_t;
|
|
||||||
|
|
||||||
static int sigalrm_triggered;
|
|
||||||
|
|
||||||
static void
|
|
||||||
sigalrm_handler(int sig)
|
|
||||||
{
|
|
||||||
sigalrm_triggered = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
iperf_run_client(struct iperf_test * test)
|
iperf_run_client(struct iperf_test * test)
|
||||||
{
|
{
|
||||||
cm_t concurrency_model;
|
|
||||||
int startup;
|
int startup;
|
||||||
int result = 0;
|
int result = 0;
|
||||||
fd_set read_set, write_set;
|
fd_set read_set, write_set;
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
struct timeval* timeout = NULL;
|
struct timeval* timeout = NULL;
|
||||||
struct itimerval itv;
|
struct iperf_stream *sp;
|
||||||
|
|
||||||
/* Termination signals. */
|
/* Termination signals. */
|
||||||
iperf_catch_sigend(sigend_handler);
|
iperf_catch_sigend(sigend_handler);
|
||||||
@ -367,10 +356,7 @@ iperf_run_client(struct iperf_test * test)
|
|||||||
cpu_util(NULL);
|
cpu_util(NULL);
|
||||||
|
|
||||||
startup = 1;
|
startup = 1;
|
||||||
concurrency_model = cm_select; /* always start in select mode */
|
|
||||||
while (test->state != IPERF_DONE) {
|
while (test->state != IPERF_DONE) {
|
||||||
|
|
||||||
if (concurrency_model == cm_select) {
|
|
||||||
memcpy(&read_set, &test->read_set, sizeof(fd_set));
|
memcpy(&read_set, &test->read_set, sizeof(fd_set));
|
||||||
memcpy(&write_set, &test->write_set, sizeof(fd_set));
|
memcpy(&write_set, &test->write_set, sizeof(fd_set));
|
||||||
(void) gettimeofday(&now, NULL);
|
(void) gettimeofday(&now, NULL);
|
||||||
@ -388,33 +374,16 @@ iperf_run_client(struct iperf_test * test)
|
|||||||
FD_CLR(test->ctrl_sck, &read_set);
|
FD_CLR(test->ctrl_sck, &read_set);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (test->state == TEST_RUNNING) {
|
if (test->state == TEST_RUNNING) {
|
||||||
|
|
||||||
/* Is this our first time really running? */
|
/* Is this our first time really running? */
|
||||||
if (startup) {
|
if (startup) {
|
||||||
startup = 0;
|
startup = 0;
|
||||||
/* Decide which concurrency model to use for the real test.
|
|
||||||
** SIGALRM is less overhead but there are a bunch of cases
|
|
||||||
** where it either won't work or is ill-advised.
|
|
||||||
*/
|
|
||||||
if (test->may_use_sigalrm && test->settings->rate == 0 &&
|
|
||||||
(test->stats_interval == 0 || test->stats_interval > 0.2) &&
|
|
||||||
(test->reporter_interval == 0 || test->reporter_interval > 0.2) &&
|
|
||||||
(test->omit == 0 || test->omit > 0.2) &&
|
|
||||||
! test->reverse) {
|
|
||||||
concurrency_model = cm_itimer;
|
|
||||||
test->multisend = 1;
|
|
||||||
signal(SIGALRM, sigalrm_handler);
|
|
||||||
sigalrm_triggered = 0;
|
|
||||||
itv.it_interval.tv_sec = 0;
|
|
||||||
itv.it_interval.tv_usec = 100000;
|
|
||||||
itv.it_value.tv_sec = 0;
|
|
||||||
itv.it_value.tv_usec = 100000;
|
|
||||||
(void) setitimer(ITIMER_REAL, &itv, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
SLIST_FOREACH(sp, &test->streams, streams) {
|
||||||
|
setnonblocking(sp->socket, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test->reverse) {
|
if (test->reverse) {
|
||||||
@ -423,41 +392,30 @@ iperf_run_client(struct iperf_test * test)
|
|||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
// Regular mode. Client sends.
|
// Regular mode. Client sends.
|
||||||
if (iperf_send(test, concurrency_model == cm_itimer ? NULL : &write_set) < 0)
|
if (iperf_send(test, &write_set) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((concurrency_model == cm_select &&
|
|
||||||
(result == 0 ||
|
|
||||||
(timeout != NULL && timeout->tv_sec == 0 && timeout->tv_usec == 0))) ||
|
|
||||||
(concurrency_model == cm_itimer && sigalrm_triggered)) {
|
|
||||||
/* Run the timers. */
|
/* Run the timers. */
|
||||||
(void) gettimeofday(&now, NULL);
|
(void) gettimeofday(&now, NULL);
|
||||||
tmr_run(&now);
|
tmr_run(&now);
|
||||||
if (concurrency_model == cm_itimer)
|
|
||||||
sigalrm_triggered = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Is the test done yet? */
|
/* Is the test done yet? */
|
||||||
if ((!test->omitting) &&
|
if ((!test->omitting) &&
|
||||||
((test->duration != 0 && test->done) ||
|
((test->duration != 0 && test->done) ||
|
||||||
(test->settings->bytes != 0 && test->bytes_sent >= test->settings->bytes) ||
|
(test->settings->bytes != 0 && test->bytes_sent >= test->settings->bytes) ||
|
||||||
(test->settings->blocks != 0 && test->blocks_sent >= test->settings->blocks))) {
|
(test->settings->blocks != 0 && test->blocks_sent >= test->settings->blocks))) {
|
||||||
|
|
||||||
|
SLIST_FOREACH(sp, &test->streams, streams) {
|
||||||
|
setnonblocking(sp->socket, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Yes, done! Send TEST_END. */
|
/* Yes, done! Send TEST_END. */
|
||||||
test->done = 1;
|
test->done = 1;
|
||||||
cpu_util(test->cpu_util);
|
cpu_util(test->cpu_util);
|
||||||
test->stats_callback(test);
|
test->stats_callback(test);
|
||||||
if (iperf_set_send_state(test, TEST_END) != 0)
|
if (iperf_set_send_state(test, TEST_END) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
/* If we were doing setitimer(), go back to select() for the end. */
|
|
||||||
if (concurrency_model == cm_itimer) {
|
|
||||||
itv.it_interval.tv_sec = 0;
|
|
||||||
itv.it_interval.tv_usec = 0;
|
|
||||||
itv.it_value.tv_sec = 0;
|
|
||||||
itv.it_value.tv_usec = 0;
|
|
||||||
(void) setitimer(ITIMER_REAL, &itv, NULL);
|
|
||||||
concurrency_model = cm_select;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If we're in reverse mode, continue draining the data
|
// If we're in reverse mode, continue draining the data
|
||||||
|
@ -516,6 +516,8 @@ iperf_run_server(struct iperf_test *test)
|
|||||||
FD_SET(s, &test->read_set);
|
FD_SET(s, &test->read_set);
|
||||||
if (s > test->max_fd) test->max_fd = s;
|
if (s > test->max_fd) test->max_fd = s;
|
||||||
|
|
||||||
|
setnonblocking(s, 1);
|
||||||
|
|
||||||
streams_accepted++;
|
streams_accepted++;
|
||||||
if (test->on_new_stream)
|
if (test->on_new_stream)
|
||||||
test->on_new_stream(sp);
|
test->on_new_stream(sp);
|
||||||
|
@ -79,9 +79,6 @@ main(int argc, char **argv)
|
|||||||
iperf_errexit(NULL, "create new test error - %s", iperf_strerror(i_errno));
|
iperf_errexit(NULL, "create new test error - %s", iperf_strerror(i_errno));
|
||||||
iperf_defaults(test); /* sets defaults */
|
iperf_defaults(test); /* sets defaults */
|
||||||
|
|
||||||
/* This main program doesn't use SIGALRM, so the iperf API may use it. */
|
|
||||||
iperf_set_test_may_use_sigalrm(test, 1);
|
|
||||||
|
|
||||||
if (iperf_parse_arguments(test, argc, argv) < 0) {
|
if (iperf_parse_arguments(test, argc, argv) < 0) {
|
||||||
iperf_err(test, "parameter error - %s", iperf_strerror(i_errno));
|
iperf_err(test, "parameter error - %s", iperf_strerror(i_errno));
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
|
@ -171,8 +171,8 @@ Nread(int fd, char *buf, size_t count, int prot)
|
|||||||
while (nleft > 0) {
|
while (nleft > 0) {
|
||||||
r = read(fd, buf, nleft);
|
r = read(fd, buf, nleft);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR || errno == EAGAIN)
|
||||||
r = 0;
|
break;
|
||||||
else
|
else
|
||||||
return NET_HARDERROR;
|
return NET_HARDERROR;
|
||||||
} else if (r == 0)
|
} else if (r == 0)
|
||||||
@ -200,9 +200,9 @@ Nwrite(int fd, const char *buf, size_t count, int prot)
|
|||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
case EINTR:
|
case EINTR:
|
||||||
|
case EAGAIN:
|
||||||
return count - nleft;
|
return count - nleft;
|
||||||
|
|
||||||
case EAGAIN:
|
|
||||||
case ENOBUFS:
|
case ENOBUFS:
|
||||||
return NET_SOFTERROR;
|
return NET_SOFTERROR;
|
||||||
|
|
||||||
@ -271,9 +271,9 @@ Nsendfile(int fromfd, int tofd, const char *buf, size_t count)
|
|||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
case EINTR:
|
case EINTR:
|
||||||
|
case EAGAIN:
|
||||||
return count - nleft;
|
return count - nleft;
|
||||||
|
|
||||||
case EAGAIN:
|
|
||||||
case ENOBUFS:
|
case ENOBUFS:
|
||||||
case ENOMEM:
|
case ENOMEM:
|
||||||
return NET_SOFTERROR;
|
return NET_SOFTERROR;
|
||||||
|
Loading…
Reference in New Issue
Block a user