mirror of
https://github.com/jmcorgan/fips.git
synced 2026-08-09 00:04:54 +00:00
Hybrid coordinate warmup: CoordsWarmup message and proactive fallback
Implement hybrid coordinate cache warming strategy: piggyback coords via CP flag when they fit within transport MTU, send standalone CoordsWarmup (0x14) message when they don't. On CoordsRequired or PathBroken receipt, send CoordsWarmup immediately with source-side rate limiting (default 2s per destination, configurable). - Add CoordsWarmup = 0x14 session message type (empty body, CP flag) - Add send_coords_warmup() following send_session_msg() pattern - Restructure send_session_data() to send standalone warmup before data packet when piggybacked coords exceed MTU - Add immediate CoordsWarmup response in handle_coords_required() and handle_path_broken() with per-destination rate limiting - Add coords_response_interval_ms config (node.session) - Add RoutingErrorRateLimiter::with_interval() constructor - Zero transit-path changes: existing try_warm_coord_cache() handles CoordsWarmup identically to CP-flagged data packets - Update design docs (session layer, wire formats, mesh operation, configuration)
This commit is contained in:
@@ -83,10 +83,12 @@ may traverse multiple hops, each with independent link encryption.
|
||||
FLP signals routing failures asynchronously:
|
||||
|
||||
- **CoordsRequired**: A transit node lacks the destination's tree coordinates.
|
||||
FSP responds by re-initiating discovery and resetting the coordinate warmup
|
||||
strategy.
|
||||
- **PathBroken**: Greedy routing reached a dead end. FSP responds by
|
||||
re-discovering the destination's current coordinates and resetting warmup.
|
||||
FSP responds by sending a standalone CoordsWarmup (0x14) message
|
||||
(rate-limited), re-initiating discovery, and resetting the coordinate warmup
|
||||
counter.
|
||||
- **PathBroken**: Greedy routing reached a dead end. FSP responds by sending
|
||||
a standalone CoordsWarmup (rate-limited), re-discovering the destination's
|
||||
current coordinates, and resetting the warmup counter.
|
||||
|
||||
Both signals are generated by transit nodes (not the destination) and travel
|
||||
back to the source inside a new SessionDatagram. They are plaintext (not
|
||||
@@ -190,6 +192,7 @@ independent keys and sessions. The full Noise descriptor is
|
||||
`Noise_IK_secp256k1_ChaChaPoly_SHA256`.
|
||||
|
||||
The IK pattern:
|
||||
|
||||
- **msg1** (`→ e, es, s, ss`): Initiator sends ephemeral key, encrypts static
|
||||
key to responder. Four DH operations establish session keys.
|
||||
- **msg2** (`← e, ee, se`): Responder sends ephemeral key. Both parties now
|
||||
@@ -262,7 +265,7 @@ regardless of what packets were lost or reordered.
|
||||
The same `ReplayWindow` and `decrypt_with_replay_check()` implementation is
|
||||
used at both the link and session layers.
|
||||
|
||||
## CP (Coords Present) Warmup Strategy
|
||||
## Hybrid Coordinate Warmup Strategy
|
||||
|
||||
Session establishment (SessionSetup/SessionAck) warms transit node coordinate
|
||||
caches along the path. But coordinate caches have a finite TTL (default 300s),
|
||||
@@ -270,14 +273,43 @@ and entries may be evicted under memory pressure. When a transit node's cache
|
||||
entry expires, it cannot forward data packets (which carry only addresses, not
|
||||
coordinates) and sends a CoordsRequired error.
|
||||
|
||||
FSP uses a warmup-then-reactive strategy to keep transit caches populated:
|
||||
FSP uses a hybrid warmup strategy combining proactive piggybacking with
|
||||
reactive standalone messages to keep transit caches populated:
|
||||
|
||||
### Warmup Phase
|
||||
### Proactive Warmup Phase
|
||||
|
||||
After session establishment, the first N data packets (configurable, default 5)
|
||||
include both source and destination coordinates via the CP flag in the FSP
|
||||
common prefix. The coordinates appear in cleartext between the 12-byte header
|
||||
and the ciphertext, allowing transit nodes to cache them without decryption.
|
||||
per session attempt to piggyback source and destination coordinates via the CP
|
||||
flag in the FSP common prefix. The coordinates appear in cleartext between the
|
||||
12-byte header and the ciphertext, allowing transit nodes to cache them without
|
||||
decryption.
|
||||
|
||||
If piggybacking coordinates would cause the total packet to exceed the
|
||||
transport MTU, the source sends a standalone **CoordsWarmup** message (0x14)
|
||||
first, followed by the data packet without the CP flag. This ensures transit
|
||||
caches are warmed even when data packets are near the MTU limit.
|
||||
|
||||
### CoordsWarmup Message (0x14)
|
||||
|
||||
CoordsWarmup is an encrypted FSP message (phase 0x0) with the CP flag set and
|
||||
inner msg_type 0x14. It carries cleartext source and destination coordinates
|
||||
between the FSP header and the AEAD ciphertext, using the same format as
|
||||
CP-flagged data packets. The inner body is empty — the message exists solely
|
||||
to deliver coordinates to transit nodes.
|
||||
|
||||
Transit nodes extract coordinates via the existing `try_warm_coord_cache()`
|
||||
code path with zero changes to the transit forwarding logic. CoordsWarmup is
|
||||
indistinguishable from any other CP-flagged message at the transit layer.
|
||||
|
||||
Wire format:
|
||||
|
||||
```text
|
||||
FSP header (12 bytes, AAD): ver=0, phase=0, flags=CP, counter, payload_len
|
||||
Cleartext coords: src_coords + dst_coords (same encoding as CP flag)
|
||||
AEAD ciphertext: inner_header(6) + Poly1305 tag(16) = 22 bytes
|
||||
|
||||
Total FSP payload: 12 + coords + 22
|
||||
```
|
||||
|
||||
### Steady State
|
||||
|
||||
@@ -285,31 +317,32 @@ After the warmup count is reached, FSP clears the CP flag and sends minimal
|
||||
data packets (12-byte header + ciphertext). Transit nodes serve from their
|
||||
coordinate caches.
|
||||
|
||||
### Reactive Recovery
|
||||
### Reactive Re-Warm
|
||||
|
||||
When FSP receives a CoordsRequired signal:
|
||||
When FSP receives a CoordsRequired or PathBroken signal:
|
||||
|
||||
1. The warmup counter resets — subsequent data packets include coordinates again
|
||||
2. A new LookupRequest may be initiated to rediscover the destination's
|
||||
current coordinates
|
||||
3. When the LookupResponse arrives for an established session, the warmup
|
||||
1. A standalone CoordsWarmup message is sent immediately to re-warm transit
|
||||
caches, rate-limited at one per destination per configurable interval
|
||||
(default 2000ms, `node.session.coords_response_interval_ms`)
|
||||
2. The warmup counter resets — subsequent data packets piggyback coordinates
|
||||
again when possible (or send additional CoordsWarmup messages when the
|
||||
data packet would exceed the MTU)
|
||||
3. A new LookupRequest may be initiated to rediscover the destination's
|
||||
current coordinates (always for PathBroken; optionally for CoordsRequired)
|
||||
4. When the LookupResponse arrives for an established session, the warmup
|
||||
counter resets again (handling the timing gap where warmup packets might
|
||||
fire before transit caches are repopulated by discovery)
|
||||
|
||||
When FSP receives a PathBroken signal:
|
||||
|
||||
1. A LookupRequest is initiated to discover the destination's current
|
||||
coordinates (which may have changed due to topology change)
|
||||
2. The warmup counter resets
|
||||
|
||||
Both signals are rate-limited at transit nodes (100ms per destination) to
|
||||
prevent storms during topology changes.
|
||||
The source-side rate limiting prevents amplification: at most one standalone
|
||||
CoordsWarmup response per destination per `coords_response_interval_ms`
|
||||
(default 2s). This is independent of the transit-node rate limiting on error
|
||||
signal generation (100ms per destination).
|
||||
|
||||
### Warmup State Machine
|
||||
|
||||
```text
|
||||
┌──────────────┐
|
||||
│ WARMUP │ ◄── Send first N packets with coords
|
||||
│ WARMUP │ ◄── Send first N packets with coords (CP or CoordsWarmup)
|
||||
└──────┬───────┘
|
||||
│ N packets sent without CoordsRequired
|
||||
▼
|
||||
@@ -318,8 +351,13 @@ prevent storms during topology changes.
|
||||
└──────┬───────┘
|
||||
│ CoordsRequired or PathBroken received
|
||||
▼
|
||||
┌──────────────────────────┐
|
||||
│ SEND CoordsWarmup (0x14) │ ◄── Immediate standalone warmup (rate-limited)
|
||||
└──────────┬───────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ WARMUP │ ◄── Counter reset, send coords again
|
||||
│ WARMUP │ ◄── Counter reset, piggyback coords again
|
||||
└──────────────┘
|
||||
```
|
||||
|
||||
@@ -336,6 +374,7 @@ configurable size (default 10K entries). There is no TTL — entries are evicted
|
||||
only when the cache is full and space is needed for a new entry.
|
||||
|
||||
Cache population mechanisms:
|
||||
|
||||
- **DNS lookup**: The primary path. Resolving `npub1xxx...xxx.fips` derives
|
||||
the IPv6 address and populates the identity cache.
|
||||
- **Inbound traffic**: Authenticated sessions from other nodes populate the
|
||||
@@ -454,7 +493,7 @@ MMP session metrics session=npub1tdwa...84le rtt=4.3ms loss=0.6% jitter=0.2ms go
|
||||
| Session establishment (Noise IK) | **Implemented** |
|
||||
| End-to-end encryption (ChaCha20-Poly1305) | **Implemented** |
|
||||
| Explicit counter replay protection | **Implemented** |
|
||||
| CP warmup-then-reactive | **Implemented** |
|
||||
| Hybrid coordinate warmup (CP + CoordsWarmup) | **Implemented** |
|
||||
| FSP wire format (prefix, AAD, inner header) | **Implemented** |
|
||||
| Session-layer MMP | **Implemented** |
|
||||
| Identity cache (LRU-only) | **Implemented** |
|
||||
|
||||
Reference in New Issue
Block a user