Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

81 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

GARRO: Graph Attention Routing with Reinforcement Learning

GitHub Repository: github.com/DanielAgbeni/GARRO

GARRO is a Deep Reinforcement Learning (DRL) routing framework designed for Software-Defined Networks (SDN). It combines a Graph Attention Transformer (GAT) to capture complex network topologies and traffic states with Proximal Policy Optimization (PPO) to dynamically route traffic requests.

This repository implements both Phase 1: Offline Digital Twin Training and Phase 2: Live Mininet Emulation using OS-Ken (a modern, Neutron-optimized fork of the Ryu SDN controller).


πŸ—οΈ Project Architecture

The project is structured into three clear planes: the AI Decision Plane, the Control Plane, and the Data/Simulation Plane.

                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                  β”‚       Agentic AI Layer       β”‚
                  β”‚   - LLM Orchestrator         β”‚ (Refreshes rewards from intent)
                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                  β”‚ 
                                  β–Ό (Weight updates)
                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                  β”‚       AI Decision Plane      β”‚
                  β”‚   - PPO + Graph Transformer  β”‚ (model/)
                  β”‚   - Offline Train Loop       β”‚ (train_offline.py)
                  β”‚   - Online Deploy Loop       β”‚ (deploy_online.py)
                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                     β–²                       β”‚
       HTTP GET      β”‚                       β”‚ HTTP POST
       /garro/state  β”‚                       β”‚ /garro/flow
                     β”‚                       β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    SDN Control Plane                         β”‚
β”‚                    - OS-Ken OpenFlow 1.3 App                 β”‚ (controller/garro_controller.py)
β”‚                    - Flask REST API Integration              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                  β–²
                                  β”‚ OpenFlow 1.3 (Southbound)
                                  β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚             SDN Data Plane (Phase 2 Emulation)               β”‚
β”‚             - Mininet Network Emulation                      β”‚ (topologies/mininet_*.py)
β”‚             - Open vSwitch (OVS) Kernel Datapath             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Module Descriptions

  1. State Encoder (model/graph_transformer.py):

    • Converts the NetworkX topology graph (carrying node CPU/buffer load and edge capacity/delay/utilization metrics) into a PyTorch Geometric (PyG) Data object.
    • Appends a virtual star node connected to all nodes to aggregate global graph context.
    • Runs a 3-layer TransformerConv network to output a 128-dimensional latent state representation.
  2. PPO Actor-Critic Agent (model/ppo_agent.py):

    • Actor: Predicts routing action probability distributions over candidate $K$-shortest paths.
    • Critic: Estimates the state value function to compute Generalized Advantage Estimations (GAE).
    • Optimized for CPU: Pre-computes detached graph representations once per epoch, running the Actor-Critic networks efficiently on mini-batches. It does a single encoder gradient update per epoch to prevent redundant backpropagation and avoid slow CPU runs.
  3. Digital Twin Environment (digital_twin/mm1k_env.py):

    • Implements a standard Gymnasium environment interface.
    • Models links as analytical M/M/1/K finite-capacity queues where queue length, packet loss, and latency are calculated deterministically.
    • Dynamically tracks ingress/egress rates, buffer occupancies, and links bandwidth.
  4. Traffic Generator (digital_twin/traffic_generator.py):

    • Generates traffic matrix requests using Poisson arrivals.
    • Generates microbursts (temporary elephant flows at 5Γ— base rate with a 10% probability) to stress-test routing resilience.
  5. OS-Ken Controller Application (controller/garro_controller.py):

    • Standard OS-Ken OpenFlow 1.3 controller application.
    • Listens to switch connection and link discovery events (via LLDP) to construct and maintain a live NetworkX DiGraph topology.
    • Periodically polls connected switches for port statistics to compute network utilization.
    • Integrates an internal Flask web server running on an eventlet green thread to serve a Northbound REST API (GET /garro/state, GET /garro/topology, POST /garro/flow).
    • Receives path updates from the AI plane and pushes OpenFlow 1.3 Flow Mod entries along the network switches.
  6. Mininet Network Topology (topologies/mininet_nsfnet.py):

    • Instantiates a live emulated NSFNET topology with 14 switches and 21 links.
    • Attaches one host per switch with configured subnet IPs (10.0.0.1–10.0.0.14) to allow testing.
    • Configures propagation delays matching the real physical topology nodes using Mininet TCLinks.

βš™οΈ Environment Setup

GARRO is configured to run inside a Python virtual environment (garro_env).

Activate the Environment

Before running training, evaluation, or deployment scripts, activate the virtual environment:

source garro_env/bin/activate

Dependencies

Dependencies are listed in requirements.txt and are pre-installed in the virtual environment. Key requirements include:

  • torch (PyTorch 2.3.1+cpu)
  • torch_geometric (PyG)
  • torch_scatter & torch_sparse (configured with matching CPU binaries)
  • networkx (for topology graph representations)
  • gymnasium (RL environment framework)
  • matplotlib & pandas (for visualization and analysis)
  • Flask (for controller REST API integration)

🍏 Apple Silicon (M1/M2/M3/M4 macOS) Support

GARRO fully supports native training on Apple Silicon chips (M-series) using Apple's GPU acceleration via Metal Performance Shaders (MPS).

1. Running Phase 1 (Offline Training) on macOS

To run training locally on your Mac with GPU/MPS acceleration:

  1. Ensure you have installed a native macOS python virtual environment.
  2. Install PyTorch with MPS support:
    pip install torch
  3. Install PyTorch Geometric (PyG) dependencies compatible with your PyTorch macOS version:
    pip install torch-scatter torch-sparse -f https://data.pyg.org/whl/torch-$(python -c "import torch; print(torch.__version__)").html
    pip install torch-geometric
  4. Run the training script normally. The agent will auto-detect your M-series chip and display: Device : mps (Apple Metal Performance Shaders) in the startup hardware banner:
    python train_offline.py --topology nsfnet --episodes 10000

2. Running Phase 2 (Live Mininet Emulation) on macOS

Important

Mininet is Linux-only and cannot run natively on macOS. To emulate the network topology on an Apple Silicon Mac, you must run it inside a Linux Virtual Machine (VM). We recommend:

  • UTM (Free/Open Source) or Parallels Desktop: Set up an ARM64 Ubuntu Linux VM.
  • Run both the OS-Ken Controller and Mininet inside that ARM64 Linux VM.

πŸš€ Phase 1: Offline Digital Twin Training

Train the agent offline in the Digital Twin environment by running train_offline.py.

python train_offline.py --topology <topology_name> --episodes <num_episodes>

🌐 Multi-Topology Validation Strategy

To present an academically rigorous and reliable project, it is highly recommended to train and evaluate your agent across all three topologies. This proves that the GARRO routing agent can adapt to different types of network layouts (WAN vs. Data Center) and scales (14 to 80 nodes) without overfitting to a single network structure:

  1. Topology Diversity: Shows the model's ability to handle geographic WAN nodes with high propagation delays (NSFNET, GEANT2) as well as dense, symmetric, low-latency datacenter clusters (Fat-Tree).
  2. Scale & Convergence Proof: Confirms that the Graph Attention Network (GAT) generalizes well when the network size grows from small (14 switches) to very large (80 switches).
  3. Load Balancing Resilience: Proves the routing agent can handle highly irregular network links (GEANT2) just as well as standard hierarchical ones.

πŸ“Š Recommended Training Configurations

Depending on your goal (quick testing vs. reliable publication-grade results), use the following recommended parameters:

Topology Scale Checkpoint ID Sanity Check (Episodes) Full Convergence (Recommended) Approx. CPU Time Key Learning Focus
NSFNET 14 Nodes, 21 Links nsfnet 1,000 5,000 - 10,000 ~15-25 min (GPU) Basic routing loops, WAN propagation latency awareness.
GEANT2 24 Nodes, 37 Links geant2 5,000 15,000 - 20,000 ~30-45 min (GPU) Load balancing under asymmetric constraints & irregular cross-links.
Fat-Tree (k=4) 20 Switches, 32 Links fat_tree 5,000 20,000 - 50,000 ~1-2 hours (GPU) Hierarchical paths, equal-cost multi-path (ECMP) traffic spreading in DCNs.

πŸ› οΈ Execution Commands

1. NSFNET Training

  • Sanity Check:
    python train_offline.py --topology nsfnet --episodes 1000
  • Full Reliable Training:
    python train_offline.py --topology nsfnet --episodes 10000

2. GEANT2 Training

  • Sanity Check:
    python train_offline.py --topology geant2 --episodes 5000
  • Full Reliable Training:
    python train_offline.py --topology geant2 --episodes 20000

3. Fat-Tree (k=4) Training

  • Sanity Check:
    python train_offline.py --topology fat_tree --episodes 5000
  • Full Reliable Training:
    python train_offline.py --topology fat_tree --episodes 20000

☁️ Running on Google Colab (Recommended for GPU Acceleration)

If you do not have a local GPU, you can train the offline model (Phase 1) on Google Colab to speed up the process using a free NVIDIA T4 GPU.

πŸš€ GPU & System Resource Utilization Highlights

The codebase is designed to automatically optimize hardware resources in a Google Colab notebook environment:

  • Automatic GPU Detection (CUDA): The agent (model/ppo_agent.py) auto-detects Colab's allocated NVIDIA GPU. Neural network forward/backward passes are fully accelerated on the GPU device.
  • Automatic Mixed Precision (AMP): Under CUDA, PyTorch's torch.autocast is enabled dynamically. The agent queries hardware support: it utilizes float16 on standard T4 GPU runtimes and automatically upgrades to bfloat16 (Tensor Cores) if running on premium L4/A100 runtimes. This halves VRAM requirements and maximizes matrix multiplication throughput.
  • Non-Blocking Hβ†’D Transfers: A custom FastGraphConverter pins CPU memory buffers and streams converted Graph state tensors asynchronously (non_blocking=True) to the GPU, overlapping NetworkX-to-PyG conversion with model execution.
  • JIT Compilation (torch.compile): The Graph Attention Transformer and Actor-Critic models are JIT-compiled using PyTorch 2.x's mode="reduce-overhead" to optimize the GPU execution graph and fuse kernel operations, boosting overall iteration speeds.
  • CPU-Thread Pinning: While neural network weights reside on the GPU, the analytical finite queue simulation (digital_twin/mm1k_env.py) and Poisson-gravity traffic generator (digital_twin/traffic_generator.py) run on the CPU. The training initialization pins PyTorch interop/intra-op threads to use all virtual cores allocated by Colab.

1. Setup your Colab Notebook

  1. Go to Google Colab.
  2. Change the Runtime Type to use a GPU:
    • Click Runtime > Change runtime type > Select T4 GPU (or L4/A100 if available) > Click Save.
  3. Verify the GPU assignment by running this in a cell:
    !nvidia-smi

2. Mount Google Drive (To save checkpoints)

Add this to a notebook cell to mount your Drive so checkpoints aren't lost when your session ends:

from google.colab import drive
drive.mount('/content/drive')

3. Clone the Project & Setup Files

Clone your project repository or upload your files to Google Drive, then navigate into the directory:

# Example if using git:
!git clone https://github.com/DanielAgbeni/GARRO schproject
%cd schproject

4. Install Dependencies

Colab has PyTorch preinstalled, but you must install PyTorch Geometric (PyG) and its dependencies compiled for Colab's specific PyTorch + CUDA version:

import torch
# Automatically detect installed PyTorch and CUDA versions to pull the correct PyG binary wheels
pyg_url = f"https://data.pyg.org/whl/torch-{torch.__version__}.html"
print(f"Installing PyG wheels from: {pyg_url}")

!pip install torch-scatter torch-sparse -f {pyg_url}
!pip install torch-geometric
!pip install gymnasium networkx pyyaml tqdm pandas matplotlib Flask

Verify that PyTorch successfully binds to the GPU device by executing:

import torch
print("GPU Available:", torch.cuda.is_available())
print("Active Device:", torch.cuda.get_device_name(0) if torch.cuda.is_available() else "CPU")

5. Redirect Checkpoints to Google Drive (To prevent data loss)

To avoid manual copying and guarantee you don't lose checkpoints if Colab crashes or disconnects, symlink the project's checkpoint folder directly to your Google Drive:

# Create checkpoints folder in Drive
!mkdir -p "/content/drive/MyDrive/garro_checkpoints"

