From 7146bbf518d4b390a2839b3d0e47ef2116d4915d Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 2 Feb 2022 09:38:24 -0800 Subject: [PATCH] Report number of reorder_seen TCP can detect reordering by tracking SACKs and timestamps coming back to the sender. This is useful information for investigating performance issues and testing networks as good networks should generally not reorder packets. --- src/iperf.h | 2 ++ src/iperf_api.c | 6 ++++-- src/iperf_api.h | 1 + src/tcp_info.c | 14 ++++++++++++++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/iperf.h b/src/iperf.h index 6de234325..2d280e7ee 100644 --- a/src/iperf.h +++ b/src/iperf.h @@ -110,6 +110,7 @@ struct iperf_interval_results int rtt; int rttvar; int pmtu; + int reorder; }; struct iperf_stream_result @@ -121,6 +122,7 @@ struct iperf_stream_result iperf_size_t bytes_sent_omit; int stream_prev_total_retrans; int stream_retrans; + int stream_reorder; int stream_prev_total_sacks; int stream_sacks; int stream_max_rtt; diff --git a/src/iperf_api.c b/src/iperf_api.c index 7462f823c..af0c6827f 100644 --- a/src/iperf_api.c +++ b/src/iperf_api.c @@ -3185,6 +3185,8 @@ iperf_stats_callback(struct iperf_test *test) temp.rttvar = get_rttvar(&temp); temp.pmtu = get_pmtu(&temp); + temp.reorder = get_reorder(&temp); + rp->stream_reorder = temp.reorder; } } } else { @@ -3623,7 +3625,7 @@ iperf_print_results(struct iperf_test *test) if (test->sender_has_retransmits) { /* Sender summary, TCP and SCTP 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 max_snd_cwnd: %d max_snd_wnd: %d max_rtt: %d min_rtt: %d mean_rtt: %d sender: %b", (int64_t) sp->socket, (double) start_time, (double) sender_time, (double) sender_time, (int64_t) bytes_sent, bandwidth * 8, (int64_t) sp->result->stream_retrans, (int64_t) sp->result->stream_max_snd_cwnd, (int64_t) sp->result->stream_max_snd_wnd, (int64_t) sp->result->stream_max_rtt, (int64_t) sp->result->stream_min_rtt, (int64_t) ((sp->result->stream_count_rtt == 0) ? 0 : sp->result->stream_sum_rtt / sp->result->stream_count_rtt), stream_must_be_sender)); + 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 reorder: %d max_snd_cwnd: %d max_snd_wnd: %d max_rtt: %d min_rtt: %d mean_rtt: %d sender: %b", (int64_t) sp->socket, (double) start_time, (double) sender_time, (double) sender_time, (int64_t) bytes_sent, bandwidth * 8, (int64_t) sp->result->stream_retrans, (int64_t) sp->result->stream_reorder, (int64_t) sp->result->stream_max_snd_cwnd, (int64_t) sp->result->stream_max_snd_wnd, (int64_t) sp->result->stream_max_rtt, (int64_t) sp->result->stream_min_rtt, (int64_t) ((sp->result->stream_count_rtt == 0) ? 0 : sp->result->stream_sum_rtt / sp->result->stream_count_rtt), stream_must_be_sender)); else if (test->role == 's' && !sp->sender) { if (test->verbose) @@ -4070,7 +4072,7 @@ print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON * if (test->sender_has_retransmits == 1 && sp->sender) { /* 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 snd_cwnd: %d snd_wnd: %d rtt: %d rttvar: %d pmtu: %d omitted: %b sender: %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, (int64_t) irp->snd_wnd, (int64_t) irp->rtt, (int64_t) irp->rttvar, (int64_t) irp->pmtu, irp->omitted, sp->sender)); + 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 snd_wnd: %d rtt: %d rttvar: %d pmtu: %d reorder: %d omitted: %b sender: %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, (int64_t) irp->snd_wnd, (int64_t) irp->rtt, (int64_t) irp->rttvar, (int64_t) irp->pmtu, (int64_t) irp->reorder, irp->omitted, sp->sender)); else { unit_snprintf(cbuf, UNIT_LEN, irp->snd_cwnd, 'A'); iperf_printf(test, report_bw_retrans_cwnd_format, sp->socket, mbuf, st, et, ubuf, nbuf, irp->interval_retrans, cbuf, irp->omitted?report_omitted:""); diff --git a/src/iperf_api.h b/src/iperf_api.h index b8da94d1e..84bc249c4 100644 --- a/src/iperf_api.h +++ b/src/iperf_api.h @@ -285,6 +285,7 @@ long get_snd_wnd(struct iperf_interval_results *irp); long get_rtt(struct iperf_interval_results *irp); long get_rttvar(struct iperf_interval_results *irp); long get_pmtu(struct iperf_interval_results *irp); +long get_reorder(struct iperf_interval_results *irp); void print_tcpinfo(struct iperf_test *test); void build_tcpinfo_message(struct iperf_interval_results *r, char *message); diff --git a/src/tcp_info.c b/src/tcp_info.c index 6b75384d4..1c6734d4f 100644 --- a/src/tcp_info.c +++ b/src/tcp_info.c @@ -213,6 +213,20 @@ get_pmtu(struct iperf_interval_results *irp) #endif } +/*************************************************************/ +/* + * Return number of reordering events seen. + */ +long +get_reorder(struct iperf_interval_results *irp) +{ +#if defined(linux) && defined(TCP_REPAIR_ON) + return irp->tcpInfo.tcpi_reord_seen; +#else + return -1; +#endif +} + /*************************************************************/ void build_tcpinfo_message(struct iperf_interval_results *r, char *message)