Skip to content

Server JSON Output Does Not Report Client's Results - #1908

Open
manedurphy wants to merge 2 commits into
esnet:masterfrom
manedurphy:iperf_1410_report_client_results
Open

Server JSON Output Does Not Report Client's Results#1908
manedurphy wants to merge 2 commits into
esnet:masterfrom
manedurphy:iperf_1410_report_client_results

Conversation

@manedurphy

@manedurphymanedurphy commented Jul 14, 2025

Copy link
Copy Markdown
Contributor

PLEASE NOTE the following text from the iperf3 license. Submitting a
pull request to the iperf3 repository constitutes "[making]
Enhancements available...publicly":

You are under no obligation whatsoever to provide any bug fixes, patches, or
upgrades to the features, functionality or performance of the source code
("Enhancements") to anyone; however, if you choose to make your Enhancements
available either publicly, or directly to Lawrence Berkeley National
Laboratory, without imposing a separate written license agreement for such
Enhancements, then you hereby grant the following license: a non-exclusive,
royalty-free perpetual license to install, use, modify, prepare derivative
works, incorporate into other computer software, distribute, and sublicense
such enhancements or derivative works thereof, in binary and source code form.

The complete iperf3 license is available in the LICENSE file in the
top directory of the iperf3 source tree.

  • Version of iperf3 (or development branch, such as master or
    3.1-STABLE) to which this pull request applies: master

  • Issues fixed (if any): iperf/#1410

  • Brief description of code changes (suitable for use as a commit message):

On the iperf server, no results are displayed from the client's side, even though this information is sent to the server. It appears that the reporter callback was called prior to setting the test state to DISPLAY_RESULTS. Moving the call to the reporter callback function to after that state is set seems to fix the issue, as I can now see the client's results displayed in the server's JSON output.

