Fix retransmit accounting so it works right with the --omit flag.

This commit is contained in:
Jef Poskanzer 2013-10-28 17:13:30 -07:00
parent 8a7e01eb8f
commit 69376ec7ed
6 changed files with 33 additions and 44 deletions

View File

@ -30,12 +30,11 @@ struct iperf_interval_results
int omitted; int omitted;
#if defined(linux) || defined(__FreeBSD__) #if defined(linux) || defined(__FreeBSD__)
struct tcp_info tcpInfo; /* getsockopt(TCP_INFO) for Linux and FreeBSD */ struct tcp_info tcpInfo; /* getsockopt(TCP_INFO) for Linux and FreeBSD */
int this_retrans;
#else #else
/* Just placeholders, never accessed. */ /* Just placeholders, never accessed. */
char *tcpInfo; char *tcpInfo;
int this_retrans;
#endif #endif
int interval_retrans;
TAILQ_ENTRY(iperf_interval_results) irlistentries; TAILQ_ENTRY(iperf_interval_results) irlistentries;
void *custom_data; void *custom_data;
}; };
@ -46,7 +45,8 @@ 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; int stream_prev_total_retrans;
int stream_retrans;
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;

View File

@ -952,22 +952,6 @@ iperf_exchange_parameters(struct iperf_test *test)
return 0; return 0;
} }
/*************************************************************/
int
iperf_sum_results(struct iperf_test *test)
{
struct iperf_stream *sp;
if (test->sender && test->sender_has_retransmits) {
SLIST_FOREACH(sp, &test->streams, streams) {
sp->result->retransmits = get_tcpinfo_total_retransmits(TAILQ_LAST(&sp->result->interval_results, irlisthead));
}
}
return 0;
}
/*************************************************************/ /*************************************************************/
int int
@ -1131,7 +1115,7 @@ 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; retransmits = (test->sender && test->sender_has_retransmits) ? sp->result->stream_retrans : -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_AddIntToObject(j_stream, "retransmits", retransmits);
@ -1231,7 +1215,7 @@ get_results(struct iperf_test *test)
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; sp->result->stream_retrans = retransmits;
} }
} }
} }
@ -1567,7 +1551,9 @@ iperf_reset_stats(struct iperf_test *test)
rp = sp->result; rp = sp->result;
rp->bytes_sent = rp->bytes_received = 0; rp->bytes_sent = rp->bytes_received = 0;
rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0; rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0;
rp->retransmits = 0; if (test->sender && test->sender_has_retransmits)
rp->stream_prev_total_retrans = get_total_retransmits(sp->socket);
rp->stream_retrans = 0;
rp->start_time = now; rp->start_time = now;
} }
} }
@ -1588,7 +1574,6 @@ 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;
struct iperf_interval_results *irp, temp; struct iperf_interval_results *irp, temp;
int prev_total_retransmits;
temp.omitted = test->omitting; temp.omitted = test->omitting;
SLIST_FOREACH(sp, &test->streams, streams) { SLIST_FOREACH(sp, &test->streams, streams) {
@ -1610,12 +1595,10 @@ iperf_stats_callback(struct iperf_test *test)
if (test->protocol->id == Ptcp && has_tcpinfo()) { if (test->protocol->id == Ptcp && has_tcpinfo()) {
save_tcpinfo(sp, &temp); save_tcpinfo(sp, &temp);
if (test->sender && test->sender_has_retransmits) { if (test->sender && test->sender_has_retransmits) {
irp = TAILQ_LAST(&rp->interval_results, irlisthead); long total_retrans = get_total_retransmits(sp->socket);
if (irp == NULL) temp.interval_retrans = total_retrans - rp->stream_prev_total_retrans;
prev_total_retransmits = 0; rp->stream_retrans += temp.interval_retrans;
else rp->stream_prev_total_retrans = total_retrans;
prev_total_retransmits = get_tcpinfo_total_retransmits(irp);
temp.this_retrans = get_tcpinfo_total_retransmits(&temp) - prev_total_retransmits;
} }
} }
add_to_interval_list(rp, &temp); add_to_interval_list(rp, &temp);
@ -1661,7 +1644,7 @@ iperf_print_intermediate(struct iperf_test *test)
} }
bytes += irp->bytes_transferred; bytes += irp->bytes_transferred;
if (test->sender && test->sender_has_retransmits) if (test->sender && test->sender_has_retransmits)
retransmits += irp->this_retrans; retransmits += irp->interval_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 */
iperf_err(test, "error: bytes < 0!"); iperf_err(test, "error: bytes < 0!");
@ -1748,7 +1731,7 @@ iperf_print_results(struct iperf_test *test)
if (test->protocol->id == Ptcp) { if (test->protocol->id == Ptcp) {
if (test->sender_has_retransmits) if (test->sender_has_retransmits)
total_retransmits += sp->result->retransmits; total_retransmits += sp->result->stream_retrans;
} else { } else {
total_packets += (sp->packet_count - sp->omitted_packet_count); total_packets += (sp->packet_count - sp->omitted_packet_count);
lost_packets += sp->cnt_error; lost_packets += sp->cnt_error;
@ -1763,9 +1746,9 @@ iperf_print_results(struct iperf_test *test)
fputs(" Sent\n", stdout); fputs(" Sent\n", stdout);
if (test->sender_has_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) sp->result->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->stream_retrans));
else else
printf(report_bw_retrans_format, sp->socket, start_time, end_time, ubuf, nbuf, sp->result->retransmits, ""); printf(report_bw_retrans_format, sp->socket, start_time, end_time, ubuf, nbuf, sp->result->stream_retrans, "");
} 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));
@ -1919,9 +1902,9 @@ print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON *
if (test->sender && test->sender_has_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 omitted: %b", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, (int64_t) irp->this_retrans, irp->omitted)); cJSON_AddItemToArray(json_interval_streams, iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f retransmits: %d omitted: %b", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, (int64_t) irp->interval_retrans, irp->omitted));
else else
printf(report_bw_retrans_format, sp->socket, st, et, ubuf, nbuf, irp->this_retrans, irp->omitted?report_omitted:""); printf(report_bw_retrans_format, sp->socket, st, et, ubuf, nbuf, irp->interval_retrans, irp->omitted?report_omitted:"");
} else { } else {
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 omitted: %b", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, irp->omitted)); cJSON_AddItemToArray(json_interval_streams, iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f omitted: %b", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, irp->omitted));

