Follow-on to 4cfce137e89c based on some feedback and experience.

Rip out the tcpi_sacked support...it doesn't really keep a cumulative
total of SACKs received like we thought it did (it's instantaneous
state).

Convert tcpi_snd_cwnd (originally expressed in segments) to octets before
printing.

Re-work internal APIs for functions to get stuff out of tcp_info...rather
than doing a getsockopt() call per value, grab the values out of a
saved copy of the tcp_info structure (which we were getting in almost
every case anyway).

Issue:		99 (Additional TCP_INFO items)
This commit is contained in:
Bruce A. Mah 2013-12-19 13:37:50 -08:00
parent 310bd92410
commit dcd7b32b15
4 changed files with 30 additions and 85 deletions

View File

@ -1662,10 +1662,12 @@ iperf_reset_stats(struct iperf_test *test)
rp = sp->result;
rp->bytes_sent = rp->bytes_received = 0;
rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0;
if (test->sender && test->sender_has_retransmits)
rp->stream_prev_total_retrans = get_total_retransmits(sp->socket);
if (test->sender && test->sender_has_retransmits) {
struct iperf_interval_results ir; /* temporary results structure */
save_tcpinfo(sp, &ir);
rp->stream_prev_total_retrans = get_total_retransmits(&ir);
}
rp->stream_retrans = 0;
rp->stream_sacks = 0;
rp->start_time = now;
}
}
@ -1708,19 +1710,12 @@ iperf_stats_callback(struct iperf_test *test)
if ( has_tcpinfo()) {
save_tcpinfo(sp, &temp);
if (test->sender && test->sender_has_retransmits) {
long total_retrans = get_total_retransmits(sp->socket);
long total_retrans = get_total_retransmits(&temp);
temp.interval_retrans = total_retrans - rp->stream_prev_total_retrans;
rp->stream_retrans += temp.interval_retrans;
rp->stream_prev_total_retrans = total_retrans;
long total_sacks = get_sacks(sp->socket);
temp.interval_sacks = total_sacks - rp->stream_prev_total_sacks;
rp->stream_sacks += temp.interval_sacks;
rp->stream_prev_total_sacks = total_sacks;
long snd_cwnd = get_snd_cwnd(sp->socket);
temp.snd_cwnd = snd_cwnd;
temp.snd_cwnd = get_snd_cwnd(&temp);
}
}
} else {
@ -1753,7 +1748,6 @@ iperf_print_intermediate(struct iperf_test *test)
iperf_size_t bytes = 0;
double bandwidth;
int retransmits = 0;
int sacks = 0;
double start_time, end_time;
cJSON *json_interval;
cJSON *json_interval_streams;
@ -1786,7 +1780,6 @@ iperf_print_intermediate(struct iperf_test *test)
if (test->protocol->id == Ptcp) {
if (test->sender && test->sender_has_retransmits) {
retransmits += irp->interval_retrans;
sacks += irp->interval_sacks;
}
} else {
total_packets += irp->interval_packet_count;
@ -1810,9 +1803,9 @@ iperf_print_intermediate(struct iperf_test *test)
if (test->sender && test->sender_has_retransmits) {
/* Interval sum, TCP with retransmits. */
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 sacks: %d omitted: %b", (double) start_time, (double) end_time, (double) irp->interval_duration, (int64_t) bytes, bandwidth * 8, (int64_t) retransmits, (int64_t) sacks, irp->omitted));
cJSON_AddItemToObject(json_interval, "sum", iperf_json_printf("start: %f end: %f seconds: %f bytes: %d bits_per_second: %f retransmits: %d omitted: %b", (double) start_time, (double) end_time, (double) irp->interval_duration, (int64_t) bytes, bandwidth * 8, (int64_t) retransmits, irp->omitted));
else
iprintf(test, report_sum_bw_retrans_format, start_time, end_time, ubuf, nbuf, retransmits, sacks, irp->omitted?report_omitted:"");
iprintf(test, report_sum_bw_retrans_format, start_time, end_time, ubuf, nbuf, retransmits, irp->omitted?report_omitted:"");
} else {
/* Interval sum, TCP without retransmits. */
if (test->json_output)
@ -1846,7 +1839,6 @@ iperf_print_results(struct iperf_test *test)
cJSON *json_summary_streams = NULL;
cJSON *json_summary_stream = NULL;
int total_retransmits = 0;
int total_sacks = 0;
int total_packets = 0, lost_packets = 0;
char ubuf[UNIT_LEN];
char nbuf[UNIT_LEN];
@ -1897,7 +1889,6 @@ iperf_print_results(struct iperf_test *test)
if (test->protocol->id == Ptcp) {
if (test->sender_has_retransmits) {
total_retransmits += sp->result->stream_retrans;
total_sacks += sp->result->stream_sacks;
}
} else {
total_packets += (sp->packet_count - sp->omitted_packet_count);
@ -1912,9 +1903,9 @@ iperf_print_results(struct iperf_test *test)
if (test->sender_has_retransmits) {
/* Summary, TCP with retransmits. */
if (test->json_output)
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 sacks: %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, (int64_t) sp->result->stream_sacks));
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", (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
iprintf(test, report_bw_retrans_format, sp->socket, start_time, end_time, ubuf, nbuf, sp->result->stream_retrans, sp->result->stream_sacks, 0, report_sender);
iprintf(test, report_bw_retrans_format, sp->socket, start_time, end_time, ubuf, nbuf, sp->result->stream_retrans, 0, report_sender);
} else {
/* Summary, TCP without retransmits. */
if (test->json_output)
@ -1966,9 +1957,9 @@ iperf_print_results(struct iperf_test *test)
if (test->sender_has_retransmits) {
/* Summary sum, TCP with retransmits. */
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 sacks: %d", (double) start_time, (double) end_time, (double) end_time, (int64_t) total_sent, bandwidth * 8, (int64_t) total_retransmits, (int64_t) total_sacks));
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
iprintf(test, report_sum_bw_retrans_format, start_time, end_time, ubuf, nbuf, total_retransmits, total_sacks, report_sender);
iprintf(test, report_sum_bw_retrans_format, start_time, end_time, ubuf, nbuf, total_retransmits, report_sender);
} else {
/* Summary sum, TCP without retransmits. */
if (test->json_output)
@ -2074,9 +2065,9 @@ print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON *
if (test->sender && test->sender_has_retransmits) {
/* Interval, TCP with retransmits. */
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 sacks: %d snd_cwnd: %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, (int64_t) irp->interval_sacks, (int64_t) irp->snd_cwnd, 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 snd_cwnd: %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, (int64_t) irp->snd_cwnd, irp->omitted));
else
iprintf(test, report_bw_retrans_format, sp->socket, st, et, ubuf, nbuf, irp->interval_retrans, irp->interval_sacks, irp->snd_cwnd, irp->omitted?report_omitted:"");
iprintf(test, report_bw_retrans_format, sp->socket, st, et, ubuf, nbuf, irp->interval_retrans, irp->snd_cwnd, irp->omitted?report_omitted:"");
} else {
/* Interval, TCP without retransmits. */
if (test->json_output)

View File

@ -163,9 +163,8 @@ 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_total_retransmits(int socket);
long get_sacks(int socket);
long get_snd_cwnd(int socket);
long get_total_retransmits(struct iperf_interval_results *irp);
long get_snd_cwnd(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

@ -229,7 +229,7 @@ const char report_bw_header[] =
"[ ID] Interval Transfer Bandwidth\n";
const char report_bw_retrans_header[] =
"[ ID] Interval Transfer Bandwidth Retr SACK CWND\n";
"[ ID] Interval Transfer Bandwidth Retr CWND\n";
const char report_bw_udp_header[] =
"[ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams\n";
@ -238,10 +238,10 @@ const char report_bw_udp_sender_header[] =
"[ ID] Interval Transfer Bandwidth Total Datagrams\n";
const char report_bw_format[] =
"[%3d] %6.2f-%-6.2f sec %ss %ss/sec %s\n";
"[%3d] %6.2f-%-6.2f sec %ss %ss/sec %s\n";
const char report_bw_retrans_format[] =
"[%3d] %6.2f-%-6.2f sec %ss %ss/sec %3d %3d %3d %s\n";
"[%3d] %6.2f-%-6.2f sec %ss %ss/sec %3d %3d %s\n";
const char report_bw_udp_format[] =
"[%3d] %6.2f-%-6.2f sec %ss %ss/sec %5.3f ms %d/%d (%.2g%%) %s\n";
@ -256,7 +256,7 @@ const char report_sum_bw_format[] =
"[SUM] %6.2f-%-6.2f sec %ss %ss/sec %s\n";
const char report_sum_bw_retrans_format[] =
"[SUM] %6.2f-%-6.2f sec %ss %ss/sec %3d %3d %s\n";
"[SUM] %6.2f-%-6.2f sec %ss %ss/sec %3d %s\n";
const char report_sum_bw_udp_format[] =
"[SUM] %6.2f-%-6.2f sec %ss %ss/sec %5.3f ms %d/%d (%.2g%%) %s\n";

View File

@ -86,80 +86,35 @@ save_tcpinfo(struct iperf_stream *sp, struct iperf_interval_results *irp)
/*************************************************************/
long
get_total_retransmits(int socket)
get_total_retransmits(struct iperf_interval_results *irp)
{
#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)
return ti.tcpi_total_retrans;
return irp->tcpInfo.tcpi_total_retrans;
#else
#if defined(__FreeBSD__) && __FreeBSD_version >= 600000
return ti.__tcpi_retransmits;
return irp->tcpInfo.__tcpi_retransmits;
#else
return -1;
#endif
#endif
#else
return -1;
#endif
}
/*************************************************************/
/*
* Return snd_cwnd in octets.
*/
long
get_sacks(int socket)
get_snd_cwnd(struct iperf_interval_results *irp)
{
#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)
return ti.tcpi_sacked;
return irp->tcpInfo.tcpi_snd_cwnd * irp->tcpInfo.tcpi_snd_mss;
#else
#if defined(__FreeBSD__) && __FreeBSD_version >= 600000
return ti.__tcpi_sacked;
return irp->tcpInfo.tcpi_snd_cwnd * irp->tcpInfo.tcpi_snd_mss;
#else
return -1;
#endif
#endif
#else
return -1;
#endif
}
/*************************************************************/
long
get_snd_cwnd(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)
return ti.tcpi_snd_cwnd;
#else
#if defined(__FreeBSD__) && __FreeBSD_version >= 600000
return ti.tcpi_snd_cwnd;
#else
return -1;
#endif
#endif
#else
return -1;
#endif
}
#ifdef notdef