Simulation lab

Measured, not claimed.

What happens when a relay dies, a radio is stolen, a jammer switches on or a LoRa channel fills up? Every number on this page comes from the real Wayfinder router — the same Rust that runs on the boards — compiled into a discrete-event simulator and run against models of radios, terrain, interference and failure.

  1. Router One real routing engine per node, compiled from this repository, stepped on a virtual clock.
  2. Physics Free-space and terrain-diffraction path loss, LoRa time-on-air, collisions with capture, half-duplex radios, duty-cycle limits, jammers.
  3. Measurement Results are read off delivered packets and metered airtime, never off a routing table's opinion of itself.

These are simulations, not field trials: each section states its model and parameters, and every chart can be reproduced with one command from the scenario scripts.

What it found

A simulator earns its keep by being wrong about you.

Building these scenarios turned up problems no unit test had: the tests drove one router at a time, or wired nodes through an ideal switch. Each is fixed in the router, with a test that fails without the fix — except the last, which is open.

Fixed · router

A unicast storm on shared radios

A LoRa or Bluetooth radio hears every frame in range, including ones addressed to a neighbour. An open mesh relayed those overheard frames, and on a shared channel one packet multiplied until its hop limit ran out — forty copies across three nodes in a fifth of a second.

Fixed · timing

Advert jitter that stopped at 4.3 seconds

Routing adverts are spread at random across each interval so neighbours don't transmit together. The randomness was a 32-bit count of nanoseconds, so for any interval longer than about nine seconds every advert bunched at the start of its window.

Fixed · convergence

New nodes too busy listening to speak

Each newly discovered neighbour rescheduled a node's own advert. Joining a hundred-node mesh, a node kept postponing its introduction until discovery settled: 33 seconds to become reachable, now 2.

Open · scale

A full routing table becomes a storm

Past the default router's 128-node table, evicted nodes are re-learned a moment later, each re-learning resets every router's advert timer, and the mesh drowns in its own adverts. The “Growing the mesh” result above shows the cliff.

Reproduce it

Every chart is one command.

The scenarios are plain Python scripts over the wayfinder-sim package. Each writes the JSON this page draws.

From a checkout

uv sync --group sim
uv run --group sim python \
  sim/scenarios/failover.py \
  --export www/sim/data

Or just sim-export to regenerate every result on this page.