From d3688812b8faa11e7ed0aba7df3a92f8316c1b79 Mon Sep 17 00:00:00 2001 From: Zoa Hickenlooper Date: Sun, 26 Jul 2026 01:52:23 -0400 Subject: [PATCH] docs: changelog + testing docs for #116 fix, #113 test hardening, and the spikes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CHANGELOG: #116/#117 (fresh-ephemeral punch->relay escalation) under Security; #113 io_uring loopback test hardening under Fixed. - testing-and-benchmarking.md: document the two new bench harnesses — mac_candidates (#58) and run-cpu-regime.sh (#4 go/no-go) — with their findings. --- CHANGELOG.md | 22 +++++++++++++++++++++ docs/testing-and-benchmarking.md | 34 ++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index aba2196..2402211 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,20 @@ until 0.1.0. roaming model), including the in-flight-rekey and relay-adoption edge cases. Exercised end-to-end by netns tests asserting a forged registration is refused and the legitimate node stays reachable. +- **Punch→relay escalation always draws a fresh ephemeral (#116, PR #117).** + The `#34` freshness gate requires a Punch→Relay path re-target to draw a + **fresh** Noise ephemeral; a preserved (retransmitted) ephemeral is a bare + replay a captured `Init` could ride to force a relay downgrade. The + escalation only redrew when it fired *before* the peer was flagged + relay-reached — but an inbound relayed packet (`on_relayed`) can set that + flag first, and the old guard then skipped the escalation and retransmitted + the **same** punch ephemeral over the relay. This was intermittent and + race-dependent (the path-switch money test failed on `main` whenever the + relayed packet won the race). The escalation now keys on the in-flight + `Init`'s own relay origin rather than the peer's relay flag, so a fresh + ephemeral is drawn regardless of when the flag flipped, while a relay `Init` + already in flight is still merely retransmitted (no ephemeral churn). + Covered by a deterministic regression test. ### Added - Classical session rekey + epoch handling (milestone 9a, #9, PR #90): @@ -190,6 +204,14 @@ until 0.1.0. - Gossip digest chunking (#44, PR #98): the mesh gossip digest is now chunked, and its obfuscation degrades fail-soft, instead of panicking once a mesh grows past a single-datagram digest size. +- io_uring loopback recycle tests hardened against default socket buffers + (PR #113): the recv-buffer and send-slot recycle tests now interleave + send+drain (bounded in-flight window) instead of blasting all datagrams + first, so they no longer fail on a box with a default + `net.core.rmem_default`. The old pattern asserted `>256` datagrams + round-trip but relied on the kernel buffering that many at once; the default + ~208 KB receive buffer holds only ~230 small datagrams, so the assert + failed deterministically on stock-configured machines. ### Changed - Rendezvous relay-forward counter moved off the server's mutex onto a diff --git a/docs/testing-and-benchmarking.md b/docs/testing-and-benchmarking.md index e6ca445..b539893 100644 --- a/docs/testing-and-benchmarking.md +++ b/docs/testing-and-benchmarking.md @@ -161,6 +161,40 @@ went through several rounds: ~26 µs (original RaptorQ) → ~1.3 µs (RS, general Cauchy scheme, #50) → ~0.32 µs (P+Q XOR fast path for the common R=1 case, #51). +### MAC-candidate spike (#58) + +A Criterion micro-bench comparing keyed-MAC candidates for the `yip-wire` +coverage-auth tag over the real covered region (header‖symbol, 8-byte tag): + +```sh +cargo bench -p yip-bench --bench mac_candidates +``` + +SipHash-1-3 is ~45 % cheaper than today's SipHash-2-4 at packet size; keyed +BLAKE3 is ~2.5× **slower** at a 1.4 KB symbol (its SIMD advantage needs +KB–MB inputs). Measured on the EPYC target box and a dev box. The saving is +real but third-tier behind TUN-write and AEAD, and only helps in the +CPU-bound regime below — so #58 stays parked. Full write-up: +[`crates/yip-bench/mac-candidates-58.md`](../crates/yip-bench/mac-candidates-58.md). + +### CPU-bound-regime spike (#4 go/no-go) + +Determines whether the yip receiver can become CPU-bound or is always +RTT/window-bound. Pins the receiving `yipd` to one core (models the 1-core +target), sweeps netem RTT, and records throughput + the pinned core's +utilization (needs root): + +```sh +sudo bash crates/yip-bench/tests/run-cpu-regime.sh target/release/yipd +``` + +A CPU-bound regime **exists**: under a UDP blast the single core saturates and +caps at ~1.2 Gbps at every RTT; TCP is CPU-bound at low RTT and window-bound at +high RTT. So the "CPU wins don't move throughput" observation was specific to +the 24 ms single-flow WAN path — the #4 CPU work pays off for short-RTT / +aggregate-parallel traffic. Full write-up: +[`crates/yip-bench/cpu-bound-regime.md`](../crates/yip-bench/cpu-bound-regime.md). + ### yip vs WireGuard/OpenVPN/n2n under loss (`tc netem`) The comparison tests in `crates/yip-bench/tests/netem_bench.rs` set up tunnels