# Delete default local directory (if any) and symlink to Google Drive
!rm -rf /content/schproject/checkpoints
!ln -s "/content/drive/MyDrive/garro_checkpoints" /content/schproject/checkpoints

6. Run or Resume Training

Run the training script using GPU acceleration. Checkpoints will automatically write directly to your Google Drive via the symlink.

  • Start Training from scratch:

    !python train_offline.py --topology nsfnet --episodes 10000
  • Resume Training after a disconnect: If Colab times out or you stop the cell, mount your Drive, recreate the symlink (Steps 2 & 5), look in your Drive folder for the latest saved epoch (e.g. garro_nsfnet_ep3000.pt), and run:

    !python train_offline.py --topology nsfnet --episodes 10000 --resume checkpoints/garro_nsfnet_ep3000.pt

Note

What happens during Resume? The agent automatically parses the starting episode index from the filename (e.g., ep3000 -> resumes from episode 3000). It loads the model weights along with the optimizer and gradient scaler states, allowing training to continue seamlessly with correct learning momentum.

Warning

Phase 2 (Live Mininet Emulation) is NOT supported on Google Colab. Mininet relies on loading custom Linux kernel modules (Open vSwitch) and low-level network namespace sandboxes, which are not allowed inside the lightweight Docker containers used by Google Colab. Emulation must always be run on your local Linux machine or WSL2 setup.


🟠 Running on Kaggle (Free T4 GPU β€” No Account Upgrade Required)

Kaggle provides a free NVIDIA Tesla T4 GPU (16 GB VRAM) with 29 GB RAM and up to 12 hours per session β€” a strong alternative to Google Colab for longer runs (GEANT2 / Fat-Tree). No credit card is required.

Important

Kaggle sessions auto-shutdown after 12 hours. For Fat-Tree (50 000 ep) you must save a checkpoint and resume in a new session using --checkpoint. Always download your .pt file before the session ends β€” use the Output tab in the Kaggle sidebar.

GPU & System Resource Utilization Highlights

The codebase auto-detects Kaggle's T4 and applies CUDA-optimised overrides:

  • CUDA Auto-scaling: batch_size β†’ 256 (or 512 on T4 Γ—2), update_interval β†’ 1024 (or 2048 on T4 Γ—2).
  • AMP float16: Auto-detected for T4 GPU architecture.
  • Non-blocking Hβ†’D Transfers: Graph state tensors stream asynchronously to the GPU, overlapping CPU simulation with GPU inference.
  • torch.compile enabled by default: Optimized via capture_scalar_outputs=True for maximum GPU execution speed without graph break stalls.

Approximate Speed Benchmarks (T4 / T4 Γ—2)

Topology Nodes ep/s (T4 Γ—2) 10,000 ep ETA
NSFNET 14 10–14 ~12–15 min
GEANT2 24 5–8 ~22–30 min
Fat-Tree (k=4) 20 3–6 ~30–45 min

Step 1 β€” Create a Kaggle Notebook with GPU

  1. Go to kaggle.com and sign in (free account).
  2. Click + New Notebook.
  3. In the right sidebar:
    • Accelerator β†’ GPU T4 Γ—2 ← select the dual-GPU option for maximum throughput
    • Internet β†’ On
    • Persistence β†’ Files only (keeps /kaggle/working/ between sessions)
  4. Click Save to start the session.

Step 2 β€” Clone the Repository

# Cell 1
!git clone https://github.com/DanielAgbeni/GARRO.git /kaggle/working/schproject
%cd /kaggle/working/schproject
!ls -la

If the repo is private, use a Personal Access Token:

!git clone https://YOUR_TOKEN@github.com/DanielAgbeni/GARRO.git /kaggle/working/schproject

Step 3 β€” Install Dependencies

Kaggle already ships PyTorch + CUDA. Only install the missing packages:

# Cell 2 β€” Install project packages and matching PyG CUDA wheels
!pip install -q \
    torch-geometric==2.5.3 \
    gymnasium==1.2.2 \
    networkx==3.6.1 \
    numpy==2.4.4 \
    matplotlib==3.11.0 \
    pyyaml==6.0.3 \
    tqdm==4.68.3 \
    psutil==7.2.2

