diff --git a/src/iperf.h b/src/iperf.h index dde0fdecf..b7d1eaa8e 100755 --- a/src/iperf.h +++ b/src/iperf.h @@ -295,6 +295,8 @@ struct iperf_test char *remote_congestion_used; /* what the other side used */ char *pidfile; /* -P option */ + unsigned int delay; /* --delay server delay*/ + char *logfile; /* --logfile option */ FILE *outfile; @@ -330,6 +332,7 @@ struct iperf_test int repeating_payload; /* --repeating-payload */ int multithread; /* --multithread option */ int thread_affinity; /* --thread-affinity option. Use only with --multithread option */ + int force_udp; /* --force-udp option - witnout answer*/ char *json_output_string; /* rendered JSON output if json_output is set */ /* Select related parameters */ diff --git a/src/iperf_api.c b/src/iperf_api.c index f8f886094..04bb47d91 100755 --- a/src/iperf_api.c +++ b/src/iperf_api.c @@ -756,6 +756,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) {"server", no_argument, NULL, 's'}, {"client", required_argument, NULL, 'c'}, {"udp", no_argument, NULL, 'u'}, + {"force-udp", no_argument, NULL, 'fu'}, {"bitrate", required_argument, NULL, 'b'}, {"bandwidth", required_argument, NULL, 'b'}, {"time", required_argument, NULL, 't'}, @@ -773,6 +774,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) {"version4", no_argument, NULL, '4'}, {"version6", no_argument, NULL, '6'}, {"tos", required_argument, NULL, 'S'}, + {"delay", required_argument, NULL, 'delay'}, {"dscp", required_argument, NULL, OPT_DSCP}, {"test-set", required_argument, NULL, OPT_TEST_SET}, {"extra-data", required_argument, NULL, OPT_EXTRA_DATA}, @@ -904,6 +906,9 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) set_protocol(test, Pudp); client_flag = 1; break; + case 'fu': + test->force_udp = 1; + break; case OPT_SCTP: #if defined(HAVE_SCTP) set_protocol(test, Psctp); @@ -1046,6 +1051,9 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) } client_flag = 1; break; + case 'delay': + test->delay = atoi(optarg); + break; case OPT_DSCP: test->settings->tos = parse_qos(optarg); if(test->settings->tos < 0) { @@ -1400,7 +1408,9 @@ iperf_send(struct iperf_test *test, fd_set *write_setP) if (test->settings->rate != 0 && test->settings->burst == 0) iperf_time_now(&now); streams_active = 0; - SLIST_FOREACH(sp, &test->streams, streams) { + + SLIST_FOREACH(sp, &test->streams, streams) { + if (write_setP == NULL || FD_ISSET(sp->socket, write_setP)) if ((sp->green_light && sp->sender && (write_setP == NULL || FD_ISSET(sp->socket, write_setP)))) { if ((r = sp->snd(sp)) < 0) { diff --git a/src/iperf_client_api.c b/src/iperf_client_api.c index d0555de69..146af75b5 100644 --- a/src/iperf_client_api.c +++ b/src/iperf_client_api.c @@ -331,6 +331,7 @@ iperf_handle_message_client(struct iperf_test *test) int iperf_connect(struct iperf_test *test) { + if (test->force_udp) printf("Start client without connect to setver by UDP\n"); FD_ZERO(&test->read_set); FD_ZERO(&test->write_set); @@ -340,10 +341,14 @@ iperf_connect(struct iperf_test *test) if (test->ctrl_sck < 0) // Create the control channel using an ephemeral port test->ctrl_sck = netdial(test->settings->domain, Ptcp, test->bind_address, 0, test->server_hostname, test->server_port, test->settings->connect_timeout); - if (test->ctrl_sck < 0) { - i_errno = IECONNECT; - return -1; - } + + if (test->force_udp) + if (test->ctrl_sck < 0) test->ctrl_sck = 0; + else + if ((test->ctrl_sck < 0)) { + i_errno = IECONNECT; + return -1; + } if (Nwrite(test->ctrl_sck, test->cookie, COOKIE_SIZE, Ptcp) < 0) { i_errno = IESENDCOOKIE; @@ -478,7 +483,7 @@ iperf_run_client(struct iperf_test * test) /* Start the client and connect to the server */ if (iperf_connect(test) < 0) return -1; - + /* Begin calculating CPU utilization */ cpu_util(NULL); @@ -488,57 +493,61 @@ iperf_run_client(struct iperf_test * test) memcpy(&write_set, &test->write_set, sizeof(fd_set)); iperf_time_now(&now); timeout = tmr_timeout(&now); - result = select(test->max_fd + 1, &read_set, &write_set, NULL, timeout); + if (!(test->force_udp)) result = select(test->max_fd + 1, &read_set, &write_set, NULL, timeout); + else result = 1 ; if (result < 0 && errno != EINTR) { i_errno = IESELECT; return -1; } - if (result > 0) { - if (FD_ISSET(test->ctrl_sck, &read_set)) { - if (iperf_handle_message_client(test) < 0) { - return -1; - } - FD_CLR(test->ctrl_sck, &read_set); - } - } - + if (test->force_udp) { + test->state = TEST_RUNNING; + } else { + if (result > 0) { + if (FD_ISSET(test->ctrl_sck, &read_set)) { + if (iperf_handle_message_client(test) < 0) { + return -1; + } + FD_CLR(test->ctrl_sck, &read_set); + } + } + } if (test->state == TEST_RUNNING) { /* Is this our first time really running? */ if (startup) { startup = 0; - // Set non-blocking for non-UDP tests - if (test->protocol->id != Pudp) { - SLIST_FOREACH(sp, &test->streams, streams) { - setnonblocking(sp->socket, 1); - } - } + // Set non-blocking for non-UDP tests + if (test->protocol->id != Pudp) { + SLIST_FOREACH(sp, &test->streams, streams) { + setnonblocking(sp->socket, 1); + } + } } if (test->multithread) { - if (!test->thrcontrol->started) { - int status; + if (!test->thrcontrol->started) { + int status; - test->thrcontrol->started = 1; - status = pthread_barrier_wait(&test->thrcontrol->initial_barrier); - if (status == PTHREAD_BARRIER_SERIAL_THREAD) { - pthread_barrier_destroy(&test->thrcontrol->initial_barrier); - } + test->thrcontrol->started = 1; + status = pthread_barrier_wait(&test->thrcontrol->initial_barrier); + if (status == PTHREAD_BARRIER_SERIAL_THREAD) { + pthread_barrier_destroy(&test->thrcontrol->initial_barrier); } + } usleep(1000); - if (test->mode != RECEIVER) { + if (test->mode != RECEIVER) { - test->blocks_sent = 0; - test->bytes_sent = 0; + test->blocks_sent = 0; + test->bytes_sent = 0; - SLIST_FOREACH(sp, &test->streams, streams) { - test->bytes_sent += sp->bytes_sent; - test->blocks_sent += sp->blocks_sent; - } + SLIST_FOREACH(sp, &test->streams, streams) { + test->bytes_sent += sp->bytes_sent; + test->blocks_sent += sp->blocks_sent; } + } } else { if (test->mode == BIDIRECTIONAL) @@ -549,8 +558,11 @@ iperf_run_client(struct iperf_test * test) return -1; } else if (test->mode == SENDER) { // Regular mode. Client sends. - if (iperf_send(test, &write_set) < 0) + int is = iperf_send(test, &write_set); + if (is < 0) { return -1; + } + } else { // Reverse mode. Client receives. if (iperf_recv(test, &read_set) < 0) @@ -578,7 +590,6 @@ iperf_run_client(struct iperf_test * test) /* If multisend we must to count the result after stopping all threads */ if (test->multithread && test->mode != RECEIVER) { - test->blocks_sent = 0; test->bytes_sent = 0; diff --git a/src/iperf_locale.c b/src/iperf_locale.c index e812552af..20d7951e3 100644 --- a/src/iperf_locale.c +++ b/src/iperf_locale.c @@ -117,6 +117,7 @@ const char usage_longstr[] = "Usage: iperf3 [-s|-c host] [options]\n" " -D, --daemon run the server as a daemon\n" " -I, --pidfile file write PID file\n" " -1, --one-off handle one client connection then exit\n" + " --delay delay microseconds on server\n" #if defined(HAVE_SSL) " --rsa-private-key-path path to the RSA private key used to decrypt\n" " authentication credentials\n" @@ -131,20 +132,22 @@ const char usage_longstr[] = "Usage: iperf3 [-s|-c host] [options]\n" " --nstreams # number of SCTP streams\n" #endif /* HAVE_SCTP */ " -u, --udp use UDP rather than TCP\n" + " --force-udp use for UDP when server\n" + " have same trubles and cannot answer" " --connect-timeout # timeout for control connection setup (ms)\n" " -b, --bitrate #[KMG][/#] target bitrate in bits/sec (0 for unlimited)\n" " (default %d Mbit/sec for UDP, unlimited for TCP)\n" " (optional slash and packet count for burst mode)\n" - " --pacing-timer #[KMG] set the timing for pacing, in microseconds (default 1000)\n" + " --pacing-timer #[KMG] set the timing for pacing, in microseconds (default 1000)\n" #if defined(HAVE_SO_MAX_PACING_RATE) " --fq-rate #[KMG] enable fair-queuing based socket pacing in\n" - " bits/sec (Linux only)\n" + " bits/sec (Linux only)\n" #endif " -t, --time # time in seconds to transmit for (default %d secs)\n" " -n, --bytes #[KMG] number of bytes to transmit (instead of -t)\n" " -k, --blockcount #[KMG] number of blocks (packets) to transmit (instead of -t or -n)\n" " -l, --length #[KMG] length of buffer to read or write\n" - " (default %d KB for TCP, dynamic or %d for UDP)\n" + " (default %d KB for TCP, dynamic or %d for UDP)\n" " --cport bind to a specific client port (TCP and UDP, default: ephemeral port)\n" " -P, --parallel # number of parallel client streams to run\n" " --multithread creates a number of threads equal to the number of streams.\n"