Server JSON
{
"start": {
"connected": [{
"socket": 5,
"local_host": "127.0.0.1",
"local_port": 5202,
"remote_host": "127.0.0.1",
"remote_port": 54714
}],
"version": "iperf 3.19+",
"system_info": "Linux windows-nexus 6.6.87.2-microsoft-standard-WSL2 #1 SMP PREEMPT_DYNAMIC Thu Jun 5 18:30:46 UTC 2025 x86_64",
"sock_bufsize": 0,
"sndbuf_actual": 16384,
"rcvbuf_actual": 131072,
"timestamp": {
"time": "Mon, 14 Jul 2025 17:47:32 GMT",
"timesecs": 1752515252,
"timemillisecs": 1752515252430
},
"accepted_connection": {
"host": "127.0.0.1",
"port": 54708
},
"cookie": "6qnxxmqahsmytu7tr3spkqhgrk7irlyktagx",
"tcp_mss_default": 0,
"target_bitrate": 0,
"fq_rate": 500000000,
"test_start": {
"protocol": "TCP",
"num_streams": 1,
"blksize": 131072,
"omit": 1,
"duration": 2,
"bytes": 0,
"blocks": 0,
"reverse": 0,
"tos": 0,
"target_bitrate": 0,
"bidir": 0,
"fqrate": 500000000,
"interval": 1
}
},
"intervals": [{
"streams": [{
"socket": 5,
"start": 0,
"end": 1.001054,
"seconds": 1.001054048538208,
"bytes": 62914560,
"bits_per_second": 502786518.6050337,
"omitted": true,
"sender": false
}],
"sum": {
"start": 0,
"end": 1.001054,
"seconds": 1.001054048538208,
"bytes": 62914560,
"bits_per_second": 502786518.6050337,
"omitted": true,
"sender": false
}
}, {
"streams": [{
"socket": 5,
"start": 1.3e-05,
"end": 1.000991,
"seconds": 1.0010039806365967,
"bytes": 62521344,
"bits_per_second": 499669093.90501356,
"omitted": false,
"sender": false
}],
"sum": {
"start": 1.3e-05,
"end": 1.000991,
"seconds": 1.0010039806365967,
"bytes": 62521344,
"bits_per_second": 499669093.90501356,
"omitted": false,
"sender": false
}
}, {
"streams": [{
"socket": 5,
"start": 1.000991,
"end": 2.001042,
"seconds": 1.0000510215759277,
"bytes": 62390272,
"bits_per_second": 499096711.29924917,
"omitted": false,
"sender": false
}],
"sum": {
"start": 1.000991,
"end": 2.001042,
"seconds": 1.0000510215759277,
"bytes": 62390272,
"bits_per_second": 499096711.29924917,
"omitted": false,
"sender": false
}
}, {
"streams": [{
"socket": 5,
"start": 2.001042,
"end": 2.002375,
"seconds": 0.0013330000219866633,
"bytes": 131072,
"bits_per_second": 786628644.189543,
"omitted": false,
"sender": false
}],
"sum": {
"start": 2.001042,
"end": 2.002375,
"seconds": 0.0013330000219866633,
"bytes": 131072,
"bits_per_second": 786628644.189543,
"omitted": false,
"sender": false
}
}],
"end": {
"streams": [{
"sender": {
"socket": 5,
"start": 0,
"end": 2.002327,
"seconds": 2.002327,
"bytes": 124649472,
"bits_per_second": 498018443.54094,
"retransmits": 0,
"reorder": 0,
"max_snd_cwnd": 0,
"max_snd_wnd": 0,
"max_rtt": 0,
"min_rtt": 0,
"mean_rtt": 0,
"sender": false
},
"receiver": {
"socket": 5,
"start": 0,
"end": 2.002375,
"seconds": 2.002375,
"bytes": 125042688,
"bits_per_second": 499577503.71433926,
"sender": false
}
}],
"sum_sent": {
"start": 0,
"end": 2.002327,
"seconds": 2.002327,
"bytes": 124649472,
"bits_per_second": 498018443.54094,
"retransmits": 0,
"sender": false
},
"sum_received": {
"start": 0,
"end": 2.002375,
"seconds": 2.002375,
"bytes": 125042688,
"bits_per_second": 499577503.71433926,
"sender": false
},
"cpu_utilization_percent": {
"host_total": 2.0814591122934472,
"host_user": 0.16557515140820453,
"host_system": 1.9158839608852427,
"remote_total": 1.5036114967449765,
"remote_user": 0.023864735875288281,
"remote_system": 1.4797800450201419
},
"sender_tcp_congestion": "cubic",
"receiver_tcp_congestion": "cubic"
}
}
Client JSON
{
"start": {
"connected": [{
"socket": 5,
"local_host": "127.0.0.1",
"local_port": 54714,
"remote_host": "127.0.0.1",
"remote_port": 5202
}],
"version": "iperf 3.19+",
"system_info": "Linux windows-nexus 6.6.87.2-microsoft-standard-WSL2 #1 SMP PREEMPT_DYNAMIC Thu Jun 5 18:30:46 UTC 2025 x86_64",
"timestamp": {
"time": "Mon, 14 Jul 2025 17:47:32 GMT",
"timesecs": 1752515252,
"timemillisecs": 1752515252430
},
"connecting_to": {
"host": "127.0.0.1",
"port": 5202
},
"cookie": "6qnxxmqahsmytu7tr3spkqhgrk7irlyktagx",
"tcp_mss_default": 32768,
"target_bitrate": 0,
"fq_rate": 500000000,
"sock_bufsize": 0,
"sndbuf_actual": 16384,
"rcvbuf_actual": 131072,
"test_start": {
"protocol": "TCP",
"num_streams": 1,
"blksize": 131072,
"omit": 1,
"duration": 2,
"bytes": 0,
"blocks": 0,
"reverse": 0,
"tos": 0,
"target_bitrate": 0,
"bidir": 0,
"fqrate": 500000000,
"interval": 1
}
},
"intervals": [{
"streams": [{
"socket": 5,
"start": 0,
"end": 1.000937,
"seconds": 1.0009369850158691,
"bytes": 65404928,
"bits_per_second": 522749615.44327831,
"retransmits": 0,
"snd_cwnd": 654830,
"snd_wnd": 6127872,
"rtt": 1083,
"rttvar": 9,
"pmtu": 65535,
"reorder": 0,
"omitted": true,
"sender": true
}],
"sum": {
"start": 0,
"end": 1.000937,
"seconds": 1.0009369850158691,
"bytes": 65404928,
"bits_per_second": 522749615.44327831,
"retransmits": 0,
"omitted": true,
"sender": true
}
}, {
"streams": [{
"socket": 5,
"start": 8.6e-05,
"end": 1.00049,
"seconds": 1.0005760192871094,
"bytes": 62259200,
"bits_per_second": 497786865.16479534,
"retransmits": 0,
"snd_cwnd": 654830,
"snd_wnd": 6127872,
"rtt": 1083,
"rttvar": 7,
"pmtu": 65535,
"reorder": 0,
"omitted": false,
"sender": true
}],
"sum": {
"start": 8.6e-05,
"end": 1.00049,
"seconds": 1.0005760192871094,
"bytes": 62259200,
"bits_per_second": 497786865.16479534,
"retransmits": 0,
"omitted": false,
"sender": true
}
}, {
"streams": [{
"socket": 5,
"start": 1.00049,
"end": 2.002327,
"seconds": 1.0018370151519775,
"bytes": 62390272,
"bits_per_second": 498206962.26150489,
"retransmits": 0,
"snd_cwnd": 654830,
"snd_wnd": 6127872,
"rtt": 1091,
"rttvar": 20,
"pmtu": 65535,
"reorder": 0,
"omitted": false,
"sender": true
}],
"sum": {
"start": 1.00049,
"end": 2.002327,
"seconds": 1.0018370151519775,
"bytes": 62390272,
"bits_per_second": 498206962.26150489,
"retransmits": 0,
"omitted": false,
"sender": true
}
}],
"end": {
"streams": [{
"sender": {
"socket": 5,
"start": 0,
"end": 2.002327,
"seconds": 2.002327,
"bytes": 124649472,
"bits_per_second": 498018443.54094,
"retransmits": 0,
"reorder": 0,
"max_snd_cwnd": 654830,
"max_snd_wnd": 6127872,
"max_rtt": 1091,
"min_rtt": 1083,
"mean_rtt": 1085,
"sender": true
},
"receiver": {
"socket": 5,
"start": 0,
"end": 2.002375,
"seconds": 2.002327,
"bytes": 125042688,
"bits_per_second": 499577503.71433926,
"sender": true
}
}],
"sum_sent": {
"start": 0,
"end": 2.002327,
"seconds": 2.002327,
"bytes": 124649472,
"bits_per_second": 498018443.54094,
"retransmits": 0,
"sender": true
},
"sum_received": {
"start": 0,
"end": 2.002375,
"seconds": 2.002375,
"bytes": 125042688,
"bits_per_second": 499577503.71433926,
"sender": true
},
"cpu_utilization_percent": {
"host_total": 1.5036114967449765,
"host_user": 0.023864735875288281,
"host_system": 1.4797800450201419,
"remote_total": 2.0814591122934472,
"remote_user": 0.16557515140820453,
"remote_system": 1.9158839608852427
},
"sender_tcp_congestion": "cubic",
"receiver_tcp_congestion": "cubic"
}
}

Update 07-14-2025

My first round of changes were breaking. Moving the call to the reporter callback function would break --get-server-output by leaving the end section empty. The root of this issue is that the server calls the callback BEFORE receiving results from the client as part of iperf_exchange_results. The expected behavior for the server is as follows:

  1. Set the state to EXCHANGE_RESULTS.
  2. Get results from the client.
  3. Use the results from the client to finalize/populate the JSON output for the server's output.
  4. Send the server's JSON result to the client.

The latest changes reflect this flow, and a change to the report callback was made to also trigger for the EXCHANGE_RESULTS test state. I have not thoroughly tested how that change impacts other areas of the code, so I would definitely appreciate any thoughts for concern there from the maintainers.

