Fix retransmit reporting for Linux.

This commit is contained in:
Jef Poskanzer 2012-12-03 15:48:54 -08:00
parent 437537fe30
commit acad430d3d
4 changed files with 19 additions and 10 deletions

View File

@ -27,6 +27,7 @@ struct iperf_interval_results
float interval_duration;
#if defined(linux) || defined(__FreeBSD__)
struct tcp_info tcpInfo; /* getsockopt(TCP_INFO) for Linux and FreeBSD */
int this_retrans;
#else
char *tcpInfo; /* just a placeholder */
#endif

View File

@ -1019,13 +1019,12 @@ JSON_read(int fd)
/*************************************************************/
/**
* add_to_interval_list -- adds new interval to the interval_list
* XXX: Interval lists should use SLIST implementation fro queue
*/
void
add_to_interval_list(struct iperf_stream_result * rp, struct iperf_interval_results * new)
{
struct iperf_interval_results *irp = NULL;
struct iperf_interval_results *irp;
irp = (struct iperf_interval_results *) malloc(sizeof(struct iperf_interval_results));
memcpy(irp, new, sizeof(struct iperf_interval_results));
@ -1251,7 +1250,8 @@ iperf_stats_callback(struct iperf_test * test)
{
struct iperf_stream *sp;
struct iperf_stream_result *rp = NULL;
struct iperf_interval_results *irp = NULL, temp;
struct iperf_interval_results *irp, temp;
int prev_total_retransmits;
SLIST_FOREACH(sp, &test->streams, streams) {
rp = sp->result;
@ -1272,8 +1272,15 @@ iperf_stats_callback(struct iperf_test * test)
memcpy(&temp.interval_end_time, &rp->end_time, sizeof(struct timeval));
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()) {
irp = TAILQ_LAST(&rp->interval_results, irlisthead);
if (irp == NULL)
prev_total_retransmits = 0;
else
prev_total_retransmits = get_tcpinfo_total_retransmits(irp);
save_tcpinfo(sp, &temp);
temp.this_retrans = get_tcpinfo_total_retransmits(&temp) - prev_total_retransmits;
}
add_to_interval_list(rp, &temp);
rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0;
}
@ -1296,7 +1303,7 @@ iperf_print_intermediate(struct iperf_test *test)
irp = TAILQ_LAST(&sp->result->interval_results, irlisthead);
bytes += irp->bytes_transferred;
if (test->protocol->id == Ptcp && has_tcpinfo_retransmits())
retransmits += get_tcpinfo_retransmits(irp);
retransmits += irp->this_retrans;
}
if (bytes <=0 ) { /* this can happen if timer goes off just when client exits */
fprintf(stderr, "error: bytes <= 0!\n");
@ -1355,7 +1362,7 @@ iperf_print_results (struct iperf_test *test)
if (test->protocol->id == Ptcp) {
if (has_tcpinfo_retransmits()) {
retransmits = get_tcpinfo_retransmits(TAILQ_LAST(&sp->result->interval_results, irlisthead));
retransmits = get_tcpinfo_total_retransmits(TAILQ_LAST(&sp->result->interval_results, irlisthead));
total_retransmits += retransmits;
}
} else {
@ -1481,7 +1488,7 @@ print_interval_results(struct iperf_test * test, struct iperf_stream * sp)
et = timeval_diff(&sp->result->start_time,&irp->interval_end_time);
if (test->protocol->id == Ptcp && has_tcpinfo_retransmits())
printf(report_bw_retrans_format, sp->socket, st, et, ubuf, nbuf, get_tcpinfo_retransmits(irp));
printf(report_bw_retrans_format, sp->socket, st, et, ubuf, nbuf, irp->this_retrans);
else
printf(report_bw_format, sp->socket, st, et, ubuf, nbuf);
}

View File

@ -150,7 +150,7 @@ void iperf_free_stream(struct iperf_stream * sp);
int has_tcpinfo(void);
int has_tcpinfo_retransmits(void);
void save_tcpinfo(struct iperf_stream *sp, struct iperf_interval_results *irp);
long get_tcpinfo_retransmits(struct iperf_interval_results *irp);
long get_tcpinfo_total_retransmits(struct iperf_interval_results *irp);
void print_tcpinfo(struct iperf_test *test);
void build_tcpinfo_message(struct iperf_interval_results *r, char *message);

View File

@ -27,6 +27,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/types.h>
#include <sys/socket.h>
@ -79,10 +80,10 @@ save_tcpinfo(struct iperf_stream *sp, struct iperf_interval_results *irp)
/*************************************************************/
long
get_tcpinfo_retransmits(struct iperf_interval_results *irp)
get_tcpinfo_total_retransmits(struct iperf_interval_results *irp)
{
#if defined(linux)
return irp->tcpInfo.tcpi_retransmits;
return irp->tcpInfo.tcpi_total_retrans;
#else
#if defined(__FreeBSD__) && __FreeBSD_version >= 600000
return irp->tcpInfo.__tcpi_retransmits;