Skip to content

Lab Setup Guide — Running the Complete System

Overview

The lab orchestrates all three layers (foundation, controller, fabric) in a Docker Compose environment. This guide walks you through starting, testing, and debugging the lab.

Quick Start

cd lab
docker-compose up -d
docker-compose ps

Check that all services are healthy:

docker-compose logs --follow

Wait for messages like:

sdn-controller | INFO Server listening on :8080
fabric-node-1 | INFO BGP peer established with fabric-node-2

Service Architecture

graph TB
    subgraph "Docker Compose Network (sdn-net)"
        subgraph "Control Plane"
            CTRL["sdn-controller<br/>Go · gRPC :50051<br/>REST :8080<br/>Topology Discovery<br/>Intent Handling"]
        end

        subgraph "Foundation Layer (Packet Processing)"
            DPDK["dpdk-agent<br/>C · DPDK<br/>User-space forwarding<br/>gRPC client"]
            EBPF["ebpf-agent<br/>Rust · eBPF<br/>Kernel XDP<br/>gRPC client"]
        end

        subgraph "Fabric Layer (Routing Protocols)"
            F1["fabric-node-1<br/>Python · BGP/VXLAN/EVPN<br/>gRPC client"]
            F2["fabric-node-2<br/>Python · BGP/VXLAN/EVPN<br/>gRPC client"]
            F3["fabric-node-3<br/>Python · BGP/VXLAN/EVPN<br/>gRPC client"]
        end

        TG["traffic-gen<br/>iperf3 server/client<br/>Synthetic load generation"]

        subgraph "Peering & Tunneling"
            BGP["BGP Peers<br/>TCP :179"]
            VXLAN["VXLAN Tunnels<br/>UDP :4789"]
        end
    end

    CTRL -->|gRPC| DPDK
    CTRL -->|gRPC| EBPF
    CTRL -->|gRPC| F1
    CTRL -->|gRPC| F2
    CTRL -->|gRPC| F3

    F1 -->|TCP| BGP
    F2 -->|TCP| BGP
    F3 -->|TCP| BGP

    F1 -->|UDP| VXLAN
    F2 -->|UDP| VXLAN
    F3 -->|UDP| VXLAN

    DPDK -.->|forward| TG
    EBPF -.->|forward| TG

    style CTRL fill:#2196F3,color:#fff
    style DPDK fill:#4CAF50,color:#fff
    style EBPF fill:#FF9800,color:#fff
    style F1 fill:#9C27B0,color:#fff
    style F2 fill:#9C27B0,color:#fff
    style F3 fill:#9C27B0,color:#fff
    style TG fill:#F44336,color:#fff
    style BGP fill:#FFE66D,color:#333
    style VXLAN fill:#95E1D3,color:#333

Services

sdn-controller - Listens on :8080 (REST API) - Listens on :50051 (gRPC for agents) - Manages topology, handles intent requests - Health check: curl localhost:8080/api/v1/health

dpdk-agent - Implements DPDK forwarding engine - Registers with controller on startup - Exposes gRPC interface for route/tunnel updates - Health check: TCP :50051 responds

ebpf-agent - Loads eBPF XDP program - Registers with controller on startup - Health check: TCP :50051 responds

fabric-node-1, fabric-node-2, fabric-node-3 - Python simulated switches - Establish BGP peering with each other - Register with controller - Health check: Can connect to BGP port :179

traffic-gen - iperf3 server listening on :5201 - Optional: iperf3 client to generate traffic - Tests end-to-end forwarding

Configuration

Edit lab/.env.example to customize:

# .env.example
DPDK_AGENT_IP=dpdk-agent
EBPF_AGENT_IP=ebpf-agent
CONTROLLER_IP=sdn-controller
FABRIC_NODE_1_IP=fabric-node-1
FABRIC_NODE_2_IP=fabric-node-2
FABRIC_NODE_3_IP=fabric-node-3

Pass environment variables to compose:

export DPDK_AGENT_IP=my-host
docker-compose up -d

Testing Workflows

1. Verify Services Started

docker-compose ps
# All services should show "Up" and healthy

