Design documentation illustration pass and FLP→FMP rename
Rename FIPS Link Protocol (FLP) to FIPS Mesh Protocol (FMP)
The "Link Protocol" name understated the layer's scope — spanning tree
construction, bloom filter routing, greedy forwarding, and mesh-wide
coordination go well beyond link-level concerns. Rename fips-link-layer.md
to fips-mesh-layer.md, update FLP→FMP throughout docs and source code
(FLP_VERSION→FMP_VERSION, wire.rs, rx_loop.rs, spanning_tree.rs).
New SVG illustrations
- Protocol stack: color-coded layer diagram replacing ASCII art
- OSI mapping: side-by-side comparison with traditional networking layers
- Bloom filter propagation: 6-node tree with sender-colored filter boxes
showing split-horizon computation per link
- Routing decision flowchart: 5-step priority chain with candidate ranking
by tree distance and link performance
- Coordinate discovery: sequence diagram showing LookupRequest propagation,
response caching, and SessionSetup cache warming
Redesigned existing SVGs
- Architecture overview: uniform node layout, U-shaped encrypted link
connectors, separate end-to-end session line
- Node architecture: split Router Core into FSP and FMP layers, reorganize
transports into Overlay/Shared Medium/Point-to-Point categories
- Identity derivation: wider boxes, visible encode arrow, dashed npub line
fips-intro.md revisions
- Add inline references to prior work: Yggdrasil/Ironwood for coordinate
routing, Noise Protocol Framework for IK handshakes, WireGuard for
index-based session dispatch, Wikipedia for bloom filters, split-horizon,
and greedy embedding
- Add explanatory paragraphs after bloom filter diagram describing
split-horizon filter computation and candidate selection behavior
- Simplify transport abstraction language, remove I2P/LoRa references
- Fix LookupRequest wording ("propagates" not "floods"), note intermediate
node coordinate caching on lookup responses
- Rewrite architecture overview prose to match redesigned diagrams
@@ -16,7 +16,7 @@ specific topics.
|
||||
| -------- | ----------- |
|
||||
| [fips-intro.md](fips-intro.md) | Protocol introduction: goals, architecture, layer model |
|
||||
| [fips-transport-layer.md](fips-transport-layer.md) | Transport layer: datagram delivery over arbitrary media |
|
||||
| [fips-link-layer.md](fips-link-layer.md) | FIPS Link Protocol (FLP): peer authentication, link encryption, forwarding |
|
||||
| [fips-mesh-layer.md](fips-mesh-layer.md) | FIPS Mesh Protocol (FMP): peer authentication, link encryption, forwarding |
|
||||
| [fips-session-layer.md](fips-session-layer.md) | FIPS Session Protocol (FSP): end-to-end encryption, sessions |
|
||||
| [fips-ipv6-adapter.md](fips-ipv6-adapter.md) | IPv6 adaptation: TUN interface, DNS, MTU enforcement |
|
||||
|
||||
@@ -58,7 +58,7 @@ specific topics.
|
||||
fips-transport-layer fips-mesh- fips-software-
|
||||
│ operation architecture
|
||||
▼ │ │
|
||||
fips-link-layer ◄────────┤ ▼
|
||||
fips-mesh-layer ◄────────┤ ▼
|
||||
│ │ fips-state-machines
|
||||
▼ │
|
||||
fips-session-layer ├──► fips-spanning-tree
|
||||
|
||||
@@ -1,122 +1,113 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 420" font-family="monospace" font-size="13">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 455" font-family="monospace" font-size="13">
|
||||
<style>
|
||||
rect.node { fill: #1a1a2e; stroke: #e0e0e0; stroke-width: 1.5; rx: 4; }
|
||||
rect.app { fill: #2a2a4e; stroke: #e0e0e0; stroke-width: 1; rx: 2; }
|
||||
rect.fips { fill: #2e3a5e; stroke: #e0e0e0; stroke-width: 1; rx: 2; }
|
||||
rect.xport { fill: #3a2e2e; stroke: #e0e0e0; stroke-width: 1; rx: 2; }
|
||||
rect.app { fill: #1a3a2a; stroke: #40a060; stroke-width: 1; rx: 2; }
|
||||
rect.fips { fill: #2e3a5e; stroke: #5080c0; stroke-width: 1; rx: 2; }
|
||||
rect.xport { fill: #2a1a1a; stroke: #c06040; stroke-width: 1; rx: 2; }
|
||||
text { fill: #e0e0e0; }
|
||||
text.label { font-size: 14px; font-weight: bold; }
|
||||
text.npub { font-size: 11px; fill: #90a0b0; }
|
||||
text.label { font-size: 15px; font-weight: bold; }
|
||||
text.role { font-size: 11px; fill: #90a0b0; }
|
||||
text.layer { font-size: 12px; }
|
||||
text.transport-label { font-size: 11px; fill: #c0c0c0; }
|
||||
line.link { stroke: #70a0d0; stroke-width: 2; }
|
||||
line.session { stroke: #d0a040; stroke-width: 2; stroke-dasharray: 6,3; }
|
||||
text.link-label { font-size: 11px; fill: #70a0d0; }
|
||||
text.session-label { font-size: 12px; fill: #d0a040; }
|
||||
text.caption { font-size: 13px; fill: #808090; font-style: italic; }
|
||||
path.link { fill: none; stroke: #5080c0; stroke-width: 2; }
|
||||
text.link-label { font-size: 12px; fill: #5080c0; font-weight: bold; }
|
||||
text.link-enc { font-size: 10px; fill: #5080c0; }
|
||||
line.session { stroke: #d0a040; stroke-width: 2; stroke-dasharray: 8,4; }
|
||||
text.session-label { font-size: 13px; fill: #d0a040; }
|
||||
text.legend { font-size: 12px; }
|
||||
</style>
|
||||
|
||||
<!-- Background -->
|
||||
<rect width="900" height="420" fill="#0d1117" rx="8"/>
|
||||
<rect width="880" height="420" fill="#0d1117" rx="8"/>
|
||||
|
||||
<!-- Node positions: x = 60, 230, 400, 570, 740 width=100 -->
|
||||
<!-- ============ NODES ============ -->
|
||||
<!-- Node A (source) -->
|
||||
<text x="100" y="30" text-anchor="middle" class="label">Node A</text>
|
||||
<text x="100" y="46" text-anchor="middle" class="role">(source)</text>
|
||||
<rect x="50" y="56" width="100" height="130" class="node"/>
|
||||
<rect x="60" y="66" width="80" height="28" class="app"/>
|
||||
<text x="100" y="85" text-anchor="middle" class="layer">App</text>
|
||||
<rect x="60" y="102" width="80" height="28" class="fips"/>
|
||||
<text x="100" y="121" text-anchor="middle" class="layer">FIPS</text>
|
||||
<rect x="60" y="138" width="80" height="28" class="xport"/>
|
||||
<text x="100" y="157" text-anchor="middle" class="layer">WiFi</text>
|
||||
|
||||
<!-- Node A -->
|
||||
<text x="110" y="30" text-anchor="middle" class="label">Node A</text>
|
||||
<text x="110" y="46" text-anchor="middle" class="npub">npub1aaa...</text>
|
||||
<text x="110" y="60" text-anchor="middle" class="role">(source)</text>
|
||||
<rect x="60" y="70" width="100" height="130" class="node"/>
|
||||
<rect x="70" y="80" width="80" height="30" class="app"/>
|
||||
<text x="110" y="100" text-anchor="middle" class="layer">App</text>
|
||||
<rect x="70" y="118" width="80" height="30" class="fips"/>
|
||||
<text x="110" y="138" text-anchor="middle" class="layer">FIPS</text>
|
||||
<rect x="70" y="156" width="80" height="30" class="xport"/>
|
||||
<text x="110" y="176" text-anchor="middle" class="layer">WiFi</text>
|
||||
|
||||
<!-- Node B -->
|
||||
<!-- Node B (transit) -->
|
||||
<text x="280" y="30" text-anchor="middle" class="label">Node B</text>
|
||||
<text x="280" y="46" text-anchor="middle" class="npub">npub1bbb...</text>
|
||||
<text x="280" y="60" text-anchor="middle" class="role">(relay)</text>
|
||||
<rect x="230" y="70" width="100" height="130" class="node"/>
|
||||
<rect x="240" y="118" width="80" height="30" class="fips"/>
|
||||
<text x="280" y="138" text-anchor="middle" class="layer">FIPS</text>
|
||||
<rect x="240" y="156" width="37" height="30" class="xport"/>
|
||||
<text x="258" y="176" text-anchor="middle" class="layer">WiFi</text>
|
||||
<rect x="283" y="156" width="37" height="30" class="xport"/>
|
||||
<text x="302" y="176" text-anchor="middle" class="layer">Eth</text>
|
||||
<text x="280" y="46" text-anchor="middle" class="role">(transit)</text>
|
||||
<rect x="230" y="56" width="100" height="130" class="node"/>
|
||||
<rect x="240" y="102" width="80" height="28" class="fips"/>
|
||||
<text x="280" y="121" text-anchor="middle" class="layer">FIPS</text>
|
||||
<rect x="240" y="138" width="36" height="28" class="xport"/>
|
||||
<text x="258" y="157" text-anchor="middle" class="layer">WiFi</text>
|
||||
<rect x="284" y="138" width="36" height="28" class="xport"/>
|
||||
<text x="302" y="157" text-anchor="middle" class="layer">Eth</text>
|
||||
|
||||
<!-- Node C -->
|
||||
<text x="450" y="30" text-anchor="middle" class="label">Node C</text>
|
||||
<text x="450" y="46" text-anchor="middle" class="npub">npub1ccc...</text>
|
||||
<text x="450" y="60" text-anchor="middle" class="role">(relay)</text>
|
||||
<rect x="400" y="70" width="100" height="130" class="node"/>
|
||||
<rect x="410" y="118" width="80" height="30" class="fips"/>
|
||||
<text x="450" y="138" text-anchor="middle" class="layer">FIPS</text>
|
||||
<rect x="410" y="156" width="37" height="30" class="xport"/>
|
||||
<text x="428" y="176" text-anchor="middle" class="layer">Eth</text>
|
||||
<rect x="453" y="156" width="37" height="30" class="xport"/>
|
||||
<text x="472" y="176" text-anchor="middle" class="layer">UDP</text>
|
||||
<!-- Node C (transit) -->
|
||||
<text x="460" y="30" text-anchor="middle" class="label">Node C</text>
|
||||
<text x="460" y="46" text-anchor="middle" class="role">(transit)</text>
|
||||
<rect x="410" y="56" width="100" height="130" class="node"/>
|
||||
<rect x="420" y="102" width="80" height="28" class="fips"/>
|
||||
<text x="460" y="121" text-anchor="middle" class="layer">FIPS</text>
|
||||
<rect x="420" y="138" width="36" height="28" class="xport"/>
|
||||
<text x="438" y="157" text-anchor="middle" class="layer">Eth</text>
|
||||
<rect x="464" y="138" width="36" height="28" class="xport"/>
|
||||
<text x="482" y="157" text-anchor="middle" class="layer">UDP</text>
|
||||
|
||||
<!-- Node D -->
|
||||
<text x="620" y="30" text-anchor="middle" class="label">Node D</text>
|
||||
<text x="620" y="46" text-anchor="middle" class="npub">npub1ddd...</text>
|
||||
<text x="620" y="60" text-anchor="middle" class="role">(relay)</text>
|
||||
<rect x="570" y="70" width="100" height="130" class="node"/>
|
||||
<rect x="580" y="118" width="80" height="30" class="fips"/>
|
||||
<text x="620" y="138" text-anchor="middle" class="layer">FIPS</text>
|
||||
<rect x="580" y="156" width="37" height="30" class="xport"/>
|
||||
<text x="598" y="176" text-anchor="middle" class="layer">UDP</text>
|
||||
<rect x="623" y="156" width="37" height="30" class="xport"/>
|
||||
<text x="642" y="176" text-anchor="middle" class="layer">Tor</text>
|
||||
<!-- Node D (transit) -->
|
||||
<text x="640" y="30" text-anchor="middle" class="label">Node D</text>
|
||||
<text x="640" y="46" text-anchor="middle" class="role">(transit)</text>
|
||||
<rect x="590" y="56" width="100" height="130" class="node"/>
|
||||
<rect x="600" y="102" width="80" height="28" class="fips"/>
|
||||
<text x="640" y="121" text-anchor="middle" class="layer">FIPS</text>
|
||||
<rect x="600" y="138" width="36" height="28" class="xport"/>
|
||||
<text x="618" y="157" text-anchor="middle" class="layer">UDP</text>
|
||||
<rect x="644" y="138" width="36" height="28" class="xport"/>
|
||||
<text x="662" y="157" text-anchor="middle" class="layer">Tor</text>
|
||||
|
||||
<!-- Node E -->
|
||||
<text x="790" y="30" text-anchor="middle" class="label">Node E</text>
|
||||
<text x="790" y="46" text-anchor="middle" class="npub">npub1eee...</text>
|
||||
<text x="790" y="60" text-anchor="middle" class="role">(dest)</text>
|
||||
<rect x="740" y="70" width="100" height="130" class="node"/>
|
||||
<rect x="750" y="80" width="80" height="30" class="app"/>
|
||||
<text x="790" y="100" text-anchor="middle" class="layer">App</text>
|
||||
<rect x="750" y="118" width="80" height="30" class="fips"/>
|
||||
<text x="790" y="138" text-anchor="middle" class="layer">FIPS</text>
|
||||
<rect x="750" y="156" width="80" height="30" class="xport"/>
|
||||
<text x="790" y="176" text-anchor="middle" class="layer">Tor</text>
|
||||
<!-- Node E (destination) -->
|
||||
<text x="800" y="30" text-anchor="middle" class="label">Node E</text>
|
||||
<text x="800" y="46" text-anchor="middle" class="role">(destination)</text>
|
||||
<rect x="750" y="56" width="100" height="130" class="node"/>
|
||||
<rect x="760" y="66" width="80" height="28" class="app"/>
|
||||
<text x="800" y="85" text-anchor="middle" class="layer">App</text>
|
||||
<rect x="760" y="102" width="80" height="28" class="fips"/>
|
||||
<text x="800" y="121" text-anchor="middle" class="layer">FIPS</text>
|
||||
<rect x="760" y="138" width="80" height="28" class="xport"/>
|
||||
<text x="800" y="157" text-anchor="middle" class="layer">Tor</text>
|
||||
|
||||
<!-- Link lines (from bottom of transport boxes) -->
|
||||
<!-- WiFi: A(110) -> B-WiFi(258) -->
|
||||
<line x1="110" y1="200" x2="110" y2="240" class="link"/>
|
||||
<line x1="110" y1="240" x2="258" y2="240" class="link"/>
|
||||
<line x1="258" y1="240" x2="258" y2="200" class="link"/>
|
||||
<text x="184" y="256" text-anchor="middle" class="link-label">WiFi</text>
|
||||
<!-- ============ LINK CONNECTIONS (U-shaped, all same depth) ============ -->
|
||||
<!-- WiFi: A ↔ B -->
|
||||
<path d="M 100 186 L 100 240 L 258 240 L 258 186" class="link"/>
|
||||
<text x="179" y="256" text-anchor="middle" class="link-label">WiFi</text>
|
||||
<text x="179" y="268" text-anchor="middle" class="link-enc">encrypted FMP link</text>
|
||||
|
||||
<!-- Ethernet: B-Eth(302) -> C-Eth(428) -->
|
||||
<line x1="302" y1="200" x2="302" y2="270" class="link"/>
|
||||
<line x1="302" y1="270" x2="428" y2="270" class="link"/>
|
||||
<line x1="428" y1="270" x2="428" y2="200" class="link"/>
|
||||
<text x="365" y="286" text-anchor="middle" class="link-label">Ethernet</text>
|
||||
<!-- Ethernet: B ↔ C -->
|
||||
<path d="M 302 186 L 302 240 L 438 240 L 438 186" class="link"/>
|
||||
<text x="370" y="256" text-anchor="middle" class="link-label">Ethernet</text>
|
||||
<text x="370" y="268" text-anchor="middle" class="link-enc">encrypted FMP link</text>
|
||||
|
||||
<!-- UDP/IP: C-UDP(472) -> D-UDP(598) -->
|
||||
<line x1="472" y1="200" x2="472" y2="300" class="link"/>
|
||||
<line x1="472" y1="300" x2="598" y2="300" class="link"/>
|
||||
<line x1="598" y1="300" x2="598" y2="200" class="link"/>
|
||||
<text x="535" y="316" text-anchor="middle" class="link-label">UDP/IP</text>
|
||||
<!-- UDP/IP: C ↔ D -->
|
||||
<path d="M 482 186 L 482 240 L 618 240 L 618 186" class="link"/>
|
||||
<text x="550" y="256" text-anchor="middle" class="link-label">UDP/IP</text>
|
||||
<text x="550" y="268" text-anchor="middle" class="link-enc">encrypted FMP link</text>
|
||||
|
||||
<!-- Tor: D-Tor(642) -> E(790) -->
|
||||
<line x1="642" y1="200" x2="642" y2="330" class="link"/>
|
||||
<line x1="642" y1="330" x2="790" y2="330" class="link"/>
|
||||
<line x1="790" y1="330" x2="790" y2="200" class="link"/>
|
||||
<text x="716" y="346" text-anchor="middle" class="link-label">Tor</text>
|
||||
<!-- Tor: D ↔ E -->
|
||||
<path d="M 662 186 L 662 240 L 800 240 L 800 186" class="link"/>
|
||||
<text x="731" y="256" text-anchor="middle" class="link-label">Tor</text>
|
||||
<text x="731" y="268" text-anchor="middle" class="link-enc">encrypted FMP link</text>
|
||||
|
||||
<!-- End-to-end session (dashed) -->
|
||||
<line x1="110" y1="380" x2="790" y2="380" class="session"/>
|
||||
<text x="450" y="375" text-anchor="middle" class="session-label">End-to-end encrypted session (A ↔ E)</text>
|
||||
<!-- ============ END-TO-END SESSION (below links, no intersection) ============ -->
|
||||
<line x1="100" y1="305" x2="800" y2="305" class="session"/>
|
||||
<text x="450" y="298" text-anchor="middle" class="session-label">End-to-end FSP session encryption (A ↔ E)</text>
|
||||
|
||||
<!-- Link labels -->
|
||||
<text x="184" y="405" text-anchor="middle" class="link-label">Link</text>
|
||||
<line x1="110" y1="395" x2="258" y2="395" class="link" stroke-dasharray="3,2"/>
|
||||
<text x="365" y="405" text-anchor="middle" class="link-label">Link</text>
|
||||
<line x1="302" y1="395" x2="428" y2="395" class="link" stroke-dasharray="3,2"/>
|
||||
<text x="535" y="405" text-anchor="middle" class="link-label">Link</text>
|
||||
<line x1="472" y1="395" x2="598" y2="395" class="link" stroke-dasharray="3,2"/>
|
||||
<text x="716" y="405" text-anchor="middle" class="link-label">Link</text>
|
||||
<line x1="642" y1="395" x2="790" y2="395" class="link" stroke-dasharray="3,2"/>
|
||||
<!-- ============ LEGEND ============ -->
|
||||
<line x1="60" y1="345" x2="120" y2="345" class="session"/>
|
||||
<text x="132" y="349" class="legend" fill="#d0a040">FSP session encryption (end-to-end)</text>
|
||||
|
||||
<path d="M 60 370 L 60 380 L 120 380 L 120 370" class="link"/>
|
||||
<text x="132" y="381" class="legend" fill="#5080c0">FMP link encryption (hop-by-hop)</text>
|
||||
|
||||
<!-- Caption -->
|
||||
<text x="440" y="443" text-anchor="middle" class="caption">Multi-transport architecture — each link encrypted independently, session spans the full path</text>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.2 KiB |
@@ -0,0 +1,147 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 840 620" font-family="monospace" font-size="12">
|
||||
<style>
|
||||
rect.callout { fill: #151520; stroke: #505040; stroke-width: 1; rx: 3; }
|
||||
rect.bloom { fill: #1a1a2e; stroke-width: 1; rx: 3; }
|
||||
text { fill: #e0e0e0; }
|
||||
text.title { font-size: 16px; font-weight: bold; }
|
||||
text.subtitle { font-size: 12px; fill: #909090; }
|
||||
text.nlabel { font-size: 14px; font-weight: bold; }
|
||||
text.bloom-t { font-size: 11px; fill: #b0b0c0; }
|
||||
text.sender { font-size: 12px; font-weight: bold; }
|
||||
text.op { font-size: 10px; fill: #b0b0b0; font-style: italic; }
|
||||
text.caption { font-size: 13px; fill: #808090; font-style: italic; }
|
||||
line.link { stroke: #404860; stroke-width: 2; }
|
||||
</style>
|
||||
|
||||
<!-- Background -->
|
||||
<rect width="840" height="620" fill="#0d1117" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="420" y="28" text-anchor="middle" class="title">Bloom Filter Propagation</text>
|
||||
<text x="420" y="46" text-anchor="middle" class="subtitle">Each link carries two filters — one in each direction (split-horizon)</text>
|
||||
|
||||
<!--
|
||||
Node colors (sender-coded):
|
||||
R: #d0a040 (amber) B: #40a0a0 (teal)
|
||||
C: #a060c0 (purple) D: #c07050 (coral)
|
||||
E: #50a060 (green) F: #5090d0 (sky)
|
||||
|
||||
Filter contents (tree-only, no mesh links):
|
||||
D to B = {D} B to D = {B C E F R}
|
||||
E to B = {E} B to E = {B C D F R}
|
||||
F to C = {F} C to F = {B C D E R}
|
||||
B to R = {B D E} R to B = {C F R}
|
||||
C to R = {C F} R to C = {B D E R}
|
||||
-->
|
||||
|
||||
<!-- ═══ Edges (drawn first so nodes/boxes overlay) ═══ -->
|
||||
<line x1="400" y1="120" x2="232" y2="252" class="link"/>
|
||||
<line x1="440" y1="120" x2="610" y2="252" class="link"/>
|
||||
<line x1="192" y1="272" x2="130" y2="412" class="link"/>
|
||||
<line x1="228" y1="272" x2="290" y2="412" class="link"/>
|
||||
<line x1="630" y1="272" x2="630" y2="412" class="link"/>
|
||||
|
||||
<!-- ═══ Nodes (colored per-node) ═══ -->
|
||||
|
||||
<rect x="388" y="92" width="64" height="36" fill="#2e3020" stroke="#d0a040" stroke-width="2" rx="6"/>
|
||||
<text x="420" y="115" text-anchor="middle" class="nlabel" fill="#d0a040">R</text>
|
||||
|
||||
<rect x="178" y="248" width="64" height="36" fill="#1e3030" stroke="#40a0a0" stroke-width="2" rx="6"/>
|
||||
<text x="210" y="271" text-anchor="middle" class="nlabel" fill="#40a0a0">B</text>
|
||||
|
||||
<rect x="598" y="248" width="64" height="36" fill="#2a1e30" stroke="#a060c0" stroke-width="2" rx="6"/>
|
||||
<text x="630" y="271" text-anchor="middle" class="nlabel" fill="#a060c0">C</text>
|
||||
|
||||
<rect x="78" y="408" width="64" height="36" fill="#2e2018" stroke="#c07050" stroke-width="2" rx="6"/>
|
||||
<text x="110" y="431" text-anchor="middle" class="nlabel" fill="#c07050">D</text>
|
||||
|
||||
<rect x="278" y="408" width="64" height="36" fill="#1a2e1a" stroke="#50a060" stroke-width="2" rx="6"/>
|
||||
<text x="310" y="431" text-anchor="middle" class="nlabel" fill="#50a060">E</text>
|
||||
|
||||
<rect x="598" y="408" width="64" height="36" fill="#1a2030" stroke="#5090d0" stroke-width="2" rx="6"/>
|
||||
<text x="630" y="431" text-anchor="middle" class="nlabel" fill="#5090d0">F</text>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════ -->
|
||||
<!-- Filter boxes colored by sender node. -->
|
||||
<!-- Every filter: self + merge(all inbound except recipient's) -->
|
||||
<!-- ═══════════════════════════════════════════════════════ -->
|
||||
|
||||
<!-- ─── R—B link ─── -->
|
||||
|
||||
<!-- B to R -->
|
||||
<text x="210" y="120" class="sender" fill="#40a0a0">B to R</text>
|
||||
<rect x="210" y="124" width="80" height="26" class="bloom" stroke="#40a0a0"/>
|
||||
<text x="218" y="142" class="bloom-t">B D E</text>
|
||||
|
||||
<!-- R to B -->
|
||||
<text x="210" y="166" class="sender" fill="#d0a040">R to B</text>
|
||||
<rect x="210" y="170" width="80" height="26" class="bloom" stroke="#d0a040"/>
|
||||
<text x="218" y="188" class="bloom-t">C F R</text>
|
||||
|
||||
<!-- ─── R—C link ─── -->
|
||||
|
||||
<!-- C to R -->
|
||||
<text x="560" y="120" class="sender" fill="#a060c0">C to R</text>
|
||||
<rect x="560" y="124" width="80" height="26" class="bloom" stroke="#a060c0"/>
|
||||
<text x="568" y="142" class="bloom-t">C F</text>
|
||||
|
||||
<!-- R to C -->
|
||||
<text x="560" y="166" class="sender" fill="#d0a040">R to C</text>
|
||||
<rect x="560" y="170" width="80" height="26" class="bloom" stroke="#d0a040"/>
|
||||
<text x="568" y="188" class="bloom-t">B D E R</text>
|
||||
|
||||
<!-- ─── B—D link ─── -->
|
||||
|
||||
<!-- D to B -->
|
||||
<text x="52" y="320" class="sender" fill="#c07050">D to B</text>
|
||||
<rect x="52" y="324" width="80" height="26" class="bloom" stroke="#c07050"/>
|
||||
<text x="60" y="342" class="bloom-t">D</text>
|
||||
|
||||
<!-- B to D -->
|
||||
<text x="52" y="366" class="sender" fill="#40a0a0">B to D</text>
|
||||
<rect x="52" y="370" width="80" height="26" class="bloom" stroke="#40a0a0"/>
|
||||
<text x="60" y="388" class="bloom-t">B C E F R</text>
|
||||
|
||||
<!-- ─── B—E link ─── -->
|
||||
|
||||
<!-- E to B -->
|
||||
<text x="298" y="320" class="sender" fill="#50a060">E to B</text>
|
||||
<rect x="298" y="324" width="80" height="26" class="bloom" stroke="#50a060"/>
|
||||
<text x="306" y="342" class="bloom-t">E</text>
|
||||
|
||||
<!-- B to E -->
|
||||
<text x="298" y="366" class="sender" fill="#40a0a0">B to E</text>
|
||||
<rect x="298" y="370" width="80" height="26" class="bloom" stroke="#40a0a0"/>
|
||||
<text x="306" y="388" class="bloom-t">B C D F R</text>
|
||||
|
||||
<!-- ─── C—F link ─── -->
|
||||
|
||||
<!-- F to C -->
|
||||
<text x="668" y="320" class="sender" fill="#5090d0">F to C</text>
|
||||
<rect x="668" y="324" width="80" height="26" class="bloom" stroke="#5090d0"/>
|
||||
<text x="676" y="342" class="bloom-t">F</text>
|
||||
|
||||
<!-- C to F -->
|
||||
<text x="668" y="366" class="sender" fill="#a060c0">C to F</text>
|
||||
<rect x="668" y="370" width="80" height="26" class="bloom" stroke="#a060c0"/>
|
||||
<text x="676" y="388" class="bloom-t">B C D E R</text>
|
||||
|
||||
<!-- ═══ Merge annotations ═══ -->
|
||||
<text x="248" y="271" class="op">merges D + E + self, sends to R</text>
|
||||
<text x="592" y="271" text-anchor="end" class="op">merges F + self, sends to R</text>
|
||||
|
||||
<!-- ═══ Legend ═══ -->
|
||||
<rect x="40" y="462" width="760" height="36" class="callout"/>
|
||||
<text x="60" y="486" font-size="12" font-weight="bold" fill="#e0e0e0">X to Y</text>
|
||||
<rect x="116" y="474" width="54" height="20" class="bloom" stroke="#e0e0e0"/>
|
||||
<text x="180" y="488" class="bloom-t">filter X sends to Y — box color matches sender node</text>
|
||||
|
||||
<!-- ═══ Callout: candidate selection ═══ -->
|
||||
<rect x="40" y="512" width="760" height="62" class="callout"/>
|
||||
<text x="56" y="532" font-size="11" font-weight="bold" fill="#d0a040">Candidate selection</text>
|
||||
<text x="56" y="548" font-size="10" fill="#c0c0c0">At any node, each peer's filter answers: "can you maybe reach destination X?"</text>
|
||||
<text x="56" y="564" font-size="10" fill="#c0c0c0">Example: D wants to reach F. D checks the filter from B: B C E F R — F present, so B is a candidate.</text>
|
||||
|
||||
<!-- Caption -->
|
||||
<text x="420" y="604" text-anchor="middle" class="caption">At steady state, every node knows full network reachability through each of its peers</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.2 KiB |
@@ -166,7 +166,7 @@ configurable.
|
||||
### Link-Layer MMP (`node.mmp.*`)
|
||||
|
||||
Metrics Measurement Protocol for per-peer link measurement. See
|
||||
[fips-link-layer.md](fips-link-layer.md) for behavioral details.
|
||||
[fips-mesh-layer.md](fips-mesh-layer.md) for behavioral details.
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 860 680" font-family="monospace" font-size="12">
|
||||
<style>
|
||||
rect.node { fill: #2e3a5e; stroke: #5080c0; stroke-width: 2; rx: 6; }
|
||||
rect.cache { fill: #151520; stroke: #404060; stroke-width: 1; rx: 3; }
|
||||
rect.phase { fill: none; stroke: none; }
|
||||
text { fill: #e0e0e0; }
|
||||
text.title { font-size: 16px; font-weight: bold; }
|
||||
text.subtitle { font-size: 12px; fill: #909090; }
|
||||
text.nlabel { font-size: 13px; font-weight: bold; }
|
||||
text.nrole { font-size: 10px; fill: #909090; }
|
||||
text.plabel { font-size: 13px; font-weight: bold; fill: #909090; }
|
||||
text.annot { font-size: 10px; fill: #909090; font-style: italic; }
|
||||
text.alabel { font-size: 11px; }
|
||||
text.clabel { font-size: 9px; fill: #c0c0c0; }
|
||||
text.caption { font-size: 11px; fill: #707080; font-style: italic; }
|
||||
line.sep { stroke: #303040; stroke-width: 1; stroke-dasharray: 6,4; }
|
||||
line.life { stroke: #303040; stroke-width: 1; stroke-dasharray: 2,3; }
|
||||
line.disco { stroke: #5080c0; stroke-width: 2; }
|
||||
line.resp { stroke: #d0a040; stroke-width: 2; stroke-dasharray: 6,3; }
|
||||
line.data { stroke: #40a060; stroke-width: 2; }
|
||||
polygon.disco { fill: #5080c0; }
|
||||
polygon.resp { fill: #d0a040; }
|
||||
polygon.data { fill: #40a060; }
|
||||
</style>
|
||||
|
||||
<!-- Background -->
|
||||
<rect width="860" height="680" fill="#0d1117" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="430" y="28" text-anchor="middle" class="title">Coordinate Discovery and Caching</text>
|
||||
<text x="430" y="46" text-anchor="middle" class="subtitle">LookupRequest/Response warms caches along the path</text>
|
||||
|
||||
<!-- ═══ Node headers ═══ -->
|
||||
<!-- Node positions: A=160, B=340, C=520, D=700 -->
|
||||
|
||||
<!-- Node A — Source -->
|
||||
<rect x="110" y="68" width="100" height="42" class="node"/>
|
||||
<text x="160" y="88" text-anchor="middle" class="nlabel">A</text>
|
||||
<text x="160" y="101" text-anchor="middle" class="nrole">Source</text>
|
||||
|
||||
<!-- Node B — Transit -->
|
||||
<rect x="290" y="68" width="100" height="42" class="node"/>
|
||||
<text x="340" y="88" text-anchor="middle" class="nlabel">B</text>
|
||||
<text x="340" y="101" text-anchor="middle" class="nrole">Transit</text>
|
||||
|
||||
<!-- Node C — Transit -->
|
||||
<rect x="470" y="68" width="100" height="42" class="node"/>
|
||||
<text x="520" y="88" text-anchor="middle" class="nlabel">C</text>
|
||||
<text x="520" y="101" text-anchor="middle" class="nrole">Transit</text>
|
||||
|
||||
<!-- Node D — Destination -->
|
||||
<rect x="650" y="68" width="100" height="42" class="node"/>
|
||||
<text x="700" y="88" text-anchor="middle" class="nlabel">D</text>
|
||||
<text x="700" y="101" text-anchor="middle" class="nrole">Destination</text>
|
||||
|
||||
<!-- ═══ Lifelines ═══ -->
|
||||
<line x1="160" y1="110" x2="160" y2="620" class="life"/>
|
||||
<line x1="340" y1="110" x2="340" y2="620" class="life"/>
|
||||
<line x1="520" y1="110" x2="520" y2="620" class="life"/>
|
||||
<line x1="700" y1="110" x2="700" y2="620" class="life"/>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════ -->
|
||||
<!-- Phase 1 — Discovery (y: 130–290) -->
|
||||
<!-- ═══════════════════════════════════════════════ -->
|
||||
|
||||
<text x="40" y="148" text-anchor="middle" class="plabel">Phase 1</text>
|
||||
<text x="40" y="164" text-anchor="middle" class="annot">Discovery</text>
|
||||
|
||||
<!-- A → B LookupRequest -->
|
||||
<line x1="170" y1="170" x2="328" y2="170" class="disco"/>
|
||||
<polygon points="326,165 336,170 326,175" class="disco"/>
|
||||
<text x="250" y="163" text-anchor="middle" class="alabel" fill="#5080c0">LookupRequest</text>
|
||||
|
||||
<!-- B → C LookupRequest -->
|
||||
<line x1="350" y1="200" x2="508" y2="200" class="disco"/>
|
||||
<polygon points="506,195 516,200 506,205" class="disco"/>
|
||||
<text x="430" y="193" text-anchor="middle" class="alabel" fill="#5080c0">LookupRequest</text>
|
||||
|
||||
<!-- C → D LookupRequest -->
|
||||
<line x1="530" y1="230" x2="688" y2="230" class="disco"/>
|
||||
<polygon points="686,225 696,230 686,235" class="disco"/>
|
||||
<text x="610" y="223" text-anchor="middle" class="alabel" fill="#5080c0">LookupRequest</text>
|
||||
|
||||
<!-- Bloom filter annotation -->
|
||||
<text x="430" y="260" text-anchor="middle" class="annot">guided by bloom filters at each hop</text>
|
||||
|
||||
<!-- ═══ Phase separator ═══ -->
|
||||
<line x1="70" y1="285" x2="830" y2="285" class="sep"/>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════ -->
|
||||
<!-- Phase 2 — Response (y: 295–460) -->
|
||||
<!-- ═══════════════════════════════════════════════ -->
|
||||
|
||||
<text x="40" y="318" text-anchor="middle" class="plabel">Phase 2</text>
|
||||
<text x="40" y="334" text-anchor="middle" class="annot">Response</text>
|
||||
|
||||
<!-- D → C LookupResponse -->
|
||||
<line x1="690" y1="340" x2="532" y2="340" class="resp"/>
|
||||
<polygon points="534,335 524,340 534,345" class="resp"/>
|
||||
<text x="610" y="333" text-anchor="middle" class="alabel" fill="#d0a040">LookupResponse + coords</text>
|
||||
|
||||
<!-- Cache box at C -->
|
||||
<rect x="490" y="358" width="60" height="22" class="cache"/>
|
||||
<text x="520" y="373" text-anchor="middle" class="clabel">cache D</text>
|
||||
|
||||
<!-- C → B LookupResponse -->
|
||||
<line x1="510" y1="395" x2="352" y2="395" class="resp"/>
|
||||
<polygon points="354,390 344,395 354,400" class="resp"/>
|
||||
<text x="430" y="388" text-anchor="middle" class="alabel" fill="#d0a040">LookupResponse + coords</text>
|
||||
|
||||
<!-- Cache box at B -->
|
||||
<rect x="310" y="413" width="60" height="22" class="cache"/>
|
||||
<text x="340" y="428" text-anchor="middle" class="clabel">cache D</text>
|
||||
|
||||
<!-- B → A LookupResponse -->
|
||||
<line x1="330" y1="448" x2="172" y2="448" class="resp"/>
|
||||
<polygon points="174,443 164,448 174,453" class="resp"/>
|
||||
<text x="250" y="441" text-anchor="middle" class="alabel" fill="#d0a040">LookupResponse + coords</text>
|
||||
|
||||
<!-- ═══ Phase separator ═══ -->
|
||||
<line x1="70" y1="475" x2="830" y2="475" class="sep"/>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════ -->
|
||||
<!-- Phase 3 — Efficient routing (y: 485–610) -->
|
||||
<!-- ═══════════════════════════════════════════════ -->
|
||||
|
||||
<text x="40" y="508" text-anchor="middle" class="plabel">Phase 3</text>
|
||||
<text x="40" y="524" text-anchor="middle" class="annot">Routing</text>
|
||||
|
||||
<!-- A → B Data -->
|
||||
<line x1="170" y1="530" x2="328" y2="530" class="data"/>
|
||||
<polygon points="326,525 336,530 326,535" class="data"/>
|
||||
<text x="250" y="523" text-anchor="middle" class="alabel" fill="#40a060">Data</text>
|
||||
|
||||
<!-- Cached coords note at B -->
|
||||
<text x="340" y="553" text-anchor="middle" class="annot">cached coords</text>
|
||||
|
||||
<!-- B → C Data -->
|
||||
<line x1="350" y1="565" x2="508" y2="565" class="data"/>
|
||||
<polygon points="506,560 516,565 506,570" class="data"/>
|
||||
<text x="430" y="558" text-anchor="middle" class="alabel" fill="#40a060">Data</text>
|
||||
|
||||
<!-- Cached coords note at C -->
|
||||
<text x="520" y="588" text-anchor="middle" class="annot">cached coords</text>
|
||||
|
||||
<!-- C → D Data -->
|
||||
<line x1="530" y1="600" x2="688" y2="600" class="data"/>
|
||||
<polygon points="686,595 696,600 686,605" class="data"/>
|
||||
<text x="610" y="593" text-anchor="middle" class="alabel" fill="#40a060">Data</text>
|
||||
|
||||
<!-- Efficient forwarding annotation -->
|
||||
<text x="430" y="622" text-anchor="middle" class="annot">cached coords enable efficient forwarding — no re-discovery needed</text>
|
||||
|
||||
<!-- ═══ Caption ═══ -->
|
||||
<text x="430" y="660" text-anchor="middle" class="caption">Each transit node caches coordinates from the LookupResponse return path</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.8 KiB |
@@ -1,4 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 370" font-family="monospace" font-size="12">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 840 370" font-family="monospace" font-size="12">
|
||||
<style>
|
||||
rect.box { rx: 4; stroke-width: 1.5; }
|
||||
rect.source { fill: #1a3a2a; stroke: #40a060; }
|
||||
@@ -22,11 +22,11 @@
|
||||
</style>
|
||||
|
||||
<!-- Background -->
|
||||
<rect width="800" height="370" fill="#0d1117" rx="8"/>
|
||||
<rect width="840" height="370" fill="#0d1117" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="400" y="28" text-anchor="middle" class="title">FIPS Identity Derivation</text>
|
||||
<text x="400" y="46" text-anchor="middle" class="subtitle">From Nostr keypair to protocol identifiers</text>
|
||||
<text x="420" y="28" text-anchor="middle" class="title">FIPS Identity Derivation</text>
|
||||
<text x="420" y="46" text-anchor="middle" class="subtitle">From Nostr keypair to protocol identifiers</text>
|
||||
|
||||
<!-- ═══ Source: pubkey ═══ -->
|
||||
<rect x="280" y="70" width="240" height="50" class="box source"/>
|
||||
@@ -36,8 +36,8 @@
|
||||
<!-- ═══ Left branch: bech32 encoding → npub ═══ -->
|
||||
|
||||
<!-- Arrow: pubkey left edge → npub -->
|
||||
<line x1="280" y1="95" x2="180" y2="95" class="encode"/>
|
||||
<polygon points="182,91 172,95 182,99" class="ehead"/>
|
||||
<line x1="280" y1="95" x2="188" y2="95" class="encode"/>
|
||||
<polygon points="190,91 180,95 190,99" class="ehead"/>
|
||||
<text x="226" y="87" text-anchor="middle" class="op">encode</text>
|
||||
|
||||
<!-- npub box -->
|
||||
@@ -46,14 +46,13 @@
|
||||
<text x="105" y="106" text-anchor="middle" class="detail">human-readable form</text>
|
||||
|
||||
<!-- npub use box -->
|
||||
<rect x="20" y="144" width="170" height="50" class="use"/>
|
||||
<rect x="10" y="144" width="190" height="54" class="use"/>
|
||||
<text x="105" y="162" text-anchor="middle" class="use-text">Display & configuration</text>
|
||||
<text x="105" y="176" text-anchor="middle" class="use-text">User-facing identifiers</text>
|
||||
<text x="105" y="190" text-anchor="middle" class="use-text">DNS queries (npub.fips)</text>
|
||||
|
||||
<!-- npub → use arrow -->
|
||||
<line x1="105" y1="120" x2="105" y2="144" class="arrow"/>
|
||||
<polygon points="101,142 105,150 109,142" class="head"/>
|
||||
<!-- npub → use connection -->
|
||||
<line x1="105" y1="120" x2="105" y2="144" stroke="#606080" stroke-width="1" stroke-dasharray="3,3"/>
|
||||
|
||||
<!-- ═══ Right branch: pubkey → session encryption ═══ -->
|
||||
|
||||
@@ -62,10 +61,10 @@
|
||||
<polygon points="618,91 628,95 618,99" class="head"/>
|
||||
|
||||
<!-- pubkey use box -->
|
||||
<rect x="620" y="70" width="160" height="50" class="use"/>
|
||||
<text x="700" y="88" text-anchor="middle" class="use-text">Endpoint authentication</text>
|
||||
<text x="700" y="102" text-anchor="middle" class="use-text">Link & session encryption</text>
|
||||
<text x="700" y="116" text-anchor="middle" class="use-text">Known only to endpoints</text>
|
||||
<rect x="620" y="66" width="200" height="58" class="use"/>
|
||||
<text x="720" y="86" text-anchor="middle" class="use-text">Endpoint authentication</text>
|
||||
<text x="720" y="100" text-anchor="middle" class="use-text">Link & session encryption</text>
|
||||
<text x="720" y="114" text-anchor="middle" class="use-text">Known only to endpoints</text>
|
||||
|
||||
<!-- ═══ Down: pubkey → one-way hash → node_addr ═══ -->
|
||||
|
||||
@@ -86,10 +85,10 @@
|
||||
<polygon points="618,197 628,201 618,205" class="head"/>
|
||||
|
||||
<!-- node_addr use box -->
|
||||
<rect x="620" y="176" width="160" height="50" class="use"/>
|
||||
<text x="700" y="194" text-anchor="middle" class="use-text">Packet header addressing</text>
|
||||
<text x="700" y="208" text-anchor="middle" class="use-text">Spanning tree coordinates</text>
|
||||
<text x="700" y="222" text-anchor="middle" class="use-text">Bloom filter entries</text>
|
||||
<rect x="620" y="172" width="200" height="58" class="use"/>
|
||||
<text x="720" y="192" text-anchor="middle" class="use-text">Packet header addressing</text>
|
||||
<text x="720" y="206" text-anchor="middle" class="use-text">Spanning tree coordinates</text>
|
||||
<text x="720" y="220" text-anchor="middle" class="use-text">Bloom filter entries</text>
|
||||
|
||||
<!-- ═══ Down: node_addr → derive → IPv6 address ═══ -->
|
||||
|
||||
@@ -110,17 +109,17 @@
|
||||
<polygon points="618,303 628,307 618,311" class="head"/>
|
||||
|
||||
<!-- IPv6 use box -->
|
||||
<rect x="620" y="282" width="160" height="50" class="use"/>
|
||||
<text x="700" y="298" text-anchor="middle" class="use-text">TUN interface (fips0)</text>
|
||||
<text x="700" y="312" text-anchor="middle" class="use-text">Unmodified IP applications</text>
|
||||
<text x="700" y="326" text-anchor="middle" class="use-text">ping, curl, ssh, etc.</text>
|
||||
<rect x="620" y="278" width="200" height="58" class="use"/>
|
||||
<text x="720" y="298" text-anchor="middle" class="use-text">TUN interface (fips0)</text>
|
||||
<text x="720" y="312" text-anchor="middle" class="use-text">Unmodified IP applications</text>
|
||||
<text x="720" y="326" text-anchor="middle" class="use-text">ping, curl, ssh, etc.</text>
|
||||
|
||||
<!-- ═══ Left: privacy annotation ═══ -->
|
||||
<rect x="20" y="218" width="230" height="62" fill="#151520" stroke="#505040" stroke-width="1" rx="3"/>
|
||||
<text x="135" y="236" text-anchor="middle" font-size="11" font-weight="bold" fill="#d0a040">Privacy boundary</text>
|
||||
<text x="135" y="252" text-anchor="middle" class="use-text">Intermediate routers see only</text>
|
||||
<text x="135" y="266" text-anchor="middle" class="use-text">node_addr — never the pubkey.</text>
|
||||
<rect x="10" y="218" width="245" height="62" fill="#151520" stroke="#505040" stroke-width="1" rx="3"/>
|
||||
<text x="132" y="236" text-anchor="middle" font-size="11" font-weight="bold" fill="#d0a040">Privacy boundary</text>
|
||||
<text x="132" y="252" text-anchor="middle" class="use-text">Intermediate routers see only</text>
|
||||
<text x="132" y="266" text-anchor="middle" class="use-text">node_addr — never the pubkey.</text>
|
||||
|
||||
<!-- Dashed line connecting privacy box to node_addr -->
|
||||
<line x1="250" y1="249" x2="280" y2="201" stroke="#505040" stroke-width="1" stroke-dasharray="3,3"/>
|
||||
<line x1="255" y1="249" x2="280" y2="201" stroke="#505040" stroke-width="1" stroke-dasharray="3,3"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.2 KiB |
@@ -14,12 +14,17 @@ as an IPv6 endpoint for compatibility with existing IP-based applications.
|
||||
|
||||
## Why FIPS?
|
||||
|
||||
**Self-sovereign identity**: FIPS nodes generate their own addresses, node IDs,
|
||||
and security credentials without coordination with any central authority. The
|
||||
identity system uses Nostr keypairs (secp256k1), so existing npub/nsec pairs
|
||||
work directly.
|
||||
|
||||
**Infrastructure independence**: The internet depends on centralized
|
||||
infrastructure — ISPs, backbone providers, DNS, certificate authorities. FIPS
|
||||
works over any transport that can carry packets: a LoRa radio link between
|
||||
mountain towns, a serial cable between air-gapped systems, onion-routed
|
||||
connections through Tor, or the existing internet as an overlay. When the
|
||||
internet is unavailable, unreliable, or untrusted, the mesh still works.
|
||||
works over any transport that can carry packets: a serial cable between
|
||||
air-gapped systems, onion-routed connections through Tor, radio links between
|
||||
remote sites, or the existing internet as an overlay. When the internet is
|
||||
unavailable, unreliable, or untrusted, the mesh still works.
|
||||
|
||||
**End-to-end security**: FIPS provides secure, authenticated, and encrypted
|
||||
communication between any two nodes in the mesh, independent of the mix of
|
||||
@@ -33,11 +38,6 @@ exposure is limited to direct peers only.
|
||||
automatically. Connect to one peer and you can reach the entire mesh. The
|
||||
network self-heals around failures and adapts to changing topology.
|
||||
|
||||
**Self-sovereign identity**: FIPS nodes generate their own addresses, node IDs,
|
||||
and security credentials without coordination with any central authority. The
|
||||
identity system uses Nostr keypairs (secp256k1), so existing npub/nsec pairs
|
||||
work directly.
|
||||
|
||||
## A Self-Organizing Mesh
|
||||
|
||||
Traditional networks are built top-down. A central authority assigns addresses,
|
||||
@@ -86,62 +86,16 @@ FIPS is organized in three protocol layers, each with distinct responsibilities
|
||||
and clean service boundaries. Understanding these layers is key to understanding
|
||||
how FIPS works.
|
||||
|
||||
```text
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Applications │
|
||||
│ (native FIPS API / IPv6 adapter) │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ FIPS Session Protocol (FSP) │
|
||||
│ End-to-end authenticated encryption between endpoints │
|
||||
│ Session lifecycle, coordinate caching, replay protection │
|
||||
│ │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ FIPS Link Protocol (FLP) │
|
||||
│ Hop-by-hop link encryption, peer authentication │
|
||||
│ Spanning tree, bloom filters, routing, forwarding │
|
||||
│ │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Transport Layer │
|
||||
│ Datagram delivery over arbitrary media │
|
||||
│ UDP, Ethernet, LoRa, Tor, serial, ... │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||

|
||||
|
||||
### Mapping to Traditional Networking
|
||||
|
||||
Readers familiar with the OSI model or TCP/IP networking may find it helpful to
|
||||
see how FIPS concepts relate to traditional layers:
|
||||
|
||||
```text
|
||||
Traditional FIPS Key Difference
|
||||
─────────────────────────────────────────────────────────────────────
|
||||
Application Applications Same role — user-facing
|
||||
(IPv6 adapter) software
|
||||
─────────────────────────────────────────────────────────────────────
|
||||
Transport (TCP/UDP) (not present) FIPS provides datagrams,
|
||||
not reliable streams
|
||||
─────────────────────────────────────────────────────────────────────
|
||||
Session FSP End-to-end encryption
|
||||
and session management
|
||||
─────────────────────────────────────────────────────────────────────
|
||||
Network (IP) FLP Routing, forwarding,
|
||||
address resolution —
|
||||
but self-organizing
|
||||
─────────────────────────────────────────────────────────────────────
|
||||
Link (Ethernet/WiFi) FLP (link encryption) Peer authentication
|
||||
and hop-by-hop crypto
|
||||
─────────────────────────────────────────────────────────────────────
|
||||
Physical (PHY) Transport layer Abstracted — FIPS
|
||||
(UDP, radio, serial) treats all media the
|
||||
same way
|
||||
─────────────────────────────────────────────────────────────────────
|
||||
```
|
||||

|
||||
|
||||
Note that FLP spans what would traditionally be separate link and network
|
||||
Note that FMP spans what would traditionally be separate link and network
|
||||
layers. This is intentional — in a self-organizing mesh, the same layer that
|
||||
authenticates peers also makes routing decisions, because routing depends on
|
||||
authenticated peer state (spanning tree positions, bloom filters).
|
||||
@@ -152,27 +106,28 @@ authenticated peer state (spanning tree positions, bloom filters).
|
||||
medium. Each transport type (UDP socket, Ethernet interface, radio modem)
|
||||
implements the same abstract interface: send and receive datagrams, report MTU.
|
||||
The transport layer knows nothing about FIPS identities, routing, or encryption.
|
||||
It provides raw datagram delivery to FLP above.
|
||||
It provides raw datagram delivery to FMP above.
|
||||
|
||||
See [fips-transport-layer.md](fips-transport-layer.md) for the transport layer
|
||||
specification.
|
||||
|
||||
**FIPS Link Protocol (FLP)**: Manages peer connections, authenticates peers via
|
||||
Noise IK handshakes, and encrypts all traffic on each link. FLP is where the
|
||||
**FIPS Mesh Protocol (FMP)**: Manages peer connections, authenticates peers via
|
||||
Noise IK handshakes, and encrypts all traffic on each link. FMP is where the
|
||||
mesh organizes itself — nodes exchange spanning tree announcements and bloom
|
||||
filters with their direct peers, and FLP makes forwarding decisions for transit
|
||||
traffic. FLP provides authenticated, encrypted forwarding to FSP above.
|
||||
filters with their direct peers, and FMP makes forwarding decisions for transit
|
||||
traffic. FMP provides authenticated, encrypted forwarding to FSP above.
|
||||
|
||||
See [fips-link-layer.md](fips-link-layer.md) for the FLP specification and
|
||||
[fips-mesh-operation.md](fips-mesh-operation.md) for how FLP's routing and
|
||||
See [fips-mesh-layer.md](fips-mesh-layer.md) for the FMP specification and
|
||||
[fips-mesh-operation.md](fips-mesh-operation.md) for how FMP's routing and
|
||||
self-organization work in practice.
|
||||
|
||||
**FIPS Session Protocol (FSP)**: Provides end-to-end authenticated encryption
|
||||
between any two nodes, regardless of how many intermediate hops separate them.
|
||||
FSP manages session lifecycle (setup, data transfer, teardown), caches
|
||||
destination coordinates for efficient routing, and handles the warmup strategy
|
||||
that keeps transit node caches populated. FSP provides a datagram service to
|
||||
applications above.
|
||||
that keeps transit node caches populated. Session dispatch uses index-based
|
||||
routing inspired by [WireGuard](https://www.wireguard.com/), enabling O(1)
|
||||
packet demultiplexing. FSP provides a datagram service to applications above.
|
||||
|
||||
See [fips-session-layer.md](fips-session-layer.md) for the FSP specification.
|
||||
|
||||
@@ -187,48 +142,38 @@ See [fips-ipv6-adapter.md](fips-ipv6-adapter.md) for the IPv6 adapter.
|
||||
|
||||
## Architecture Overview
|
||||
|
||||

|
||||
Each node is a self-contained protocol stack with a strict layered architecture.
|
||||
No layer depends on the specifics of the layers above or below it — transport
|
||||
plugins know nothing about sessions, the routing layer knows nothing about
|
||||
application addressing, and applications know nothing about which physical
|
||||
media carry their traffic. This separation means new transports, protocol
|
||||
features, and application interfaces can be added independently.
|
||||
|
||||
Each link uses a different transport, but the end-to-end session encryption is
|
||||
independent of the transport mix. Intermediate nodes decrypt the link layer to
|
||||
make routing decisions, then re-encrypt for the next hop. They cannot read the
|
||||
session-layer payload.
|
||||
|
||||
```text
|
||||
Application ──────────── End-to-end FSP session ──────────── Application
|
||||
│ │
|
||||
▼ ▼
|
||||
┌─────────┐ FLP link ┌─────────┐ FLP link ┌─────────┐
|
||||
│ Node A │◄──────────────►│ Node B │◄──────────────►│ Node C │
|
||||
└────┬────┘ (Noise IK) └────┬────┘ (Noise IK) └────┬────┘
|
||||
│ │ │
|
||||
UDP/IP Ethernet LoRa
|
||||
transport transport transport
|
||||
```
|
||||
|
||||
Each FLP link operates over its own transport type, with independent link-layer
|
||||
encryption. The FSP session spans the entire path, providing end-to-end
|
||||
confidentiality that is independent of the transport mix along the route.
|
||||
Two application interfaces sit at the top of the stack: a native datagram API
|
||||
addressed by npub, and an IPv6 TUN adapter that maps npubs to `fd::/8`
|
||||
addresses so unmodified IP applications can use the network transparently. Below
|
||||
them, FSP manages end-to-end encrypted sessions while FMP handles mesh routing,
|
||||
peer authentication, and hop-by-hop link encryption. At the bottom, transport
|
||||
plugins abstract the physical diversity — each implements the same interface, so
|
||||
the router treats UDP, Ethernet, Tor, and serial links identically.
|
||||
|
||||

|
||||
|
||||
Internally, each node is organized in the three protocol layers. At the top,
|
||||
two application interfaces provide access to the mesh: a native datagram API
|
||||
addressed by npub, and an IPv6 TUN adapter that maps npubs to `fd::/8`
|
||||
addresses so unmodified IP applications can use the network transparently. The
|
||||
FSP and FLP layers in the middle implement session management, routing, and
|
||||
encryption. At the bottom, transport plugins handle the physical diversity —
|
||||
each plugin implements the same interface, so the router treats UDP, Ethernet,
|
||||
LoRa, Tor, and serial links identically. Adding a new transport requires no
|
||||
changes to the routing or session layers.
|
||||
The mesh routes application traffic across heterogeneous transports
|
||||
transparently. A packet may traverse WiFi, Ethernet, UDP/IP, and Tor links on
|
||||
its way from source to destination — the application never needs to know which
|
||||
transports are involved. Each hop is independently encrypted at the link layer,
|
||||
while a single end-to-end session protects the payload across the entire path.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Identity System
|
||||
|
||||
FIPS uses Nostr keypairs (secp256k1) as node identities. The public key
|
||||
identifies the node; the private key signs protocol messages and establishes
|
||||
encrypted sessions.
|
||||
FIPS uses [Nostr](https://github.com/nostr-protocol/nips) keypairs (secp256k1)
|
||||
as node identities. The public key identifies the node; the private key signs
|
||||
protocol messages and establishes encrypted sessions.
|
||||
|
||||
The FIPS address (synonymous with the pubkey) is the primary means for
|
||||
application-layer software to identify communication endpoints. The
|
||||
@@ -238,7 +183,7 @@ native API to the FIPS node software, or through an IPv6 adaptation layer that
|
||||
converts the node identity into an IPv6 address and provides DNS resolution
|
||||
from npub to this address for traditional software.
|
||||
|
||||
### Node Address Derivation
|
||||
### FIPS Identity Handling
|
||||
|
||||

|
||||
|
||||
@@ -250,44 +195,23 @@ Intermediate routers see only node_addrs — they can forward traffic without
|
||||
learning the Nostr identities of the endpoints. An observer can verify "does
|
||||
this node_addr belong to pubkey X?" but cannot enumerate which pubkeys are
|
||||
communicating by inspecting traffic. The IPv6 address prepends `fd` to the
|
||||
first 15 bytes of the node_addr, providing an overlay address for unmodified
|
||||
first 15 bytes of the node_addr, providing a ULA overlay address for unmodified
|
||||
IP applications via the TUN interface.
|
||||
|
||||
### Address Format
|
||||
|
||||
When using the IPv6 adaptation layer, FIPS addresses use the IPv6 Unique Local
|
||||
Address (ULA) prefix `fd00::/8`, providing 120 bits from the node_addr hash.
|
||||
These are overlay identifiers — they appear in the TUN interface for application
|
||||
compatibility but are not routable on the underlying transport. The fd prefix
|
||||
ensures no collision with addresses that may be in use on the transport network.
|
||||
Below the FIPS identity layer, each transport uses its own native addressing —
|
||||
IP:port tuples, MAC addresses, .onion identifiers. These **link addresses** are
|
||||
opaque to everything above FMP and discarded once link authentication completes.
|
||||
|
||||
### Identity Verification
|
||||
|
||||
The Noise Protocol Framework is used to mutually authenticate both peer-to-peer
|
||||
link connections (at FLP) and end-to-end session traffic (at FSP), proving each
|
||||
The Noise Protocol Framework mutually authenticates both peer-to-peer link
|
||||
connections (at FMP) and end-to-end session traffic (at FSP), proving each
|
||||
party controls the private key for their claimed identity.
|
||||
|
||||
See [fips-link-layer.md](fips-link-layer.md) for peer authentication and
|
||||
See [fips-mesh-layer.md](fips-mesh-layer.md) for peer authentication and
|
||||
[fips-session-layer.md](fips-session-layer.md) for end-to-end session
|
||||
establishment.
|
||||
|
||||
### Terminology: Addresses and Identifiers
|
||||
|
||||
FIPS uses several related but distinct identifiers at different protocol layers:
|
||||
|
||||
| Term | Layer | Visible To | Description |
|
||||
| ---- | ----- | ---------- | ----------- |
|
||||
| **FIPS address / pubkey** | Application/FSP | Endpoints only | 32-byte secp256k1 public key — the endpoint identity |
|
||||
| **npub** | (encoding) | Human readers | Bech32 encoding of pubkey for display/config |
|
||||
| **node_addr** | FLP (routing) | Routing nodes | SHA-256(pubkey) truncated to 128 bits — cannot be reversed to pubkey |
|
||||
| **link_addr** | Transport | Direct peers | IP:port, MAC, .onion — transport-specific |
|
||||
| **IPv6 address** | IPv6 adapter | Applications | fd::/8 derived from node_addr — optional compatibility |
|
||||
|
||||
**Privacy property**: The pubkey (FIPS address / Nostr identity) is never
|
||||
exposed to intermediate routing nodes. They see only the node_addr, a one-way
|
||||
hash. An observer can verify "does this node_addr belong to pubkey X?" but
|
||||
cannot derive the pubkey from traffic.
|
||||
|
||||
---
|
||||
|
||||
## Two-Layer Encryption
|
||||
@@ -296,14 +220,14 @@ FIPS uses independent encryption at two protocol layers:
|
||||
|
||||
| Layer | Scope | Pattern | Purpose |
|
||||
| ----- | ----- | ------- | ------- |
|
||||
| **FLP (Link)** | Hop-by-hop | Noise IK | Encrypt all traffic on each peer link |
|
||||
| **FMP (Mesh)** | Hop-by-hop | Noise IK | Encrypt all traffic on each peer link |
|
||||
| **FSP (Session)** | End-to-end | Noise IK | Encrypt application payload between endpoints |
|
||||
|
||||
### Link Layer (Hop-by-Hop)
|
||||
|
||||
When two nodes establish a direct connection, they perform a Noise IK
|
||||
handshake. This authenticates both parties and establishes symmetric keys for
|
||||
encrypting all traffic on that link. Every packet between direct peers is
|
||||
When two nodes establish a direct connection, they perform a
|
||||
[Noise IK](https://noiseprotocol.org/) handshake. This authenticates both
|
||||
parties and establishes symmetric keys for encrypting all traffic on that link. Every packet between direct peers is
|
||||
encrypted — gossip messages, routing queries, and forwarded session datagrams
|
||||
alike.
|
||||
|
||||
@@ -331,20 +255,20 @@ twice: once by the session layer (end-to-end) and once by the link layer
|
||||
A packet from A to adjacent peer B:
|
||||
|
||||
1. A encrypts payload with A↔B session key (FSP)
|
||||
2. A wraps in SessionDatagram, encrypts with A↔B link key (FLP), sends to B
|
||||
2. A wraps in SessionDatagram, encrypts with A↔B link key (FMP), sends to B
|
||||
3. B decrypts link layer, then decrypts session layer to get payload
|
||||
|
||||
A packet from A to D through intermediate node B:
|
||||
|
||||
1. A encrypts payload with A↔D session key (FSP)
|
||||
2. A wraps in SessionDatagram, encrypts with A↔B link key (FLP), sends to B
|
||||
2. A wraps in SessionDatagram, encrypts with A↔B link key (FMP), sends to B
|
||||
3. B decrypts link layer, reads destination, re-encrypts with B↔D link key
|
||||
4. D decrypts link layer, then decrypts session layer to get payload
|
||||
|
||||
Intermediate nodes can route based on destination node_addr but cannot read
|
||||
session-layer payloads.
|
||||
|
||||
See [fips-link-layer.md](fips-link-layer.md) for link encryption and
|
||||
See [fips-mesh-layer.md](fips-mesh-layer.md) for link encryption and
|
||||
[fips-session-layer.md](fips-session-layer.md) for session encryption.
|
||||
|
||||
---
|
||||
@@ -363,7 +287,9 @@ mechanisms provide the information each node needs.
|
||||
Nodes self-organize into a spanning tree rooted at a deterministically-elected
|
||||
node (the one with the smallest node_addr). Each node selects a single parent
|
||||
from among its direct peers, and the resulting tree gives every node a
|
||||
**coordinate** — its path from itself to the root.
|
||||
**coordinate** — its path from itself to the root. This coordinate-based
|
||||
approach is adapted from [Yggdrasil](https://yggdrasil-network.github.io/)'s
|
||||
[Ironwood](https://github.com/Arceliar/ironwood) routing library.
|
||||
|
||||
These coordinates enable distance calculations between any two nodes: the
|
||||
distance is the number of hops from each node to their lowest common ancestor
|
||||
@@ -382,10 +308,13 @@ walkthroughs.
|
||||
|
||||
### Bloom Filters: Candidate Selection
|
||||
|
||||
Each node maintains bloom filters summarizing which destinations are reachable
|
||||
through each of its peers. Bloom filters propagate via gossip, with each node
|
||||
computing outbound filters by merging the filters received from its other
|
||||
peers. At steady state, filters represent the entire reachable network.
|
||||
Each node maintains [bloom filters](https://en.wikipedia.org/wiki/Bloom_filter)
|
||||
summarizing which destinations are reachable through each of its peers. Bloom
|
||||
filters propagate via gossip, with each node computing outbound filters by
|
||||
merging the filters received from its other peers (a
|
||||
[split-horizon](https://en.wikipedia.org/wiki/Split_horizon_route_advertisement)
|
||||
technique borrowed from distance-vector routing). At steady state, filters
|
||||
represent the entire reachable network.
|
||||
|
||||
Bloom filters answer a single question: "can peer P possibly reach destination
|
||||
D?" The answer is either "no" (definitive) or "maybe" (probabilistic — false
|
||||
@@ -396,17 +325,35 @@ decision requires tree coordinates to rank those candidates by distance.
|
||||
See [fips-bloom-filters.md](fips-bloom-filters.md) for filter parameters and
|
||||
mathematical properties.
|
||||
|
||||

|
||||
|
||||
Every filter is computed identically regardless of link type: the outbound filter
|
||||
for peer Q merges this node's identity with all inbound filters except Q's
|
||||
(split-horizon exclusion). The protocol makes no distinction between tree parents,
|
||||
tree children, or mesh peers — the asymmetry visible in the diagram is a
|
||||
consequence of tree topology, not a different operation.
|
||||
|
||||
A node with multiple peers receives genuinely different filters from each. In the
|
||||
diagram, R receives {B, D, E} from B and {C, F} from C — two disjoint subtrees.
|
||||
When R needs to reach F, only C's filter matches. This is where bloom filters
|
||||
provide real candidate selection: a node with several peers can narrow the
|
||||
forwarding choice before consulting tree coordinates. Leaf nodes like D have only
|
||||
one peer, so their single inbound filter is necessarily near-complete (everything
|
||||
except themselves) and offers no selection — but leaf nodes have no choice to make
|
||||
anyway.
|
||||
|
||||
### Routing Decisions
|
||||
|
||||
At each hop, FLP makes a local forwarding decision using the following priority
|
||||
At each hop, FMP makes a local forwarding decision using the following priority
|
||||
chain:
|
||||
|
||||
1. **Local delivery** — the destination is this node
|
||||
2. **Direct peer** — the destination is an authenticated neighbor
|
||||
3. **Bloom-guided candidate selection** — bloom filters identify peers that can
|
||||
reach the destination; tree coordinates rank them by distance
|
||||
4. **Greedy tree routing** — fallback when bloom filters haven't converged;
|
||||
forward to the peer that minimizes tree distance to the destination
|
||||
4. **[Greedy routing](https://en.wikipedia.org/wiki/Greedy_embedding)** —
|
||||
fallback when bloom filters haven't converged; forward to the peer that
|
||||
minimizes tree distance to the destination
|
||||
5. **No route** — destination unreachable; send error signal to source
|
||||
|
||||
All multi-hop routing depends on knowing the destination's tree coordinates.
|
||||
@@ -414,17 +361,23 @@ These are cached at each node after being learned through discovery
|
||||
(LookupRequest/LookupResponse) or session establishment (SessionSetup). The
|
||||
coordinate cache is the critical piece that enables efficient forwarding.
|
||||
|
||||

|
||||
|
||||
### Coordinate Caching and Discovery
|
||||
|
||||
When a node first needs to reach an unknown destination, it sends a
|
||||
LookupRequest that floods through the network guided by bloom filters. The
|
||||
destination responds with its coordinates, which the source caches. Subsequent
|
||||
traffic routes efficiently using the cached coordinates.
|
||||
LookupRequest that propagates through the network guided by bloom filters and
|
||||
loop prevention. The
|
||||
destination responds with its coordinates, which the source and intermediate
|
||||
nodes along the return path cache. Subsequent traffic routes efficiently using
|
||||
the cached coordinates.
|
||||
|
||||
Session establishment (SessionSetup) also carries coordinates, warming transit
|
||||
node caches along the path so that data packets can be forwarded without
|
||||
individual discovery at each hop.
|
||||
|
||||

|
||||
|
||||
### Error Recovery
|
||||
|
||||
When routing fails — because cached coordinates are stale or a path has
|
||||
@@ -446,13 +399,13 @@ and mesh behavior description.
|
||||
## Transport Abstraction
|
||||
|
||||
FIPS is transport-agnostic. The protocol operates identically whether peers
|
||||
connect over UDP, Ethernet, LoRa radio, serial cables, or Tor hidden services.
|
||||
connect over UDP, Bluetooth, or whatever transport is available.
|
||||
|
||||
A **transport** is a physical or logical interface: a UDP socket, an Ethernet
|
||||
NIC, a Tor client, a radio modem. A **link** is a peer connection established
|
||||
over a transport. Transport addresses (IP:port, MAC address, .onion) are opaque
|
||||
to all layers above FLP — they are used only to deliver datagrams and are
|
||||
discarded once FLP has authenticated the peer.
|
||||
to all layers above FMP — they are used only to deliver datagrams and are
|
||||
discarded once FMP has authenticated the peer.
|
||||
|
||||
A node with multiple transports automatically bridges between networks. Peers
|
||||
from all transports feed into a single spanning tree; the router selects the
|
||||
@@ -461,10 +414,9 @@ automatically routes through alternatives.
|
||||
|
||||
| Category | Examples | Characteristics |
|
||||
| -------- | -------- | --------------- |
|
||||
| Overlay | UDP/IP, TCP/TLS, WebSocket | Internet connectivity, NAT traversal |
|
||||
| Shared medium | Ethernet, WiFi, Bluetooth, LoRa | Local discovery, broadcast |
|
||||
| Point-to-point | Serial, dialup | Static config, no discovery |
|
||||
| Anonymity | Tor, I2P | High latency, strong privacy |
|
||||
| Overlay | UDP/IP, Tor | Internet connectivity, NAT traversal |
|
||||
| Shared medium | Ethernet, WiFi, Bluetooth, Radio | Local discovery, broadcast |
|
||||
| Point-to-point | Serial | Static config, no discovery |
|
||||
|
||||
> **Implementation status**: UDP/IP is the only implemented transport. All
|
||||
> others are future directions.
|
||||
@@ -565,8 +517,8 @@ approach, enabling O(1) packet routing without relying on source addresses.
|
||||
|
||||
| Document | Description |
|
||||
| -------- | ----------- |
|
||||
| [fips-transport-layer.md](fips-transport-layer.md) | Transport layer: abstraction, types, services provided to FLP |
|
||||
| [fips-link-layer.md](fips-link-layer.md) | FLP: peer authentication, link encryption, forwarding |
|
||||
| [fips-transport-layer.md](fips-transport-layer.md) | Transport layer: abstraction, types, services provided to FMP |
|
||||
| [fips-mesh-layer.md](fips-mesh-layer.md) | FMP: peer authentication, link encryption, forwarding |
|
||||
| [fips-session-layer.md](fips-session-layer.md) | FSP: end-to-end encryption, session lifecycle |
|
||||
| [fips-ipv6-adapter.md](fips-ipv6-adapter.md) | IPv6 adaptation: DNS, TUN interface, MTU enforcement |
|
||||
|
||||
|
||||
@@ -155,7 +155,7 @@ transport path MTU for the IPv6 adapter is therefore:
|
||||
1280 + 106 = 1386 bytes
|
||||
```
|
||||
|
||||
Transports with smaller MTUs (LoRa at ~250 bytes, serial at 256 bytes) cannot
|
||||
Transports with smaller MTUs (radio at ~250 bytes, serial at 256 bytes) cannot
|
||||
support the IPv6 adapter — applications on those transports must use the
|
||||
native FIPS datagram API.
|
||||
|
||||
@@ -227,7 +227,7 @@ The TUN reader receives raw IPv6 packets from applications and processes them:
|
||||
4. Retrieve NodeAddr and PublicKey from cache
|
||||
5. Look up or establish FSP session
|
||||
6. Encrypt payload with session keys
|
||||
7. Route through FLP toward destination
|
||||
7. Route through FMP toward destination
|
||||
|
||||
### Writer Thread
|
||||
|
||||
@@ -295,7 +295,7 @@ TUN device creation requires `CAP_NET_ADMIN`. Options:
|
||||
Two complementary mechanisms support full PMTUD:
|
||||
|
||||
1. **Proactive**: The `path_mtu` field (2 bytes) in the SessionDatagram envelope
|
||||
is implemented at the FLP level. The source sets it to its outbound link MTU
|
||||
is implemented at the FMP level. The source sets it to its outbound link MTU
|
||||
minus overhead; each transit node applies
|
||||
`min(current, own_outbound_mtu - overhead)`. The destination receives the
|
||||
forward-path minimum. PathMtuNotification is handled at the session layer;
|
||||
|
||||
@@ -1,49 +1,49 @@
|
||||
# FIPS Link Protocol (FLP)
|
||||
# FIPS Mesh Protocol (FMP)
|
||||
|
||||
The FIPS Link Protocol is the middle layer of the FIPS protocol stack. It sits
|
||||
The FIPS Mesh Protocol is the middle layer of the FIPS protocol stack. It sits
|
||||
between the transport layer below and the FIPS Session Protocol (FSP) above.
|
||||
FLP is where anonymous transport addresses become authenticated peers, where
|
||||
FMP is where anonymous transport addresses become authenticated peers, where
|
||||
the mesh self-organizes, and where forwarding decisions are made.
|
||||
|
||||
## Role
|
||||
|
||||
FLP manages direct peer connections over transports. When a transport delivers
|
||||
a datagram from an unknown address, FLP authenticates the sender through a
|
||||
FMP manages direct peer connections over transports. When a transport delivers
|
||||
a datagram from an unknown address, FMP authenticates the sender through a
|
||||
Noise IK handshake, establishing a cryptographic link. Once authenticated, the
|
||||
link carries all inter-peer communication: spanning tree gossip, bloom filter
|
||||
updates, coordinate discovery, and forwarded session datagrams — all encrypted
|
||||
per-hop.
|
||||
|
||||
FLP is the boundary between opaque transport addresses and identified peers.
|
||||
Below FLP, everything is transport-specific addresses (IP:port, MAC, .onion).
|
||||
Above FLP, everything is peers identified by public keys and routable by
|
||||
FMP is the boundary between opaque transport addresses and identified peers.
|
||||
Below FMP, everything is transport-specific addresses (IP:port, MAC, .onion).
|
||||
Above FMP, everything is peers identified by public keys and routable by
|
||||
node_addr. The transport layer never sees FIPS-level structure; FSP never sees
|
||||
transport addresses or routing details.
|
||||
|
||||
## Services Provided to FSP
|
||||
|
||||
From the session layer's perspective, FLP is a black box providing three
|
||||
From the session layer's perspective, FMP is a black box providing three
|
||||
services. FSP knows nothing about transports, links, peers, spanning trees,
|
||||
coordinates, bloom filters, hop counts, or network topology.
|
||||
|
||||
### Datagram Forwarding
|
||||
|
||||
FLP accepts a datagram addressed by source and destination node_addr and
|
||||
FMP accepts a datagram addressed by source and destination node_addr and
|
||||
delivers it best-effort toward the destination. The datagram travels hop by
|
||||
hop — at each node, FLP decrypts the link layer, reads the destination
|
||||
hop — at each node, FMP decrypts the link layer, reads the destination
|
||||
node_addr, makes a local forwarding decision, and re-encrypts onto the
|
||||
next-hop link.
|
||||
|
||||
FSP provides: source node_addr, destination node_addr, hop limit, and an
|
||||
opaque payload (the session-layer encrypted message).
|
||||
|
||||
FLP provides: best-effort delivery. No acknowledgment, no retransmission, no
|
||||
FMP provides: best-effort delivery. No acknowledgment, no retransmission, no
|
||||
ordering guarantee. Datagrams may be dropped, duplicated, or delivered out of
|
||||
order.
|
||||
|
||||
### Error Signaling
|
||||
|
||||
When forwarding fails, FLP signals the source endpoint asynchronously:
|
||||
When forwarding fails, FMP signals the source endpoint asynchronously:
|
||||
|
||||
- **CoordsRequired**: A transit node lacks the destination's tree coordinates
|
||||
and cannot make a forwarding decision. The source should re-initiate
|
||||
@@ -60,21 +60,21 @@ storms during topology changes.
|
||||
### Local Delivery
|
||||
|
||||
When a datagram arrives with a destination node_addr matching the local node,
|
||||
FLP delivers it up to FSP for session-layer processing.
|
||||
FMP delivers it up to FSP for session-layer processing.
|
||||
|
||||
## Services Required from Transport Layer
|
||||
|
||||
FLP requires the following from each transport:
|
||||
FMP requires the following from each transport:
|
||||
|
||||
### Datagram Delivery
|
||||
|
||||
Send and receive raw datagrams to/from transport addresses. The transport
|
||||
handles all medium-specific details. FLP sees only "send bytes to address" and
|
||||
handles all medium-specific details. FMP sees only "send bytes to address" and
|
||||
"bytes arrived from address."
|
||||
|
||||
### MTU Reporting
|
||||
|
||||
The maximum datagram size for a given link. FLP needs this to determine how
|
||||
The maximum datagram size for a given link. FMP needs this to determine how
|
||||
much payload fits in a single packet after link encryption overhead (37 bytes
|
||||
for the encrypted frame wrapper: 16-byte outer header + 5-byte inner header +
|
||||
16-byte AEAD tag).
|
||||
@@ -82,13 +82,13 @@ for the encrypted frame wrapper: 16-byte outer header + 5-byte inner header +
|
||||
### Connection Lifecycle
|
||||
|
||||
For connection-oriented transports, the transport must establish the underlying
|
||||
connection before FLP can begin the Noise IK handshake. For connectionless
|
||||
connection before FMP can begin the Noise IK handshake. For connectionless
|
||||
transports, datagrams can flow immediately.
|
||||
|
||||
### Endpoint Discovery (Optional)
|
||||
|
||||
When a transport discovers a FIPS-capable endpoint (via beacon, query, or
|
||||
other transport-specific mechanism), it notifies FLP so that link setup can
|
||||
other transport-specific mechanism), it notifies FMP so that link setup can
|
||||
be initiated. Transports without discovery support provide peer addresses
|
||||
through configuration.
|
||||
|
||||
@@ -124,14 +124,14 @@ handshake completion:
|
||||
### Reconnection
|
||||
|
||||
When a Noise IK msg1 arrives from a peer that already has an authenticated
|
||||
link, FLP accepts the new handshake alongside the existing session. If the new
|
||||
link, FMP accepts the new handshake alongside the existing session. If the new
|
||||
handshake completes successfully, it replaces the old session. This handles
|
||||
legitimate reconnection (network change, process restart, NAT rebinding)
|
||||
without disrupting ongoing traffic until the new session is confirmed.
|
||||
|
||||
### Auto-Reconnect
|
||||
|
||||
When MMP's liveness detection removes a peer (dead timeout exceeded), FLP
|
||||
When MMP's liveness detection removes a peer (dead timeout exceeded), FMP
|
||||
automatically re-initiates the connection if the peer is configured for it.
|
||||
The auto-reconnect path:
|
||||
|
||||
@@ -256,7 +256,7 @@ authenticity.
|
||||
|
||||
When an encrypted packet successfully decrypts, the sender is the
|
||||
authenticated peer regardless of what transport address the packet arrived
|
||||
from. FLP updates the peer's current address to the packet's source address,
|
||||
from. FMP updates the peer's current address to the packet's source address,
|
||||
and subsequent outbound packets use the updated address.
|
||||
|
||||
This allows peers to change transport addresses (IP:port for UDP, connection
|
||||
@@ -294,7 +294,7 @@ Handshake initiation (msg1) is the primary attack surface for unauthenticated
|
||||
traffic. Each msg1 requires Noise DH operations (~200µs on modern CPUs),
|
||||
state allocation, and response generation.
|
||||
|
||||
FLP uses a global token bucket rate limiter:
|
||||
FMP uses a global token bucket rate limiter:
|
||||
- **Burst capacity**: Handles legitimate connection storms (e.g., node restart
|
||||
with many configured peers)
|
||||
- **Sustained rate**: Limits steady-state new connections per second
|
||||
@@ -310,13 +310,13 @@ Additional protections:
|
||||
|
||||
## Disconnect
|
||||
|
||||
FLP supports orderly link teardown via a Disconnect message carrying a reason
|
||||
FMP supports orderly link teardown via a Disconnect message carrying a reason
|
||||
code (shutdown, restart, protocol error, transport failure, resource
|
||||
exhaustion, security violation, configuration change, timeout).
|
||||
|
||||
On receiving Disconnect, FLP immediately cleans up state: removes the peer
|
||||
On receiving Disconnect, FMP immediately cleans up state: removes the peer
|
||||
from the peer table, frees the session index, removes the link, and cleans up
|
||||
address mappings. If the departed peer was the tree parent, FLP triggers parent
|
||||
address mappings. If the departed peer was the tree parent, FMP triggers parent
|
||||
reselection.
|
||||
|
||||
Disconnect is best-effort — if the transport is broken, the message won't
|
||||
@@ -328,7 +328,7 @@ stopped.
|
||||
|
||||
## Liveness Detection
|
||||
|
||||
FLP detects link liveness through a combination of explicit heartbeats and
|
||||
FMP detects link liveness through a combination of explicit heartbeats and
|
||||
traffic observation.
|
||||
|
||||
### Heartbeat
|
||||
@@ -357,7 +357,7 @@ event-driven, and MMP reports require at least one side running Full mode).
|
||||
|
||||
## Link Message Types
|
||||
|
||||
FLP defines eight message types carried inside encrypted frames:
|
||||
FMP defines eight message types carried inside encrypted frames:
|
||||
|
||||
| Type | Name | Purpose |
|
||||
| ---- | ---- | ------- |
|
||||
@@ -392,7 +392,7 @@ routing layer for link-cost decisions.
|
||||
### Metrics Tracked
|
||||
|
||||
MMP computes the following metrics from the per-frame counter and timestamp
|
||||
fields in the FLP wire format:
|
||||
fields in the FMP wire format:
|
||||
|
||||
- **SRTT** — Smoothed round-trip time (Jacobson/RFC 6298, α=1/8). Derived
|
||||
from timestamp-echo in ReceiverReports with dwell-time compensation.
|
||||
@@ -426,7 +426,7 @@ formula is `clamp(2 × SRTT, 100ms, 2000ms)`.
|
||||
|
||||
### Spin Bit and RTT
|
||||
|
||||
The SP (spin bit) flag in the FLP inner header follows the QUIC spin bit
|
||||
The SP (spin bit) flag in the FMP inner header follows the QUIC spin bit
|
||||
pattern: reflected on receive, toggled on send when the reflected value
|
||||
matches the last sent value. The spin bit state machine runs for TX
|
||||
reflection, but **RTT samples from the spin bit are discarded**. In a mesh
|
||||
@@ -437,7 +437,7 @@ bit RTT measurements unpredictably. Timestamp-echo from ReceiverReports
|
||||
|
||||
### CE Echo
|
||||
|
||||
The CE (Congestion Experienced) echo flag (bit 1 in the FLP flags byte) is
|
||||
The CE (Congestion Experienced) echo flag (bit 1 in the FMP flags byte) is
|
||||
reserved for ECN signaling. The transport trait does not currently expose
|
||||
ECN marking, so the CE echo flag is never set. One-way delay trend serves
|
||||
as the sole pre-loss congestion indicator.
|
||||
@@ -515,8 +515,8 @@ an attacker sends invalid packets to elicit responses.
|
||||
## References
|
||||
|
||||
- [fips-intro.md](fips-intro.md) — Protocol overview and architecture
|
||||
- [fips-transport-layer.md](fips-transport-layer.md) — Transport layer (below FLP)
|
||||
- [fips-session-layer.md](fips-session-layer.md) — FSP (above FLP)
|
||||
- [fips-mesh-operation.md](fips-mesh-operation.md) — How FLP's routing and
|
||||
- [fips-transport-layer.md](fips-transport-layer.md) — Transport layer (below FMP)
|
||||
- [fips-session-layer.md](fips-session-layer.md) — FSP (above FMP)
|
||||
- [fips-mesh-operation.md](fips-mesh-operation.md) — How FMP's routing and
|
||||
self-organization work in practice
|
||||
- [fips-wire-formats.md](fips-wire-formats.md) — Byte-level wire format reference
|
||||
@@ -136,7 +136,7 @@ FPR calculations, and size class folding.
|
||||
|
||||
## Routing Decision Process
|
||||
|
||||
At each hop, FLP makes a local forwarding decision using the `find_next_hop()`
|
||||
At each hop, FMP makes a local forwarding decision using the `find_next_hop()`
|
||||
priority chain. This is the core routing algorithm.
|
||||
|
||||
### Priority Chain
|
||||
@@ -585,7 +585,7 @@ recovery).
|
||||
## References
|
||||
|
||||
- [fips-intro.md](fips-intro.md) — Protocol overview
|
||||
- [fips-link-layer.md](fips-link-layer.md) — FLP specification
|
||||
- [fips-mesh-layer.md](fips-mesh-layer.md) — FMP specification
|
||||
- [fips-spanning-tree.md](fips-spanning-tree.md) — Tree algorithms and data
|
||||
structures
|
||||
- [fips-bloom-filters.md](fips-bloom-filters.md) — Filter parameters and math
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 520" font-family="monospace" font-size="12">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 560" font-family="monospace" font-size="12">
|
||||
<style>
|
||||
rect.outer { fill: #151525; stroke: #505070; stroke-width: 2; rx: 6; }
|
||||
rect.layer { rx: 4; }
|
||||
rect.api { fill: #1a3a2a; stroke: #40a060; stroke-width: 1.5; }
|
||||
rect.tun { fill: #1a2a3a; stroke: #4080c0; stroke-width: 1.5; }
|
||||
rect.router { fill: #2a2040; stroke: #8060c0; stroke-width: 1.5; }
|
||||
rect.fsp { fill: #2a2040; stroke: #8060c0; stroke-width: 1.5; }
|
||||
rect.fmp { fill: #2e3a5e; stroke: #5080c0; stroke-width: 1.5; }
|
||||
rect.xport { fill: #2a1a1a; stroke: #c06040; stroke-width: 1.5; }
|
||||
rect.cat { fill: none; stroke: #404060; stroke-width: 1; stroke-dasharray: 4,3; rx: 3; }
|
||||
text { fill: #e0e0e0; }
|
||||
@@ -18,21 +19,17 @@
|
||||
</style>
|
||||
|
||||
<!-- Background -->
|
||||
<rect width="800" height="520" fill="#0d1117" rx="8"/>
|
||||
<rect width="800" height="560" fill="#0d1117" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="400" y="28" text-anchor="middle" class="title">FIPS Node Architecture</text>
|
||||
<text x="400" y="46" text-anchor="middle" class="subtitle">Application interfaces, router core, and transport abstraction layer</text>
|
||||
<text x="400" y="46" text-anchor="middle" class="subtitle">Application interfaces, protocol layers, and transport abstraction</text>
|
||||
|
||||
<!-- Outer node box -->
|
||||
<rect x="40" y="60" width="720" height="310" class="outer"/>
|
||||
<rect x="40" y="60" width="720" height="350" class="outer"/>
|
||||
<text x="56" y="80" class="sub">FIPS Node</text>
|
||||
|
||||
<!-- === Application layer (centered) === -->
|
||||
<!-- Router core center = 390, gap = 20, each box = 200 wide -->
|
||||
<!-- Left box: 390 - 10 - 200 = 180..380, center = 280 -->
|
||||
<!-- Right box: 390 + 10 = 400..600, center = 500 -->
|
||||
|
||||
<!-- === Application layer === -->
|
||||
<!-- FIPS-native API (left) -->
|
||||
<rect x="180" y="90" width="200" height="50" class="layer api"/>
|
||||
<text x="280" y="108" text-anchor="middle" class="label">FIPS-Native API</text>
|
||||
@@ -53,122 +50,111 @@
|
||||
<line x1="280" y1="78" x2="280" y2="90" class="conn"/>
|
||||
<line x1="500" y1="78" x2="500" y2="90" class="conn"/>
|
||||
|
||||
<!-- === Router Core === -->
|
||||
<rect x="80" y="170" width="620" height="60" class="layer router"/>
|
||||
<text x="390" y="196" text-anchor="middle" class="label">Router Core</text>
|
||||
<text x="390" y="212" text-anchor="middle" class="sub">Spanning tree · Bloom filters · Greedy routing · Session management · Noise IK</text>
|
||||
<!-- === FSP Layer === -->
|
||||
<rect x="80" y="170" width="620" height="50" class="layer fsp"/>
|
||||
<text x="390" y="191" text-anchor="middle" class="label">FIPS Session Protocol (FSP)</text>
|
||||
<text x="390" y="205" text-anchor="middle" class="sub">End-to-end encryption · Session lifecycle · Path discovery · In-band metrics</text>
|
||||
|
||||
<!-- Connections: API/TUN → Router -->
|
||||
<!-- Connections: API/TUN → FSP -->
|
||||
<line x1="280" y1="140" x2="280" y2="170" class="conn"/>
|
||||
<line x1="500" y1="140" x2="500" y2="170" class="conn"/>
|
||||
|
||||
<!-- === Router → Transport connections (single trunk, branching to groups) === -->
|
||||
<!-- === FMP Layer === -->
|
||||
<rect x="80" y="240" width="620" height="50" class="layer fmp"/>
|
||||
<text x="390" y="261" text-anchor="middle" class="label">FIPS Mesh Protocol (FMP)</text>
|
||||
<text x="390" y="275" text-anchor="middle" class="sub">Link encryption · Spanning tree · Bloom filters · Routing · Peer management</text>
|
||||
|
||||
<!-- Single vertical trunk from router bottom center -->
|
||||
<line x1="390" y1="230" x2="390" y2="252" class="conn"/>
|
||||
<!-- Connection: FSP → FMP -->
|
||||
<line x1="390" y1="220" x2="390" y2="240" class="conn"/>
|
||||
|
||||
<!-- === FMP → Transport connections === -->
|
||||
<!-- Single vertical trunk from FMP bottom center -->
|
||||
<line x1="390" y1="290" x2="390" y2="312" class="conn"/>
|
||||
|
||||
<!-- Horizontal bar at branch point -->
|
||||
<line x1="160" y1="252" x2="690" y2="252" class="conn"/>
|
||||
<line x1="155" y1="312" x2="625" y2="312" class="conn"/>
|
||||
|
||||
<!-- Vertical drops to each category group outline -->
|
||||
<line x1="160" y1="252" x2="160" y2="276" class="conn"/>
|
||||
<line x1="400" y1="252" x2="400" y2="276" class="conn"/>
|
||||
<line x1="580" y1="252" x2="580" y2="276" class="conn"/>
|
||||
<line x1="690" y1="252" x2="690" y2="276" class="conn"/>
|
||||
<line x1="155" y1="312" x2="155" y2="336" class="conn"/>
|
||||
<line x1="390" y1="312" x2="390" y2="336" class="conn"/>
|
||||
<line x1="625" y1="312" x2="625" y2="336" class="conn"/>
|
||||
|
||||
<!-- === Transport layer === -->
|
||||
|
||||
<!-- Overlay transports -->
|
||||
<rect x="60" y="276" width="200" height="80" class="cat"/>
|
||||
<text x="160" y="289" text-anchor="middle" class="cat">Overlay</text>
|
||||
<rect x="80" y="336" width="150" height="60" class="cat"/>
|
||||
<text x="155" y="349" text-anchor="middle" class="cat">Overlay</text>
|
||||
|
||||
<rect x="72" y="296" width="56" height="36" class="layer xport"/>
|
||||
<text x="100" y="312" text-anchor="middle" font-size="10" font-weight="bold" fill="#e0e0e0">UDP</text>
|
||||
<text x="100" y="324" text-anchor="middle" class="sub">IP</text>
|
||||
<rect x="92" y="356" width="60" height="30" class="layer xport"/>
|
||||
<text x="122" y="371" text-anchor="middle" font-size="10" font-weight="bold" fill="#e0e0e0">UDP</text>
|
||||
<text x="122" y="381" text-anchor="middle" class="sub">IP</text>
|
||||
|
||||
<rect x="134" y="296" width="56" height="36" class="layer xport"/>
|
||||
<text x="162" y="312" text-anchor="middle" font-size="10" font-weight="bold" fill="#e0e0e0">QUIC</text>
|
||||
<text x="162" y="324" text-anchor="middle" class="sub">IP</text>
|
||||
|
||||
<rect x="196" y="296" width="56" height="36" class="layer xport"/>
|
||||
<text x="224" y="312" text-anchor="middle" font-size="10" font-weight="bold" fill="#e0e0e0">WS</text>
|
||||
<text x="224" y="324" text-anchor="middle" class="sub">TCP</text>
|
||||
<rect x="158" y="356" width="60" height="30" class="layer xport"/>
|
||||
<text x="188" y="371" text-anchor="middle" font-size="10" font-weight="bold" fill="#e0e0e0">Tor</text>
|
||||
<text x="188" y="381" text-anchor="middle" class="sub">.onion</text>
|
||||
|
||||
<!-- Shared medium transports -->
|
||||
<rect x="270" y="276" width="260" height="80" class="cat"/>
|
||||
<text x="400" y="289" text-anchor="middle" class="cat">Shared Medium</text>
|
||||
<rect x="240" y="336" width="300" height="60" class="cat"/>
|
||||
<text x="390" y="349" text-anchor="middle" class="cat">Shared Medium</text>
|
||||
|
||||
<rect x="282" y="296" width="56" height="36" class="layer xport"/>
|
||||
<text x="310" y="312" text-anchor="middle" font-size="10" font-weight="bold" fill="#e0e0e0">Ether</text>
|
||||
<text x="310" y="324" text-anchor="middle" class="sub">802.3</text>
|
||||
<rect x="254" y="356" width="60" height="30" class="layer xport"/>
|
||||
<text x="284" y="371" text-anchor="middle" font-size="10" font-weight="bold" fill="#e0e0e0">Ether</text>
|
||||
<text x="284" y="381" text-anchor="middle" class="sub">802.3</text>
|
||||
|
||||
<rect x="344" y="296" width="56" height="36" class="layer xport"/>
|
||||
<text x="372" y="312" text-anchor="middle" font-size="10" font-weight="bold" fill="#e0e0e0">WiFi</text>
|
||||
<text x="372" y="324" text-anchor="middle" class="sub">802.11</text>
|
||||
<rect x="320" y="356" width="60" height="30" class="layer xport"/>
|
||||
<text x="350" y="371" text-anchor="middle" font-size="10" font-weight="bold" fill="#e0e0e0">WiFi</text>
|
||||
<text x="350" y="381" text-anchor="middle" class="sub">802.11</text>
|
||||
|
||||
<rect x="406" y="296" width="56" height="36" class="layer xport"/>
|
||||
<text x="434" y="312" text-anchor="middle" font-size="10" font-weight="bold" fill="#e0e0e0">BT</text>
|
||||
<text x="434" y="324" text-anchor="middle" class="sub">RFCOMM</text>
|
||||
<rect x="386" y="356" width="60" height="30" class="layer xport"/>
|
||||
<text x="416" y="371" text-anchor="middle" font-size="10" font-weight="bold" fill="#e0e0e0">BT</text>
|
||||
<text x="416" y="381" text-anchor="middle" class="sub">RFCOMM</text>
|
||||
|
||||
<rect x="468" y="296" width="56" height="36" class="layer xport"/>
|
||||
<text x="496" y="312" text-anchor="middle" font-size="10" font-weight="bold" fill="#e0e0e0">LoRa</text>
|
||||
<text x="496" y="324" text-anchor="middle" class="sub">radio</text>
|
||||
<rect x="452" y="356" width="60" height="30" class="layer xport"/>
|
||||
<text x="482" y="371" text-anchor="middle" font-size="10" font-weight="bold" fill="#e0e0e0">Radio</text>
|
||||
<text x="482" y="381" text-anchor="middle" class="sub">Sat, ...</text>
|
||||
|
||||
<!-- Point-to-point transports -->
|
||||
<rect x="540" y="276" width="80" height="80" class="cat"/>
|
||||
<text x="580" y="289" text-anchor="middle" class="cat">P-to-P</text>
|
||||
<rect x="550" y="336" width="150" height="60" class="cat"/>
|
||||
<text x="625" y="349" text-anchor="middle" class="cat">Point-to-Point</text>
|
||||
|
||||
<rect x="552" y="296" width="56" height="36" class="layer xport"/>
|
||||
<text x="580" y="312" text-anchor="middle" font-size="10" font-weight="bold" fill="#e0e0e0">Serial</text>
|
||||
<text x="580" y="324" text-anchor="middle" class="sub">UART</text>
|
||||
<rect x="562" y="356" width="60" height="30" class="layer xport"/>
|
||||
<text x="592" y="371" text-anchor="middle" font-size="10" font-weight="bold" fill="#e0e0e0">Serial</text>
|
||||
<text x="592" y="381" text-anchor="middle" class="sub">UART</text>
|
||||
|
||||
<!-- Anonymity transports -->
|
||||
<rect x="630" y="276" width="120" height="80" class="cat"/>
|
||||
<text x="690" y="289" text-anchor="middle" class="cat">Anonymity</text>
|
||||
|
||||
<rect x="642" y="296" width="46" height="36" class="layer xport"/>
|
||||
<text x="665" y="312" text-anchor="middle" font-size="10" font-weight="bold" fill="#e0e0e0">Tor</text>
|
||||
<text x="665" y="324" text-anchor="middle" class="sub">.onion</text>
|
||||
|
||||
<rect x="694" y="296" width="46" height="36" class="layer xport"/>
|
||||
<text x="717" y="312" text-anchor="middle" font-size="10" font-weight="bold" fill="#e0e0e0">I2P</text>
|
||||
<text x="717" y="324" text-anchor="middle" class="sub">tunnel</text>
|
||||
<rect x="628" y="356" width="60" height="30" class="layer xport"/>
|
||||
<text x="658" y="371" text-anchor="middle" font-size="10" font-weight="bold" fill="#e0e0e0">...</text>
|
||||
<text x="658" y="381" text-anchor="middle" class="sub"></text>
|
||||
|
||||
<!-- === Peer networks below node box === -->
|
||||
<text x="155" y="436" text-anchor="middle" class="sub">Internet / Overlay Peers</text>
|
||||
<line x1="155" y1="410" x2="155" y2="426" class="peer"/>
|
||||
|
||||
<!-- Overlay peers -->
|
||||
<text x="160" y="396" text-anchor="middle" class="sub">Internet Peers</text>
|
||||
<line x1="160" y1="370" x2="160" y2="386" class="peer"/>
|
||||
<text x="390" y="436" text-anchor="middle" class="sub">Local / Radio Peers</text>
|
||||
<line x1="390" y1="410" x2="390" y2="426" class="peer"/>
|
||||
|
||||
<!-- Shared medium peers -->
|
||||
<text x="400" y="396" text-anchor="middle" class="sub">Local / Radio Peers</text>
|
||||
<line x1="400" y1="370" x2="400" y2="386" class="peer"/>
|
||||
|
||||
<!-- Point-to-point peers -->
|
||||
<text x="580" y="396" text-anchor="middle" class="sub">Wired Peer</text>
|
||||
<line x1="580" y1="370" x2="580" y2="386" class="peer"/>
|
||||
|
||||
<!-- Anonymity peers -->
|
||||
<text x="690" y="396" text-anchor="middle" class="sub">Anonymous Peers</text>
|
||||
<line x1="690" y1="370" x2="690" y2="386" class="peer"/>
|
||||
<text x="625" y="436" text-anchor="middle" class="sub">Wired Peers</text>
|
||||
<line x1="625" y1="410" x2="625" y2="426" class="peer"/>
|
||||
|
||||
<!-- === Legend === -->
|
||||
<rect x="40" y="420" width="720" height="85" fill="#151520" stroke="#404060" stroke-width="1" rx="4"/>
|
||||
<rect x="40" y="458" width="720" height="88" fill="#151520" stroke="#404060" stroke-width="1" rx="4"/>
|
||||
|
||||
<rect x="60" y="438" width="24" height="14" class="layer api"/>
|
||||
<text x="92" y="450" class="sub">Application interface</text>
|
||||
<rect x="60" y="476" width="24" height="14" class="layer api"/>
|
||||
<text x="92" y="488" class="sub">Application interface</text>
|
||||
|
||||
<rect x="60" y="460" width="24" height="14" class="layer tun"/>
|
||||
<text x="92" y="472" class="sub">IPv6 compatibility layer</text>
|
||||
<rect x="60" y="496" width="24" height="14" class="layer tun"/>
|
||||
<text x="92" y="508" class="sub">IPv6 compatibility layer</text>
|
||||
|
||||
<rect x="60" y="482" width="24" height="14" class="layer router"/>
|
||||
<text x="92" y="494" class="sub">Router core (protocol engine)</text>
|
||||
<rect x="300" y="476" width="24" height="14" class="layer fsp"/>
|
||||
<text x="332" y="488" class="sub">FSP — end-to-end session encryption</text>
|
||||
|
||||
<rect x="300" y="438" width="24" height="14" class="layer xport"/>
|
||||
<text x="332" y="450" class="sub">Transport plugin</text>
|
||||
<rect x="300" y="496" width="24" height="14" class="layer fmp"/>
|
||||
<text x="332" y="508" class="sub">FMP — mesh routing and link encryption</text>
|
||||
|
||||
<rect x="300" y="460" width="24" height="14" fill="none" stroke="#404060" stroke-width="1" stroke-dasharray="4,3" rx="2"/>
|
||||
<text x="332" y="472" class="sub">Transport category grouping</text>
|
||||
<rect x="590" y="476" width="24" height="14" class="layer xport"/>
|
||||
<text x="622" y="488" class="sub">Transport plugin</text>
|
||||
|
||||
<text x="300" y="494" class="sub">All transports use the same Router Core interface</text>
|
||||
<rect x="590" y="496" width="24" height="14" fill="none" stroke="#404060" stroke-width="1" stroke-dasharray="4,3" rx="2"/>
|
||||
<text x="622" y="508" class="sub">Transport category</text>
|
||||
|
||||
<text x="300" y="536" class="sub">All transports use the same FMP protocol</text>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.0 KiB |
@@ -0,0 +1,64 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 820 400" font-family="monospace" font-size="15">
|
||||
<style>
|
||||
text { fill: #e0e0e0; }
|
||||
text.header { font-size: 16px; font-weight: bold; fill: #e0e0e0; }
|
||||
text.layer { font-size: 15px; fill: #e0e0e0; }
|
||||
text.fips { font-size: 15px; fill: #80b0e0; }
|
||||
text.diff { font-size: 14px; fill: #a0a0b0; }
|
||||
line.rule { stroke: #404050; stroke-width: 1; }
|
||||
line.top { stroke: #606070; stroke-width: 1.5; }
|
||||
</style>
|
||||
|
||||
<!-- Background -->
|
||||
<rect width="800" height="360" fill="#0d1117" rx="8"/>
|
||||
|
||||
<!-- Column headers -->
|
||||
<text x="40" y="35" class="header">Traditional</text>
|
||||
<text x="280" y="35" class="header">FIPS</text>
|
||||
<text x="560" y="35" class="header">Key Difference</text>
|
||||
<line x1="20" y1="48" x2="780" y2="48" class="top"/>
|
||||
|
||||
<!-- Application -->
|
||||
<text x="40" y="75" class="layer">Application</text>
|
||||
<text x="280" y="75" class="fips">Application</text>
|
||||
<text x="560" y="75" class="diff">Same role</text>
|
||||
<line x1="20" y1="90" x2="780" y2="90" class="rule"/>
|
||||
|
||||
<!-- Transport -->
|
||||
<text x="40" y="117" class="layer">Transport</text>
|
||||
<text x="280" y="117" class="fips">(not present)</text>
|
||||
<text x="560" y="117" class="diff">Datagrams, not streams</text>
|
||||
<line x1="20" y1="132" x2="780" y2="132" class="rule"/>
|
||||
|
||||
<!-- Session -->
|
||||
<text x="40" y="159" class="layer">Session</text>
|
||||
<text x="280" y="159" class="fips">FIPS Session Protocol</text>
|
||||
<text x="560" y="159" class="diff">End-to-end encryption</text>
|
||||
<text x="280" y="177" class="fips">(FSP)</text>
|
||||
<text x="560" y="177" class="diff">and session management</text>
|
||||
<line x1="20" y1="192" x2="780" y2="192" class="rule"/>
|
||||
|
||||
<!-- Network -->
|
||||
<text x="40" y="219" class="layer">Network (IP)</text>
|
||||
<text x="280" y="219" class="fips">FIPS Mesh Protocol</text>
|
||||
<text x="560" y="219" class="diff">Self-organizing routing</text>
|
||||
<text x="280" y="237" class="fips">(FMP)</text>
|
||||
<text x="560" y="237" class="diff">and forwarding</text>
|
||||
<line x1="20" y1="252" x2="780" y2="252" class="rule"/>
|
||||
|
||||
<!-- Link -->
|
||||
<text x="40" y="279" class="layer">Link</text>
|
||||
<text x="280" y="279" class="fips">FMP (link encryption)</text>
|
||||
<text x="560" y="279" class="diff">Hop-by-hop crypto</text>
|
||||
<line x1="20" y1="294" x2="780" y2="294" class="rule"/>
|
||||
|
||||
<!-- Physical -->
|
||||
<text x="40" y="321" class="layer">Physical</text>
|
||||
<text x="280" y="321" class="fips">Transport layer</text>
|
||||
<text x="560" y="321" class="diff">Abstracted — all media</text>
|
||||
<text x="280" y="339" class="fips">(UDP, radio, serial)</text>
|
||||
<text x="560" y="339" class="diff">treated the same</text>
|
||||
|
||||
<!-- Caption -->
|
||||
<text x="400" y="393" text-anchor="middle" font-size="14" fill="#808090" font-style="italic">Mapping FIPS protocol layers to the traditional networking model</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
@@ -0,0 +1,49 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 895 620" font-family="monospace" font-size="15">
|
||||
<style>
|
||||
rect.layer { rx: 5; }
|
||||
rect.app { fill: #1a3a2a; stroke: #40a060; stroke-width: 2; }
|
||||
rect.fsp { fill: #2a2040; stroke: #8060c0; stroke-width: 2; }
|
||||
rect.fmp { fill: #2e3a5e; stroke: #5080c0; stroke-width: 2; }
|
||||
rect.xport { fill: #2a1a1a; stroke: #c06040; stroke-width: 2; }
|
||||
text { fill: #e0e0e0; }
|
||||
text.name { font-size: 23px; font-weight: bold; }
|
||||
text.desc { font-size: 18px; fill: #a0a0b0; }
|
||||
text.scope { font-size: 17px; fill: #707080; font-style: italic; }
|
||||
text.caption { font-size: 18px; fill: #808090; font-style: italic; }
|
||||
</style>
|
||||
|
||||
<!-- Background -->
|
||||
<rect width="875" height="560" fill="#0d1117" rx="10"/>
|
||||
|
||||
<!-- Applications layer -->
|
||||
<rect x="50" y="25" width="775" height="100" class="layer app"/>
|
||||
<text x="75" y="58" class="name">Application Layer Interface</text>
|
||||
<text x="75" y="78" class="desc">Native FIPS API — for FIPS-aware applications</text>
|
||||
<text x="75" y="98" class="desc">IPv6 Shim — for traditional IP application backward compatibility</text>
|
||||
|
||||
<!-- FSP layer -->
|
||||
<rect x="50" y="150" width="775" height="120" class="layer fsp"/>
|
||||
<text x="75" y="183" class="name">FIPS Session Protocol (FSP)</text>
|
||||
<text x="75" y="205" class="desc">End-to-end authenticated encryption between endpoints</text>
|
||||
<text x="75" y="225" class="desc">Session lifecycle, path discovery, in-band metrics</text>
|
||||
<text x="75" y="245" class="desc">Replay protection, forward secrecy, identity privacy</text>
|
||||
<text x="800" y="183" class="scope" text-anchor="end">end-to-end</text>
|
||||
|
||||
<!-- FMP layer -->
|
||||
<rect x="50" y="295" width="775" height="120" class="layer fmp"/>
|
||||
<text x="75" y="328" class="name">FIPS Mesh Protocol (FMP)</text>
|
||||
<text x="75" y="350" class="desc">Hop-by-hop peer authentication, link encryption, liveness detection</text>
|
||||
<text x="75" y="370" class="desc">Spanning tree, bloom filters, routing, forwarding, repair</text>
|
||||
<text x="75" y="390" class="desc">Link quality monitoring, maintenance, optional discovery</text>
|
||||
<text x="800" y="328" class="scope" text-anchor="end">hop-by-hop</text>
|
||||
|
||||
<!-- Transport layer -->
|
||||
<rect x="50" y="440" width="775" height="95" class="layer xport"/>
|
||||
<text x="75" y="473" class="name">Transport Layer</text>
|
||||
<text x="800" y="473" class="scope" text-anchor="end">(overlay, shared medium, point-to-point)</text>
|
||||
<text x="75" y="495" class="desc">Datagram delivery over arbitrary media</text>
|
||||
<text x="75" y="515" class="desc">UDP, Ethernet, WiFi, Bluetooth, Tor, serial, ...</text>
|
||||
|
||||
<!-- Caption -->
|
||||
<text x="438" y="585" text-anchor="middle" class="caption">FIPS protocol layer stack — three layers with clean service boundaries</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
@@ -0,0 +1,153 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 920" font-family="monospace" font-size="12">
|
||||
<style>
|
||||
text { fill: #e0e0e0; }
|
||||
text.title { font-size: 16px; font-weight: bold; }
|
||||
text.subtitle { font-size: 12px; fill: #909090; }
|
||||
text.step { font-size: 11px; fill: #5080c0; font-weight: bold; }
|
||||
text.decision { font-size: 12px; }
|
||||
text.action { font-size: 12px; }
|
||||
text.branch { font-size: 11px; fill: #a0a0b0; }
|
||||
text.caption { font-size: 13px; fill: #808090; font-style: italic; }
|
||||
polygon.diamond { fill: #1a1a2e; stroke: #5080c0; stroke-width: 1.5; }
|
||||
rect.start { fill: #2e3a5e; stroke: #5080c0; stroke-width: 1.5; }
|
||||
rect.outcome { fill: #1a3a2a; stroke: #40a060; stroke-width: 1.5; rx: 4; }
|
||||
rect.error { fill: #2a1a1a; stroke: #c06040; stroke-width: 1.5; rx: 4; }
|
||||
rect.interim { fill: #1a2a3a; stroke: #4080c0; stroke-width: 1.5; rx: 4; }
|
||||
line.arrow { stroke: #606080; stroke-width: 1.5; }
|
||||
marker { fill: #606080; }
|
||||
</style>
|
||||
|
||||
<defs>
|
||||
<marker id="arrowhead" markerWidth="8" markerHeight="6" refX="8" refY="3" orient="auto">
|
||||
<polygon points="0 0, 8 3, 0 6" fill="#606080"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<!-- Background -->
|
||||
<rect width="720" height="920" fill="#0d1117" rx="8"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="360" y="30" text-anchor="middle" class="title">Routing Decision Chain</text>
|
||||
<text x="360" y="48" text-anchor="middle" class="subtitle">Per-hop forwarding priority at each FMP router</text>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- START: Packet arrives -->
|
||||
<!-- ============================================================ -->
|
||||
<rect x="260" y="74" width="200" height="36" rx="18" class="start"/>
|
||||
<text x="360" y="97" text-anchor="middle" class="action">Packet arrives</text>
|
||||
|
||||
<!-- Arrow: start → decision 1 -->
|
||||
<line x1="360" y1="110" x2="360" y2="140" class="arrow" marker-end="url(#arrowhead)"/>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- STEP 1: Local delivery? -->
|
||||
<!-- ============================================================ -->
|
||||
<text x="240" y="155" text-anchor="end" class="step">1</text>
|
||||
<polygon points="360,140 440,180 360,220 280,180" class="diamond"/>
|
||||
<text x="360" y="176" text-anchor="middle" class="decision">Local</text>
|
||||
<text x="360" y="190" text-anchor="middle" class="decision">delivery?</text>
|
||||
|
||||
<!-- Yes → right to outcome -->
|
||||
<line x1="440" y1="180" x2="520" y2="180" class="arrow" marker-end="url(#arrowhead)"/>
|
||||
<text x="475" y="172" text-anchor="middle" class="branch">Yes</text>
|
||||
<rect x="528" y="162" width="160" height="36" class="outcome"/>
|
||||
<text x="608" y="185" text-anchor="middle" class="action">Deliver to application</text>
|
||||
|
||||
<!-- No → down -->
|
||||
<line x1="360" y1="220" x2="360" y2="260" class="arrow" marker-end="url(#arrowhead)"/>
|
||||
<text x="372" y="244" class="branch">No</text>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- STEP 2: Direct peer? -->
|
||||
<!-- ============================================================ -->
|
||||
<text x="240" y="275" text-anchor="end" class="step">2</text>
|
||||
<polygon points="360,260 440,300 360,340 280,300" class="diamond"/>
|
||||
<text x="360" y="296" text-anchor="middle" class="decision">Direct</text>
|
||||
<text x="360" y="310" text-anchor="middle" class="decision">peer?</text>
|
||||
|
||||
<!-- Yes → right to outcome -->
|
||||
<line x1="440" y1="300" x2="520" y2="300" class="arrow" marker-end="url(#arrowhead)"/>
|
||||
<text x="475" y="292" text-anchor="middle" class="branch">Yes</text>
|
||||
<rect x="528" y="282" width="160" height="36" class="outcome"/>
|
||||
<text x="608" y="305" text-anchor="middle" class="action">Forward to peer</text>
|
||||
|
||||
<!-- No → down -->
|
||||
<line x1="360" y1="340" x2="360" y2="380" class="arrow" marker-end="url(#arrowhead)"/>
|
||||
<text x="372" y="364" class="branch">No</text>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- STEP 3: Bloom filter hit? -->
|
||||
<!-- ============================================================ -->
|
||||
<text x="240" y="395" text-anchor="end" class="step">3</text>
|
||||
<polygon points="360,380 440,420 360,460 280,420" class="diamond"/>
|
||||
<text x="360" y="416" text-anchor="middle" class="decision">Bloom filter</text>
|
||||
<text x="360" y="430" text-anchor="middle" class="decision">hit?</text>
|
||||
|
||||
<!-- Yes → right to interim step -->
|
||||
<line x1="440" y1="420" x2="520" y2="420" class="arrow" marker-end="url(#arrowhead)"/>
|
||||
<text x="475" y="412" text-anchor="middle" class="branch">Yes</text>
|
||||
<rect x="520" y="396" width="176" height="48" class="interim"/>
|
||||
<text x="608" y="412" text-anchor="middle" class="action">Rank candidates by</text>
|
||||
<text x="608" y="426" text-anchor="middle" class="action">tree distance and</text>
|
||||
<text x="608" y="440" text-anchor="middle" class="action">link performance</text>
|
||||
|
||||
<!-- Arrow from interim → final outcome -->
|
||||
<line x1="608" y1="444" x2="608" y2="470" class="arrow" marker-end="url(#arrowhead)"/>
|
||||
<rect x="528" y="478" width="160" height="36" class="outcome"/>
|
||||
<text x="608" y="501" text-anchor="middle" class="action">Forward to 'best'</text>
|
||||
|
||||
<!-- No → down -->
|
||||
<line x1="360" y1="460" x2="360" y2="530" class="arrow" marker-end="url(#arrowhead)"/>
|
||||
<text x="372" y="500" class="branch">No</text>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- STEP 4: Coords known? -->
|
||||
<!-- ============================================================ -->
|
||||
<text x="240" y="545" text-anchor="end" class="step">4</text>
|
||||
<polygon points="360,530 440,570 360,610 280,570" class="diamond"/>
|
||||
<text x="360" y="566" text-anchor="middle" class="decision">Coords</text>
|
||||
<text x="360" y="580" text-anchor="middle" class="decision">known?</text>
|
||||
|
||||
<!-- Yes → right to outcome -->
|
||||
<line x1="440" y1="570" x2="520" y2="570" class="arrow" marker-end="url(#arrowhead)"/>
|
||||
<text x="475" y="562" text-anchor="middle" class="branch">Yes</text>
|
||||
<rect x="528" y="552" width="160" height="36" class="outcome"/>
|
||||
<text x="608" y="575" text-anchor="middle" class="action">Greedy tree forward</text>
|
||||
|
||||
<!-- No → down -->
|
||||
<line x1="360" y1="610" x2="360" y2="660" class="arrow" marker-end="url(#arrowhead)"/>
|
||||
<text x="372" y="640" class="branch">No</text>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- STEP 5: No route → error signal -->
|
||||
<!-- ============================================================ -->
|
||||
<text x="240" y="683" text-anchor="end" class="step">5</text>
|
||||
<rect x="260" y="668" width="200" height="36" class="error"/>
|
||||
<text x="360" y="691" text-anchor="middle" class="action">No route → error signal</text>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- Legend -->
|
||||
<!-- ============================================================ -->
|
||||
<rect x="40" y="740" width="640" height="120" fill="#151520" stroke="#404060" stroke-width="1" rx="4"/>
|
||||
|
||||
<rect x="60" y="762" width="24" height="14" rx="7" fill="#2e3a5e" stroke="#5080c0" stroke-width="1"/>
|
||||
<text x="92" y="774" font-size="11" fill="#a0a0b0">Start / entry point</text>
|
||||
|
||||
<polygon points="64,800 72,793 80,800 72,807" fill="#1a1a2e" stroke="#5080c0" stroke-width="1"/>
|
||||
<text x="88" y="804" font-size="11" fill="#a0a0b0">Routing decision (checked in priority order)</text>
|
||||
|
||||
<rect x="60" y="822" width="24" height="14" rx="4" fill="#1a3a2a" stroke="#40a060" stroke-width="1"/>
|
||||
<text x="92" y="834" font-size="11" fill="#a0a0b0">Forwarding action (packet delivered or sent)</text>
|
||||
|
||||
<rect x="410" y="762" width="24" height="14" rx="4" fill="#1a2a3a" stroke="#4080c0" stroke-width="1"/>
|
||||
<text x="442" y="774" font-size="11" fill="#a0a0b0">Intermediate processing step</text>
|
||||
|
||||
<rect x="410" y="793" width="24" height="14" rx="4" fill="#2a1a1a" stroke="#c06040" stroke-width="1"/>
|
||||
<text x="442" y="805" font-size="11" fill="#a0a0b0">Terminal error (no route available)</text>
|
||||
|
||||
<line x1="410" y1="831" x2="434" y2="831" stroke="#606080" stroke-width="1.5" marker-end="url(#arrowhead)"/>
|
||||
<text x="442" y="835" font-size="11" fill="#a0a0b0">Control flow direction</text>
|
||||
|
||||
<!-- Caption -->
|
||||
<text x="360" y="896" text-anchor="middle" class="caption">Each hop evaluates destinations in priority order 1–4, falling through on miss</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.5 KiB |
@@ -1,7 +1,7 @@
|
||||
# FIPS Session Protocol (FSP)
|
||||
|
||||
The FIPS Session Protocol is the top protocol layer in the FIPS stack. It sits
|
||||
above the FIPS Link Protocol (FLP) and below applications (native FIPS API or
|
||||
above the FIPS Mesh Protocol (FMP) and below applications (native FIPS API or
|
||||
IPv6 adapter). FSP provides end-to-end authenticated, encrypted datagram
|
||||
delivery between any two FIPS nodes, regardless of how many intermediate hops
|
||||
separate them.
|
||||
@@ -34,7 +34,7 @@ Applications access the FIPS mesh through two interfaces, both served by FSP:
|
||||
|
||||
Applications address destinations directly by npub or public key. The FIPS
|
||||
stack resolves the destination's node_addr, establishes or reuses a session,
|
||||
encrypts the payload, and routes through FLP. No DNS involvement.
|
||||
encrypts the payload, and routes through FMP. No DNS involvement.
|
||||
|
||||
### IPv6 Adapter
|
||||
|
||||
@@ -66,21 +66,21 @@ layer.
|
||||
TCP over IPv6 get TCP's congestion control; native API applications must
|
||||
manage their own sending rate.
|
||||
|
||||
## Services Required from FLP
|
||||
## Services Required from FMP
|
||||
|
||||
FSP treats FLP as a black box providing three services. FSP knows nothing about
|
||||
FSP treats FMP as a black box providing three services. FSP knows nothing about
|
||||
transports, transport addresses, links, peers, spanning trees, coordinates,
|
||||
bloom filters, hop counts, or network topology.
|
||||
|
||||
### SessionDatagram Forwarding
|
||||
|
||||
FLP accepts a SessionDatagram (source node_addr, destination node_addr, TTL,
|
||||
FMP accepts a SessionDatagram (source node_addr, destination node_addr, TTL,
|
||||
path MTU, payload) and delivers it best-effort toward the destination. Delivery
|
||||
may traverse multiple hops, each with independent link encryption.
|
||||
|
||||
### Error Signaling
|
||||
|
||||
FLP signals routing failures asynchronously:
|
||||
FMP signals routing failures asynchronously:
|
||||
|
||||
- **CoordsRequired**: A transit node lacks the destination's tree coordinates.
|
||||
FSP responds by sending a standalone CoordsWarmup (0x14) message
|
||||
@@ -97,7 +97,7 @@ end-to-end encrypted) because transit nodes have no session with the source.
|
||||
### Local Delivery
|
||||
|
||||
When a SessionDatagram arrives with a destination node_addr matching the local
|
||||
node, FLP delivers it to FSP for session-layer processing.
|
||||
node, FMP delivers it to FSP for session-layer processing.
|
||||
|
||||
## Session Lifecycle
|
||||
|
||||
@@ -189,7 +189,7 @@ transport addresses or routing paths. A session survives:
|
||||
|
||||
### Noise IK Pattern
|
||||
|
||||
FSP uses the same Noise IK pattern as FLP link encryption, but with
|
||||
FSP uses the same Noise IK pattern as FMP link encryption, but with
|
||||
independent keys and sessions. The full Noise descriptor is
|
||||
`Noise_IK_secp256k1_ChaChaPoly_SHA256`.
|
||||
|
||||
@@ -386,7 +386,7 @@ Cache population mechanisms:
|
||||
|
||||
The coordinate cache maps `NodeAddr → TreeCoordinate` and is the critical
|
||||
data structure that enables efficient multi-hop routing. Without cached
|
||||
coordinates for a destination, FLP cannot make forwarding decisions and must
|
||||
coordinates for a destination, FMP cannot make forwarding decisions and must
|
||||
either fall back to bloom-filter-only routing or signal CoordsRequired.
|
||||
|
||||
### Unified Cache
|
||||
@@ -506,13 +506,13 @@ MMP session metrics session=npub1tdwa...84le rtt=4.3ms loss=0.6% jitter=0.2ms go
|
||||
| Simultaneous initiation tie-breaker | **Implemented** |
|
||||
| Flush coord cache on parent change | **Implemented** |
|
||||
| Rekey | Planned |
|
||||
| Path MTU tracking (FLP SessionDatagram field) | **Implemented** |
|
||||
| Path MTU tracking (FMP SessionDatagram field) | **Implemented** |
|
||||
| Path MTU notification (end-to-end echo) | **Implemented** |
|
||||
|
||||
## References
|
||||
|
||||
- [fips-intro.md](fips-intro.md) — Protocol overview and architecture
|
||||
- [fips-link-layer.md](fips-link-layer.md) — FLP specification (below FSP)
|
||||
- [fips-mesh-layer.md](fips-mesh-layer.md) — FMP specification (below FSP)
|
||||
- [fips-ipv6-adapter.md](fips-ipv6-adapter.md) — IPv6 adaptation layer (above FSP)
|
||||
- [fips-mesh-operation.md](fips-mesh-operation.md) — Routing, discovery, and
|
||||
error recovery
|
||||
|
||||
@@ -93,7 +93,7 @@ FIPS uses independent Noise IK encryption at two layers:
|
||||
|
||||
| Layer | Scope | What It Protects |
|
||||
| ----- | ----- | ---------------- |
|
||||
| FLP (link) | Hop-by-hop | All traffic on each peer link |
|
||||
| FMP (mesh) | Hop-by-hop | All traffic on each peer link |
|
||||
| FSP (session) | End-to-end | Application payload between endpoints |
|
||||
|
||||
**Why two layers instead of one**:
|
||||
@@ -163,7 +163,7 @@ MMP is instantiated at two independent layers, each with its own
|
||||
configuration and state:
|
||||
|
||||
- **Link layer**: One `MmpPeerState` per `ActivePeer`. Measures per-hop
|
||||
quality using the FLP counter and timestamp fields that already exist on
|
||||
quality using the FMP counter and timestamp fields that already exist on
|
||||
every encrypted frame. No additional message overhead beyond periodic
|
||||
SenderReport/ReceiverReport exchanges.
|
||||
|
||||
@@ -224,13 +224,13 @@ increase in bloom filter occupancy).
|
||||
|
||||
## Transport Opacity
|
||||
|
||||
Transport addresses are opaque byte vectors above FLP. The transport layer
|
||||
Transport addresses are opaque byte vectors above FMP. The transport layer
|
||||
interprets them (e.g., UDP parses "ip:port" strings); all layers above treat
|
||||
them as handles passed back to the transport for sending.
|
||||
|
||||
**Architectural boundary**: Adding a new transport type (e.g., BLE) requires
|
||||
implementing the transport trait and potentially a new `TransportHandle`
|
||||
variant. No changes to FLP, FSP, or any routing logic. The transport trait
|
||||
variant. No changes to FMP, FSP, or any routing logic. The transport trait
|
||||
defines the interface:
|
||||
|
||||
- `send(addr, data)` — send a datagram
|
||||
@@ -300,7 +300,7 @@ The `TransportHandle` enum provides async dispatch for methods that need it
|
||||
## References
|
||||
|
||||
- [fips-intro.md](fips-intro.md) — Protocol overview
|
||||
- [fips-link-layer.md](fips-link-layer.md) — FLP specification
|
||||
- [fips-mesh-layer.md](fips-mesh-layer.md) — FMP specification
|
||||
- [fips-session-layer.md](fips-session-layer.md) — FSP specification
|
||||
- [fips-state-machines.md](fips-state-machines.md) — Phase-based state
|
||||
machine pattern
|
||||
|
||||
@@ -8,14 +8,14 @@ session management — is built on the services the transport layer provides.
|
||||
## Role
|
||||
|
||||
A **transport** is a driver for a particular communication medium: a UDP
|
||||
socket, an Ethernet interface, a LoRa radio, a serial line, a Tor circuit.
|
||||
socket, an Ethernet interface, a serial line, a Tor circuit, a radio modem.
|
||||
The transport layer's job is simple: accept a datagram and a transport
|
||||
address, deliver the datagram to that address, and push inbound datagrams up
|
||||
to the FIPS Link Protocol (FLP) above.
|
||||
to the FIPS Mesh Protocol (FMP) above.
|
||||
|
||||
The transport layer deals exclusively in **transport addresses** — IP:port
|
||||
tuples, MAC addresses, LoRa device addresses, .onion identifiers. These are
|
||||
opaque to every layer above FLP. The mapping from transport address to FIPS
|
||||
tuples, MAC addresses, .onion identifiers, radio device addresses. These are
|
||||
opaque to every layer above FMP. The mapping from transport address to FIPS
|
||||
identity happens at the link layer after the Noise IK handshake completes.
|
||||
The word "peer" belongs to the link layer and above; the transport layer
|
||||
knows only about remote endpoints identified by transport addresses.
|
||||
@@ -23,29 +23,29 @@ knows only about remote endpoints identified by transport addresses.
|
||||
A single transport instance can serve multiple remote endpoints
|
||||
simultaneously — a UDP socket exchanges datagrams with many remote
|
||||
addresses, an Ethernet interface communicates with many MAC addresses on the
|
||||
same segment. Each endpoint may become a separate FLP link, but the
|
||||
same segment. Each endpoint may become a separate FMP link, but the
|
||||
transport layer itself maintains no per-endpoint state.
|
||||
|
||||
## Services Provided to FLP
|
||||
## Services Provided to FMP
|
||||
|
||||
The transport layer provides four services to the FIPS Link Protocol above:
|
||||
The transport layer provides four services to the FIPS Mesh Protocol above:
|
||||
|
||||
### Datagram Delivery
|
||||
|
||||
Send and receive datagrams to/from transport addresses. The transport
|
||||
handles all medium-specific details: socket management, framing for stream
|
||||
transports, radio configuration. FLP sees only "send bytes to address" and
|
||||
transports, radio configuration. FMP sees only "send bytes to address" and
|
||||
"bytes arrived from address."
|
||||
|
||||
Inbound datagrams are pushed to FLP through a channel. The transport spawns
|
||||
Inbound datagrams are pushed to FMP through a channel. The transport spawns
|
||||
a receive task that pushes arriving datagrams (along with the source
|
||||
transport address and transport identifier) onto a bounded channel. FLP
|
||||
transport address and transport identifier) onto a bounded channel. FMP
|
||||
reads from this channel and dispatches based on the source address and
|
||||
packet content.
|
||||
|
||||
### MTU Reporting
|
||||
|
||||
Report the maximum datagram size for a given link. FLP needs this to
|
||||
Report the maximum datagram size for a given link. FMP needs this to
|
||||
determine how much payload can fit in a single packet after link-layer
|
||||
encryption overhead.
|
||||
|
||||
@@ -63,7 +63,7 @@ link individually.
|
||||
### Connection Lifecycle
|
||||
|
||||
For connection-oriented transports, manage the underlying connection: TCP
|
||||
handshake, Tor circuit establishment, Bluetooth pairing. FLP cannot begin
|
||||
handshake, Tor circuit establishment, Bluetooth pairing. FMP cannot begin
|
||||
the Noise IK handshake until the transport-layer connection is established.
|
||||
|
||||
Connectionless transports (UDP, raw Ethernet) skip this — datagrams can flow
|
||||
@@ -71,7 +71,7 @@ immediately to any reachable address.
|
||||
|
||||
### Discovery (Optional)
|
||||
|
||||
Notify FLP when FIPS-capable endpoints are discovered on the local medium.
|
||||
Notify FMP when FIPS-capable endpoints are discovered on the local medium.
|
||||
This is an optional capability — transports that don't support it simply
|
||||
don't provide discovery events.
|
||||
|
||||
@@ -94,7 +94,6 @@ for internet connectivity:
|
||||
| TCP/IP | IP:port | Stream | Reliable | Requires length-prefix framing |
|
||||
| WebSocket | URL | Stream | Reliable | Browser-compatible |
|
||||
| Tor | .onion | Stream | Reliable | High latency, strong anonymity |
|
||||
| I2P | Destination | ~32K | Unreliable | Datagram mode |
|
||||
|
||||
**Shared medium transports** operate over broadcast- or multicast-capable
|
||||
media:
|
||||
@@ -105,7 +104,7 @@ media:
|
||||
| WiFi | MAC | 1500 | Unreliable | Infrastructure mode = Ethernet |
|
||||
| Bluetooth | BD_ADDR | 672–64K | Reliable | L2CAP |
|
||||
| BLE | BD_ADDR | 23–517 | Reliable | Negotiated ATT_MTU |
|
||||
| LoRa | Device addr | 51–222 | Unreliable | Low bandwidth, long range |
|
||||
| Radio | Device addr | 51–222 | Unreliable | Low bandwidth, long range |
|
||||
|
||||
**Point-to-point transports** connect exactly two endpoints:
|
||||
|
||||
@@ -114,9 +113,9 @@ media:
|
||||
| Serial | None (P2P) | 256–1500 | Reliable | SLIP/COBS framing |
|
||||
| Dialup | None (P2P) | 1500 | Reliable | PPP framing |
|
||||
|
||||
### Properties That Matter to FLP
|
||||
### Properties That Matter to FMP
|
||||
|
||||
**MTU**: Determines how much data FLP can pack into a single datagram after
|
||||
**MTU**: Determines how much data FMP can pack into a single datagram after
|
||||
accounting for link encryption overhead. Heterogeneous MTUs across the mesh
|
||||
are normal — the IPv6 minimum (1280 bytes) is the safe baseline for FIPS
|
||||
packet sizing.
|
||||
@@ -129,19 +128,19 @@ and duplication at the routing layer.
|
||||
|
||||
**Connection model**: Connectionless transports (UDP, raw Ethernet) allow
|
||||
immediate datagram exchange. Connection-oriented transports (TCP, Tor, BLE)
|
||||
require connection setup before FLP can begin the Noise IK handshake,
|
||||
require connection setup before FMP can begin the Noise IK handshake,
|
||||
adding startup latency.
|
||||
|
||||
**Stream vs. datagram**: Datagram transports have natural packet boundaries.
|
||||
Stream transports (TCP, WebSocket, Tor) require framing to delineate FIPS
|
||||
packets within the byte stream. The FLP common prefix includes a payload
|
||||
packets within the byte stream. The FMP common prefix includes a payload
|
||||
length field that provides this framing directly, replacing the need for a
|
||||
separate length-prefix layer.
|
||||
|
||||
**Addressing opacity**: Transport addresses are opaque byte vectors. FLP
|
||||
**Addressing opacity**: Transport addresses are opaque byte vectors. FMP
|
||||
doesn't interpret them — it just passes them back to the transport when
|
||||
sending. This means adding a new transport type with a novel address format
|
||||
requires no changes to FLP or FSP.
|
||||
requires no changes to FMP or FSP.
|
||||
|
||||
## Connection Model
|
||||
|
||||
@@ -154,13 +153,12 @@ are lightweight — a transport address is sufficient to begin communication.
|
||||
| --------- | ----- |
|
||||
| UDP/IP | Stateless datagrams; NAT state is implicit |
|
||||
| Ethernet | Send to MAC address directly |
|
||||
| LoRa | Raw packets to device address |
|
||||
| I2P | Datagram mode |
|
||||
| Radio | Raw packets to device address |
|
||||
|
||||
### Connection-Oriented Transports
|
||||
|
||||
Explicit connection setup is required before FIPS traffic can flow. The link
|
||||
must complete transport-layer connection before FLP authentication can
|
||||
must complete transport-layer connection before FMP authentication can
|
||||
proceed.
|
||||
|
||||
| Transport | Connection Setup |
|
||||
@@ -185,7 +183,7 @@ circuit). Peer timeout configuration must account for transport-specific
|
||||
setup times.
|
||||
|
||||
**Framing**: Stream transports must delimit FIPS packets within the byte
|
||||
stream. The FLP common prefix includes a payload length field that provides
|
||||
stream. The FMP common prefix includes a payload length field that provides
|
||||
integrated framing. Datagram transports preserve packet boundaries naturally.
|
||||
|
||||
## UDP/IP: The Primary Internet Transport
|
||||
@@ -248,14 +246,14 @@ discovery; a FIPS-specific announcement or response is.
|
||||
|
||||
Discovery is an optional transport capability. Transports that don't support
|
||||
it (configured UDP endpoints, TCP) simply don't provide discovery events.
|
||||
FLP handles both cases uniformly: with discovery, it waits for events then
|
||||
FMP handles both cases uniformly: with discovery, it waits for events then
|
||||
initiates link setup; without discovery, it initiates link setup directly to
|
||||
configured addresses.
|
||||
|
||||
### Local/Medium Discovery *(future direction)*
|
||||
|
||||
For transports where endpoints share a physical or link-layer medium — LAN
|
||||
broadcast, LoRa, BLE — discovery uses beacon and query mechanisms:
|
||||
broadcast, radio, BLE — discovery uses beacon and query mechanisms:
|
||||
|
||||
- **Beacon**: A node periodically broadcasts its FIPS presence on the shared
|
||||
medium. Content is a FIPS-defined discovery frame carrying enough
|
||||
@@ -264,13 +262,13 @@ broadcast, LoRa, BLE — discovery uses beacon and query mechanisms:
|
||||
respond. Responses arrive on the same channel as beacon events.
|
||||
|
||||
Both produce the same result: "FIPS endpoint available at transport address
|
||||
X." FLP does not need to distinguish beacons from query responses.
|
||||
X." FMP does not need to distinguish beacons from query responses.
|
||||
|
||||
| Transport | Discovery | Notes |
|
||||
| --------- | --------- | ----- |
|
||||
| UDP (LAN) | Broadcast/multicast | On local network segment |
|
||||
| Ethernet | Broadcast | Custom EtherType, ff:ff:ff:ff:ff:ff |
|
||||
| LoRa | Beacon | Shared RF channel, natural fit |
|
||||
| Radio | Beacon | Shared RF channel, natural fit |
|
||||
| BLE | Advertising | GATT service UUID |
|
||||
|
||||
### Nostr Relay Discovery *(future direction)*
|
||||
@@ -290,7 +288,7 @@ Key properties:
|
||||
is authenticated
|
||||
- Relay selection acts as scoping — which relays a node publishes to and
|
||||
subscribes on determines its discovery neighborhood
|
||||
- Can only advertise IP-reachable endpoints (not LoRa, BLE, serial)
|
||||
- Can only advertise IP-reachable endpoints (not radio, BLE, serial)
|
||||
- Higher latency than local discovery (relay propagation delays)
|
||||
|
||||
### Current State
|
||||
@@ -333,7 +331,7 @@ Each inbound datagram carries:
|
||||
|
||||
### Transport Metadata
|
||||
|
||||
Transport types carry static metadata that FLP can query:
|
||||
Transport types carry static metadata that FMP can query:
|
||||
|
||||
```text
|
||||
TransportType {
|
||||
@@ -373,7 +371,7 @@ transitions through `Starting` to `Up` (operational). `stop()` moves to
|
||||
| WiFi | Future direction | Infrastructure mode = Ethernet driver |
|
||||
| Tor | Future direction | High latency, .onion addressing |
|
||||
| BLE | Future direction | ATT_MTU negotiation, per-link MTU |
|
||||
| LoRa | Future direction | Constrained MTU (51–222 bytes) |
|
||||
| Radio | Future direction | Constrained MTU (51–222 bytes) |
|
||||
| Serial | Future direction | SLIP/COBS framing, point-to-point |
|
||||
|
||||
## Design Considerations
|
||||
@@ -399,7 +397,7 @@ traffic automatically routes through alternatives. A node with both UDP and
|
||||
Ethernet transports bridges between internet-connected and local-only
|
||||
networks transparently.
|
||||
|
||||
Multiple links to the same peer over different transports are possible. FLP
|
||||
Multiple links to the same peer over different transports are possible. FMP
|
||||
manages these independently — each link has its own Noise session, its own
|
||||
MTU, and its own liveness tracking.
|
||||
|
||||
@@ -413,7 +411,7 @@ consider transport quality. This is a potential area for future optimization.
|
||||
## References
|
||||
|
||||
- [fips-intro.md](fips-intro.md) — Protocol overview and layer architecture
|
||||
- [fips-link-layer.md](fips-link-layer.md) — FLP specification (the layer above)
|
||||
- [fips-mesh-layer.md](fips-mesh-layer.md) — FMP specification (the layer above)
|
||||
- [fips-wire-formats.md](fips-wire-formats.md) — Transport framing details
|
||||
- [fips-software-architecture.md](fips-software-architecture.md) — Transport
|
||||
trait implementation details
|
||||
|
||||
@@ -32,7 +32,7 @@ tag). No separate length prefix is needed.
|
||||
|
||||
## Link-Layer Formats
|
||||
|
||||
All FLP packets begin with a **4-byte common prefix** that identifies the
|
||||
All FMP packets begin with a **4-byte common prefix** that identifies the
|
||||
protocol version, session lifecycle phase, per-packet flags, and payload
|
||||
length.
|
||||
|
||||
@@ -663,11 +663,11 @@ Layer 3: Session encryption (FSP)
|
||||
FSP header (12 bytes) + AEAD(inner_hdr (6) + payload (1024)) + AEAD tag (16)
|
||||
= 1058 bytes
|
||||
|
||||
Layer 2: SessionDatagram envelope (FLP routing)
|
||||
Layer 2: SessionDatagram envelope (FMP routing)
|
||||
msg_type (1) + ttl (1) + path_mtu (2) + src_addr (16) + dest_addr (16) + payload (1058)
|
||||
= 1094 bytes
|
||||
|
||||
Layer 1: Link encryption (FLP per-hop)
|
||||
Layer 1: Link encryption (FMP per-hop)
|
||||
outer header (16) + encrypted(inner_hdr (5) + datagram (1094)) + AEAD tag (16)
|
||||
= 1131 bytes
|
||||
|
||||
@@ -754,7 +754,7 @@ endpoint session keys).
|
||||
|
||||
## References
|
||||
|
||||
- [fips-link-layer.md](fips-link-layer.md) — FLP behavioral specification
|
||||
- [fips-mesh-layer.md](fips-mesh-layer.md) — FMP behavioral specification
|
||||
- [fips-session-layer.md](fips-session-layer.md) — FSP behavioral specification
|
||||
- [fips-transport-layer.md](fips-transport-layer.md) — Transport framing
|
||||
- [fips-mesh-operation.md](fips-mesh-operation.md) — How messages work together
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//!
|
||||
//! Measures link quality between adjacent peers: RTT, loss, jitter,
|
||||
//! throughput, one-way delay trend, and ETX. Operates on the per-frame
|
||||
//! hooks (counter, timestamp, flags) introduced by the FLP wire format
|
||||
//! hooks (counter, timestamp, flags) introduced by the FMP wire format
|
||||
//! revision.
|
||||
//!
|
||||
//! Three operating modes trade measurement fidelity for overhead:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
use crate::node::{Node, NodeError};
|
||||
use crate::transport::ReceivedPacket;
|
||||
use crate::node::wire::{CommonPrefix, PHASE_ESTABLISHED, PHASE_MSG1, PHASE_MSG2, FLP_VERSION, COMMON_PREFIX_SIZE};
|
||||
use crate::node::wire::{CommonPrefix, PHASE_ESTABLISHED, PHASE_MSG1, PHASE_MSG2, FMP_VERSION, COMMON_PREFIX_SIZE};
|
||||
use std::time::Duration;
|
||||
use tracing::{debug, info};
|
||||
|
||||
@@ -110,11 +110,11 @@ impl Node {
|
||||
None => return, // Malformed prefix
|
||||
};
|
||||
|
||||
if prefix.version != FLP_VERSION {
|
||||
if prefix.version != FMP_VERSION {
|
||||
debug!(
|
||||
version = prefix.version,
|
||||
transport_id = %packet.transport_id,
|
||||
"Unknown FLP version, dropping"
|
||||
"Unknown FMP version, dropping"
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -133,7 +133,7 @@ impl Node {
|
||||
debug!(
|
||||
phase = prefix.phase,
|
||||
transport_id = %packet.transport_id,
|
||||
"Unknown FLP phase, dropping"
|
||||
"Unknown FMP phase, dropping"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ impl FspCommonPrefix {
|
||||
/// ```
|
||||
///
|
||||
/// The full 12-byte header is used as AAD for the AEAD construction.
|
||||
/// No receiver_idx — unlike FLP, FSP is end-to-end (dispatched by src_addr
|
||||
/// No receiver_idx — unlike FMP, FSP is end-to-end (dispatched by src_addr
|
||||
/// from the SessionDatagram envelope, not by index).
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct FspEncryptedHeader {
|
||||
|
||||
@@ -204,7 +204,7 @@ pub(super) fn print_tree_snapshot(label: &str, nodes: &[TestNode]) {
|
||||
///
|
||||
/// Returns the number of packets processed.
|
||||
pub(super) async fn process_available_packets(nodes: &mut [TestNode]) -> usize {
|
||||
use crate::node::wire::{CommonPrefix, FLP_VERSION, PHASE_ESTABLISHED, PHASE_MSG1, PHASE_MSG2, COMMON_PREFIX_SIZE};
|
||||
use crate::node::wire::{CommonPrefix, FMP_VERSION, PHASE_ESTABLISHED, PHASE_MSG1, PHASE_MSG2, COMMON_PREFIX_SIZE};
|
||||
|
||||
let mut count = 0;
|
||||
for node in nodes.iter_mut() {
|
||||
@@ -213,7 +213,7 @@ pub(super) async fn process_available_packets(nodes: &mut [TestNode]) -> usize {
|
||||
continue;
|
||||
}
|
||||
if let Some(prefix) = CommonPrefix::parse(&packet.data) {
|
||||
if prefix.version != FLP_VERSION {
|
||||
if prefix.version != FMP_VERSION {
|
||||
continue;
|
||||
}
|
||||
match prefix.phase {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! Wire Format Parsing and Serialization
|
||||
//!
|
||||
//! Defines the FIPS link-layer wire format (FLP) for packet dispatch.
|
||||
//! Defines the FIPS mesh-layer wire format (FMP) for packet dispatch.
|
||||
//! All packets begin with a 4-byte common prefix followed by phase-specific fields.
|
||||
//!
|
||||
//! ## Common Prefix (4 bytes)
|
||||
@@ -24,8 +24,8 @@ use crate::noise::{HANDSHAKE_MSG1_SIZE, HANDSHAKE_MSG2_SIZE, TAG_SIZE};
|
||||
// Constants
|
||||
// ============================================================================
|
||||
|
||||
/// FLP protocol version (4 high bits of byte 0).
|
||||
pub const FLP_VERSION: u8 = 0;
|
||||
/// FMP protocol version (4 high bits of byte 0).
|
||||
pub const FMP_VERSION: u8 = 0;
|
||||
|
||||
/// Phase value for established (encrypted) frames.
|
||||
pub const PHASE_ESTABLISHED: u8 = 0x0;
|
||||
@@ -70,7 +70,7 @@ pub const FLAG_SP: u8 = 0x04;
|
||||
// Common Prefix
|
||||
// ============================================================================
|
||||
|
||||
/// Parsed common packet prefix (first 4 bytes of every FLP packet).
|
||||
/// Parsed common packet prefix (first 4 bytes of every FMP packet).
|
||||
///
|
||||
/// Wire format:
|
||||
/// ```text
|
||||
@@ -156,7 +156,7 @@ impl EncryptedHeader {
|
||||
let version = data[0] >> 4;
|
||||
let phase = data[0] & 0x0F;
|
||||
|
||||
if version != FLP_VERSION || phase != PHASE_ESTABLISHED {
|
||||
if version != FMP_VERSION || phase != PHASE_ESTABLISHED {
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -222,7 +222,7 @@ impl Msg1Header {
|
||||
let version = data[0] >> 4;
|
||||
let phase = data[0] & 0x0F;
|
||||
|
||||
if version != FLP_VERSION || phase != PHASE_MSG1 {
|
||||
if version != FMP_VERSION || phase != PHASE_MSG1 {
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -278,7 +278,7 @@ impl Msg2Header {
|
||||
let version = data[0] >> 4;
|
||||
let phase = data[0] & 0x0F;
|
||||
|
||||
if version != FLP_VERSION || phase != PHASE_MSG2 {
|
||||
if version != FMP_VERSION || phase != PHASE_MSG2 {
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -317,7 +317,7 @@ pub fn build_msg1(sender_idx: SessionIndex, noise_msg1: &[u8]) -> Vec<u8> {
|
||||
let payload_len = (4 + noise_msg1.len()) as u16; // sender_idx + noise_msg1
|
||||
|
||||
let mut packet = Vec::with_capacity(MSG1_WIRE_SIZE);
|
||||
packet.push(CommonPrefix::ver_phase_byte(FLP_VERSION, PHASE_MSG1));
|
||||
packet.push(CommonPrefix::ver_phase_byte(FMP_VERSION, PHASE_MSG1));
|
||||
packet.push(0x00); // flags must be zero
|
||||
packet.extend_from_slice(&payload_len.to_le_bytes());
|
||||
packet.extend_from_slice(&sender_idx.to_le_bytes());
|
||||
@@ -334,7 +334,7 @@ pub fn build_msg2(sender_idx: SessionIndex, receiver_idx: SessionIndex, noise_ms
|
||||
let payload_len = (4 + 4 + noise_msg2.len()) as u16; // sender + receiver + noise
|
||||
|
||||
let mut packet = Vec::with_capacity(MSG2_WIRE_SIZE);
|
||||
packet.push(CommonPrefix::ver_phase_byte(FLP_VERSION, PHASE_MSG2));
|
||||
packet.push(CommonPrefix::ver_phase_byte(FMP_VERSION, PHASE_MSG2));
|
||||
packet.push(0x00); // flags must be zero
|
||||
packet.extend_from_slice(&payload_len.to_le_bytes());
|
||||
packet.extend_from_slice(&sender_idx.to_le_bytes());
|
||||
@@ -353,7 +353,7 @@ pub fn build_established_header(
|
||||
payload_len: u16,
|
||||
) -> [u8; ESTABLISHED_HEADER_SIZE] {
|
||||
let mut header = [0u8; ESTABLISHED_HEADER_SIZE];
|
||||
header[0] = CommonPrefix::ver_phase_byte(FLP_VERSION, PHASE_ESTABLISHED);
|
||||
header[0] = CommonPrefix::ver_phase_byte(FMP_VERSION, PHASE_ESTABLISHED);
|
||||
header[1] = flags;
|
||||
header[2..4].copy_from_slice(&payload_len.to_le_bytes());
|
||||
header[4..8].copy_from_slice(&receiver_idx.to_le_bytes());
|
||||
|
||||
@@ -268,7 +268,7 @@ impl CipherState {
|
||||
|
||||
/// Encrypt plaintext with Additional Authenticated Data (AAD).
|
||||
///
|
||||
/// The AAD is authenticated but not encrypted. Used for the FLP
|
||||
/// The AAD is authenticated but not encrypted. Used for the FMP
|
||||
/// established frame format where the 16-byte outer header is
|
||||
/// bound to the AEAD tag.
|
||||
pub fn encrypt_with_aad(
|
||||
|
||||
@@ -118,7 +118,7 @@ impl NoiseSession {
|
||||
|
||||
/// Decrypt with explicit counter, replay protection, and AAD.
|
||||
///
|
||||
/// This is the primary decryption method for the FLP transport phase
|
||||
/// This is the primary decryption method for the FMP transport phase
|
||||
/// with AAD binding. The AAD (typically the 16-byte outer header) must
|
||||
/// match what was used during encryption.
|
||||
pub fn decrypt_with_replay_check_and_aad(
|
||||
|
||||
@@ -565,7 +565,7 @@ impl SessionAck {
|
||||
|
||||
/// Session-layer sender report (msg_type 0x11).
|
||||
///
|
||||
/// Mirrors the FLP `SenderReport` fields but carried as an FSP session
|
||||
/// Mirrors the FMP `SenderReport` fields but carried as an FSP session
|
||||
/// message inside the AEAD envelope. The msg_type is in the FSP inner
|
||||
/// header, so the body starts with reserved bytes.
|
||||
///
|
||||
@@ -634,7 +634,7 @@ impl SessionSenderReport {
|
||||
|
||||
/// Session-layer receiver report (msg_type 0x12).
|
||||
///
|
||||
/// Mirrors the FLP `ReceiverReport` fields but carried as an FSP session
|
||||
/// Mirrors the FMP `ReceiverReport` fields but carried as an FSP session
|
||||
/// message inside the AEAD envelope.
|
||||
///
|
||||
/// ## Wire Format (66 bytes body, after inner header stripped)
|
||||
|
||||
@@ -69,22 +69,22 @@ const MAX_ORIGINAL_PACKET: usize = MIN_IPV6_MTU - IPV6_HEADER_LEN - ICMPV6_HEADE
|
||||
/// Breakdown (traced through the actual send path):
|
||||
///
|
||||
/// ```text
|
||||
/// FLP outer header (cleartext AAD) 16
|
||||
/// FMP outer header (cleartext AAD) 16
|
||||
/// common prefix (4) + receiver_idx (4) + counter (8)
|
||||
/// FLP AEAD ciphertext:
|
||||
/// timestamp (4) + msg_type (1) 5 [FLP inner header]
|
||||
/// FMP AEAD ciphertext:
|
||||
/// timestamp (4) + msg_type (1) 5 [FMP inner header]
|
||||
/// ttl (1) + path_mtu (2) + src (16) + dst (16) 35 [SessionDatagram body]
|
||||
/// FSP header (4 prefix + 8 counter) 12 [cleartext AAD]
|
||||
/// FSP AEAD ciphertext:
|
||||
/// timestamp (4) + msg_type (1) + flags (1) 6 [FSP inner header]
|
||||
/// <application data>
|
||||
/// Poly1305 tag 16 [FSP AEAD]
|
||||
/// FLP Poly1305 tag 16 [FLP AEAD]
|
||||
/// FMP Poly1305 tag 16 [FMP AEAD]
|
||||
/// ────
|
||||
/// 106
|
||||
/// ```
|
||||
///
|
||||
/// Note: the FLP inner header msg_type byte IS the SessionDatagram msg_type
|
||||
/// Note: the FMP inner header msg_type byte IS the SessionDatagram msg_type
|
||||
/// byte (shared, not double-counted). The "35 bytes" is the SessionDatagram
|
||||
/// body after msg_type is consumed by the dispatch layer.
|
||||
pub const FIPS_OVERHEAD: u16 = 16 + 16 + 5 + 35 + 12 + 6 + 16; // 106 bytes
|
||||
|
||||