Run the demo replay
The demo replay is the fastest way to verify the system works without
any real network gear. It seeds a one-device, two-port topology and
publishes three mac_learned events that exercise the
first-sight → move classification path.
For a richer, data-populated TUI experience (3 devices, 15 hosts across realistic vendor OUIs, 48 hours of history including a host move and a cross-source disagreement), use the realistic seed instead:
make seed-realisticThat populates the bitemporal log directly with ~80 observations spanning the last 48 hours, then sets liveness pointers so the OPS FDB tree shows current state. All the screenshots in these docs were captured against this seed. The rest of this page covers the minimal replay.
Run it
Section titled “Run it”make replayYou’ll see output like:
[1/3] seeding topology... device_id=1 Eth1=1 Eth2=2
[2/3] publishing 3 events to NATS... → mac_learned mac=aa:bb:cc:11:22:33 port=Eth1 event_id=019e1432-6d6f-7ba8-... → mac_learned mac=aa:bb:cc:44:55:66 port=Eth2 event_id=019e1432-947f-7839-... → mac_learned mac=aa:bb:cc:11:22:33 port=Eth2 event_id=019e1432-bb8f-726e-...The reconciler is already running (make up started it). It picks up
the three events from NATS and writes them through the state machine into
mac_observation automatically.
What the events do
Section titled “What the events do”| Event | Wire-time | Classification |
|---|---|---|
aa:bb:cc:11:22:33 learned on Eth1 | T+0 | first-sight |
aa:bb:cc:44:55:66 learned on Eth2 | T+10s | first-sight |
aa:bb:cc:11:22:33 learned on Eth2 | T+20s | move (closes Eth1, opens Eth2) |
After replay, three rows land in mac_observation:
SELECT entry_id, mac, port_id, observed_at, upper_inf(valid_during) AS still_openFROM mac_observation ORDER BY entry_id; entry_id | mac | port_id | observed_at | still_open----------+-------------------+---------+----------------------------+----------- 1 | aa:bb:cc:11:22:33 | 1 | 2026-05-10 22:06:53.95+00 | f ← closed by the move 2 | aa:bb:cc:44:55:66 | 2 | 2026-05-10 22:07:03.95+00 | t 3 | aa:bb:cc:11:22:33 | 2 | 2026-05-10 22:07:13.95+00 | tThe first row’s valid_during was closed at T+20s when the move event
landed. The third row’s valid_during opens at T+20s and stays open.
Verify in the TUI
Section titled “Verify in the TUI”make tuiPress Ctrl+H (HISTORY), enter aa:bb:cc:11:22:33, press Enter. You’ll
see two timeline entries — the closed Eth1 row and the open Eth2 row.
Press Ctrl+O (OPS) for the FDB tree. You’ll see sw1 with Eth1 (no
MACs — the move emptied it) and Eth2 (two MACs — both demo hosts).
What the demo doesn’t exercise
Section titled “What the demo doesn’t exercise”The demo is intentionally minimal. It does not exercise:
- Late arrivals (events arriving with
observed_atin the past) - Cross-source disagreements (only
gnmiis used) - Quarantine events (no skew, no integrity errors)
- Multi-hop topology (only one device)
For multi-source and cross-vendor scenarios, you’d point a real collector at real switches — or write a more elaborate replay script.
To replay again from a clean slate:
make nuke # removes containers AND volumesmake upmake migratemake oui-refresh # optionalmake replayThe volume drop is what resets the bitemporal log; make down alone
keeps it.
See also
Section titled “See also”- How move classification actually works
- The replay script source:
scripts/demo_replay.py