docs: record frag_send and the current testing state
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
a7dccf7da2
commit
35744c609e
@@ -728,3 +728,49 @@ tenfold asymmetry that a round-trip measurement cannot see at all.
|
||||
|
||||
10 unit tests on the arithmetic (a wrong denominator here does not crash, it produces a plausible
|
||||
number pointing at the wrong half of the network) plus the live correlation check.
|
||||
|
||||
### frag_send: crafted IP fragments, so *ordering* is testable (server-v0.6.0, 2026-08-01)
|
||||
`big_send` with `df=false` answers one question — do fragments get through. It cannot answer the
|
||||
more interesting one, because the kernel always emits fragments in order, first one first.
|
||||
|
||||
The classic middlebox fault is exactly about that ordering. Only the **first** fragment carries the
|
||||
UDP header, and therefore the ports; a stateful firewall or NAT that has not seen it has no flow to
|
||||
match the rest against, and many simply drop them. That is invisible to every in-order test, and in
|
||||
the field it looks like "large DNS answers fail on this network" or "the tunnel breaks when the MTU
|
||||
drops" — it works until the network reorders, then fails intermittently, which is the hardest kind
|
||||
of fault to chase.
|
||||
|
||||
So the server builds the fragments itself (raw socket, `IP_HDRINCL`) and controls their order:
|
||||
`in_order` (baseline), `reversed` (last fragment first), `first_last` (first fragment held back
|
||||
250 ms). The datagram is assembled and **signed whole** before being cut up, so what the client
|
||||
reassembles is indistinguishable from an ordinary packet — otherwise the test would be measuring
|
||||
our sender rather than the path. New test type `mtu.frag_ordering`; findings
|
||||
`mtu.fragments_blocked` and `mtu.fragment_reorder_sensitive`.
|
||||
|
||||
Two details that would otherwise produce confidently wrong answers:
|
||||
- **The UDP checksum is computed, not left zero.** Zero is legal in IPv4 and would be less code,
|
||||
but zero-checksum datagrams are dropped by some middleboxes — and that drop would be recorded as
|
||||
a fragmentation failure, which is the wrong conclusion entirely.
|
||||
- **Fragment offsets are in 8-byte units**, so non-final fragments are rounded down to a multiple
|
||||
of 8. A 100-byte fragment is not an error; it is a datagram no host will ever reassemble.
|
||||
|
||||
`frag-send` is advertised only when a raw socket can actually be opened — checked by opening one,
|
||||
because a permission model has more ways to say no (userns, seccomp, LSM) than a capability bit has
|
||||
to say yes. fmr runs as root with `cap_net_raw` in its bounding set, so it is available there.
|
||||
|
||||
Fragment ordering runs only after `mtu.frag_delivery` shows fragments arrive at all; otherwise the
|
||||
three orderings would each report "not delivered" and read as three faults instead of one.
|
||||
|
||||
The header arithmetic is unit-tested (reassembly coverage with no gaps or double-delivery, MF
|
||||
flags, shared IP ID, 8-byte offsets, checksum verification over odd and even lengths). Because the
|
||||
code is `//go:build linux`, the tests are **cross-compiled and run on fmr** — there is no Go
|
||||
toolchain there, so `go test -c` plus scp is the loop.
|
||||
|
||||
Live against fmr: 4 fragments per burst, and all three orderings reassembled — a healthy path, and
|
||||
the baseline against which a mobile network will be interesting.
|
||||
|
||||
### Testing state (2026-08-01)
|
||||
Six live tests against fmr, all green, no device involved: `LiveServerTest`, `LiveMeasurement`,
|
||||
`LiveGranted`, `LiveDownstream`, `LiveUpload`, `LiveCompat`, `LiveEnrollment`. Plus 74 client unit
|
||||
tests and the full Go suite. Everything in the last several entries is verified from the PC; the
|
||||
app's UI (settings, history, deep-link enrollment) and `mtu.pmtud_up` remain device-only.
|
||||
|
||||
Reference in New Issue
Block a user