From 2f97c35c043a247ae4681fd83482c075dfa9c452 Mon Sep 17 00:00:00 2001 From: "Pedro A. Aranda" Date: Mon, 24 Sep 2018 11:10:54 +0200 Subject: [PATCH 1/2] CLI backward compatible fix for issue #768 --- src/iperf_api.c | 76 ++++++++++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 30 deletions(-) diff --git a/src/iperf_api.c b/src/iperf_api.c index 246cc013e..4b9181046 100755 --- a/src/iperf_api.c +++ b/src/iperf_api.c @@ -920,6 +920,22 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) client_flag = 1; break; case 'n': + /* take the same approach as with -b to make it backwards compatible */ + /* -b as legacy + -b / for new behaviour + -b /1 should make iperf3 repeatable */ + slash = strchr(optarg, '/'); + if (slash) { + *slash = '\0'; + ++slash; + test->settings->burst = atoi(slash); + if (test->settings->burst <= 0 || + test->settings->burst > MAX_BURST) { + i_errno = IEBURST; + return -1; + } + } + test->settings->bytes = unit_atoi(optarg); client_flag = 1; break; @@ -945,7 +961,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) break; case 'w': // XXX: This is a socket buffer, not specific to TCP - // Do sanity checks as double-precision floating point + // Do sanity checks as double-precision floating point // to avoid possible integer overflows. farg = unit_atof(optarg); if (farg > (double) MAX_TCP_BUFFER) { @@ -1055,7 +1071,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) case 'A': #if defined(HAVE_CPU_AFFINITY) test->affinity = strtol(optarg, &endptr, 0); - if (endptr == optarg || + if (endptr == optarg || test->affinity < 0 || test->affinity > 1024) { i_errno = IEAFFINITY; return -1; @@ -1181,7 +1197,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) if (test->role == 's' && (client_username || client_rsa_public_key)){ i_errno = IECLIENTONLY; return -1; - } else if (test->role == 'c' && (client_username || client_rsa_public_key) && + } else if (test->role == 'c' && (client_username || client_rsa_public_key) && !(client_username && client_rsa_public_key)) { i_errno = IESETCLIENTAUTH; return -1; @@ -1191,7 +1207,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) size_t s; if (iperf_getpass(&client_password, &s, stdin) < 0){ return -1; - } + } if (strlen(client_username) > 20 || strlen(client_password) > 20){ i_errno = IESETCLIENTAUTH; @@ -1211,7 +1227,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) if (test->role == 'c' && (server_rsa_private_key || test->server_authorized_users)){ i_errno = IESERVERONLY; return -1; - } else if (test->role == 's' && (server_rsa_private_key || test->server_authorized_users) && + } else if (test->role == 's' && (server_rsa_private_key || test->server_authorized_users) && !(server_rsa_private_key && test->server_authorized_users)) { i_errno = IESETSERVERAUTH; return -1; @@ -1231,7 +1247,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) else blksize = DEFAULT_TCP_BLKSIZE; } - if ((test->protocol->id != Pudp && blksize <= 0) + if ((test->protocol->id != Pudp && blksize <= 0) || blksize > MAX_BLOCKSIZE) { i_errno = IEBLOCKSIZE; return -1; @@ -2156,7 +2172,7 @@ protocol_new(void) void protocol_free(struct protocol *proto) { - free(proto); + free(proto); } /**************************************************************************/ @@ -2331,7 +2347,7 @@ iperf_free_test(struct iperf_test *test) /* Free protocol list */ while (!SLIST_EMPTY(&test->protocols)) { prot = SLIST_FIRST(&test->protocols); - SLIST_REMOVE_HEAD(&test->protocols, protocols); + SLIST_REMOVE_HEAD(&test->protocols, protocols); free(prot); } @@ -2416,7 +2432,7 @@ iperf_reset_test(struct iperf_test *test) CPU_ZERO(&test->cpumask); #endif /* HAVE_CPUSET_SETAFFINITY */ test->state = 0; - + test->ctrl_sck = -1; test->prot_listener = -1; @@ -2428,7 +2444,7 @@ iperf_reset_test(struct iperf_test *test) FD_ZERO(&test->read_set); FD_ZERO(&test->write_set); - + test->num_streams = 1; test->settings->socket_bufsize = 0; test->settings->blksize = DEFAULT_TCP_BLKSIZE; @@ -2530,7 +2546,7 @@ iperf_stats_callback(struct iperf_test *test) rp = sp->result; temp.bytes_transferred = test->sender ? rp->bytes_sent_this_interval : rp->bytes_received_this_interval; - + irp = TAILQ_LAST(&rp->interval_results, irlisthead); /* result->end_time contains timestamp of previous interval */ if ( irp != NULL ) /* not the 1st interval */ @@ -2555,7 +2571,7 @@ iperf_stats_callback(struct iperf_test *test) if (temp.snd_cwnd > rp->stream_max_snd_cwnd) { rp->stream_max_snd_cwnd = temp.snd_cwnd; } - + temp.rtt = get_rtt(&temp); if (temp.rtt > rp->stream_max_rtt) { rp->stream_max_rtt = temp.rtt; @@ -2789,7 +2805,7 @@ iperf_print_results(struct iperf_test *test) start_time = 0.; sp = SLIST_FIRST(&test->streams); - /* + /* * If there is at least one stream, then figure out the length of time * we were running the tests and print out some statistics about * the streams. It's possible to not have any streams at all @@ -2838,7 +2854,7 @@ iperf_print_results(struct iperf_test *test) sender_packet_count = sp->peer_packet_count; receiver_packet_count = sp->packet_count; } - + if (test->protocol->id == Ptcp || test->protocol->id == Psctp) { if (test->sender_has_retransmits) { total_retransmits += sp->result->stream_retrans; @@ -2871,7 +2887,7 @@ iperf_print_results(struct iperf_test *test) cJSON_AddItemToObject(json_summary_stream, "sender", iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f retransmits: %d max_snd_cwnd: %d max_rtt: %d min_rtt: %d mean_rtt: %d", (int64_t) sp->socket, (double) start_time, (double) sender_time, (double) sender_time, (int64_t) bytes_sent, bandwidth * 8, (int64_t) sp->result->stream_retrans, (int64_t) sp->result->stream_max_snd_cwnd, (int64_t) sp->result->stream_max_rtt, (int64_t) sp->result->stream_min_rtt, (int64_t) ((sp->result->stream_count_rtt == 0) ? 0 : sp->result->stream_sum_rtt / sp->result->stream_count_rtt))); else if (test->role == 's' && !test->sender) { - if (test->verbose) + if (test->verbose) iperf_printf(test, report_sender_not_available_format, sp->socket); } else { @@ -2899,7 +2915,7 @@ iperf_print_results(struct iperf_test *test) lost_percent = 0.0; } if (test->json_output) { - /* + /* * For hysterical raisins, we only emit one JSON * object for the UDP summary, and it contains * information for both the sender and receiver @@ -2927,7 +2943,7 @@ iperf_print_results(struct iperf_test *test) * results. */ if (test->role == 's' && !test->sender) { - if (test->verbose) + if (test->verbose) iperf_printf(test, report_sender_not_available_format, sp->socket); } else { @@ -2974,7 +2990,7 @@ iperf_print_results(struct iperf_test *test) cJSON_AddItemToObject(json_summary_stream, "receiver", 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) receiver_time, (double) end_time, (int64_t) bytes_received, bandwidth * 8)); else if (test->role == 's' && test->sender) { - if (test->verbose) + if (test->verbose) iperf_printf(test, report_receiver_not_available_format, sp->socket); } else { @@ -2982,7 +2998,7 @@ iperf_print_results(struct iperf_test *test) } } else { - /* + /* * Receiver summary, UDP. Note that JSON was emitted with * the sender summary, so we only deal with human-readable * data here. @@ -3036,7 +3052,7 @@ iperf_print_results(struct iperf_test *test) 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) sender_time, (double) sender_time, (int64_t) total_sent, bandwidth * 8)); else if (test->role == 's' && !test->sender) { - if (test->verbose) + if (test->verbose) iperf_printf(test, report_sender_not_available_summary_format, "SUM"); } else { @@ -3056,7 +3072,7 @@ iperf_print_results(struct iperf_test *test) 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) receiver_time, (double) receiver_time, (int64_t) total_received, bandwidth * 8)); else if (test->role == 's' && test->sender) { - if (test->verbose) + if (test->verbose) iperf_printf(test, report_receiver_not_available_summary_format, "SUM"); } else { @@ -3163,8 +3179,8 @@ iperf_print_results(struct iperf_test *test) /** * Main report-printing callback. - * Prints results either during a test (interval report only) or - * after the entire test has been run (last interval report plus + * Prints results either during a test (interval report only) or + * after the entire test has been run (last interval report plus * overall summary). */ void @@ -3181,7 +3197,7 @@ iperf_reporter_callback(struct iperf_test *test) iperf_print_intermediate(test); iperf_print_results(test); break; - } + } } @@ -3237,10 +3253,10 @@ print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON * bandwidth = 0.0; } unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format); - + st = timeval_diff(&sp->result->start_time, &irp->interval_start_time); et = timeval_diff(&sp->result->start_time, &irp->interval_end_time); - + if (test->protocol->id == Ptcp || test->protocol->id == Psctp) { if (test->sender_has_retransmits == 1) { /* Interval, TCP with retransmits. */ @@ -3347,7 +3363,7 @@ iperf_new_stream(struct iperf_test *test, int s) memset(sp->result, 0, sizeof(struct iperf_stream_result)); TAILQ_INIT(&sp->result->interval_results); - + /* Create and randomize the buffer */ sp->buffer_fd = mkstemp(template); if (sp->buffer_fd == -1) { @@ -3619,10 +3635,10 @@ iperf_create_pidfile(struct iperf_test *test) } } } - + /* - * File didn't exist, we couldn't read it, or it didn't correspond to - * a running process. Try to create it. + * File didn't exist, we couldn't read it, or it didn't correspond to + * a running process. Try to create it. */ fd = open(test->pidfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR|S_IWUSR); if (fd < 0) { From de63078967b218b62e4c9fa49a8f3c9118fbff2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20A=2E=20Aranda=20Guti=C3=A9rrez?= Date: Mon, 24 Sep 2018 12:24:45 +0200 Subject: [PATCH 2/2] Alternative using multisend --- src/iperf_api.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/iperf_api.c b/src/iperf_api.c index 4b9181046..ffb7a1696 100755 --- a/src/iperf_api.c +++ b/src/iperf_api.c @@ -925,17 +925,16 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) -b / for new behaviour -b /1 should make iperf3 repeatable */ slash = strchr(optarg, '/'); - if (slash) { - *slash = '\0'; - ++slash; - test->settings->burst = atoi(slash); - if (test->settings->burst <= 0 || - test->settings->burst > MAX_BURST) { - i_errno = IEBURST; - return -1; - } - } - + if (slash) { + *slash = '\0'; + ++slash; + test->multisend = atoi(slash); + if (test->multisend <= 0 || + test->multisend > MAX_BURST) { + i_errno = IEBURST; + return -1; + } + } test->settings->bytes = unit_atoi(optarg); client_flag = 1; break;