Skip to content

UDP loss figures incorrect and self-inconsistent against pre-3.13 peers (omitted_* substitution) #2055

Description

@therealevanhenry

Context

When the peer is an older iperf3 that does not exchange the omitted_errors/omitted_packets stream keys (≤3.12 — the keys and the backward-compat acceptance were added later), iperf_get_results substitutes omit baselines locally (src/iperf_api.c, the j_omitted_packets == NULL arms around lines 2914–2950 in 3.21 @ d39cf41). The substituted values make the rendered UDP loss figures incorrect and self-inconsistent in three ways, all reproducible with a stock 3.21 client against a stock 3.12 server on loopback.

Repro (loss forced via a small receive window):

# 3.12 server
iperf-3.12/src/iperf3 -s -1
# 3.21 client, three variants
iperf-3.21/src/iperf3 -c 127.0.0.1 -u -b 2G -l 1200 -w 8K -t 2 -J          # (a)
iperf-3.21/src/iperf3 -c 127.0.0.1 -u -b 2G -l 1200 -w 8K -t 2 -O 1 -J     # (b)
iperf-3.21/src/iperf3 -c 127.0.0.1 -u -b 2G -l 1200 -w 8K -t 2 -R -J       # (c)

Symptom 1 — real loss reported as zero (no -O)

In case (a) the client renders lost_packets: 0 / lost_percent: 0 (observed: 0/417713) despite heavy real loss (the same setup with -O 1 or -R shows hundreds to thousands of lost packets). Cause: the sender arm's else-branch assigns sp->omitted_cnt_error = sp->cnt_error; when there is no omit window, so the render sites' cnt_error - omitted_cnt_error nets the entire count away. Since the old peer's exchanged counts are gross and there is no omit window, the correct baseline here is 0.

Symptom 2 — the same document disagrees with itself by one (-O)

In case (b) the stream object and the sum object differ by exactly 1 (observed: stream lost_packets: 2852, sum lost_packets: 2851). Cause: with an omit window, the sender arm stores the -1 "unknown" sentinel in omitted_cnt_error; the per-stream render subtracts it unconditionally (cnt_error - (-1) = count+1, ~line 4312) while the sum accumulation skips it (if (sp->omitted_cnt_error > -1), lines 4246–4248).

Symptom 3 — lost_percent: 0 beside a nonzero lost_packets (-R)

In case (c) the client's stream object renders e.g. lost_packets: 643, packets: 417573, lost_percent: 0 while the sum shows the true percentage (0.154). Cause: the receiver arm assigns sp->peer_omitted_packet_count = sp->peer_packet_count; (everything omitted), and the stream lost_percent denominator uses sender_packet_count - sender_omitted_packet_count (= 0, lines 4288–4292) even though the adjacent packets field is computed with a different subtraction and stays nonzero.

Suggested direction

For the no-omit case the baselines should be 0 (the exchanged gross counts are already the net figures). With -O, the sender side's own omitted-sent count is a usable estimate for the peer's omitted packets (the code already does this), the receiver side's own omitted-received count is a better estimate than all-omitted, and the error split is genuinely unknown — but the sentinel should not leak into the subtraction on one surface while being skipped on another.

Found while validating riperf3's output compatibility against 3.21/3.12 pairs; happy to provide the full JSON captures.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions