GSP stands up a complete parallel internet on your own hardware:
real ISP routing, mission-relevant SATCOM and degraded-link effects, and real devices
living on emulated public address space. Fully airgapped. Inside your wire.
Real routing, not mocked pathsTime-varying SATCOM effectsReal devices and mission traffic
0internet dependencies at deploy time. The verified package crosses the airgap once.
Realrouters, BGP paths, packet hops, addressing, traffic, and endpoint behavior.
Livelatency, jitter, loss, bandwidth, corruption, handovers, fades, and outages.
1declarative configuration and one management plane for the entire environment.
Why it exists
The tactical edge is DDIL. The lab usually isn’t.
Systems proven on perfect networks meet latency, handovers, rain fade, congestion, and loss for the first time in theater. GSP moves that discovery left—into a repeatable lab environment.
01 · FIDELITY
◎
A real parallel internet
Packets cross real routing domains and real policy boundaries. Traceroute, TTL, peering, customer transit, and failure behavior have the structure operators expect.
02 · REPEATABILITY
↻
Reproduce the hard failure
Declarative topology and seeded impairment schedules let teams replay the same contested network condition after a fix—not argue about an unrepeatable anomaly.
03 · SOVEREIGNTY
◇
Entirely inside your wire
No cloud control plane, license server, phone-home, or deploy-time pull. GSP brings the internet behavior you need without bringing the internet into the enclave.
How to use this
Emulate it. Automate it. Rehearse on it.
SCROLL ▾
01 EMULATE THE INTERNET
Every hop degrades traffic its own way — because every hop has its own emulator.
GSP stands up real ISPs on real router software, then drops a dedicated WAN emulator into each inter-ISP link. Traffic is shaped hop by hop, the way it is on the internet.
Real control planes. VyOS routers run multi-area OSPF with area-0 cores, dual-homed provider ABRs, stub edge areas, and inter-ISP eBGP. Paths are selected and reconverged, not looked up.
One emulator per inter-ISP link. A terrestrial peering hop and a LEO SATCOM hop carry entirely independent delay, jitter, loss, correlation, and rate.
Real devices on emulated public space. Laptops, phones, servers, and whole enclaves get public identities and cross true customer, peer, and transit policy boundaries.
Impairment composes. Independent per-hop distributions produce the reordering, burst loss, and tail latency a single averaged pipe can never generate.
A single WAN emulator gives you one averaged pipe with one delay distribution and one hop of TTL. GSP composes impairment hop by hop across real routing — the most realistic emulated internet you can put inside an airgap.
PER-HOP EMULATION ACROSS REAL ROUTING vs. ONE AVERAGED PIPE
02 AUTOMATE IT
One profile change in a pipeline stage, and the same suite runs on a different internet.
GSP is API driven end to end and idempotent by construction. A gsp test stage owns the network its tests run under — it runs the suite clean, reshapes the link over REST, and runs the exact same suite again.
Before and after, same job.PUT /api/wanemu/{link}/profile swaps terrestrial-fiber for starlink-maritime between two identical test runs. The delta is the finding.
Reshape any link, live.PATCH /api/wanemu/{link}/impairment sets delay, jitter, loss, correlation, corruption, and rate per link and per direction on the running emulator. POST .../disable and /enable cut a hop and restore it mid-suite.
Real devices, driven from CI.POST /api/customers declares the endpoints; gspcli deploy customers converges them onto emulated public space and every router on the path carries their traffic.
Idempotent, so re-runs are free. Every layer reconciles toward config.yaml: unchanged config touches nothing, allocation is seeded, and the same input rebuilds a byte-identical environment.
Matrix your tests over network conditions the way you already matrix them over OS versions — unattended, reproducible, and inside the airgap.
ONE PIPELINE STAGE, TWO IDENTICAL RUNS, TWO DIFFERENT INTERNETS
03 REHEARSE THE MISSION
Rehearse the operation on the network you will actually have — before it counts.
The same emulated internet becomes a mission-rehearsal range. Blue operators work from their real tooling across a degraded SATCOM reachback; the target sits behind real ISP hops on red-held infrastructure.
Rehearsal, not a tabletop. The operator drives the actual C2 console, over the actual tunnel, across links impaired to match the theater they deploy into.
The adversary has real distance. Reaching red infrastructure crosses genuine routing domains and policy boundaries, so hop count, TTL, and RTT signatures behave as they will on mission.
Replay the exact condition. Seeded impairment schedules make a failed rehearsal reproducible: change tradecraft, re-run the same network, compare honestly.
Train the failure, not the happy path. Handover gaps, rain fade, and emissions-control blackouts are scheduled events — operators learn where their tooling breaks in the lab.
Rehearsal finding: a 30-second fixed beacon straddles the 45-second LEO handover gap and the C2 session dies mid-operation. Re-run with a 12-second jittered beacon and resume tokens: the session re-establishes 8 seconds after the fade. That lesson cost nothing to learn here.
ONE OPERATOR, FOUR EMULATED HOPS, A RED TARGET — AND A LESSON LEARNED EARLY
Why it is different
Nothing important is hand-waved.
GSP combines deployment, routing, customer ingress, dynamic WAN impairment, and observability into one product instead of asking the customer to assemble a range from unrelated tools.
operator@edge-kit — connected through GSP
$ gspcli connect afloat-02
✓ identity 175.148.93.101 (customer afloat-02)✓ tunnel up (emulated public routes installed)$ ping 89.69.91.10 # ship → SATCOM → emulated internet
64 bytes: icmp_seq=1 ttl=58 time=561 ms
64 bytes: icmp_seq=2 ttl=58 time=574 msRequest timeout for icmp_seq 3← that is the point
64 bytes: icmp_seq=4 ttl=58 time=559 ms
L2 bump-in-the-wire impairmentRouters keep their real adjacency while the link between them degrades.
Dynamic profilesLEO handovers, rain fade, busy-hour congestion, sea-state swell, bursts, and outages evolve over time.
Real customer endpointsServers, laptops, radios, phones, enclaves, gateways, and remote operators exchange actual traffic.
One common operating pictureMonitor topology, inspect routers, control impairments, onboard customers, and open documentation from the UI.
Airgap-first by design
Airgap is not a deployment option. It is the only supported deployment model.
We develop and validate the product from day one as a disconnected system so continuous airgap operation remains a first-class requirement—not a late-stage packaging exercise.
Connected once. Airgapped for operation.
A connected build device assembles and verifies one package. That package crosses the boundary through the customer’s approved transfer process. Every runtime artifact, image, chart, binary, and dependency is already inside.
No deploy-time pulls. No license server. No cloud control plane. No phone-home path.
The disconnected path is exercised continuously in development because it is the product path.
Routers make the path real. The emulators make the path hard. Every impaired link is a transparent Layer-2 bump-in-the-wire: the routers either side keep their real adjacency while the wire between them behaves like weather, orbit, congestion, or emissions control.
REAL SHIPPED PROFILES · REPLAYED THE SAME WAY EVERY RUN
bandwidth tbf rate caplatency + jitterloss + correlationcorruption bit errorsqueue limit buffer depthper direction a2b · b2a · bothenable / disable hard cut
Pulse — brief, repeating hits
A clean link that keeps getting punched on a schedule. handover, burst, outage: LEO beam switches, obstruction loss bursts, mast blockage, EMCON blackout windows, flapping backhaul.
Envelope — it comes on gradually
Ramp in, dwell at the worst of it, recover, run clear. fade, swell, congestion: rain storms, sea-state mispointing, diurnal busy hour, and buffer-filling congestion collapse.
Ladder — capacity steps down
Adaptive coding and modulation under fade. acm walks bandwidth down through real modcod tiers and holds a loss floor at the bottom rung, the way a satellite modem actually degrades.
Markov — good and bad regimes
Session-level burstiness instead of tidy averages. gilbert-elliott flips between a good state and a lossy bad state on mean dwell times, so retransmits clump the way they do on a real link.
Oscillator — continuous wobble
doppler walks delay up and down on a period, modelling range-rate change as a satellite or a ship moves. Layer it under any of the above — modulators stack in an ordered list.
21built-in profiles
9modulator types
∞your own, same schema
Terrestrial fiber and congestion · GEO, MEO and LEO satellite · WGS Ka maritime and MUOS narrowband · Starlink at sea · sea state · EMCON · LTE and 5G · congestion collapse. All shipped inside the airgap package, all controllable over REST.
01 / 06
Full ecosystem
GSP Architecture
GSP creates an airgapped internet as a software-defined range, then lets real mission systems interact with it through controlled customer ingress. The internet behavior is abstracted from the infrastructure that hosts it.
Presenter cue Start at the bottom with customer-owned infrastructure. Move upward through Kubernetes and the emulated internet, then finish with real operators and mission systems.
The complete documentation set is embedded in this one file and rendered with the same sidebar/search pattern as the GSP UI Docs tab.
WAN Emulator — Profiles & Effects, Explained
GSP · WAN Emulator · engineer & user reference
How the WAN emulator shapes traffic
Every impairment the emulator can apply, and every built-in profile, shown as
live traffic. Watch packets cross a link and get delayed, dropped, corrupted, reordered,
throttled, or buffered — then see the time-varying dynamics you can name in config, how the
built-in profiles combine them, and build your own. Start on Overview; jump to Build your
own when you want to author one.
How to read the animations. Each demo is one link: a sender (TX) on the
left, a receiver (RX) on the right, and the emulator in between. Little squares are packets. The
stack climbing at TX is the emulator's queue; watch it drain packet-by-packet into the sender as
the link serves it. A big bright ✕ marks a drop. Animations are
illustrative, not to scale — exact values are in the grey chips. Dynamic demos draw a
timeline of their schedule with a moving playhead.
This page teaches; the emulator decides. The simulations here are approximations —
in particular, when several dynamics overlap, the real scheduler merges them per field
(strongest departure from base wins), while this page picks one dominant envelope. Before using
any profile YAML for real, check it against the running emulator:
POST /api/v1/profiles/validate.
Profile focus
The deep reference for one profile at a time: what it models, how the schedule
behaves, exactly where you'd reach for it, what you can and can't tune today, how it differs from its
neighbours, the tweaks people actually make, and the modulators worth stacking with it in a custom
profile. Pick a profile — the Overview tab is the at-a-glance catalog; this is the manual.
What's configurable, across every profile. A profile is a static
base (all absolute values) plus an ordered list of dynamics. Base fields:
bandwidth latency jitter loss lossCorr corrupt corruptCorr delayCorr duplicate reorder limit.
Pulse fields (handover/burst/outage) must be deltas (+/-) so overlapping
pulses add; envelope peak_* may be absolute or delta; an envelope takes either a
cycleor phase durations, not both; markov bad: values are absolute.
config.yaml
The emulator is authoritative — validate any edit before use:
POST /api/v1/profiles/validate. A per-link emulation: field overrides a
single parameter at deploy without touching the profile.
Build your own profile
Start from a built-in profile (or from scratch), then tune the static base
and stack on any of the nine dynamics — the link reacts live above. The right column shows the
two ways to ship what you built. Approach A — a named custom profile under the top-level
wanemu_profiles: key: reusable across links and it carries dynamics:.
Approach B — reference the nearest built-in profile and pin individual fields with a per-link
emulation: override under wanemu:: quick for a one-off, but static base fields only.
Approach A always works; approach B appears only when a static pin can faithfully reproduce your build (it is
withheld, with the reason, when it cannot).
base — static impairment
dynamics — time-varying modulators
config.yaml — approach A: a named custom profile
Define it once under the top-level wanemu_profiles: key (a sibling of
wanemu:, not nested inside it), then reference it by name from any impaired link's
profile:. The whole base + dynamics travel with the name, and it is reusable across links.
config.yaml — approach B: a built-in plus per-link overrides
A per-link emulation: block pins static base fields only. It cannot add,
remove, or edit dynamics:, and pinning a field a dynamic drives freezes that field flat. When
your build can't be expressed this way, approach B is withheld and only A is valid. (Verified against the
engine: emulation parses to an EmulationSpec applied as pins, last each tick.)
the emulator is authoritative — validate before use:
POST /api/v1/profiles/validate