Skip to content

remote: bound updates to MTU-safe UDP datagrams - #25

Open
JxnLexn wants to merge 2 commits into
openwrt:masterfrom
JxnLexn:fix/remote-update-datagram-size
Open

remote: bound updates to MTU-safe UDP datagrams#25
JxnLexn wants to merge 2 commits into
openwrt:masterfrom
JxnLexn:fix/remote-update-datagram-size

Conversation

@JxnLexn

@JxnLexn JxnLexn commented Sep 7, 2026

Copy link
Copy Markdown

Problem

Remote updates grow with the number of observed stations. Sending the entire
blob in one UDP datagram can exceed the interface MTU and cause IP fragmentation.
Losing one fragment loses the whole update; increasing the receive buffer does
not address this transport problem.

Changes

  • Bound UDP payloads to min(1200, interface MTU - IP/UDP headers), separately
    accounting for IPv4 and IPv6. The conservative cap leaves headroom on an IPv6
    minimum-MTU link; this is not general routed/tunnel path-MTU discovery.
  • Pass small messages through byte-for-byte. Split larger messages into complete
    existing-format node/station batches, repeating host and node metadata.
  • Preserve the logical update ID/sequence. The existing receiver updates
    individual station records and does not discard chunks with the same sequence;
    no wire-format or receive-parser changes are required.
  • Preflight the whole update before sending. Indivisible oversized metadata or a
    station record produces EMSGSIZE, with no truncation or oversized fallback.
    Socket send errors are propagated; as with ordinary UDP, a later send failure
    can still leave a partially received update until the next periodic refresh.
  • Initialize the remote socket before the initial update and skip sends while it
    is unregistered. Initialize the descriptor to -1 and handle descriptor 0 as a
    valid descriptor. This follow-up fixes an initial MTU ioctl on an unopened
    socket observed during the pilot deployment.

Tests

  • Regression tests using the unchanged upstream parser: byte-identical small
    updates, exact boundaries, 1,001 payload limits with 300 stations across two
    nodes plus an empty node, preservation of unknown metadata, no missing/duplicate
    records or input mutation, oversized metadata/station preflight, and send errors.

  • Actual IPv4 and IPv6 loopback UDP send/receive tests.

  • Socket lifecycle regression with mocked syscalls, including descriptor 0 and
    MTU query failure.

  • Normal and ASan/UBSan runs passed. Cross-builds for ARM64 release, ARM64
    snapshot, and MIPS little-endian passed. Both test executables also passed on
    actual ARM64 snapshot and MIPS hardware, plus the ARM64 release runtime.

  • Pilot deployment: a 10-minute transport test, followed by another 5-minute
    window with the socket initialization follow-up. No uplink packet loss or
    observed fragmentation; no new startup MTU warnings after the follow-up.

  • Sequential rollout to nine APs spanning ARM64 release/snapshot and MIPS:
    each retained eight peers across eleven samples in a shared 5-minute window,
    stable daemon PIDs, unchanged configuration and no new relevant error logs.
    Each AP passed 301/301 ICMP probes in both directions against the gateway.
    Four gateway-side series were repeated after concurrent SSH setup failures;
    those failures were not counted as completed packet-loss tests.

  • All 36 locally connected station records at the final shared sample were
    present on another peer, with no missing remote nodes in that comparison.

  • Additional 60-second egress captures on eight APs: 935 UDP datagrams, maximum
    payload 1,184 bytes, no IP fragments. The ninth AP's receiver-side capture
    contained 304 updates, all at most 568 bytes.

Capture caveat: receiver-side GRO can merge separate UDP datagrams before
packet-socket capture and report an apparently oversized payload. Synchronized
captures confirmed two separate 1,072/288-byte source datagrams appearing as a
single 1,360-byte receiver observation. Egress captures were therefore used for
the payload-size acceptance check, not unqualified receiver aggregate lengths.

This is scoped to remote-update transport and initialization. It does not claim
to fix unrelated client radio loss, nor establish comprehensive roaming or
long-term stability. Existing steering policy and configuration are unchanged by
the patch.

Split oversized updates into existing-format node/station batches without
changing the receive protocol. Validate indivisible records before sending
and cover the splitter with parser and UDP regression tests.

Signed-off-by: Jan Leon <Jan.gaschler@gmail.com>
Skip sends on unregistered sockets and handle descriptor zero correctly.
Add a socket lifecycle regression test and English test documentation.

Signed-off-by: Jan Leon <Jan.gaschler@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant