feat(proto): validate negotiated datagram budgets

PLAN.md keeps MVP traffic to one Ethernet frame per QUIC datagram with no
fragmentation. The relay already negotiates a datagram budget, but the client
and gateway send paths still relied on Quinn to reject oversized encoded
Ethernet datagrams.

Add a shared protocol validation helper for encoded datagram length versus the
negotiated QUIC budget. Thread the negotiated budget into client and gateway
send boundaries, reject oversized datagrams before send, and count those valid
but unsent frames as local drops.

Document the budget check in the workspace decomposition and gateway behavior.

Test Plan:
- cargo fmt --check
- cargo test -p lanparty-proto -p lanparty-client-core -p lanparty-gateway
- cargo test --workspace
- cargo clippy --workspace --all-targets -- -D warnings
- git diff --check

Refs: PLAN.md
This commit is contained in:
2026-05-21 22:03:15 +02:00
parent e533131c74
commit 325e5651a2
5 changed files with 92 additions and 10 deletions
+8 -5
View File
@@ -20,6 +20,7 @@ Monorepo for a Layer 2 over QUIC LAN party bridge.
Transport-agnostic tunnel contract shared by all binaries:
- overlay datagram header encoding and decoding
- negotiated QUIC datagram budget validation before send
- Ethernet frame header parsing
- MAC address parsing and identity validation
- QUIC datagram to TAP MTU budget helpers
@@ -59,7 +60,7 @@ Platform-neutral remote client relay session:
- welcome/reject handling with assigned peer id and effective TAP MTU
- QUIC DATAGRAM support and negotiated datagram budget diagnostics
- reliable relay control-event reads for peer lifecycle messages
- Ethernet frame send/receive helpers over QUIC DATAGRAM
- Ethernet frame send/receive helpers over QUIC DATAGRAM with budget checks
- client tunnel statistics for frame/datagram rx/tx and drops
- reliable client stats snapshot sends for relay diagnostics
- best-effort graceful disconnect messages before QUIC close
@@ -158,10 +159,12 @@ cargo run -p lanparty-gateway -- \
The gateway connects to the relay as `role = gateway`, completes the
control-stream hello/welcome handshake, opens an AF_PACKET socket on the LAN
interface with promiscuous packet membership, and bridges Ethernet frames
between the relay and wired LAN until shutdown. `--relay` accepts a DNS name or
socket address; bare hosts default to UDP/443. It tracks remote-client source
MACs seen from relay traffic and periodically emits small CAM refresh frames so
the physical switch keeps those MACs associated with the gateway port. Gateway
between the relay and wired LAN until shutdown. Sends fail before fragmentation
when an encoded Ethernet datagram exceeds the negotiated QUIC datagram budget.
`--relay` accepts a DNS name or socket address; bare hosts default to UDP/443.
It tracks remote-client source MACs seen from relay traffic and periodically
emits small CAM refresh frames so the physical switch keeps those MACs
associated with the gateway port. Gateway
frame logs include direction, peer id when present, MACs, ethertype/length,
frame length, action, and drop reason. The gateway also tracks frame/datagram
counters and periodically sends stats snapshots to the relay. Relay lifecycle