Server JSON
iperf3 -s -p 5202 --json
{
"start": {
"connected": [{
"socket": 5,
"local_host": "127.0.0.1",
"local_port": 5202,
"remote_host": "127.0.0.1",
"remote_port": 51526
}, {
"socket": 9,
"local_host": "127.0.0.1",
"local_port": 5202,
"remote_host": "127.0.0.1",
"remote_port": 51536
}],
"version": "iperf 3.19+",
"system_info": "Linux windows-nexus 6.6.87.2-microsoft-standard-WSL2 #1 SMP PREEMPT_DYNAMIC Thu Jun 5 18:30:46 UTC 2025 x86_64",
"sock_bufsize": 0,
"sndbuf_actual": 16384,
"rcvbuf_actual": 131072,
"timestamp": {
"time": "Mon, 14 Jul 2025 20:34:46 GMT",
"timesecs": 1752525286,
"timemillisecs": 1752525286818
},
"accepted_connection": {
"host": "127.0.0.1",
"port": 51516
},
"cookie": "abwqn6l3lf5qjnjygqipc43uzk2jt7q5wdpu",
"tcp_mss_default": 0,
"target_bitrate": 0,
"fq_rate": 500000000,
"test_start": {
"protocol": "TCP",
"num_streams": 2,
"blksize": 131072,
"omit": 1,
"duration": 2,
"bytes": 0,
"blocks": 0,
"reverse": 0,
"tos": 0,
"target_bitrate": 0,
"bidir": 0,
"fqrate": 500000000,
"interval": 1
}
},
"intervals": [{
"streams": [{
"socket": 5,
"start": 0,
"end": 1.000216,
"seconds": 1.000216007232666,
"bytes": 62783488,
"bits_per_second": 502159433.93031961,
"omitted": true,
"sender": false
}, {
"socket": 9,
"start": 0,
"end": 1.000226,
"seconds": 1.0002260208129883,
"bytes": 62783488,
"bits_per_second": 502154406.65276271,
"omitted": true,
"sender": false
}],
"sum": {
"start": 0,
"end": 1.000216,
"seconds": 1.000216007232666,
"bytes": 125566976,
"bits_per_second": 1004318867.8606392,
"omitted": true,
"sender": false
}
}, {
"streams": [{
"socket": 5,
"start": 5.1e-05,
"end": 1.00097,
"seconds": 1.0010210275650024,
"bytes": 62521344,
"bits_per_second": 499660584.76980478,
"omitted": false,
"sender": false
}, {
"socket": 9,
"start": 4.1e-05,
"end": 1.000977,
"seconds": 1.0010180473327637,
"bytes": 62521344,
"bits_per_second": 499662072.35995078,
"omitted": false,
"sender": false
}],
"sum": {
"start": 5.1e-05,
"end": 1.00097,
"seconds": 1.0010210275650024,
"bytes": 125042688,
"bits_per_second": 999321169.53960955,
"omitted": false,
"sender": false
}
}, {
"streams": [{
"socket": 5,
"start": 1.00097,
"end": 2.000962,
"seconds": 0.9999920129776,
"bytes": 62521344,
"bits_per_second": 500174746.90690744,
"omitted": false,
"sender": false
}, {
"socket": 9,
"start": 1.000977,
"end": 2.000968,
"seconds": 0.999990999698639,
"bytes": 62521344,
"bits_per_second": 500175253.728017,
"omitted": false,
"sender": false
}],
"sum": {
"start": 1.00097,
"end": 2.000962,
"seconds": 0.9999920129776,
"bytes": 125042688,
"bits_per_second": 1000349493.8138149,
"omitted": false,
"sender": false
}
}, {
"streams": [{
"socket": 5,
"start": 2.000962,
"end": 2.00393,
"seconds": 0.0029680000152438879,
"bytes": 131072,
"bits_per_second": 353293798.724538,
"omitted": false,
"sender": false
}, {
"socket": 9,
"start": 2.000968,
"end": 2.003932,
"seconds": 0.0029639999847859144,
"bytes": 131072,
"bits_per_second": 353770582.1127854,
"omitted": false,
"sender": false
}],
"sum": {
"start": 2.000962,
"end": 2.00393,
"seconds": 0.0029680000152438879,
"bytes": 262144,
"bits_per_second": 706587597.449076,
"omitted": false,
"sender": false
}
}],
"end": {
"streams": [{
"sender": {
"socket": 5,
"start": 0,
"end": 2.003197,
"seconds": 2.003197,
"bytes": 124649472,
"bits_per_second": 497802151.261209,
"retransmits": 0,
"reorder": 0,
"max_snd_cwnd": 0,
"max_snd_wnd": 0,
"max_rtt": 0,
"min_rtt": 0,
"mean_rtt": 0,
"sender": false
},
"receiver": {
"socket": 5,
"start": 0,
"end": 2.00393,
"seconds": 2.00393,
"bytes": 125173760,
"bits_per_second": 499713103.751129,
"sender": false
}
}, {
"sender": {
"socket": 9,
"start": 0,
"end": 2.003197,
"seconds": 2.003197,
"bytes": 124649472,
"bits_per_second": 497802151.261209,
"retransmits": 0,
"reorder": 0,
"max_snd_cwnd": 0,
"max_snd_wnd": 0,
"max_rtt": 0,
"min_rtt": 0,
"mean_rtt": 0,
"sender": false
},
"receiver": {
"socket": 9,
"start": 0,
"end": 2.00393,
"seconds": 2.00393,
"bytes": 125173760,
"bits_per_second": 499713103.751129,
"sender": false
}
}],
"sum_sent": {
"start": 0,
"end": 2.003197,
"seconds": 2.003197,
"bytes": 249298944,
"bits_per_second": 995604302.522418,
"retransmits": 0,
"sender": false
},
"sum_received": {
"start": 0,
"end": 2.00393,
"seconds": 2.00393,
"bytes": 250347520,
"bits_per_second": 999426207.502258,
"sender": false
},
"cpu_utilization_percent": {
"host_total": 4.3199350250562958,
"host_user": 0.279305713434535,
"host_system": 4.04059602527765,
"remote_total": 3.0420990823002212,
"remote_user": 1.4897442849610014,
"remote_system": 1.5523547973392195
},
"sender_tcp_congestion": "cubic",
"receiver_tcp_congestion": "cubic"
}
}
Client JSON
iperf3 -c 127.0.0.1 --fq-rate 0.5Gb/1s --time 2 --omit 1 --parallel 2 --json --congestion cubic --port 5202 --get-server-output
{
"start": {
"connected": [{
"socket": 5,
"local_host": "127.0.0.1",
"local_port": 51526,
"remote_host": "127.0.0.1",
"remote_port": 5202
}, {
"socket": 8,
"local_host": "127.0.0.1",
"local_port": 51536,
"remote_host": "127.0.0.1",
"remote_port": 5202
}],
"version": "iperf 3.19+",
"system_info": "Linux windows-nexus 6.6.87.2-microsoft-standard-WSL2 #1 SMP PREEMPT_DYNAMIC Thu Jun 5 18:30:46 UTC 2025 x86_64",
"timestamp": {
"time": "Mon, 14 Jul 2025 20:34:46 GMT",
"timesecs": 1752525286,
"timemillisecs": 1752525286818
},
"connecting_to": {
"host": "127.0.0.1",
"port": 5202
},
"cookie": "abwqn6l3lf5qjnjygqipc43uzk2jt7q5wdpu",
"tcp_mss_default": 32768,
"target_bitrate": 0,
"fq_rate": 500000000,
"sock_bufsize": 0,
"sndbuf_actual": 16384,
"rcvbuf_actual": 131072,
"test_start": {
"protocol": "TCP",
"num_streams": 2,
"blksize": 131072,
"omit": 1,
"duration": 2,
"bytes": 0,
"blocks": 0,
"reverse": 0,
"tos": 0,
"target_bitrate": 0,
"bidir": 0,
"fqrate": 500000000,
"interval": 1
}
},
"intervals": [{
"streams": [{
"socket": 5,
"start": 0,
"end": 1.000852,
"seconds": 1.0008519887924194,
"bytes": 65404928,
"bits_per_second": 522794009.36327845,
"retransmits": 0,
"snd_cwnd": 654830,
"snd_wnd": 3858944,
"rtt": 1078,
"rttvar": 10,
"pmtu": 65535,
"reorder": 0,
"omitted": true,
"sender": true
}, {
"socket": 8,
"start": 0,
"end": 1.000856,
"seconds": 1.0008560419082642,
"bytes": 65404928,
"bits_per_second": 522791892.23094958,
"retransmits": 0,
"snd_cwnd": 654830,
"snd_wnd": 6127872,
"rtt": 1084,
"rttvar": 6,
"pmtu": 65535,
"reorder": 0,
"omitted": true,
"sender": true
}],
"sum": {
"start": 0,
"end": 1.000852,
"seconds": 1.0008519887924194,
"bytes": 130809856,
"bits_per_second": 1045588018.7265569,
"retransmits": 0,
"omitted": true,
"sender": true
}
}, {
"streams": [{
"socket": 5,
"start": 5.2e-05,
"end": 1.000946,
"seconds": 1.0009980201721191,
"bytes": 62259200,
"bits_per_second": 497577008.10872483,
"retransmits": 0,
"snd_cwnd": 654830,
"snd_wnd": 3858944,
"rtt": 1062,
"rttvar": 17,
"pmtu": 65535,
"reorder": 0,
"omitted": false,
"sender": true
}, {
"socket": 8,
"start": 4.8e-05,
"end": 1.000952,
"seconds": 1.0010000467300415,
"bytes": 62259200,
"bits_per_second": 497576000.74750531,
"retransmits": 0,
"snd_cwnd": 654830,
"snd_wnd": 6127872,
"rtt": 1081,
"rttvar": 14,
"pmtu": 65535,
"reorder": 0,
"omitted": false,
"sender": true
}],
"sum": {
"start": 5.2e-05,
"end": 1.000946,
"seconds": 1.0009980201721191,
"bytes": 124518400,
"bits_per_second": 995154016.21744967,
"retransmits": 0,
"omitted": false,
"sender": true
}
}, {
"streams": [{
"socket": 5,
"start": 1.000946,
"end": 2.003197,
"seconds": 1.0022510290145874,
"bytes": 62390272,
"bits_per_second": 498001160.93743163,
"retransmits": 0,
"snd_cwnd": 654830,
"snd_wnd": 3858944,
"rtt": 1084,
"rttvar": 14,
"pmtu": 65535,
"reorder": 0,
"omitted": false,
"sender": true
}, {
"socket": 8,
"start": 1.000952,
"end": 2.0032,
"seconds": 1.0022480487823486,
"bytes": 62390272,
"bits_per_second": 498002641.767568,
"retransmits": 0,
"snd_cwnd": 654830,
"snd_wnd": 6127872,
"rtt": 1081,
"rttvar": 5,
"pmtu": 65535,
"reorder": 0,
"omitted": false,
"sender": true
}],
"sum": {
"start": 1.000946,
"end": 2.003197,
"seconds": 1.0022510290145874,
"bytes": 124780544,
"bits_per_second": 996002321.87486327,
"retransmits": 0,
"omitted": false,
"sender": true
}
}],
"end": {
"streams": [{
"sender": {
"socket": 5,
"start": 0,
"end": 2.003197,
"seconds": 2.003197,
"bytes": 124649472,
"bits_per_second": 497802151.261209,
"retransmits": 0,
"reorder": 0,
"max_snd_cwnd": 654830,
"max_snd_wnd": 3858944,
"max_rtt": 1084,
"min_rtt": 1062,
"mean_rtt": 1074,
"sender": true
},
"receiver": {
"socket": 5,
"start": 0,
"end": 2.00393,
"seconds": 2.003197,
"bytes": 125173760,
"bits_per_second": 499713103.751129,
"sender": true
}
}, {
"sender": {
"socket": 8,
"start": 0,
"end": 2.003197,
"seconds": 2.003197,
"bytes": 124649472,
"bits_per_second": 497802151.261209,
"retransmits": 0,
"reorder": 0,
"max_snd_cwnd": 654830,
"max_snd_wnd": 6127872,
"max_rtt": 1084,
"min_rtt": 1081,
"mean_rtt": 1082,
"sender": true
},
"receiver": {
"socket": 8,
"start": 0,
"end": 2.00393,
"seconds": 2.003197,
"bytes": 125173760,
"bits_per_second": 499713103.751129,
"sender": true
}
}],
"sum_sent": {
"start": 0,
"end": 2.003197,
"seconds": 2.003197,
"bytes": 249298944,
"bits_per_second": 995604302.522418,
"retransmits": 0,
"sender": true
},
"sum_received": {
"start": 0,
"end": 2.00393,
"seconds": 2.00393,
"bytes": 250347520,
"bits_per_second": 999426207.502258,
"sender": true
},
"cpu_utilization_percent": {
"host_total": 3.0420990823002212,
"host_user": 1.4897442849610014,
"host_system": 1.5523547973392195,
"remote_total": 4.3199350250562958,
"remote_user": 0.279305713434535,
"remote_system": 4.04059602527765
},
"sender_tcp_congestion": "cubic",
"receiver_tcp_congestion": "cubic"
},
"server_output_json": {
"start": {
"connected": [{
"socket": 5,
"local_host": "127.0.0.1",
"local_port": 5202,
"remote_host": "127.0.0.1",
"remote_port": 51526
}, {
"socket": 9,
"local_host": "127.0.0.1",
"local_port": 5202,
"remote_host": "127.0.0.1",
"remote_port": 51536
}],
"version": "iperf 3.19+",
"system_info": "Linux windows-nexus 6.6.87.2-microsoft-standard-WSL2 #1 SMP PREEMPT_DYNAMIC Thu Jun 5 18:30:46 UTC 2025 x86_64",
"sock_bufsize": 0,
"sndbuf_actual": 16384,
"rcvbuf_actual": 131072,
"timestamp": {
"time": "Mon, 14 Jul 2025 20:34:46 GMT",
"timesecs": 1752525286,
"timemillisecs": 1752525286818
},
"accepted_connection": {
"host": "127.0.0.1",
"port": 51516
},
"cookie": "abwqn6l3lf5qjnjygqipc43uzk2jt7q5wdpu",
"tcp_mss_default": 0,
"target_bitrate": 0,
"fq_rate": 500000000,
"test_start": {
"protocol": "TCP",
"num_streams": 2,
"blksize": 131072,
"omit": 1,
"duration": 2,
"bytes": 0,
"blocks": 0,
"reverse": 0,
"tos": 0,
"target_bitrate": 0,
"bidir": 0,
"fqrate": 500000000,
"interval": 1
}
},
"intervals": [{
"streams": [{
"socket": 5,
"start": 0,
"end": 1.000216,
"seconds": 1.000216007232666,
"bytes": 62783488,
"bits_per_second": 502159433.93031961,
"omitted": true,
"sender": false
}, {
"socket": 9,
"start": 0,
"end": 1.000226,
"seconds": 1.0002260208129883,
"bytes": 62783488,
"bits_per_second": 502154406.65276271,
"omitted": true,
"sender": false
}],
"sum": {
"start": 0,
"end": 1.000216,
"seconds": 1.000216007232666,
"bytes": 125566976,
"bits_per_second": 1004318867.8606392,
"omitted": true,
"sender": false
}
}, {
"streams": [{
"socket": 5,
"start": 5.1e-05,
"end": 1.00097,
"seconds": 1.0010210275650024,
"bytes": 62521344,
"bits_per_second": 499660584.76980478,
"omitted": false,
"sender": false
}, {
"socket": 9,
"start": 4.1e-05,
"end": 1.000977,
"seconds": 1.0010180473327637,
"bytes": 62521344,
"bits_per_second": 499662072.35995078,
"omitted": false,
"sender": false
}],
"sum": {
"start": 5.1e-05,
"end": 1.00097,
"seconds": 1.0010210275650024,
"bytes": 125042688,
"bits_per_second": 999321169.53960955,
"omitted": false,
"sender": false
}
}, {
"streams": [{
"socket": 5,
"start": 1.00097,
"end": 2.000962,
"seconds": 0.9999920129776,
"bytes": 62521344,
"bits_per_second": 500174746.90690744,
"omitted": false,
"sender": false
}, {
"socket": 9,
"start": 1.000977,
"end": 2.000968,
"seconds": 0.999990999698639,
"bytes": 62521344,
"bits_per_second": 500175253.728017,
"omitted": false,
"sender": false
}],
"sum": {
"start": 1.00097,
"end": 2.000962,
"seconds": 0.9999920129776,
"bytes": 125042688,
"bits_per_second": 1000349493.8138149,
"omitted": false,
"sender": false
}
}, {
"streams": [{
"socket": 5,
"start": 2.000962,
"end": 2.00393,
"seconds": 0.0029680000152438879,
"bytes": 131072,
"bits_per_second": 353293798.724538,
"omitted": false,
"sender": false
}, {
"socket": 9,
"start": 2.000968,
"end": 2.003932,
"seconds": 0.0029639999847859144,
"bytes": 131072,
"bits_per_second": 353770582.1127854,
"omitted": false,
"sender": false
}],
"sum": {
"start": 2.000962,
"end": 2.00393,
"seconds": 0.0029680000152438879,
"bytes": 262144,
"bits_per_second": 706587597.449076,
"omitted": false,
"sender": false
}
}],
"end": {
"streams": [{
"sender": {
"socket": 5,
"start": 0,
"end": 2.003197,
"seconds": 2.003197,
"bytes": 124649472,
"bits_per_second": 497802151.261209,
"retransmits": 0,
"reorder": 0,
"max_snd_cwnd": 0,
"max_snd_wnd": 0,
"max_rtt": 0,
"min_rtt": 0,
"mean_rtt": 0,
"sender": false
},
"receiver": {
"socket": 5,
"start": 0,
"end": 2.00393,
"seconds": 2.00393,
"bytes": 125173760,
"bits_per_second": 499713103.751129,
"sender": false
}
}, {
"sender": {
"socket": 9,
"start": 0,
"end": 2.003197,
"seconds": 2.003197,
"bytes": 124649472,
"bits_per_second": 497802151.261209,
"retransmits": 0,
"reorder": 0,
"max_snd_cwnd": 0,
"max_snd_wnd": 0,
"max_rtt": 0,
"min_rtt": 0,
"mean_rtt": 0,
"sender": false
},
"receiver": {
"socket": 9,
"start": 0,
"end": 2.00393,
"seconds": 2.00393,
"bytes": 125173760,
"bits_per_second": 499713103.751129,
"sender": false
}
}],
"sum_sent": {
"start": 0,
"end": 2.003197,
"seconds": 2.003197,
"bytes": 249298944,
"bits_per_second": 995604302.522418,
"retransmits": 0,
"sender": false
},
"sum_received": {
"start": 0,
"end": 2.00393,
"seconds": 2.00393,
"bytes": 250347520,
"bits_per_second": 999426207.502258,
"sender": false
},
"cpu_utilization_percent": {
"host_total": 4.3199350250562958,
"host_user": 0.279305713434535,
"host_system": 4.04059602527765,
"remote_total": 3.0420990823002212,
"remote_user": 1.4897442849610014,
"remote_system": 1.5523547973392195
},
"sender_tcp_congestion": "cubic",
"receiver_tcp_congestion": "cubic"
}
}
}

