Skip to content

Commit 4e52e5a

Browse files
Improve context on data
1 parent 0c9374a commit 4e52e5a

1 file changed

Lines changed: 43 additions & 14 deletions

File tree

docs/explanation/nuclearnet.md

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -260,8 +260,11 @@ block-beta
260260

261261
## Fragmentation and reassembly
262262

263-
UDP datagrams have a practical size limit (the network MTU).
264-
Large messages are automatically split across multiple packets.
263+
Because NUClearNet uses UDP, each packet must fit within a single network datagram.
264+
UDP datagrams have a practical size limit — the network's MTU.
265+
Messages larger than this limit are automatically split into fragments,
266+
each sent as a separate UDP datagram.
267+
The receiver reassembles the fragments back into the complete message.
265268

266269
### MTU calculation
267270

@@ -304,8 +307,13 @@ If a message's total size would exceed this limit, the assembly is rejected.
304307

305308
## Reliable delivery
306309

307-
By default, NUClearNet is **unreliable** — packets are fire-and-forget, just like raw UDP.
308-
When you need guaranteed delivery, the reliable mode adds ACK-based retransmission.
310+
Fragmentation solves the message *size* problem, but UDP itself provides no delivery guarantees.
311+
Packets can be lost, reordered, or duplicated by the network.
312+
For many robotics use cases (sensor streams, video frames), this is fine — a missing update is quickly superseded by the next one.
313+
But some messages *must* arrive: configuration commands, state transitions, calibration data.
314+
315+
NUClearNet's reliable delivery mode adds ACK-based retransmission on top of the same fragmented UDP transport.
316+
When you send a message reliably, the system tracks which fragments have been acknowledged by the receiver and retransmits any that go missing.
309317

310318
### Unreliable (default)
311319

@@ -316,6 +324,8 @@ When you need guaranteed delivery, the reliable mode adds ACK-based retransmissi
316324

317325
### Reliable mode
318326

327+
When reliable delivery is requested, the sender and receiver engage in a conversation to ensure all fragments arrive:
328+
319329
```mermaid
320330
sequenceDiagram
321331
participant S as Sender
@@ -342,18 +352,22 @@ Key mechanisms:
342352
it responds with an ACK containing a bitset of *all* received fragments for that packet group.
343353
This gives the sender full visibility into what's been received.
344354
- **RTO-based retransmission** — the sender waits one RTO (Retransmission Timeout) before retransmitting un-ACKed fragments.
345-
Retransmitting too early wastes bandwidth; too late adds latency.
346-
- **Adaptive RTO estimation** — each peer's round-trip time is tracked using the Jacobson/Karels algorithm.
347-
The RTO adapts to changing network conditions.
355+
The RTO is calculated per peer based on measured round-trip times (see below).
348356
- **NACK support** — the receiver can proactively request retransmission of specific missing fragments via NACK packets,
349-
which forces the sender to retransmit immediately.
357+
which forces the sender to retransmit immediately rather than waiting for the RTO.
350358
- **No retransmission limit** — reliable packets are retransmitted indefinitely until either all fragments are ACKed,
351359
or the peer is removed (due to timeout or graceful leave).
352360
This guarantees delivery as long as the connection remains alive.
353361

354-
### RTT estimation (Jacobson/Karels)
362+
### How long to wait before retransmitting (RTT estimation)
363+
364+
The key challenge in retransmission is choosing *when* to retransmit.
365+
Too soon, and you waste bandwidth resending packets that were simply delayed.
366+
Too late, and the receiver is left waiting for data that was lost.
355367

356-
NUClearNet uses the TCP-standard Jacobson/Karels algorithm (RFC 6298) for per-peer RTT estimation:
368+
The answer depends on how long packets actually take to travel between two specific peers — the round-trip time.
369+
NUClearNet measures this per peer by timing how long it takes between sending a fragment and receiving its ACK.
370+
This measurement is then smoothed using the Jacobson/Karels algorithm (the same approach TCP uses, defined in RFC 6298):
357371

358372
```
359373
RTTVAR = (1 - β) × RTTVAR + β × |SRTT - sample|
@@ -369,11 +383,21 @@ Where:
369383
- `RTTVAR` — RTT variation (jitter)
370384
- `RTO` — retransmission timeout (clamped between 100 ms and 60 s)
371385

372-
This provides smooth, responsive RTT tracking that adapts to network congestion without oscillating.
386+
The RTO is the actual wait time before retransmitting.
387+
It's set slightly above the smoothed RTT (plus a jitter margin) so that under normal conditions,
388+
the ACK arrives just before the timeout fires.
389+
If the network gets congested and round-trip times increase, the RTO automatically grows to compensate.
390+
If the network recovers, the RTO shrinks back down.
391+
392+
This means retransmission timing is always appropriate for the current link conditions between each specific pair of peers,
393+
rather than relying on a fixed timeout that would be too aggressive for slow links or too conservative for fast ones.
373394

374395
## Subscription-based routing
375396

376-
Nodes advertise which message types they want to receive via subscription hashes in their announce packets.
397+
With fragmentation, reliability, and deduplication handling the *transport* of messages,
398+
the final piece is deciding *which peers* should receive each message.
399+
Rather than broadcasting everything to all peers (which wastes bandwidth),
400+
nodes advertise which message types they want to receive via subscription hashes in their announce packets.
377401
This allows senders to skip transmitting messages to peers that aren't interested in them.
378402

379403
```mermaid
@@ -400,8 +424,13 @@ the `NetworkController` adds the corresponding type hash to this node's subscrip
400424

401425
## Packet deduplication
402426

403-
Each peer has an associated `PacketDeduplicator` — a sliding-window bitset that tracks the last 256 packet IDs seen from that peer.
404-
When a packet arrives:
427+
Reliable delivery creates a new problem: duplicate packets.
428+
When a sender retransmits a fragment because the ACK was lost (not the fragment itself),
429+
the receiver may process the same fragment twice.
430+
Similarly, network anomalies can cause any UDP packet to arrive more than once.
431+
432+
To handle this, each peer has an associated `PacketDeduplicator` — a sliding-window bitset that tracks the last 256 packet IDs seen from that peer.
433+
When a data packet arrives:
405434

406435
1. If the packet ID falls within the window and is already marked as seen, it's dropped as a duplicate.
407436
1. If the packet ID is newer than the window, the window slides forward and the packet is accepted.

0 commit comments

Comments
 (0)