Files
fips/docs/design/fips-configuration.md
Johnathan Corgan 0a72317b59 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
2026-02-21 22:05:44 +00:00

14 KiB

FIPS Configuration

FIPS uses YAML-based configuration with a cascading multi-file priority system. All parameters have sensible defaults; a node can run with no configuration file at all (it will generate an ephemeral identity and listen on default addresses).

Configuration Loading

Search Paths

When started without the -c flag, FIPS searches for fips.yaml in these locations, lowest to highest priority:

Priority Path Purpose
1 (lowest) /etc/fips/fips.yaml System-wide defaults
2 ~/.config/fips/fips.yaml User preferences
3 ~/.fips.yaml Legacy user config
4 (highest) ./fips.yaml Deployment-specific overrides

All found files are loaded and merged in priority order. Values from higher priority files override those from lower priority files. This allows a system administrator to set site-wide defaults in /etc/fips/fips.yaml while individual deployments override specific values in ./fips.yaml.

CLI Option

fips -c /path/to/config.yaml

When -c is specified, only that file is loaded (search paths are skipped).

Partial Configuration

Every field has a built-in default. A configuration file only needs to specify values that differ from defaults. For example, a minimal config might contain only the identity and peer list, inheriting all other defaults.

YAML Structure

The configuration is organized into five top-level sections:

node:        # Node behavior, protocol parameters, and tuning
tun:         # TUN virtual interface
dns:         # DNS responder for .fips domain
transports:  # Network transports (UDP, future: TCP, Tor)
peers:       # Static peer list

All tunable protocol parameters live under node.*, organized as sysctl-style dotted paths. The top-level sections (tun, dns, transports, peers) handle infrastructure concerns only.

Node Parameters (node.*)

Identity (node.identity.*)

Parameter Type Default Description
node.identity.nsec string (generate random) Hex-encoded secret key. If omitted, an ephemeral identity is generated on each start.

General

Parameter Type Default Description
node.leaf_only bool false Leaf-only mode: node does not forward traffic or participate in routing
node.tick_interval_secs u64 1 Periodic maintenance tick interval (retry checks, timeout cleanup, tree refresh)
node.base_rtt_ms u64 100 Initial RTT estimate for new links before measurements converge
node.heartbeat_interval_secs u64 10 Heartbeat send interval per peer for liveness detection
node.link_dead_timeout_secs u64 30 No-traffic timeout before a peer is declared dead and removed

Resource Limits (node.limits.*)

Controls capacity for connections, peers, and links.

Parameter Type Default Description
node.limits.max_connections usize 256 Max handshake-phase connections
node.limits.max_peers usize 128 Max authenticated peers
node.limits.max_links usize 256 Max active links
node.limits.max_pending_inbound usize 1000 Max pending inbound handshakes

Rate Limiting (node.rate_limit.*)

Handshake rate limiting protects against DoS on the Noise IK handshake path.

Parameter Type Default Description
node.rate_limit.handshake_burst u32 100 Token bucket burst capacity
node.rate_limit.handshake_rate f64 10.0 Tokens per second refill rate
node.rate_limit.handshake_timeout_secs u64 30 Stale handshake cleanup timeout
node.rate_limit.handshake_resend_interval_ms u64 1000 Initial handshake message resend interval
node.rate_limit.handshake_resend_backoff f64 2.0 Resend backoff multiplier (1s, 2s, 4s, 8s, 16s with defaults)
node.rate_limit.handshake_max_resends u32 5 Max resends per handshake attempt

Retry / Backoff (node.retry.*)

Connection retry with exponential backoff.

Parameter Type Default Description
node.retry.max_retries u32 5 Max connection retry attempts
node.retry.base_interval_secs u64 5 Base backoff interval
node.retry.max_backoff_secs u64 300 Cap on exponential backoff (5 minutes)

Auto-reconnect (triggered by MMP link-dead removal) uses the same backoff parameters but bypasses max_retries, retrying indefinitely. See peers[].auto_reconnect below.

Cache Parameters (node.cache.*)

Controls caching of tree coordinates and identity mappings.

Parameter Type Default Description
node.cache.coord_size usize 50000 Max entries in coordinate cache
node.cache.coord_ttl_secs u64 300 Coordinate cache entry TTL (5 minutes)
node.cache.identity_size usize 10000 Max entries in identity cache (LRU, no TTL)