@manedurphy
manedurphy marked this pull request as draft July 14, 2025 18:00
@bmah888

Copy link
Copy Markdown
Contributor

Thanks for the PR! Admittedly we want to be a little careful with the order of operations, just something we would need to test for this (and any other similar) code change.

@manedurphy

Copy link
Copy Markdown
ContributorAuthor

@bmah888, I agree, and after further testing, these changes will need more thought from my end. I've moved this PR into a draft state and will add some updates to the template with more meaningful findings and a description of the new changes.

@manedurphy
manedurphy marked this pull request as ready for review July 14, 2025 20:38
@manedurphy

Copy link
Copy Markdown
ContributorAuthor

PR back in the Open state.

FD_CLR(sp->socket, &test->write_set);
close(sp->socket);
}
test->reporter_callback(test);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that the right change is to move this call to reporter_callbackafter setting the state to DISPLAY_RESULTS, i.e. move this line after original line 284 below. With this change, all other changes in this PR should probably be undone.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was the change I made in my first attempt, but then I saw that it broke the --get-server-output flag on the client side. My understanding is that at the test's end, the call to reporter_callback populates the (potentially) last interval in the JSON and then populates the end field, so moving the call to after setting the state to DISPLAY_RESULTS would give the client a JSON result with a (potentially) missing interval and missing end. In this snippet, the last interval on the server side was discarded instead of added to the JSON so both the client and server have 4 intervals, but I have seen cases where the server has one more wualified interval that this change never appends. The end is always missing:

Client JSON w/Server Json (First Attempt)
{
"start":	{
"connected":	[{
"socket":	5,
"local_host":	"127.0.0.1",
"local_port":	64953,
"remote_host":	"127.0.0.1",
"remote_port":	5201
}],
"version":	"iperf 3.19.1+",
"system_info":	"Darwin CASML-K204175 24.6.0 Darwin Kernel Version 24.6.0: Mon Aug 11 21:16:31 PDT 2025; root:xnu-11417.140.69.701.11~1/RELEASE_ARM64_T6030 arm64",
"timestamp":	{
"time":	"Wed, 22 Oct 2025 01:05:27 UTC",
"timesecs":	1761095127,
"timemillisecs":	1761095127061
},
"connecting_to":	{
"host":	"127.0.0.1",
"port":	5201
},
"cookie":	"44tsufxw2whdis7ollqo5w62gm5hyjtpagwq",
"tcp_mss_default":	16332,
"target_bitrate":	170000000,
"fq_rate":	0,
"sock_bufsize":	0,
"sndbuf_actual":	131072,
"rcvbuf_actual":	131072,
"test_start":	{
"protocol":	"TCP",
"num_streams":	1,
"blksize":	131072,
"omit":	0,
"duration":	4,
"bytes":	0,
"blocks":	0,
"reverse":	1,
"tos":	0,
"target_bitrate":	170000000,
"bidir":	0,
"fqrate":	0,
"interval":	1
}
},
"intervals":	[{
"streams":	[{
"socket":	5,
"start":	0,
"end":	1.005023,
"seconds":	1.0050230026245117,
"bytes":	21364736,
"bits_per_second":	170063657.80053386,
"omitted":	false,
"sender":	false
}],
"sum":	{
"start":	0,
"end":	1.005023,
"seconds":	1.0050230026245117,
"bytes":	21364736,
"bits_per_second":	170063657.80053386,
"omitted":	false,
"sender":	false
}
}, {
"streams":	[{
"socket":	5,
"start":	1.005023,
"end":	2.005025,
"seconds":	1.0000020265579224,
"bytes":	21233664,
"bits_per_second":	169868967.75069764,
"omitted":	false,
"sender":	false
}],
"sum":	{
"start":	1.005023,
"end":	2.005025,
"seconds":	1.0000020265579224,
"bytes":	21233664,
"bits_per_second":	169868967.75069764,
"omitted":	false,
"sender":	false
}
}, {
"streams":	[{
"socket":	5,
"start":	2.005025,
"end":	3.001299,
"seconds":	0.99627399444580078,
"bytes":	21233664,
"bits_per_second":	170504613.13555968,
"omitted":	false,
"sender":	false
}],
"sum":	{
"start":	2.005025,
"end":	3.001299,
"seconds":	0.99627399444580078,
"bytes":	21233664,
"bits_per_second":	170504613.13555968,
"omitted":	false,
"sender":	false
}
}, {
"streams":	[{
"socket":	5,
"start":	3.001299,
"end":	4.004282,
"seconds":	1.0029829740524292,
"bytes":	21233664,
"bits_per_second":	169364103.27451918,
"omitted":	false,
"sender":	false
}],
"sum":	{
"start":	3.001299,
"end":	4.004282,
"seconds":	1.0029829740524292,
"bytes":	21233664,
"bits_per_second":	169364103.27451918,
"omitted":	false,
"sender":	false
}
}],
"end":	{
"streams":	[{
"sender":	{
"socket":	5,
"start":	0,
"end":	4.0049,
"seconds":	4.0049,
"bytes":	85196800,
"bits_per_second":	170185123.22405052,
"sender":	false
},
"receiver":	{
"socket":	5,
"start":	0,
"end":	4.004282,
"seconds":	4.004282,
"bytes":	85065728,
"bits_per_second":	169949525.03345171,
"sender":	false
}
}],
"sum_sent":	{
"start":	0,
"end":	4.0049,
"seconds":	4.0049,
"bytes":	85196800,
"bits_per_second":	170185123.22405052,
"sender":	false
},
"sum_received":	{
"start":	0,
"end":	4.004282,
"seconds":	4.004282,
"bytes":	85065728,
"bits_per_second":	169949525.03345171,
"sender":	false
},
"cpu_utilization_percent":	{
"host_total":	5.1971978267434347,
"host_user":	0.068432125663544535,
"host_system":	5.1289154431491752,
"remote_total":	9.33060535336937,
"remote_user":	0.11053911978700184,
"remote_system":	9.22014114150181
}
},
"server_output_json":	{
"start":	{
"connected":	[{
"socket":	5,
"local_host":	"127.0.0.1",
"local_port":	5201,
"remote_host":	"127.0.0.1",
"remote_port":	64953
}],
"version":	"iperf 3.19.1+",
"system_info":	"Darwin CASML-K204175 24.6.0 Darwin Kernel Version 24.6.0: Mon Aug 11 21:16:31 PDT 2025; root:xnu-11417.140.69.701.11~1/RELEASE_ARM64_T6030 arm64",
"target_bitrate":	170000000,
"sock_bufsize":	0,
"sndbuf_actual":	131072,
"rcvbuf_actual":	131072,
"timestamp":	{
"time":	"Wed, 22 Oct 2025 01:05:27 UTC",
"timesecs":	1761095127,
"timemillisecs":	1761095127061
},
"accepted_connection":	{
"host":	"127.0.0.1",
"port":	64952
},
"cookie":	"44tsufxw2whdis7ollqo5w62gm5hyjtpagwq",
"tcp_mss_default":	0,
"target_bitrate":	170000000,
"fq_rate":	0,
"test_start":	{
"protocol":	"TCP",
"num_streams":	1,
"blksize":	131072,
"omit":	0,
"duration":	4,
"bytes":	0,
"blocks":	0,
"reverse":	1,
"tos":	0,
"target_bitrate":	170000000,
"bidir":	0,
"fqrate":	0,
"interval":	1
}
},
"intervals":	[{
"streams":	[{
"socket":	5,
"start":	0,
"end":	1.005005,
"seconds":	1.0050050020217896,
"bytes":	21364736,
"bits_per_second":	170066703.80362377,
"omitted":	false,
"sender":	true
}],
"sum":	{
"start":	0,
"end":	1.005005,
"seconds":	1.0050050020217896,
"bytes":	21364736,
"bits_per_second":	170066703.80362377,
"omitted":	false,
"sender":	true
}
}, {
"streams":	[{
"socket":	5,
"start":	1.005005,
"end":	2.002644,
"seconds":	0.997639000415802,
"bytes":	21233664,
"bits_per_second":	170271322.52167451,
"omitted":	false,
"sender":	true
}],
"sum":	{
"start":	1.005005,
"end":	2.002644,
"seconds":	0.997639000415802,
"bytes":	21233664,
"bits_per_second":	170271322.52167451,
"omitted":	false,
"sender":	true
}
}, {
"streams":	[{
"socket":	5,
"start":	2.002644,
"end":	3.005021,
"seconds":	1.0023770332336426,
"bytes":	21233664,
"bits_per_second":	169466484.53427345,
"omitted":	false,
"sender":	true
}],
"sum":	{
"start":	2.002644,
"end":	3.005021,
"seconds":	1.0023770332336426,
"bytes":	21233664,
"bits_per_second":	169466484.53427345,
"omitted":	false,
"sender":	true
}
}, {
"streams":	[{
"socket":	5,
"start":	3.005021,
"end":	4.00263,
"seconds":	0.99760901927948,
"bytes":	21233664,
"bits_per_second":	170276439.68444431,
"omitted":	false,
"sender":	true
}],
"sum":	{
"start":	3.005021,
"end":	4.00263,
"seconds":	0.99760901927948,
"bytes":	21233664,
"bits_per_second":	170276439.68444431,
"omitted":	false,
"sender":	true
}
}],
"end":	{
}
}
}

My most recent change adjusts the order of operations, where the server first acquires the Client's results, takes what it needs from those results and inserts them into its results, and then sends its results back to the Client.

Client JSON w/Server Json (Final)
{
"start":	{
"connected":	[{
"socket":	5,
"local_host":	"127.0.0.1",
"local_port":	60354,
"remote_host":	"127.0.0.1",
"remote_port":	5201
}],
"version":	"iperf 3.19.1+",
"system_info":	"Darwin CASML-K204175 24.6.0 Darwin Kernel Version 24.6.0: Mon Aug 11 21:16:31 PDT 2025; root:xnu-11417.140.69.701.11~1/RELEASE_ARM64_T6030 arm64",
"timestamp":	{
"time":	"Wed, 22 Oct 2025 15:43:56 UTC",
"timesecs":	1761147836,
"timemillisecs":	1761147836394
},
"connecting_to":	{
"host":	"127.0.0.1",
"port":	5201
},
"cookie":	"oavle55tz4jfn4u4i4gqvcmect33esyt72jx",
"tcp_mss_default":	16332,
"target_bitrate":	170000000,
"fq_rate":	0,
"sock_bufsize":	0,
"sndbuf_actual":	131072,
"rcvbuf_actual":	131072,
"test_start":	{
"protocol":	"TCP",
"num_streams":	1,
"blksize":	131072,
"omit":	0,
"duration":	4,
"bytes":	0,
"blocks":	0,
"reverse":	1,
"tos":	0,
"target_bitrate":	170000000,
"bidir":	0,
"fqrate":	0,
"interval":	1
}
},
"intervals":	[{
"streams":	[{
"socket":	5,
"start":	0,
"end":	1.000461,
"seconds":	1.0004609823226929,
"bytes":	21233664,
"bits_per_second":	169791041.33139461,
"omitted":	false,
"sender":	false
}],
"sum":	{
"start":	0,
"end":	1.000461,
"seconds":	1.0004609823226929,
"bytes":	21233664,
"bits_per_second":	169791041.33139461,
"omitted":	false,
"sender":	false
}
}, {
"streams":	[{
"socket":	5,
"start":	1.000461,
"end":	2.005027,
"seconds":	1.004565954208374,
"bytes":	21364736,
"bits_per_second":	170141031.83965462,
"omitted":	false,
"sender":	false
}],
"sum":	{
"start":	1.000461,
"end":	2.005027,
"seconds":	1.004565954208374,
"bytes":	21364736,
"bits_per_second":	170141031.83965462,
"omitted":	false,
"sender":	false
}
}, {
"streams":	[{
"socket":	5,
"start":	2.005027,
"end":	3.004404,
"seconds":	0.99937701225280762,
"bytes":	21233664,
"bits_per_second":	169975204.46971115,
"omitted":	false,
"sender":	false
}],
"sum":	{
"start":	2.005027,
"end":	3.004404,
"seconds":	0.99937701225280762,
"bytes":	21233664,
"bits_per_second":	169975204.46971115,
"omitted":	false,
"sender":	false
}
}, {
"streams":	[{
"socket":	5,
"start":	3.004404,
"end":	4.003841,
"seconds":	0.99943697452545166,
"bytes":	21233664,
"bits_per_second":	169965006.62851363,
"omitted":	false,
"sender":	false
}],
"sum":	{
"start":	3.004404,
"end":	4.003841,
"seconds":	0.99943697452545166,
"bytes":	21233664,
"bits_per_second":	169965006.62851363,
"omitted":	false,
"sender":	false
}
}],
"end":	{
"streams":	[{
"sender":	{
"socket":	5,
"start":	0,
"end":	4.004357,
"seconds":	4.004357,
"bytes":	85065728,
"bits_per_second":	169946341.94703421,
"sender":	false
},
"receiver":	{
"socket":	5,
"start":	0,
"end":	4.003841,
"seconds":	4.003841,
"bytes":	85065728,
"bits_per_second":	169968243.993705,
"sender":	false
}
}],
"sum_sent":	{
"start":	0,
"end":	4.004357,
"seconds":	4.004357,
"bytes":	85065728,
"bits_per_second":	169946341.94703421,
"sender":	false
},
"sum_received":	{
"start":	0,
"end":	4.003841,
"seconds":	4.003841,
"bytes":	85065728,
"bits_per_second":	169968243.993705,
"sender":	false
},
"cpu_utilization_percent":	{
"host_total":	5.85302413254988,
"host_user":	0.071980644596251531,
"host_system":	5.78116789280084,
"remote_total":	11.173274335841226,
"remote_user":	0.096386986258611779,
"remote_system":	11.076762495973473
}
},
"server_output_json":	{
"start":	{
"connected":	[{
"socket":	5,
"local_host":	"127.0.0.1",
"local_port":	5201,
"remote_host":	"127.0.0.1",
"remote_port":	60354
}],
"version":	"iperf 3.19.1+",
"system_info":	"Darwin CASML-K204175 24.6.0 Darwin Kernel Version 24.6.0: Mon Aug 11 21:16:31 PDT 2025; root:xnu-11417.140.69.701.11~1/RELEASE_ARM64_T6030 arm64",
"target_bitrate":	170000000,
"sock_bufsize":	0,
"sndbuf_actual":	131072,
"rcvbuf_actual":	131072,
"timestamp":	{
"time":	"Wed, 22 Oct 2025 15:43:56 UTC",
"timesecs":	1761147836,
"timemillisecs":	1761147836394
},
"accepted_connection":	{
"host":	"127.0.0.1",
"port":	60353
},
"cookie":	"oavle55tz4jfn4u4i4gqvcmect33esyt72jx",
"tcp_mss_default":	0,
"target_bitrate":	170000000,
"fq_rate":	0,
"test_start":	{
"protocol":	"TCP",
"num_streams":	1,
"blksize":	131072,
"omit":	0,
"duration":	4,
"bytes":	0,
"blocks":	0,
"reverse":	1,
"tos":	0,
"target_bitrate":	170000000,
"bidir":	0,
"fqrate":	0,
"interval":	1
}
},
"intervals":	[{
"streams":	[{
"socket":	5,
"start":	0,
"end":	1.002389,
"seconds":	1.0023889541625977,
"bytes":	21364736,
"bits_per_second":	170510546.12107724,
"omitted":	false,
"sender":	true
}],
"sum":	{
"start":	0,
"end":	1.002389,
"seconds":	1.0023889541625977,
"bytes":	21364736,
"bits_per_second":	170510546.12107724,
"omitted":	false,
"sender":	true
}
}, {
"streams":	[{
"socket":	5,
"start":	1.002389,
"end":	2.000762,
"seconds":	0.998372972011566,
"bytes":	21233664,
"bits_per_second":	170146144.53928953,
"omitted":	false,
"sender":	true
}],
"sum":	{
"start":	1.002389,
"end":	2.000762,
"seconds":	0.998372972011566,
"bytes":	21233664,
"bits_per_second":	170146144.53928953,
"omitted":	false,
"sender":	true
}
}, {
"streams":	[{
"socket":	5,
"start":	2.000762,
"end":	3.004524,
"seconds":	1.0037620067596436,
"bytes":	21233664,
"bits_per_second":	169232657.59816328,
"omitted":	false,
"sender":	true
}],
"sum":	{
"start":	2.000762,
"end":	3.004524,
"seconds":	1.0037620067596436,
"bytes":	21233664,
"bits_per_second":	169232657.59816328,
"omitted":	false,
"sender":	true
}
}, {
"streams":	[{
"socket":	5,
"start":	3.004524,
"end":	4.004357,
"seconds":	0.99983298778533936,
"bytes":	21233664,
"bits_per_second":	169897686.98896974,
"omitted":	false,
"sender":	true
}],
"sum":	{
"start":	3.004524,
"end":	4.004357,
"seconds":	0.99983298778533936,
"bytes":	21233664,
"bits_per_second":	169897686.98896974,
"omitted":	false,
"sender":	true
}
}],
"end":	{
"streams":	[{
"sender":	{
"socket":	5,
"start":	0,
"end":	4.004357,
"seconds":	4.004357,
"bytes":	85065728,
"bits_per_second":	169946341.94703421,
"sender":	true
},
"receiver":	{
"socket":	5,
"start":	0,
"end":	4.003841,
"seconds":	4.004357,
"bytes":	85065728,
"bits_per_second":	169968243.993705,
"sender":	true
}
}],
"sum_sent":	{
"start":	0,
"end":	4.004357,
"seconds":	4.004357,
"bytes":	85065728,
"bits_per_second":	169946341.94703421,
"sender":	true
},
"sum_received":	{
"start":	0,
"end":	4.003841,
"seconds":	4.003841,
"bytes":	85065728,
"bits_per_second":	169968243.993705,
"sender":	true
},
"cpu_utilization_percent":	{
"host_total":	11.173274335841226,
"host_user":	0.096386986258611779,
"host_system":	11.076762495973473,
"remote_total":	5.85302413254988,
"remote_user":	0.071980644596251531,
"remote_system":	5.78116789280084
}
}
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. Thanks for the explanation.

@manedurphy
manedurphyforce-pushed the iperf_1410_report_client_results branch 3 times, most recently from a9f8e50 to 0cd3be1CompareOctober 22, 2025 17:59
@manedurphy

Copy link
Copy Markdown
ContributorAuthor

These changes will have to wait for #1956. Merging those changes will resolve the failing tests in the pipeline.

@manedurphy
manedurphyforce-pushed the iperf_1410_report_client_results branch from 0cd3be1 to 8c3a2f4CompareOctober 23, 2025 22:29
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@manedurphy@bmah888@davidBar-On