From 85ba835d612f992f8fe73c3b722557acc4e05632 Mon Sep 17 00:00:00 2001 From: Martino Ferrari Date: Thu, 8 Oct 2026 17:49:11 +0200 Subject: [PATCH] test: the mock can release a withheld packet past the reorder window --- tools/mock_udpstreamer.py | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/tools/mock_udpstreamer.py b/tools/mock_udpstreamer.py index 1c76a91..eb18559 100644 --- a/tools/mock_udpstreamer.py +++ b/tools/mock_udpstreamer.py @@ -278,6 +278,17 @@ def main(): "rather than cancelling it, since the held packet waits for the next packet " "actually sent. 0 = never", ) + ap.add_argument( + "--reorder-delay-ms", + type=float, + default=0.0, + metavar="MS", + help="hold a withheld packet this many milliseconds instead of releasing it " + "immediately behind the packet that overtook it. Under the receiver's reorder " + "window the packet is resequenced and no hole is ever seen; past it the hole is " + "committed first and the packet has to backfill it -- which is the only way to " + "reach the backfill path at all, since a 0 ms delay always wins the race.", + ) args = ap.parse_args() dt = args.stream_scale / args.rate # stream seconds per sample @@ -309,7 +320,7 @@ def main(): t_stream = 0.0 started = None next_send = time.monotonic() - held = None # (counter, datagram) built but withheld, for --reorder-every + held = None # (counter, datagram, release_deadline) built but withheld, for --reorder-every drop_left = 0 dropped = 0 inverted = 0 @@ -401,21 +412,20 @@ def main(): and held is None and counter % args.reorder_every == 0 ): - held = (counter, pkt) + held = (counter, pkt, now + args.reorder_delay_ms / 1000.0) else: sock.sendto(pkt, peer) - if held is not None: - # Out of order on the wire now: the receiver has already taken this - # packet's counter, so the held one no longer advances it and is stale by - # definition -- one counter gap for the packet that overtook it, one stale - # packet for the one that lost, and the loser's samples are gone. + if held is not None and now >= held[2]: + # Within the receiver's reorder window, this packet is put back in order and + # costs nothing. Past the window, the receiver has already committed a hole + # and this packet is what fills it. sock.sendto(held[1], peer) inverted += 1 if not noted_reorder: noted_reorder = True print( - "mock udpstreamer: sent packet %d before %d" - % (counter, held[0]), + "mock udpstreamer: sent packet %d before %d, releasing it %.1f ms late" + % (counter, held[0], args.reorder_delay_ms), flush=True, ) held = None