Architecture
This document explains the two simulation architectures in FUSION: the Legacy Engine (pre-v6.0) and the Orchestrator (v6.0+). Understanding these architectures is essential for contributing to the core module.
Overview
FUSION evolved from a monolithic design to a modular, pipeline-based architecture. Both architectures are fully supported and share the same underlying algorithms, but differ in how they organize and coordinate components.
+-----------------------------------------------------------------+
| FUSION Core |
+-----------------------------------------------------------------+
| |
| +---------------------------+ +---------------------------+ |
| | LEGACY ENGINE | | ORCHESTRATOR | |
| | (Pre-v6.0) | | (v6.0+) | |
| +---------------------------+ +---------------------------+ |
| | | | | |
| | SimulationEngine | | SimulationEngine | |
| | | | | | | |
| | v | | v | |
| | SDNController | | SDNOrchestrator | |
| | | | | | | |
| | +-> Routing | | +-> RoutingPipeline | |
| | +-> SpectrumAssign | | +-> SpectrumPipeline | |
| | +-> SnrMeasurements | | +-> SNRPipeline | |
| | +-> Grooming | | +-> GroomingPipeline | |
| | | | +-> SlicingPipeline | |
| | | | +-> ProtectionPipeline| |
| +---------------------------+ +---------------------------+ |
| |
| +---------------------------+ +---------------------------+ |
| | SHARED COMPONENTS | | NEW COMPONENTS | |
| +---------------------------+ +---------------------------+ |
| | - SimStats (metrics) | | - Adapters (migration) | |
| | - Request generation | | - PipelineFactory | |
| | - Network topology | | - ControlPolicy interface | |
| | - Properties classes | | - Result objects | |
| +---------------------------+ +---------------------------+ |
| |
+-----------------------------------------------------------------+
Legacy Engine (Pre-v6.0)
The legacy architecture uses direct component orchestration with mutable state.
Key Components
- SimulationEngine
The main entry point that initializes the network, generates requests, and coordinates the simulation loop.
- SDNController
Directly manages request allocation by calling routing, spectrum assignment, SNR validation, and grooming methods in sequence.
- Properties Classes
Mutable objects (
RoutingProps,SpectrumProps,SDNProps, etc.) that carry state between components.
Configuration Flow
INI File
|
v
config_setup.py
|
v
engine_props (dict) <-- Mutable, flat key-value pairs
|
v
SimulationEngine
|
v
SDNController
|
+-> self.engine_props['k_paths']
+-> self.engine_props['network']
+-> ... (direct dict access)
Request Processing Flow
# Simplified legacy flow in SDNController.allocate()
def allocate(self, request_data):
# 1. Initialize request properties
self.sdn_props.source = request_data['source']
self.sdn_props.destination = request_data['destination']
self.sdn_props.bandwidth = request_data['bandwidth']
# 2. Try grooming first (if enabled)
if self.engine_props.get('grooming'):
self.grooming.handle_grooming()
if self.sdn_props.was_groomed:
return # Success via grooming
# 3. Find routes
self.routing.get_route()
if not self.routing.route_props.paths_matrix:
self.sdn_props.block_reason = 'distance'
return # Blocked - no route
# 4. For each candidate path, try spectrum assignment
for path_index, path in enumerate(self.routing.route_props.paths_matrix):
self.spectrum_assignment.get_spectrum(modulation_list)
if self.spectrum_props.is_free:
# 5. Validate SNR (if enabled)
if self.engine_props.get('snr_type'):
self.snr_measurements.check_snr()
if not snr_valid:
continue # Try next path
# 6. Success - allocate and return
self._update_network_state()
return
# All paths exhausted
self.sdn_props.block_reason = 'congestion'
Characteristics
Advantages:
Simple, straightforward control flow
Easy to understand for single-path debugging
All state in one place (SDNController)
Limitations:
Tight coupling between components
Difficult to test individual components in isolation
Hard to add new pipeline stages without modifying controller
Mutable state makes debugging complex scenarios difficult
No clear interface for external policies (RL/ML)
Orchestrator (v6.0+)
The orchestrator architecture uses a pipeline-based design with immutable state.
Key Components
- SDNOrchestrator
A thin coordination layer that routes requests through pipelines. Contains NO algorithm logic - all computation is delegated to pipelines.
- PipelineFactory
Creates and configures pipelines based on
SimulationConfig. Uses lazy imports to avoid circular dependencies.- PipelineSet
A frozen dataclass containing all pipeline instances:
routing(required): Finds candidate pathsspectrum(required): Assigns spectrum slotsgrooming(optional): Uses existing lightpath capacitysnr(optional): Validates signal qualityslicing(optional): Splits large requests
- Adapters
Temporary wrappers that make legacy components compatible with pipeline protocols. See Adapters for details.
- SimulationConfig
An immutable frozen dataclass with typed attributes and computed properties. Replaces the mutable
engine_propsdict.- Result Objects
Immutable frozen dataclasses (
RouteResult,SpectrumResult,AllocationResult, etc.) that capture pipeline outputs. See Data Structures for details.
Configuration Flow
INI File
|
v
config_setup.py
|
v
engine_props (dict)
|
v
SimulationConfig.from_engine_props() <-- Immutable, typed, validated
|
v
PipelineFactory.create_orchestrator()
|
v
SDNOrchestrator
|
+-> config.k_paths # Typed attribute
+-> config.network_name # Computed property
+-> config.total_slots # Computed property
Request Processing Flow
# Simplified orchestrator flow in SDNOrchestrator.handle_arrival()
def handle_arrival(self, request, network_state):
# network_state is passed per-call (stateless design)
# Stage 1: Grooming (if enabled)
if self.grooming and self.config.grooming_enabled:
groom_result = self.grooming.try_groom(request, network_state)
if groom_result.fully_groomed:
return AllocationResult.success_groomed(...)
if groom_result.partially_groomed:
remaining_bw = groom_result.remaining_bandwidth_gbps
forced_path = groom_result.forced_path
# Stage 2: Routing
route_result = self.routing.find_routes(
request.source, request.destination,
remaining_bw, network_state
)
if route_result.is_empty:
return AllocationResult.blocked(BlockReason.NO_PATH)
# Stage 3: Try each path
for path_index in range(route_result.num_paths):
path = route_result.get_path(path_index)
modulations = route_result.get_modulations_for_path(path_index)
# Stage 3a: Spectrum assignment
spectrum_result = self.spectrum.find_spectrum(
path, modulations, remaining_bw, network_state
)
if not spectrum_result.is_free:
continue
# Stage 3b: SNR validation (if enabled)
if self.snr:
snr_result = self.snr.validate_snr(
path, spectrum_result, network_state
)
if not snr_result.passed:
continue
# Success
return AllocationResult.success_new_lightpath(...)
# Stage 4: Try slicing (if enabled)
if self.slicing:
slicing_result = self.slicing.slice_request(...)
if slicing_result.success:
return AllocationResult.success_sliced(...)
return AllocationResult.blocked(BlockReason.CONGESTION)
Characteristics
Advantages:
Modular, testable components
Clear interfaces between stages (pipeline protocols)
Easy to add new pipeline stages without modifying orchestrator
Immutable state simplifies debugging
Clean RL/ML integration via ControlPolicy interface
Stateless design enables better parallelization
Limitations:
More complex initial setup
Adapters add indirection during migration period
Requires understanding of multiple components
How to Choose
Use Legacy (SDNController) When:
Running existing experiments that depend on legacy behavior
Debugging specific v5.x issues
Working with configurations that explicitly set
use_orchestrator = False
Use Orchestrator (SDNOrchestrator) When:
Starting new development or experiments
Implementing survivability features (protection, failure handling)
Integrating RL/ML policies
Adding new pipeline stages
Writing unit tests for specific components
Working with configurations that set
use_orchestrator = True
Switching Between Architectures
The architecture is controlled by the use_orchestrator flag:
Via Configuration File
[general_settings]
use_orchestrator = True ; Use orchestrator path
; OR
use_orchestrator = False ; Use legacy path (default)
Via Environment Variable
export FUSION_USE_ORCHESTRATOR=1 # Use orchestrator
python -m fusion.cli.run_sim ...
Via Code
engine_props = {
'use_orchestrator': True, # or False
# ... other settings
}
engine = SimulationEngine(engine_props)
Resolution Priority
Environment variable
FUSION_USE_ORCHESTRATOR(highest)Configuration parameter
use_orchestratorDefault:
False(legacy path)
Migration Status
The project is in active migration from legacy to orchestrator:
Completed:
Core orchestrator structure
Pipeline protocols and interfaces
All four adapters (routing, spectrum, SNR, grooming)
SimulationConfig dataclass
Result objects
Basic pipeline implementations
In Progress:
Slicing pipeline integration
Protection pipeline for 1+1
Planned (v6.1.0):
Replace adapters with clean implementations
Remove legacy adapter code
Full documentation update
See Adapters for detailed migration status of each component.
Design Principles
The orchestrator follows these design principles:
No Algorithm Logic in Orchestrator
The orchestrator coordinates pipelines but never implements algorithm logic. All computation (K-shortest-path, first-fit, SNR calculation) is delegated to pipelines.
Stateless Per-Call Design
The orchestrator receives
NetworkStateas a parameter for each call and never stores it. This enables better testing and parallelization.Immutable Results
All result objects are frozen dataclasses. Once created, they cannot be modified. This prevents subtle bugs from state mutation.
Pipeline Protocols
Each pipeline implements a protocol (
RoutingPipeline,SpectrumPipeline, etc.) defined infusion.interfaces.pipelines. This enables substitution and testing.Adapter Pattern for Migration
Legacy components are wrapped in adapters to satisfy pipeline protocols. Adapters are temporary and will be replaced with clean implementations.
See Also
Orchestrator Guide - Detailed pipeline flow documentation
Adapters - Adapter pattern and migration status
Simulation Guide - SimulationEngine documentation
Configs Module - Configuration system