Blob Blame History Raw
From 7146bbf518d4b390a2839b3d0e47ef2116d4915d Mon Sep 17 00:00:00 2001
From: Jakub Kicinski <kuba@kernel.org>
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)