import torch
TORCH = torch.__version__.split("+")[0]          # e.g. "2.3.1"
CUDA  = "cu" + torch.version.cuda.replace(".", "")  # e.g. "cu121"
print(f"PyTorch: {TORCH} | CUDA tag: {CUDA}")

!pip install -q \
    torch-scatter -f https://data.pyg.org/whl/torch-{TORCH}+{CUDA}.html \
    torch-sparse  -f https://data.pyg.org/whl/torch-{TORCH}+{CUDA}.html

Step 4 β€” Verify the GPU

# Cell 3 β€” Sanity check (dual GPU)
import torch, os, sys

print("CUDA available :", torch.cuda.is_available())
print("GPU count      :", torch.cuda.device_count())
for i in range(torch.cuda.device_count()):
    props = torch.cuda.get_device_properties(i)
    print(f"  GPU {i}       : {props.name}  ({props.total_memory/1e9:.1f} GB VRAM)")

sys.path.insert(0, "/kaggle/working/schproject")
print("Python path    : OK")

Expected output (T4 Γ—2):

CUDA available : True
GPU count      : 2
  GPU 0        : Tesla T4  (15.8 GB VRAM)
  GPU 1        : Tesla T4  (15.8 GB VRAM)

Step 5 β€” Patch config.yaml for T4 Γ—2

# Cell 4 β€” Configure for T4 Γ—2 (compile ON, penalties set per topology)
import yaml, torch

CONFIG_PATH = "/kaggle/working/schproject/config.yaml"
with open(CONFIG_PATH) as f:
    cfg = yaml.safe_load(f)

# torch.compile mode="default" + dynamic=True is stable on T4 + PyTorch 2.x
# and gives 10–20% encoder speedup. "reduce-overhead" caused stalls; this does not.
cfg["training"]["compile_model"] = True

# amp_dtype is auto-detected as float16 for T4 β€” no manual override needed.
# (ppo_agent._autocast_dtype() detects bfloat16 support and falls back to float16)

# Set topology penalty weights (change before each topology run):
cfg["reward_weights"]["hop_weight"]        = 0.02   # NSFNET / GEANT2
cfg["reward_weights"]["congestion_weight"] = 1.0    # NSFNET / GEANT2
# Fat-Tree: set 0.05 and 2.0 instead

with open(CONFIG_PATH, "w") as f:
    yaml.dump(cfg, f, default_flow_style=False)

print(f"config.yaml patched β€” compile_model=True, amp_dtype=auto (float16 on T4)")
print(f"GPUs visible to PyTorch: {torch.cuda.device_count()}")

Step 6 β€” Run Training

Important

With GPU T4 Γ—2 the training script automatically:

  • Detects both GPUs and wraps encoder + AC-net with nn.DataParallel
  • Doubles batch_size β†’ 512 and update_interval β†’ 4096
  • Applies the linear LR scaling rule (lr_actor β†’ 2Γ—, lr_critic β†’ 2Γ—)
  • Prints [MultiGPU] 2Γ— T4 detected in the banner

No extra flags needed β€” --no-compile is no longer used.

Approximate Speed on T4 Γ—2

Topology ep/s (single T4) ep/s (T4 Γ—2) 10,000 ep ETA (Γ—2)
NSFNET 7–10 10–14 ~12–15 min
GEANT2 3–5 5–8 ~22–30 min
Fat-Tree (k=4) 2–4 3–6 ~30–45 min

NSFNET (~12–15 min for 10 000 episodes on T4 Γ—2):

!cd /kaggle/working/schproject && \
    python train_offline.py --topology nsfnet --episodes 10000

GEANT2 (~30 min for 20 000 episodes):

!cd /kaggle/working/schproject && \
    python train_offline.py --topology geant2 --episodes 20000

Fat-Tree (k=4) (~1–1.5 hours for 20 000 episodes):

!cd /kaggle/working/schproject && \
    python train_offline.py --topology fat_tree --episodes 20000

Tip

Topology-aware penalty weights β€” update config.yaml β†’ reward_weights before training each topology to avoid reward scaling bias:

# Wide-area (NSFNET / GEANT2)
cfg["reward_weights"]["hop_weight"]        = 0.02
cfg["reward_weights"]["congestion_weight"] = 1.0

# Data-centre (Fat-Tree)
cfg["reward_weights"]["hop_weight"]        = 0.05
cfg["reward_weights"]["congestion_weight"] = 2.0

Step 7 β€” Download Checkpoints Before Session Ends

# Cell 6 β€” List all outputs
import os, glob

for f in sorted(glob.glob("/kaggle/working/schproject/checkpoints/*")):
    size = os.path.getsize(f) / 1e6
    print(f"{os.path.basename(f):50s}  {size:.1f} MB")

Then click Output in the Kaggle sidebar β†’ download garro_<topology>_final.pt and training_curve_<topology>.png.

Caution

The session disk is wiped on shutdown if Persistence is off. Always download your checkpoint, or copy it to a Kaggle Dataset for permanent cloud storage.

Step 8 β€” Resume Training in a New Session (Multi-Session Fat-Tree)

Upload your saved .pt file as a Kaggle Dataset or re-upload it to the notebook input, then:

# Cell 7 β€” Resume Fat-Tree from episode 10 000
CHECKPOINT = "/kaggle/working/schproject/checkpoints/garro_fat_tree_ep10000.pt"

!cd /kaggle/working/schproject && \
    python train_offline.py \
        --topology fat_tree \
        --episodes 20000 \
        --checkpoint {CHECKPOINT}

The script parses the episode index from the filename and resumes the progress bar automatically.

Step 9 β€” Evaluate the Trained Model

# Cell 8 β€” Evaluate GARRO vs OSPF / ECMP / Random
CHECKPOINT = "/kaggle/working/schproject/checkpoints/garro_nsfnet_final.pt"

!cd /kaggle/working/schproject && \
    python evaluate.py \
        --checkpoint {CHECKPOINT} \
        --topology nsfnet \
        --episodes 500 \
        --output-dir evaluation_outputs

Results are saved under evaluation_outputs/<run_id>/ as a .csv metrics table and a .png comparison bar chart.

Warning

Phase 2 (Live Mininet Emulation) is NOT supported on Kaggle. Mininet requires loading custom Linux kernel modules (Open vSwitch) and network namespaces that are blocked in Kaggle's container environment. Phase 2 must be run on a local Linux machine or WSL2 setup.


Training Outputs

  • Checkpoints: Periodic model weights are saved to checkpoints/garro_<topology>_ep<N>.pt.
  • Final Model: The converged weights are saved to checkpoints/garro_<topology>_final.pt.
  • Training Curve: A plot of episodic rewards over time is saved to checkpoints/training_curve_<topology>.png.

Understanding Training Metrics

During updates, the script outputs the following diagnostic metrics:

  • PL (Policy Loss): The surrogate objective of PPO. A stable negative or slightly fluctuating value indicates policy improvement.
  • VL (Value Loss): Mean-squared error of the critic. Should trend downwards as the critic learns to accurately estimate state values.
  • Ent (Entropy): Policy diversity. Starts high (~1.6 for $K=5$ paths) as the agent explores randomly, and should steadily decrease (to ~0.3–0.6) as the agent becomes confident in its routing decisions.
  • KL (KL Divergence): Difference between the old and updated policy. PPO clips this; values should stay very low ($&lt;0.02$) to guarantee stable learning.

How to Run Benchmarking & Evaluation

To evaluate the performance of your trained agent against traditional SDN routing baselines in the Digital Twin, run evaluate.py.

python evaluate.py --checkpoint <path_to_checkpoint> --topology <topology_name> --episodes <num_episodes>
  • Example:
    python evaluate.py \
      --checkpoint checkpoints/garro_nsfnet_final.pt \
      --topology nsfnet \
      --episodes 500
  • Compared Baselines:
    • OSPF (Open Shortest Path First): A static shortest-path heuristic choosing the path with the minimum delay (Dijkstra).
    • ECMP (Equal-Cost Multi-Path): Distributes traffic round-robin across the candidate paths without network utilization awareness.
    • Random: Randomly selects path options (defines the lower performance bound).
  • Outputs: Each evaluation creates its own folder under evaluation_outputs/, named with the evaluated checkpoint/model name, topology, episode count, and timestamp. The results are saved as eval_results_<model>_<topology>_ep<episodes>.csv and eval_results_<model>_<topology>_ep<episodes>.png inside that folder.

🌐 Phase 2: Live Mininet Emulation

Phase 2 runs the DRL agent in a closed loop, routing real traffic demands in an emulated SDN network.

Prerequisites (System-Wide)

Running Mininet and Open vSwitch (OVS) requires root permissions (sudo) and system-wide packages. They cannot be run inside the Python virtual environment.

  • On Ubuntu/Debian:
    sudo apt-get update
    sudo apt-get install mininet openvswitch-switch
  • If using WSL2, you must ensure the OVS kernel module or service is started before running:
    sudo service openvswitch-switch start

Step-by-Step Emulation Execution

You will need three separate terminal sessions to execute the loop.

1. Terminal A: Start the OS-Ken Controller

Activate the environment and start the OpenFlow controller app. You can use either of the following commands (Option 2 is recommended if the standard command does not work):

Option 1: Standard Command

source garro_env/bin/activate
osken-manager controller/garro_controller.py --observe-links

Option 2: Explicit Python3 Script Command

source garro_env/bin/activate
python3 /usr/bin/osken-manager controller/garro_controller.py --observe-links

2. Terminal B: Launch the Mininet Topology (Requires Sudo)

Launch the emulated data plane using system Python.

sudo python topologies/mininet_nsfnet.py

(This starts the Mininet prompt mininet> once topology initialization is complete).

3. Terminal C: Launch the DRL Online Agent Loop

Activate the environment and run the deployment loop script pointing to your trained checkpoint file.

source garro_env/bin/activate
python deploy_online.py --checkpoint checkpoints/garro_nsfnet_final.pt --topology nsfnet

(The agent will start polling the REST API on port 8080 every 2 seconds, selecting paths, and installing them onto the switches).


πŸ§ͺ Verifying Live Traffic Routing in Mininet

Once all three terminal sessions are running, use the Mininet CLI (Terminal B) to generate traffic and verify routing behavior:

1. Test Network Connectivity

Verify that all hosts can reach one another:

mininet> pingall

2. Verify Flow Rules Installation

Ping from host h1 to host h14 to trigger PPO-driven routing:

mininet> h1 ping h14 -c 10

While the ping is running, inspect Terminal C and Terminal A. You will see:

  • Terminal C log: [Deploy] Flow installed: [1, 4, 5, 12, 14] | 10.0.0.1β†’10.0.0.14
  • Terminal A log: [GARRO] Installed path: [1, 4, 5, 12, 14] for 10.0.0.1 β†’ 10.0.0.14

3. Dump Switch Flows

To inspect the exact OpenFlow rules installed on any switch (e.g. switch s1), run this command in a normal bash shell:

sudo ovs-ofctl -O OpenFlow13 dump-flows s1

You will see routing flow rules matching IP source 10.0.0.1 and destination 10.0.0.14 routing packets to the corresponding output ports chosen by the PPO agent.

4. Benchmarking Throughput

To run a bandwidth throughput test using iperf:

mininet> h1 iperf -s &
mininet> h14 iperf -c 10.0.0.1 -t 30

This generates traffic between h1 and h14 for 30 seconds, forcing the agent to continuously monitor utilization changes and dynamically adjust paths to avoid link congestion.


πŸ”§ Troubleshooting Guide

Issue Cause Fix
AttributeError: module 'os_ken.base.app_manager' has no attribute 'RyuApp' legacy Ryu class name conflict Ensure controller uses app_manager.OSKenApp instead of RyuApp (fixed in repository).
ModuleNotFoundError: No module named 'os_ken.app.wsgi' WSGI module missing/renamed in OS-Ken Expose APIs using Flask on a background eventlet thread (fixed in repository).
OVS is not running error in Mininet Open vSwitch service inactive Run sudo service openvswitch-switch start before launching Mininet.
Mininet cannot connect to controller Controller not running or ports bound Ensure OS-Ken is running in Terminal A first. Check for bound ports: ss -tlnp | grep -E "6633|8080".
LLM weight updates fail .env file does not contain keys The agentic layer defaults to standard fallback weights (alpha1..alpha4) if GEMINI_API_KEY is not present, avoiding application crash.

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages