# UDP RX investigation and follow-up fix — 2026-10-30 The earlier live checks at a fixed 2 Mbit/s target did not cover the dashboard's default **UDP / Both / Unlimited / 1472-byte** case. The user's next test exposed that gap, so it was reproduced from the remote DebTik against 172.16.233.2. ## Findings The user's ten-second test recorded an average TX of 1306 Mbit/s, but that number counted bytes accepted by the sender's local UDP socket, not delivery to the other node. Its RX averaged 0.963 Mbit/s and the final reported loss was 99.85%. This was an unpaced UDP flood, with large numbers of dropped/queued datagrams. The old sequence accounting also treated reordering as permanent loss. Separate RX-only checks confirmed that UDP RX at a fixed 2 Mbit/s delivered 2.023 Mbit/s, while the old unlimited RX case delivered only 1.225 Mbit/s and reported very high loss. TCP RX at 2 Mbit/s delivered 1.966 Mbit/s. A subsequent limited UDP test could also suffer from the preceding flood's backlog. Additionally, a 1472-byte UDP payload plus IP/UDP headers exceeds the effective 1292-byte AeroTUN MTU. Fragmenting every datagram increased packet work and made loss of a single fragment discard the whole UDP datagram. ## Changes - TX throughput and TX bytes/packets now use peer-reported successful reception. Locally offered TX is a separate metric and appears in the TX tooltip. - Zero/default UDP limit now selects **Auto**, using receiver-feedback pacing in both directions. It starts at 2 Mbit/s, probes upward, and backs off when the receiver cannot sustain the offered rate. Missing feedback also reduces the rate. An explicitly selected nonzero limit remains a fixed offered rate. - The client sends reverse-receiver feedback to the server. All outbound client UDP streams share one pacing budget, rather than multiplying the target rate. - Datagram size is negotiated to fit both routes. On this overlay the requested 1472 bytes become **1264 bytes** when the overlay MTU is 1292 (or 1304 bytes at MTU 1332): the current route MTU minus IPv4/UDP headers. The effective datagram size is shown in the dashboard. - RX-only clients send a UDP probe. The server learns the real UDP source port, including NAT mappings, without depending on outgoing benchmark data. Probe packets do not count as bandwidth. Discovery is restricted to the TCP peer IP. - Loss tracking is per stream, excludes duplicate packets, and accounts for late packets within a bounded reorder window. - TX-only tests no longer label delivery reports as downloaded RX traffic. - A duplicate packet-size selector/HTML ID was removed so changing the visible selector controls the requested size. Automatic UDP mode requires the new receiver-feedback support on both peers; unsupported peers return an upgrade error. It is a capacity probe, not a promise that a short run reaches the maximum possible rate. Use longer runs to observe convergence; excessive fixed offered rates can still cause intentional overload. ## Validation Unit and race tests cover RX/TX/both, multiple streams, pacing feedback/backoff, cancellation, reordered/duplicate datagrams and confirmed byte accounting. The integration harness uses two isolated AeroTUN peers and constrains each outer link to 5 Mbit/s, with 15 ms delay and a 64-packet queue. Default automatic UDP RX delivered about 3.36 Mbit/s with 1.0% reported loss; Both delivered confirmed TX 2.34 / RX 3.36 Mbit/s with 0.4% reported loss. The payload negotiated to 1264 bytes. These are controlled local tests, separate from live link measurements. Both production services are updated using architecture-specific amd64/arm64 builds and independent SSH management. Before this follow-up, another backup was saved on both hosts at: `/root/.local/share/debtik-backups/aerotun-v2-20261030T115144Z/` The persistent AeroTUN configuration and PSK are preserved. Raw live validation JSON is stored in `/root/.local/share/debtik-builds/aerotun-v2/live-test-results/` with names beginning `rx-fix-`. ## Live results after the follow-up deployment | Client and mode | Duration | Confirmed TX | RX | Reported loss | Negotiated UDP size | | --- | ---: | ---: | ---: | ---: | ---: | | Remote → local, Both / Auto | 10 s | 3.934 Mbit/s | 12.988 Mbit/s | 0.951% | 1304 bytes | | Remote → local, RX-only / Auto | 8 s | 0 | 8.403 Mbit/s | 1.153% | 1304 bytes | | Local → remote, Both / Auto, 4 streams | 8 s | 8.002 Mbit/s | 5.324 Mbit/s | 0.162% | 1264 bytes | The first two tests started while the overlay MTU was 1332; a cached outer path MTU later reduced the overlay to 1292, so the third test negotiated 1264-byte datagrams. Datagram size is negotiated at the beginning of each test. The final telemetry shows both peers connected at MTU 1292 with no authentication failures or replay drops. Short automatic runs probe capacity and vary with the route; these values are observed throughput, not a promised maximum. The ten-second Both test repeated the user's direction, target overlay address, automatic/zero limit, one stream and requested 1472-byte packet size. RX no longer starved. Both services are active, installed hashes match the built artifacts, rollback timers were cancelled after verification, and the persistent AeroTUN configuration/PSK remained unchanged.