mirror of
https://github.com/jmcorgan/fips.git
synced 2026-08-09 08:14:42 +00:00
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
This commit is contained in:
@@ -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 {
|
||||
|
||||
+10
-10
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user