Keep track of SACKs and snd_cwnd from tcp_info (Linux only for now).
Committing this WIP so we can get some experimentation done with it.
This commit is contained in:
parent
cfe8c5fb47
commit
5cdc6a4ac8
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2011, The Regents of the University of California,
|
||||
* Copyright (c) 2009-2013, The Regents of the University of California,
|
||||
* through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
* required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
*
|
||||
@ -45,6 +45,8 @@ struct iperf_interval_results
|
||||
char *tcpInfo;
|
||||
#endif
|
||||
int interval_retrans;
|
||||
int interval_sacks;
|
||||
int snd_cwnd;
|
||||
TAILQ_ENTRY(iperf_interval_results) irlistentries;
|
||||
void *custom_data;
|
||||
};
|
||||
@ -57,6 +59,8 @@ struct iperf_stream_result
|
||||
iperf_size_t bytes_sent_this_interval;
|
||||
int stream_prev_total_retrans;
|
||||
int stream_retrans;
|
||||
int stream_prev_total_sacks;
|
||||
int stream_sacks;
|
||||
struct timeval start_time;
|
||||
struct timeval end_time;
|
||||
TAILQ_HEAD(irlisthead, iperf_interval_results) interval_results;
|
||||
|
@ -1595,6 +1595,7 @@ iperf_reset_stats(struct iperf_test *test)
|
||||
if (test->sender && test->sender_has_retransmits)
|
||||
rp->stream_prev_total_retrans = get_total_retransmits(sp->socket);
|
||||
rp->stream_retrans = 0;
|
||||
rp->stream_sacks = 0;
|
||||
rp->start_time = now;
|
||||
}
|
||||
}
|
||||
@ -1641,6 +1642,15 @@ iperf_stats_callback(struct iperf_test *test)
|
||||
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;
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -1673,6 +1683,7 @@ 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;
|
||||
@ -1703,8 +1714,10 @@ iperf_print_intermediate(struct iperf_test *test)
|
||||
}
|
||||
bytes += irp->bytes_transferred;
|
||||
if (test->protocol->id == Ptcp) {
|
||||
if (test->sender && test->sender_has_retransmits)
|
||||
if (test->sender && test->sender_has_retransmits) {
|
||||
retransmits += irp->interval_retrans;
|
||||
sacks += irp->interval_sacks;
|
||||
}
|
||||
} else {
|
||||
total_packets += irp->interval_packet_count;
|
||||
lost_packets += irp->interval_cnt_error;
|
||||
@ -1727,9 +1740,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 omitted: %b", (double) start_time, (double) end_time, (double) irp->interval_duration, (int64_t) bytes, bandwidth * 8, (int64_t) retransmits, irp->omitted));
|
||||
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));
|
||||
else
|
||||
iprintf(test, report_sum_bw_retrans_format, start_time, end_time, ubuf, nbuf, retransmits, irp->omitted?report_omitted:"");
|
||||
iprintf(test, report_sum_bw_retrans_format, start_time, end_time, ubuf, nbuf, retransmits, sacks, irp->omitted?report_omitted:"");
|
||||
} else {
|
||||
/* Interval sum, TCP without retransmits. */
|
||||
if (test->json_output)
|
||||
@ -1763,6 +1776,7 @@ 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];
|
||||
@ -1811,8 +1825,10 @@ iperf_print_results(struct iperf_test *test)
|
||||
total_received += bytes_received;
|
||||
|
||||
if (test->protocol->id == Ptcp) {
|
||||
if (test->sender_has_retransmits)
|
||||
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);
|
||||
lost_packets += sp->cnt_error;
|
||||
@ -1826,9 +1842,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", (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));
|
||||
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));
|
||||
else
|
||||
iprintf(test, report_bw_retrans_format, sp->socket, start_time, end_time, ubuf, nbuf, sp->result->stream_retrans, report_sender);
|
||||
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);
|
||||
} else {
|
||||
/* Summary, TCP without retransmits. */
|
||||
if (test->json_output)
|
||||
@ -1880,9 +1896,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", (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 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));
|
||||
else
|
||||
iprintf(test, report_sum_bw_retrans_format, start_time, end_time, ubuf, nbuf, total_retransmits, report_sender);
|
||||
iprintf(test, report_sum_bw_retrans_format, start_time, end_time, ubuf, nbuf, total_retransmits, total_sacks, report_sender);
|
||||
} else {
|
||||
/* Summary sum, TCP without retransmits. */
|
||||
if (test->json_output)
|
||||
@ -1988,9 +2004,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 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));
|
||||
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));
|
||||
else
|
||||
iprintf(test, report_bw_retrans_format, sp->socket, st, et, ubuf, nbuf, irp->interval_retrans, irp->omitted?report_omitted:"");
|
||||
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:"");
|
||||
} else {
|
||||
/* Interval, TCP without retransmits. */
|
||||
if (test->json_output)
|
||||
|
@ -162,6 +162,8 @@ 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);
|
||||
void print_tcpinfo(struct iperf_test *test);
|
||||
void build_tcpinfo_message(struct iperf_interval_results *r, char *message);
|
||||
|
||||
|
@ -224,7 +224,7 @@ const char report_bw_header[] =
|
||||
"[ ID] Interval Transfer Bandwidth\n";
|
||||
|
||||
const char report_bw_retrans_header[] =
|
||||
"[ ID] Interval Transfer Bandwidth Retransmits\n";
|
||||
"[ ID] Interval Transfer Bandwidth Retr SACK CWND\n";
|
||||
|
||||
const char report_bw_udp_header[] =
|
||||
"[ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams\n";
|
||||
@ -233,10 +233,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 %s\n";
|
||||
"[%3d] %6.2f-%-6.2f sec %ss %ss/sec %3d %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";
|
||||
@ -251,7 +251,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 %s\n";
|
||||
"[SUM] %6.2f-%-6.2f sec %ss %ss/sec %3d %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";
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2011, The Regents of the University of California,
|
||||
* Copyright (c) 2009-2013, The Regents of the University of California,
|
||||
* through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
* required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
*
|
||||
@ -96,6 +96,11 @@ get_total_retransmits(int socket)
|
||||
return -1;
|
||||
|
||||
#if defined(linux) && defined(TCP_MD5SIG)
|
||||
#if 0
|
||||
printf("tcpi_sacked %d\n", ti.tcpi_sacked);
|
||||
printf("tcpi_snd_cwnd %d\n", ti.tcpi_snd_cwnd);
|
||||
printf("tcpi_total_retrans %d\n", ti.tcpi_total_retrans);
|
||||
#endif
|
||||
return ti.tcpi_total_retrans;
|
||||
#else
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version >= 600000
|
||||
@ -110,6 +115,58 @@ get_total_retransmits(int socket)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************/
|
||||
long
|
||||
get_sacks(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_sacked;
|
||||
#else
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version >= 600000
|
||||
return ti.__tcpi_sacked;
|
||||
#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
|
||||
/*************************************************************/
|
||||
//print_tcpinfo(struct iperf_interval_results *r)
|
||||
|
Loading…
Reference in New Issue
Block a user