Discovery Protocol (node.discovery.*)

Controls flood-based node discovery (LookupRequest/LookupResponse).

Parameter Type Default Description
node.discovery.ttl u8 64 Hop limit for LookupRequest flood
node.discovery.timeout_secs u64 10 Lookup completion timeout
node.discovery.recent_expiry_secs u64 10 Dedup cache expiry for recent request IDs

Spanning Tree (node.tree.*)

Controls tree construction and parent selection.

Parameter Type Default Description
node.tree.announce_min_interval_ms u64 500 Per-peer TreeAnnounce rate limit
node.tree.parent_switch_threshold usize 1 Min depth improvement required to switch parents

Bloom Filter (node.bloom.*)

Parameter Type Default Description
node.bloom.update_debounce_ms u64 500 Debounce interval for filter update propagation

Bloom filter size (1 KB), hash count (5), and size classes are protocol constants and not configurable.

Session / Data Plane (node.session.*)

Controls end-to-end session behavior and packet queuing.

Parameter Type Default Description
node.session.default_ttl u8 64 Default SessionDatagram TTL
node.session.pending_packets_per_dest usize 16 Queue depth per destination during session establishment
node.session.pending_max_destinations usize 256 Max destinations with pending packets
node.session.idle_timeout_secs u64 90 Idle session timeout; established sessions with no application data for this duration are removed. MMP reports (SenderReport, ReceiverReport, PathMtuNotification) do not count as activity
node.session.coords_warmup_packets u8 5 Number of initial data packets per session that include the CP flag for transit cache warmup; also the reset count on CoordsRequired/PathBroken receipt
node.session.coords_response_interval_ms u64 2000 Minimum interval (ms) between standalone CoordsWarmup responses to CoordsRequired/PathBroken signals per destination

The anti-replay window size (2048 packets) is a compile-time constant and not configurable.

Metrics Measurement Protocol for per-peer link measurement. See fips-mesh-layer.md for behavioral details.

Parameter Type Default Description
node.mmp.mode string "full" Operating mode: full (sender + receiver reports), lightweight (receiver reports only), or minimal (spin bit + CE echo only, no reports)
node.mmp.log_interval_secs u64 30 Periodic operator log interval for link metrics
node.mmp.owd_window_size usize 32 One-way delay trend ring buffer size

Session-Layer MMP (node.session_mmp.*)

Metrics Measurement Protocol for end-to-end session measurement. Configured independently from link-layer MMP because session reports are routed through every transit link, consuming bandwidth proportional to path length.

Parameter Type Default Description
node.session_mmp.mode string "full" Operating mode: full, lightweight, or minimal
node.session_mmp.log_interval_secs u64 30 Periodic operator log interval for session metrics
node.session_mmp.owd_window_size usize 32 One-way delay trend ring buffer size

Internal Buffers (node.buffers.*)

Channel sizes affecting throughput and memory. Primarily useful for performance tuning under high load or on memory-constrained devices.

Parameter Type Default Description
node.buffers.packet_channel usize 1024 Transport to Node packet channel capacity
node.buffers.tun_channel usize 1024 TUN to Node outbound channel capacity
node.buffers.dns_channel usize 64 DNS to Node identity channel capacity

TUN Interface (tun.*)

Parameter Type Default Description
tun.enabled bool false Enable TUN virtual interface
tun.name string "fips0" Interface name
tun.mtu u16 1280 Interface MTU (IPv6 minimum)

DNS Responder (dns.*)

Resolves <npub>.fips queries to FIPS IPv6 addresses. Resolution is pure computation (npub to public key to address); resolved identities are registered with the node for routing.

Parameter Type Default Description
dns.enabled bool false Enable DNS responder
dns.bind_addr string "127.0.0.1" Bind address
dns.port u16 5354 Listen port
dns.ttl u32 300 AAAA record TTL in seconds

The dns.ttl value should not exceed node.cache.coord_ttl_secs to avoid stale address mappings.

Transports (transports.*)

UDP (transports.udp.*)