View File

@ -161,7 +161,7 @@ void iperf_free_stream(struct iperf_stream * sp);
int has_tcpinfo(void); int has_tcpinfo(void);
int has_tcpinfo_retransmits(void); int has_tcpinfo_retransmits(void);
void save_tcpinfo(struct iperf_stream *sp, struct iperf_interval_results *irp); void save_tcpinfo(struct iperf_stream *sp, struct iperf_interval_results *irp);
long get_tcpinfo_total_retransmits(struct iperf_interval_results *irp); long get_total_retransmits(int socket);
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);
@ -173,7 +173,6 @@ 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_create_send_timers(struct iperf_test *); int iperf_create_send_timers(struct iperf_test *);

View File

@ -203,8 +203,6 @@ 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;

View File

@ -192,8 +192,6 @@ iperf_handle_message_server(struct iperf_test *test)
} }
if (iperf_set_send_state(test, EXCHANGE_RESULTS) != 0) if (iperf_set_send_state(test, EXCHANGE_RESULTS) != 0)
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;
if (iperf_set_send_state(test, DISPLAY_RESULTS) != 0) if (iperf_set_send_state(test, DISPLAY_RESULTS) != 0)

View File

@ -86,17 +86,28 @@ save_tcpinfo(struct iperf_stream *sp, struct iperf_interval_results *irp)
/*************************************************************/ /*************************************************************/
long long
get_tcpinfo_total_retransmits(struct iperf_interval_results *irp) get_total_retransmits(int socket)
{ {
#if defined(linux) || defined(__FreeBSD__)
struct tcp_info ti;
socklen_t l = sizeof(ti);
if (getsockopt(socket, IPPROTO_TCP, TCP_INFO, (void *)&ti, &l) < 0)
return -1;
#if defined(linux) && defined(TCP_MD5SIG) #if defined(linux) && defined(TCP_MD5SIG)
return irp->tcpInfo.tcpi_total_retrans; return ti.tcpi_total_retrans;
#else #else
#if defined(__FreeBSD__) && __FreeBSD_version >= 600000 #if defined(__FreeBSD__) && __FreeBSD_version >= 600000
return irp->tcpInfo.__tcpi_retransmits; return ti.__tcpi_retransmits;
#else #else
return -1; return -1;
#endif #endif
#endif #endif
#else
return -1;
#endif
} }
#ifdef notdef #ifdef notdef