2. Check Topology Discovery

curl -s http://localhost:8080/api/v1/topology | jq .

Expected response:

{
  "devices": [
    {"id": "dpdk-agent", "ip": "10.0.0.1", "capabilities": ["ipv4-forwarding"]},
    {"id": "ebpf-agent", "ip": "10.0.0.2", "capabilities": ["ipv4-forwarding"]},
    {"id": "fabric-node-1", "ip": "10.0.0.3", "capabilities": ["bgp", "vxlan"]},
    ...
  ],
  "links": [...]
}

3. Query Device Statistics

curl -s http://localhost:8080/api/v1/health | jq .

Check packet counts and tunnel state.

4. Install a Route (Intent)

curl -X POST http://localhost:8080/api/v1/routes \
  -H "Content-Type: application/json" \
  -d '{
    "source_subnet": "10.1.0.0/24",
    "dest_subnet": "10.2.0.0/24",
    "tunnel_id": 1,
    "priority": 100
  }'

This triggers the controller to compute paths and install routes on all affected devices.

5. Generate Traffic

# Inside fabric-node-1 container, send packets
docker-compose exec fabric-node-1 bash
# (Inside container)
ping 10.2.0.1  # Should succeed if routes installed

Or use iperf3:

# Terminal 1: Start iperf3 server (should already be running)
docker-compose exec traffic-gen iperf3 -s

# Terminal 2: Generate traffic
docker-compose exec traffic-gen iperf3 -c traffic-gen -t 10
# Runs 10-second traffic flow; check packet counts with curl

Debugging

Check Logs

# All services
docker-compose logs

# Specific service
docker-compose logs sdn-controller
docker-compose logs fabric-node-1

# Follow in real-time
docker-compose logs -f fabric-node-1

Inspect Topology in Controller

docker-compose exec sdn-controller bash
# (Inside container)
curl localhost:8080/api/v1/topology | jq .

Check BGP Session State

docker-compose exec fabric-node-1 bash
# (Inside container)
python -c "from device import NetworkDevice; d = NetworkDevice('node1', 65001); print(d.bgp_speaker.state)"

Trace gRPC Calls

Enable gRPC debug logging:

GRPC_VERBOSITY=debug GRPC_TRACE=all docker-compose up sdn-controller

This prints all gRPC messages. Useful for debugging agent registration failures.

Restart a Service

docker-compose restart fabric-node-1
# Service restarts; registers with controller again

Rebuild Images

If you modify source code:

docker-compose build sdn-controller
docker-compose up -d sdn-controller

Or rebuild all:

docker-compose build --no-cache
docker-compose up -d

Performance Testing

Throughput Test

# Generate 10 seconds of traffic
docker-compose exec traffic-gen iperf3 -c traffic-gen -t 10 -P 4

# Check packet counts
curl http://localhost:8080/api/v1/health | jq '.devices[0].stats'

Expected results: - DPDK agent: ~100K packets/second - eBPF agent: ~1M packets/second (kernel fast path) - Fabric devices: ~50K packets/second (Python overhead)

Latency Test

# Ping test (shows round-trip latency)
docker-compose exec fabric-node-1 ping -c 100 fabric-node-2
# Average latency should be <5ms in Docker

# For per-packet latency, inspect timestamps in controller logs

Troubleshooting

Issue Solution
Services stuck in "starting" state Check service logs: docker-compose logs. Build may have failed.
Health checks fail Ensure port mappings are correct in docker-compose.yml.
Agents can't reach controller Check docker-compose network: docker network ls and verify service names in docker-compose.yml
BGP peers don't establish Check fabric node logs for peer configuration errors. Verify IP addresses and ASN assignments.
Routes not installed on devices Check controller logs for intent validation errors. Verify subnet addresses are reachable.
Traffic doesn't flow Check topology: are all devices connected? Run curl http://localhost:8080/api/v1/topology

Stopping the Lab

# Stop all services
docker-compose down

# Stop and remove volumes (data loss)
docker-compose down -v

# Stop specific service
docker-compose stop fabric-node-1

Next Steps