Parameter Type Default Description
transports.udp.bind_addr string "0.0.0.0:4000" UDP bind address and port
transports.udp.mtu u16 1280 Transport MTU
transports.udp.recv_buf_size usize 2097152 UDP socket receive buffer size in bytes (2 MB). Linux kernel doubles the requested value internally. Host net.core.rmem_max must be >= this value.
transports.udp.send_buf_size usize 2097152 UDP socket send buffer size in bytes (2 MB). Host net.core.wmem_max must be >= this value.

Peers (peers[])

Static peer list. Each entry defines a peer to connect to.

Parameter Type Default Description
peers[].npub string (required) Peer's Nostr public key (npub-encoded)
peers[].alias string (none) Human-readable name for logging
peers[].addresses[].transport string (required) Transport type (udp)
peers[].addresses[].addr string (required) Transport address (e.g., "10.0.0.2:4000")
peers[].addresses[].priority u8 100 Address priority (lower = preferred)
peers[].connect_policy string "auto_connect" Connection policy: auto_connect, on_demand, or manual
peers[].auto_reconnect bool true Automatically reconnect after MMP link-dead removal (exponential backoff, unlimited retries)

Minimal Example

A typical node configuration enabling TUN, DNS, and a single peer:

node:
  identity:
    nsec: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"

tun:
  enabled: true
  name: fips0
  mtu: 1280

dns:
  enabled: true
  bind_addr: "127.0.0.1"
  port: 53

transports:
  udp:
    bind_addr: "0.0.0.0:4000"
    mtu: 1197

peers:
  - npub: "npub1tdwa4vjrjl33pcjdpf2t4p027nl86xrx24g4d3avg4vwvayr3g8qhd84le"
    alias: "node-b"
    addresses:
      - transport: udp
        addr: "172.20.0.11:4000"
    connect_policy: auto_connect

All node.* parameters use their defaults. To override specific values, add only the relevant sections:

node:
  identity:
    nsec: "..."
  limits:
    max_peers: 64
  retry:
    max_retries: 10
    max_backoff_secs: 600
  cache:
    coord_size: 100000

Complete Reference

The full YAML structure with all defaults:

node:
  identity:
    nsec: null                       # hex secret key (null = generate ephemeral)
  leaf_only: false
  tick_interval_secs: 1
  base_rtt_ms: 100
  heartbeat_interval_secs: 10
  link_dead_timeout_secs: 30
  limits:
    max_connections: 256
    max_peers: 128
    max_links: 256
    max_pending_inbound: 1000
  rate_limit:
    handshake_burst: 100
    handshake_rate: 10.0
    handshake_timeout_secs: 30
    handshake_resend_interval_ms: 1000
    handshake_resend_backoff: 2.0
    handshake_max_resends: 5
  retry:
    max_retries: 5
    base_interval_secs: 5
    max_backoff_secs: 300
  cache:
    coord_size: 50000
    coord_ttl_secs: 300
    identity_size: 10000
  discovery:
    ttl: 64
    timeout_secs: 10
    recent_expiry_secs: 10
  tree:
    announce_min_interval_ms: 500
    parent_switch_threshold: 1
  bloom:
    update_debounce_ms: 500
  session:
    default_ttl: 64
    pending_packets_per_dest: 16
    pending_max_destinations: 256
    idle_timeout_secs: 90
    coords_warmup_packets: 5
    coords_response_interval_ms: 2000
  mmp:
    mode: full                       # full | lightweight | minimal
    log_interval_secs: 30
    owd_window_size: 32
  session_mmp:
    mode: full                       # full | lightweight | minimal
    log_interval_secs: 30
    owd_window_size: 32
  buffers:
    packet_channel: 1024
    tun_channel: 1024
    dns_channel: 64

tun:
  enabled: false
  name: "fips0"
  mtu: 1280

dns:
  enabled: false
  bind_addr: "127.0.0.1"
  port: 5354
  ttl: 300

transports:
  udp:
    bind_addr: "0.0.0.0:4000"
    mtu: 1280
    recv_buf_size: 2097152           # 2 MB (kernel doubles to 4 MB actual)
    send_buf_size: 2097152           # 2 MB

peers:                               # static peer list
  # - npub: "npub1..."
  #   alias: "node-b"
  #   addresses:
  #     - transport: udp
  #       addr: "10.0.0.2:4000"
  #       priority: 100
  #   connect_policy: auto_connect
  #   auto_reconnect: true           # reconnect after link-dead removal