1
1

Handle retransmits correctly in reverse mode.

Этот коммит содержится в:
Jef Poskanzer 2013-05-29 15:18:18 -07:00
родитель 2c042fd469
Коммит 69bdbfd36d
5 изменённых файлов: 65 добавлений и 18 удалений

Просмотреть файл

@ -45,6 +45,7 @@ struct iperf_stream_result
iperf_size_t bytes_sent; iperf_size_t bytes_sent;
iperf_size_t bytes_received_this_interval; iperf_size_t bytes_received_this_interval;
iperf_size_t bytes_sent_this_interval; iperf_size_t bytes_sent_this_interval;
int retransmits;
struct timeval start_time; struct timeval start_time;
struct timeval end_time; struct timeval end_time;
TAILQ_HEAD(irlisthead, iperf_interval_results) interval_results; TAILQ_HEAD(irlisthead, iperf_interval_results) interval_results;
@ -126,6 +127,7 @@ struct iperf_test
{ {
char role; /* 'c' lient or 's' erver */ char role; /* 'c' lient or 's' erver */
int sender; /* client & !reverse or server & reverse */ int sender; /* client & !reverse or server & reverse */
int sender_has_retransmits;
struct protocol *protocol; struct protocol *protocol;
char state; char state;
char *server_hostname; /* -c option */ char *server_hostname; /* -c option */

Просмотреть файл

@ -619,6 +619,8 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
} }
if (test->reverse) if (test->reverse)
test->sender = ! test->sender; test->sender = ! test->sender;
if (test->sender && test->protocol->id == Ptcp && has_tcpinfo_retransmits())
test->sender_has_retransmits = 1;
return 0; return 0;
} }
@ -810,6 +812,21 @@ iperf_exchange_parameters(struct iperf_test *test)
return 0; return 0;
} }
/*************************************************************/
int
iperf_sum_results(struct iperf_test *test)
{
struct iperf_stream *sp;
SLIST_FOREACH(sp, &test->streams, streams) {
if (test->sender && test->sender_has_retransmits)
sp->result->retransmits = get_tcpinfo_total_retransmits(TAILQ_LAST(&sp->result->interval_results, irlisthead));
}
return 0;
}
/*************************************************************/ /*************************************************************/
int int
@ -918,6 +935,8 @@ get_parameters(struct iperf_test *test)
test->settings->rate = j_p->valueint; test->settings->rate = j_p->valueint;
if ((j_p = cJSON_GetObjectItem(j, "TOS")) != NULL) if ((j_p = cJSON_GetObjectItem(j, "TOS")) != NULL)
test->settings->tos = j_p->valueint; test->settings->tos = j_p->valueint;
if (test->sender && test->protocol->id == Ptcp && has_tcpinfo_retransmits())
test->sender_has_retransmits = 1;
cJSON_Delete(j); cJSON_Delete(j);
} }
return r; return r;
@ -933,7 +952,9 @@ send_results(struct iperf_test *test)
cJSON *j_streams; cJSON *j_streams;
struct iperf_stream *sp; struct iperf_stream *sp;
cJSON *j_stream; cJSON *j_stream;
int sender_has_retransmits;
iperf_size_t bytes_transferred; iperf_size_t bytes_transferred;
int retransmits;
j = cJSON_CreateObject(); j = cJSON_CreateObject();
if (j == NULL) { if (j == NULL) {
@ -941,6 +962,11 @@ send_results(struct iperf_test *test)
r = -1; r = -1;
} else { } else {
cJSON_AddFloatToObject(j, "cpu_util", test->cpu_util); cJSON_AddFloatToObject(j, "cpu_util", test->cpu_util);
if ( ! test->sender )
sender_has_retransmits = -1;
else
sender_has_retransmits = test->sender_has_retransmits;
cJSON_AddIntToObject(j, "sender_has_retransmits", sender_has_retransmits);
j_streams = cJSON_CreateArray(); j_streams = cJSON_CreateArray();
if (j_streams == NULL) { if (j_streams == NULL) {
i_errno = IEPACKAGERESULTS; i_errno = IEPACKAGERESULTS;
@ -955,8 +981,10 @@ send_results(struct iperf_test *test)
} else { } else {
cJSON_AddItemToArray(j_streams, j_stream); cJSON_AddItemToArray(j_streams, j_stream);
bytes_transferred = test->sender ? sp->result->bytes_sent : sp->result->bytes_received; bytes_transferred = test->sender ? sp->result->bytes_sent : sp->result->bytes_received;
retransmits = (test->sender && test->sender_has_retransmits) ? sp->result->retransmits : -1;
cJSON_AddIntToObject(j_stream, "id", sp->id); cJSON_AddIntToObject(j_stream, "id", sp->id);
cJSON_AddIntToObject(j_stream, "bytes", bytes_transferred); cJSON_AddIntToObject(j_stream, "bytes", bytes_transferred);
cJSON_AddIntToObject(j_stream, "retransmits", retransmits);
cJSON_AddFloatToObject(j_stream, "jitter", sp->jitter); cJSON_AddFloatToObject(j_stream, "jitter", sp->jitter);
cJSON_AddIntToObject(j_stream, "errors", sp->cnt_error); cJSON_AddIntToObject(j_stream, "errors", sp->cnt_error);
cJSON_AddIntToObject(j_stream, "packets", sp->packet_count); cJSON_AddIntToObject(j_stream, "packets", sp->packet_count);
@ -980,17 +1008,21 @@ get_results(struct iperf_test *test)
int r = 0; int r = 0;
cJSON *j; cJSON *j;
cJSON *j_cpu_util; cJSON *j_cpu_util;
cJSON *j_sender_has_retransmits;
int result_has_retransmits;
cJSON *j_streams; cJSON *j_streams;
int n, i; int n, i;
cJSON *j_stream; cJSON *j_stream;
cJSON *j_id; cJSON *j_id;
cJSON *j_bytes; cJSON *j_bytes;
cJSON *j_retransmits;
cJSON *j_jitter; cJSON *j_jitter;
cJSON *j_errors; cJSON *j_errors;
cJSON *j_packets; cJSON *j_packets;
int sid, cerror, pcount; int sid, cerror, pcount;
double jitter; double jitter;
iperf_size_t bytes_transferred; iperf_size_t bytes_transferred;
int retransmits;
struct iperf_stream *sp; struct iperf_stream *sp;
j = JSON_read(test->ctrl_sck); j = JSON_read(test->ctrl_sck);
@ -999,11 +1031,15 @@ get_results(struct iperf_test *test)
r = -1; r = -1;
} else { } else {
j_cpu_util = cJSON_GetObjectItem(j, "cpu_util"); j_cpu_util = cJSON_GetObjectItem(j, "cpu_util");
if (j_cpu_util == NULL) { j_sender_has_retransmits = cJSON_GetObjectItem(j, "sender_has_retransmits");
if (j_cpu_util == NULL || j_sender_has_retransmits == NULL) {
i_errno = IERECVRESULTS; i_errno = IERECVRESULTS;
r = -1; r = -1;
} else { } else {
test->remote_cpu_util = j_cpu_util->valuefloat; test->remote_cpu_util = j_cpu_util->valuefloat;
result_has_retransmits = j_sender_has_retransmits->valueint;
if (! test->sender)
test->sender_has_retransmits = result_has_retransmits;
j_streams = cJSON_GetObjectItem(j, "streams"); j_streams = cJSON_GetObjectItem(j, "streams");
if (j_streams == NULL) { if (j_streams == NULL) {
i_errno = IERECVRESULTS; i_errno = IERECVRESULTS;
@ -1018,15 +1054,17 @@ get_results(struct iperf_test *test)
} else { } else {
j_id = cJSON_GetObjectItem(j_stream, "id"); j_id = cJSON_GetObjectItem(j_stream, "id");
j_bytes = cJSON_GetObjectItem(j_stream, "bytes"); j_bytes = cJSON_GetObjectItem(j_stream, "bytes");
j_retransmits = cJSON_GetObjectItem(j_stream, "retransmits");
j_jitter = cJSON_GetObjectItem(j_stream, "jitter"); j_jitter = cJSON_GetObjectItem(j_stream, "jitter");
j_errors = cJSON_GetObjectItem(j_stream, "errors"); j_errors = cJSON_GetObjectItem(j_stream, "errors");
j_packets = cJSON_GetObjectItem(j_stream, "packets"); j_packets = cJSON_GetObjectItem(j_stream, "packets");
if (j_id == NULL || j_bytes == NULL || j_jitter == NULL || j_errors == NULL || j_packets == NULL) { if (j_id == NULL || j_bytes == NULL || j_retransmits == NULL || j_jitter == NULL || j_errors == NULL || j_packets == NULL) {
i_errno = IERECVRESULTS; i_errno = IERECVRESULTS;
r = -1; r = -1;
} else { } else {
sid = j_id->valueint; sid = j_id->valueint;
bytes_transferred = j_bytes->valueint; bytes_transferred = j_bytes->valueint;
retransmits = j_retransmits->valueint;
jitter = j_jitter->valuefloat; jitter = j_jitter->valuefloat;
cerror = j_errors->valueint; cerror = j_errors->valueint;
pcount = j_packets->valueint; pcount = j_packets->valueint;
@ -1041,8 +1079,10 @@ get_results(struct iperf_test *test)
sp->cnt_error = cerror; sp->cnt_error = cerror;
sp->packet_count = pcount; sp->packet_count = pcount;
sp->result->bytes_received = bytes_transferred; sp->result->bytes_received = bytes_transferred;
} else } else {
sp->result->bytes_sent = bytes_transferred; sp->result->bytes_sent = bytes_transferred;
sp->result->retransmits = retransmits;
}
} }
} }
} }
@ -1313,6 +1353,7 @@ iperf_reset_test(struct iperf_test *test)
test->role = 's'; test->role = 's';
test->sender = 0; test->sender = 0;
test->sender_has_retransmits = 0;
set_protocol(test, Ptcp); set_protocol(test, Ptcp);
test->duration = DURATION; test->duration = DURATION;
test->state = 0; test->state = 0;
@ -1374,7 +1415,7 @@ iperf_stats_callback(struct iperf_test *test)
//temp.interval_duration = timeval_diff(&temp.interval_start_time, &temp.interval_end_time); //temp.interval_duration = timeval_diff(&temp.interval_start_time, &temp.interval_end_time);
if (test->protocol->id == Ptcp && has_tcpinfo()) { if (test->protocol->id == Ptcp && has_tcpinfo()) {
save_tcpinfo(sp, &temp); save_tcpinfo(sp, &temp);
if (has_tcpinfo_retransmits()) { if (test->sender && test->sender_has_retransmits) {
irp = TAILQ_LAST(&rp->interval_results, irlisthead); irp = TAILQ_LAST(&rp->interval_results, irlisthead);
if (irp == NULL) if (irp == NULL)
prev_total_retransmits = 0; prev_total_retransmits = 0;
@ -1425,7 +1466,7 @@ iperf_print_intermediate(struct iperf_test *test)
return; return;
} }
bytes += irp->bytes_transferred; bytes += irp->bytes_transferred;
if (test->protocol->id == Ptcp && has_tcpinfo_retransmits()) if (test->sender && test->sender_has_retransmits)
retransmits += irp->this_retrans; retransmits += irp->this_retrans;
} }
if (bytes < 0) { /* this can happen if timer goes off just when client exits */ if (bytes < 0) { /* this can happen if timer goes off just when client exits */
@ -1443,7 +1484,7 @@ iperf_print_intermediate(struct iperf_test *test)
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->sender && test->sender_has_retransmits) {
if (test->json_output) if (test->json_output)
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)); 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));
else else
@ -1463,7 +1504,7 @@ iperf_print_results(struct iperf_test *test)
cJSON *json_summary_streams = NULL; cJSON *json_summary_streams = NULL;
cJSON *json_summary_stream = NULL; cJSON *json_summary_stream = NULL;
long retransmits = 0, total_retransmits = 0; int 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];
char nbuf[UNIT_LEN]; char nbuf[UNIT_LEN];
@ -1484,7 +1525,7 @@ iperf_print_results(struct iperf_test *test)
if (test->verbose) if (test->verbose)
printf("Test Complete. Summary Results:\n"); printf("Test Complete. Summary Results:\n");
if (test->protocol->id == Ptcp) if (test->protocol->id == Ptcp)
if (has_tcpinfo_retransmits()) if (test->sender_has_retransmits)
fputs(report_bw_retrans_header, stdout); fputs(report_bw_retrans_header, stdout);
else else
fputs(report_bw_header, stdout); fputs(report_bw_header, stdout);
@ -1510,10 +1551,8 @@ iperf_print_results(struct iperf_test *test)
total_received += bytes_received; total_received += bytes_received;
if (test->protocol->id == Ptcp) { if (test->protocol->id == Ptcp) {
if (has_tcpinfo_retransmits()) { if (test->sender_has_retransmits)
retransmits = get_tcpinfo_total_retransmits(TAILQ_LAST(&sp->result->interval_results, irlisthead)); total_retransmits += sp->result->retransmits;
total_retransmits += retransmits;
}
} else { } else {
total_packets += sp->packet_count; total_packets += sp->packet_count;
lost_packets += sp->cnt_error; lost_packets += sp->cnt_error;
@ -1527,11 +1566,11 @@ iperf_print_results(struct iperf_test *test)
if (test->protocol->id == Ptcp) { if (test->protocol->id == Ptcp) {
if (!test->json_output) if (!test->json_output)
fputs(" Sent\n", stdout); fputs(" Sent\n", stdout);
if (has_tcpinfo_retransmits()) { if (test->sender_has_retransmits) {
if (test->json_output) 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 retransmits: %d", (int64_t) sp->socket, (double) start_time, (double) end_time, (double) end_time, (int64_t) bytes_sent, bandwidth * 8, (int64_t) retransmits)); 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) sp->result->retransmits));
else else
printf(report_bw_retrans_format, sp->socket, start_time, end_time, ubuf, nbuf, retransmits); printf(report_bw_retrans_format, sp->socket, start_time, end_time, ubuf, nbuf, sp->result->retransmits);
} else { } else {
if (test->json_output) 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)); 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));
@ -1573,7 +1612,7 @@ iperf_print_results(struct iperf_test *test)
if (test->protocol->id == Ptcp) { if (test->protocol->id == Ptcp) {
if (!test->json_output) if (!test->json_output)
printf(" Total sent\n"); printf(" Total sent\n");
if (has_tcpinfo_retransmits()) { if (test->sender_has_retransmits) {
if (test->json_output) 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)); 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 else
@ -1658,7 +1697,7 @@ print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON *
** else nothing. ** else nothing.
*/ */
if (timeval_equals(&sp->result->start_time, &irp->interval_start_time)) if (timeval_equals(&sp->result->start_time, &irp->interval_start_time))
if (test->protocol->id == Ptcp && has_tcpinfo_retransmits()) if (test->sender && test->sender_has_retransmits)
fputs(report_bw_retrans_header, stdout); fputs(report_bw_retrans_header, stdout);
else else
fputs(report_bw_header, stdout); fputs(report_bw_header, stdout);
@ -1674,7 +1713,7 @@ print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON *
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->sender && test->sender_has_retransmits) {
if (test->json_output) 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 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)); 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));
else else

Просмотреть файл

@ -169,6 +169,7 @@ void sig_handler(int);
void usage(); void usage();
void usage_long(); void usage_long();
void warning(char *); void warning(char *);
int iperf_sum_results(struct iperf_test *);
int iperf_exchange_results(struct iperf_test *); int iperf_exchange_results(struct iperf_test *);
int iperf_init_test(struct iperf_test *); int iperf_init_test(struct iperf_test *);
int iperf_parse_arguments(struct iperf_test *, int, char **); int iperf_parse_arguments(struct iperf_test *, int, char **);

Просмотреть файл

@ -87,6 +87,8 @@ iperf_handle_message_client(struct iperf_test *test)
case TEST_RUNNING: case TEST_RUNNING:
break; break;
case EXCHANGE_RESULTS: case EXCHANGE_RESULTS:
if (iperf_sum_results(test) < 0)
return -1;
if (iperf_exchange_results(test) < 0) if (iperf_exchange_results(test) < 0)
return -1; return -1;
break; break;

Просмотреть файл

@ -185,6 +185,8 @@ iperf_handle_message_server(struct iperf_test *test)
i_errno = IESENDMESSAGE; i_errno = IESENDMESSAGE;
return -1; return -1;
} }
if (iperf_sum_results(test) < 0)
return -1;
if (iperf_exchange_results(test) < 0) if (iperf_exchange_results(test) < 0)
return -1; return -1;
test->state = DISPLAY_RESULTS; test->state = DISPLAY_RESULTS;
@ -260,6 +262,7 @@ iperf_test_reset(struct iperf_test *test)
test->reverse = 0; test->reverse = 0;
test->sender = 0; test->sender = 0;
test->sender_has_retransmits = 0;
test->no_delay = 0; test->no_delay = 0;
FD_ZERO(&test->read_set); FD_ZERO(&test->read_set);