Skip to content

fix: frame/payload ceilings, MX log level, framing comment corrections - #66

Merged
sbogomolov merged 4 commits into
mainfrom
fixes/frame-ceiling-and-log-hygiene
Aug 8, 2026
Merged

fix: frame/payload ceilings, MX log level, framing comment corrections#66
sbogomolov merged 4 commits into
mainfrom
fixes/frame-ceiling-and-log-hygiene

Conversation

@sbogomolov

Copy link
Copy Markdown
Owner

Four independent fixes, one commit each.

  • MX log level — the defaulted-MX fallback fires on every M-SEARCH including retransmits, so one non-conformant client floods the default level. Moved to debug.
  • Frame ceiling on the BPF path — Linux's recv(MSG_TRUNC) already surfaces oversized frames for the drop, but the BPF path reads into a BIOCGBLEN-sized batch and happily delivered a fully-captured frame the send path could never re-emit. The former send/receive size constants (both 4 KiB, same rationale) merge into one MAX_FRAME_SIZE.
  • Framing comments + namingconsumed == 0 also happens mid-body when a chunk-size line splits across reads, which three comments denied; StreamBuffer::Commit's no-interleaved-mutation contract is now stated; the per-session Registration was called capture, which is also what the sockets it registers on are called.
  • DIAL rewrite ceiling — a rewrite that grows the datagram past what the send path can frame used to fail deep in the frame builder. Now capped at the rewrite against MAX_UDP_PAYLOAD_SIZE and dropped: forwarding the original would advertise the device address the rewrite exists to replace.

Native (888) and docker/Linux (875) unit suites green. The DIAL cap and the BPF ceiling were each verified to fail their test when the guard is stubbed out.

The fallback fires on every M-SEARCH, retransmits included, so one
non-conformant client keeps flooding the default level. The search is
reflected either way.
Linux's receive scratch is MAX_FRAME_SIZE, so recv(MSG_TRUNC) already
surfaces anything larger for the drop. The BPF path reads into a
BIOCGBLEN-sized batch instead, which happily delivers a fully-captured
frame the send path could never re-emit; the walker now applies the
same ceiling.

The former send/receive size constants were the same 4 KiB for the
same reason, so they merge into one MAX_FRAME_SIZE.
consumed == 0 also happens mid-body, when a chunk-size line splits
across reads -- three comments claimed it only meant an incomplete
header.

StreamBuffer::Commit's contract forbids an interleaved mutating call:
Consume and a second ReserveTail both compact, so committing afterwards
publishes stale tail bytes into the forwarded stream.

The per-session Registration was called `capture`, which is also what
the sockets it registers on are called.
The rewrite can grow the datagram past what the send path can frame,
where it failed at the frame builder and was dropped three logs deep.
Cap it against MAX_UDP_PAYLOAD_SIZE at the rewrite instead.

Forwarding the original is not the fallback here: on the segment where
the rewrite matters, the device's own LOCATION is unreachable from the
client, so a verbatim copy advertises a dead address for clients to
cache and time out on.
@sbogomolov sbogomolov self-assigned this Aug 8, 2026
@sbogomolov
sbogomolov merged commit 5ba737b into main Aug 8, 2026
17 checks passed
@sbogomolov
sbogomolov deleted the fixes/frame-ceiling-and-log-hygiene branch August 8, 2026 20:46
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