Deep Space Network Simulator
Simulate the Next Generation of
Space Networks
High-fidelity, event-driven simulation for LEO megaconstellations, interplanetary networks, and delay-tolerant protocols. Run 50,000+ nodes on a single CPU core, build secure-by-design protocols, and test parameters before you launch.
Published research
"DSNS: The Deep Space Network Simulator"
2025 Security for Space Systems (3S) · IEEE
Install in seconds:
git clone https://github.com/ssloxford/DSNS
cd DSNS
pip install --editable .
Open source under GPLv3 · View on GitHub
Mission-Ready Simulation
Validate protocols, test resilience, and align with standards before you launch.
CCSDS Reference Scenarios
Built-in implementations of the standard DTN reference scenarios for Earth Observation, Lunar Communication, and Mars Communication, enabling protocol testing under known conditions.
Realistic Orbital Mechanics
Model Walker constellations, fixed ground stations, or real satellites via TLE/SGP4 propagation, orbiting realistic planets, with planetary occlusion and elevation constraints.
Security & Resilience Testing
Built-in attack models for global and targeted message loss, link flooding, and bandwidth exhaustion. Test rerouting and protocol robustness under stress.
Massive Scale, Minimal Resources
Simulate over 50,000 nodes on a single CPU core using less than 2.1 GB of RAM. Single-threaded design enables parallel parameter sweeps on one machine.
Delay-Tolerant Networking
BP-style store-and-forward routing and the Licklider Transmission Protocol (LTP) with reliable per-hop segmentation and retransmission. Build protocol logic at the abstraction level you need.
Standards-Aligned Testing
Ready for integration into testing pipelines. Run CCSDS reference scenarios, validate protocol behavior under realistic orbital mechanics, and test resilience before deployment.
Use Case: Pre-Launch Validation
Validate protocols before hardware deployment. Simulate your entire constellation topology with realistic orbital mechanics, test protocol behavior under a range of scenarios and network conditions, and run security resilience tests – all before a single satellite leaves the ground.
Simulation Scenarios
The flexibility and modularity of DSNS makes it easy to build scenarios spanning Earth orbit, deep space, and interplanetary relay networks. Use one of the provided scenarios or build your own.
An interplanetary relay network between Earth and Mars, modeling deep-space delay-tolerant networking and planetary occlusion.
Built for Research
Python-native, modular, designed for rapid prototyping and open collaboration.
Modular Event-Driven Core
The simulation advances via a priority EventQueue. Actors process events via pattern matching, while DataProviders maintain state like routing tables and lookahead windows.
Swap protocols, routing strategies, or mobility models without touching the core engine. Add a new protocol in under 50 lines of Python.
Python-Native API
No domain-specific languages. Extend via standard Python classes with full type hints. The entire simulator is built in Python, so you can build new functionality by subclassing the existing Actor, DataProvider, or Constellation classes.
Jupyter-friendly outputs, Sphinx-generated docs, and seamless integration with a huge ecosystem of existing tools.
Reference Scenarios
Comes with CCSDS reference topologies and custom large-scale setups: Walker constellations, federated CubeSat networks (with live CelesTrak data), and interplanetary relay networks.
Configurable traffic generators: constant rate, uniform, Gaussian, and Pareto distributions. Export logs and aggregate metrics directly.
Seamless Research Workflow
Run dozens of independent simulations concurrently on one machine. The simplicity of the single-threaded design gives flexibility: perfect for parameter sweeps and A/B protocol testing.
Export data in CSV/JSON for downstream analysis.
Extending DSNS
DSNS can be easily extended by building custom modules on top of the core engine. Build the parts you care about, and the rest gets out of the way.
from dsns.events import Event
from typing import Any
class CustomEvent(Event):
data: Any
def __init__(self, time: float, data: Any):
super().__init__(time, ["data"])
self.data = data
from dsns.simulation import Actor
from dsns.events import Event
from dsns.message import MessageCreatedEvent, MessageReceivedEvent
class CustomActor(Actor):
def __init__(self, params):
super().__init__()
# Custom logic
def initialize(self) -> list[Event]:
# Generate initial events
events = [MessageCreatedEvent(...)]
return events
def handle_event(self, mobility, event):
events = []
if isinstance(event, MessageReceivedEvent):
# Custom message handling logic
events.append(MessageCreatedEvent(...))
return events
import numpy as np
from dsns.constellation import Constellation, Satellite, Satellites, ISLHelper, OrbitalCenter
from dsns.helpers import IDHelper
class CustomConstellation(Constellation):
def __init__(self, name: str, id_helper: IDHelper, isl_helper: ISLHelper, orbital_center: OrbitalCenter, num_planes: int, sats_per_plane: int):
self.name = name
self.isl_helper = isl_helper
self.orbital_center = orbital_center
self.num_planes = num_planes
self.sats_per_plane = sats_per_plane
self.num_sats = num_planes * sats_per_plane
# Define initial satellite positions
self.satellites = Satellites([])
for plane in range(num_planes):
for sat in range(sats_per_plane):
sat_name = f"{name}_{plane}_{sat}"
sat_id = id_helper.assign_id(sat_name)
self.satellites.append(Satellite(sat_name, sat_id, self.name, orbital_center=orbital_center))
self.satellite_positions = np.zeros((self.num_sats, 3))
self.update_positions(0.0)
def update_positions(self, time: float):
for plane in range(self.num_planes):
for sat in range(self.sats_per_plane):
sat_index = (plane * self.sats_per_plane) + sat
pos = ...
self.satellites[sat_index].position = pos
self.satellite_positions[sat_index] = pos
from dsns.constellation import Satellites, ISLHelper
from dsns.multiconstellation import ILLHelper
from dsns.helpers import SatID
# Implement a custom Inter-Satellite Link (ISL) helper
# to define connectivity rules between nodes.
class CustomISLHelper(ISLHelper):
def get_isls(self, satellites: Satellites, positions: np.ndarray) -> list[tuple[SatID, SatID]]:
# Custom link logic based on distance,
# elevation, or other constraints
...
# Implement a custom Inter-Layer Link (ILL) helper
# to define connectivity rules between constellations or orbital shells.
class CustomILLHelper(ILLHelper):
def get_ills(self, satellites: Satellites, positions: np.ndarray) -> list[tuple[SatID, SatID]]:
# Custom link logic based on distance,
# elevation, or other constraints
...
from dsns.simulation import RoutingDataProvider
# Build a custom routing strategy by extending
# the base RoutingDataProvider.
class CustomRoutingProvider(RoutingDataProvider):
def _get_next_hop(self, source: SatID, destination: SatID) -> Optional[SatID]:
# Custom next-hop selection logic
...
def get_distance(self, source: SatID, destination: SatID) -> Optional[float]:
# Latency between a given source and destination
...
def get_neighbors(self, source: SatID, max_distance: Optional[float] = None) -> list[SatID]:
# Get the reachable neighbors for a given source, up to a maximum time difference
...
import os, pickle
from dsns.presets import EarthMoonMarsMultiConstellation
from dsns.simulation import Simulation
from dsns.transmission import LinkTransmissionActor, MessageLocationTracker
from dsns.traffic_sim import MultiPointToPointTrafficActor
from dsns.message_actors import MessageRoutingActor, LookaheadRoutingDataProvider
from dsns.logging import PreprocessedLoggingActor, BandwidthLoggingActor, LTPTransmissionLoggingActor
from dsns.message import LossConfig
constellation = EarthMoonMarsMultiConstellation(moon=True, mars=False, moon_mars_link=False)
tracker = MessageLocationTracker()
routing_data_provider = LookaheadRoutingDataProvider(resolution=15.0, num_steps=600)
actors = [
LinkTransmissionActor(default_bandwidth=100e6/8, buffer_if_link_busy=True, reroute_on_link_down=True, message_location_tracker=tracker),
MultiPointToPointTrafficActor([("EarthToMoon", 0, 345, 1e6, 15.0)], update_interval=300, reliable_messages=False, cutoff=28800),
]
actors.append(MessageRoutingActor(routing_data_provider, store_and_forward=True, model_bandwidth=True, loss_config=LossConfig()))
logging_actor_pre = PreprocessedLoggingActor(log_other=False)
logging_actor_bw = BandwidthLoggingActor()
logging_actor_ltp = LTPTransmissionLoggingActor()
sim = Simulation(constellation, actors=actors, logging_actors=[logging_actor_pre, logging_actor_bw, logging_actor_ltp], data_providers=[routing_data_provider], timestep=15.0)
sim.initialize(0)
sim.run(43200, progress=True)
os.makedirs("results", exist_ok=True)
with open("results/pre.pickle", "wb") as f: pickle.dump((pre.direct_messages, pre.broadcast_messages, pre.other_events), f)
with open("results/bw.pickle", "wb") as f: pickle.dump(bw.aggregate(1.0, default_bandwidth=100e6/8), f)
with open("results/ltp.pickle", "wb") as f: pickle.dump(ltp.aggregate(1.0), f)
Architecture
A modular, event-driven design with sub-millisecond precision and support for varying levels of abstraction, from high-level protocol logic down to bit-level fidelity.
Event-Driven Engine
Manages simulation time via a priority EventQueue. Every state change is a timestamped Event: the loop pops the next event, sends it to all actors, and enqueues any new events they generate. An optional minimum timestep batches mobility and connectivity updates. This architecture means the simulation can fast-forward through idle periods and long interplanetary gaps while preserving sub-millisecond precision when needed.
Actors
The Actor base class implements all logic via pattern-matching on events. Actors never call each other directly; they communicate solely through the event queue. This decoupling makes it trivial to swap or add protocols (e.g. MessageRoutingActor, LinkTransmissionActor, LTPActor) without any modifications to the core engine.
DataProviders
These maintain global, queryable state outside the event stream, such as routing tables and connectivity graphs. For example, the RoutingDataProvider computes next-hop routes for message delivery systems. The LookaheadRoutingDataProvider enables store-and-forward delivery by analyzing future network states over a configurable window.
Mobility & Connectivity
The MultiConstellation aggregates multiple Constellations (Walker, TLE, etc.), each with its own OrbitalCenter (Earth, Mars, etc.). ISLHelpers define links within constellations; ILLHelpers define links between constellations based on elevation, distance, and planetary occlusion. Once defined, these can be plugged into each other – the simulator handles the rest.
Message Delivery & Routing
The MessageRoutingActor provides message delivery by forwarding messages at each hop, querying a RoutingDataProvider. The LinkTransmissionActor models physical-layer constraints: bandwidth limits, queueing, and speed-of-light propagation delays. The simulator supports both best-effort (IP-style) and store-and-forward (DTN-style) delivery, swappable via a single flag.
Protocol Extensibility
The LTPActor demonstrates adding the Licklider Transmission Protocol as a full protocol layer: segmenting messages into red/green blocks, checkpointing, and retransmission with configurable timeouts. Attack simulation is supported out of the box via LossConfig (global or per-link message loss) and TrafficFloodActor (bandwidth exhaustion). Any protocol can be added by subclassing Actor or DataProvider.
Performance & Benchmarks
DSNS is resource-efficient, feature-rich, and scalable to thousands of nodes.
Scalability: Nodes vs Execution Time
Execution time (seconds) to run a 6,000-second simulation, for networks of varying sizes.
Scalability: Memory Usage
RAM usage scales linearly with network size.
Comparison with Existing Tools
| Tool | Orbital Simulation |
Interplanetary | Dynamic Links |
Dynamic Timesteps |
Extensible | Scalable | Abstracted Stack |
|---|---|---|---|---|---|---|---|
| DSNS | ● | ● | ● | ● | ● | ● | ● |
| ONE Simulator | ○ | ○ | ● | ● | ● | ◐ | ● |
| NOS3 | ○ | ○ | ◐ | ○ | ◐ | ○ | ○ |
| SpaceSecLab/NSE2 | ◐ | ◐ | ◐ | ● | ● | ◐ | ○ |
| Hypatia | ● | ○ | ○ | ● | ● | ◐ | ◐ |
| Celestial | ● | ○ | ● | ○ | ◐ | ◐ | ○ |
| StarryNet | ● | ○ | ● | ○ | ◐ | ◐ | ◐ |
| xeoverse | ● | ○ | ◐ | ○ | ◐ | ◐ | ○ |
| Stardust | ● | ○ | ● | ○ | ● | ● | ◐ |
| SatScope | ● | ○ | ● | ○ | ◐ | ◐ | ○ |
● = Full support ◐ = Partial support ○ = No support
Faster than Real-Time
Simulation speed is affected only by the number of events, enabling it to significantly outpace real time (even at 50,000+ nodes), and slow down to sub-millisecond precision when needed.
Single-Core Scalability
No multithreading overhead enables trivial horizontal scaling: run large numbers of simulations at once to cover all parameter combinations.
Abstracted Stack
No virtualization overhead: only simulate the layers you need to test. Supports highly abstracted protocols alongside bit-level implementations if required.
Cite DSNS
If you use DSNS in your research, please cite the following paper.
@inproceedings{smailesDSNS2025,
author = {Smailes, Joshua and Futera, Filip and K{\"o}hler, Sebastian and Birnbach, Simon and Strohmeier, Martin and Martinovic, Ivan},
title = {{DSNS}: {The Deep Space Network Simulator}},
booktitle = {2025 Security for Space Systems (3S)},
year = {2025},
organization = {IEEE}
}
Projects Using DSNS
KeySpace
KeySpace: Enhancing Public Key Infrastructure for Interplanetary Networks (2025)
Joshua Smailes, Filip Futera, Sebastian Köhler, Simon Birnbach, Martin Strohmeier, Ivan Martinovic
Secure Rerouting
Secure and Scalable Rerouting in LEO Satellite Networks (2025)
Lyubomir Yanev, Pietro Ronchetti, Joshua Smailes, Martin Strohmeier