triglav 0.2.0

High-performance multi-path networking tool with intelligent uplink management
Documentation
# Triglav Multi-Path Network Test Environment
#
# This creates a realistic network topology:
#
#   [Client] --[WiFi Uplink]---> [WiFi Router] --[ISP-A]--> [Internet Core] --> [Server]
#            --[Eth Uplink]----> [Eth Router]  --[ISP-B]--> [Internet Core] --> [Server]
#            --[LTE Uplink]----> [LTE Gateway] --[Mobile]-> [Internet Core] --> [Server]
#
# Each path has different characteristics:
# - WiFi: Low latency (20ms), moderate jitter (5ms), occasional packet loss (1%)
# - Ethernet: Very low latency (5ms), minimal jitter (1ms), no loss
# - LTE: Higher latency (50ms), high jitter (20ms), variable loss (2-5%), bandwidth limits

services:
  # ============================================================
  # TRIGLAV SERVER
  # ============================================================
  server:
    build:
      context: ../..
      dockerfile: docker/testnet/Dockerfile.server
    container_name: triglav-server
    hostname: server
    cap_add:
      - NET_ADMIN
    networks:
      internet_core:
        ipv4_address: 10.100.0.10
    volumes:
      - server-data:/data
      - ./scripts:/scripts:ro
    environment:
      - TRIGLAV_LOG=debug
      - TRIGLAV_LISTEN=0.0.0.0:7443
      - TRIGLAV_METRICS=0.0.0.0:9090
    ports:
      - "9090:9090"  # Metrics
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9090/health"]
      interval: 5s
      timeout: 3s
      retries: 5

  # ============================================================
  # TRIGLAV CLIENT (Multi-homed)
  # ============================================================
  client:
    build:
      context: ../..
      dockerfile: docker/testnet/Dockerfile.client
    container_name: triglav-client
    hostname: client
    cap_add:
      - NET_ADMIN
    sysctls:
      - net.ipv4.ip_forward=1
    networks:
      wifi_lan:
        ipv4_address: 10.10.1.100
      ethernet_lan:
        ipv4_address: 10.20.1.100
      lte_lan:
        ipv4_address: 10.30.1.100
    volumes:
      - client-data:/data
      - ./scripts:/scripts:ro
    environment:
      - TRIGLAV_LOG=debug
    depends_on:
      server:
        condition: service_healthy
      wifi_router:
        condition: service_started
      ethernet_router:
        condition: service_started
      lte_gateway:
        condition: service_started
    command: ["/scripts/start-client.sh"]

  # ============================================================
  # NETWORK INFRASTRUCTURE - WiFi Path
  # ============================================================
  wifi_router:
    build:
      context: .
      dockerfile: Dockerfile.router
    container_name: wifi-router
    hostname: wifi-router
    cap_add:
      - NET_ADMIN
    sysctls:
      - net.ipv4.ip_forward=1
    networks:
      wifi_lan:
        ipv4_address: 10.10.1.1
      isp_a:
        ipv4_address: 10.50.1.2
    volumes:
      - ./scripts:/scripts:ro
    environment:
      # WiFi characteristics: 20ms latency, 5ms jitter, 1% loss
      - NETEM_DELAY=20ms
      - NETEM_JITTER=5ms
      - NETEM_LOSS=1%
      - NETEM_RATE=100mbit
      - INTERFACE=eth1
    command: ["/scripts/setup-impairment.sh"]

  isp_a:
    build:
      context: .
      dockerfile: Dockerfile.router
    container_name: isp-a
    hostname: isp-a
    cap_add:
      - NET_ADMIN
    sysctls:
      - net.ipv4.ip_forward=1
    networks:
      isp_a:
        ipv4_address: 10.50.1.1
      internet_core:
        ipv4_address: 10.100.0.2
    volumes:
      - ./scripts:/scripts:ro
    environment:
      # ISP-A: Low latency backbone
      - NETEM_DELAY=5ms
      - NETEM_JITTER=1ms
      - NETEM_LOSS=0.1%
      - NETEM_RATE=1gbit
      - INTERFACE=eth1
    command: ["/scripts/setup-impairment.sh"]

  # ============================================================
  # NETWORK INFRASTRUCTURE - Ethernet Path
  # ============================================================
  ethernet_router:
    build:
      context: .
      dockerfile: Dockerfile.router
    container_name: ethernet-router
    hostname: ethernet-router
    cap_add:
      - NET_ADMIN
    sysctls:
      - net.ipv4.ip_forward=1
    networks:
      ethernet_lan:
        ipv4_address: 10.20.1.1
      isp_b:
        ipv4_address: 10.60.1.2
    volumes:
      - ./scripts:/scripts:ro
    environment:
      # Ethernet: Very low latency, minimal impairment
      - NETEM_DELAY=2ms
      - NETEM_JITTER=0.5ms
      - NETEM_LOSS=0.01%
      - NETEM_RATE=1gbit
      - INTERFACE=eth1
    command: ["/scripts/setup-impairment.sh"]

  isp_b:
    build:
      context: .
      dockerfile: Dockerfile.router
    container_name: isp-b
    hostname: isp-b
    cap_add:
      - NET_ADMIN
    sysctls:
      - net.ipv4.ip_forward=1
    networks:
      isp_b:
        ipv4_address: 10.60.1.1
      internet_core:
        ipv4_address: 10.100.0.3
    volumes:
      - ./scripts:/scripts:ro
    environment:
      # ISP-B: Premium backbone
      - NETEM_DELAY=3ms
      - NETEM_JITTER=0.5ms
      - NETEM_LOSS=0.01%
      - NETEM_RATE=10gbit
      - INTERFACE=eth1
    command: ["/scripts/setup-impairment.sh"]

  # ============================================================
  # NETWORK INFRASTRUCTURE - LTE/Mobile Path
  # ============================================================
  lte_gateway:
    build:
      context: .
      dockerfile: Dockerfile.router
    container_name: lte-gateway
    hostname: lte-gateway
    cap_add:
      - NET_ADMIN
    sysctls:
      - net.ipv4.ip_forward=1
    networks:
      lte_lan:
        ipv4_address: 10.30.1.1
      mobile_backhaul:
        ipv4_address: 10.70.1.2
    volumes:
      - ./scripts:/scripts:ro
    environment:
      # LTE Radio: Higher latency, significant jitter
      - NETEM_DELAY=30ms
      - NETEM_JITTER=15ms
      - NETEM_LOSS=2%
      - NETEM_RATE=50mbit
      - NETEM_CORRUPT=0.1%
      - NETEM_REORDER=5%
      - INTERFACE=eth1
    command: ["/scripts/setup-impairment.sh"]

  mobile_core:
    build:
      context: .
      dockerfile: Dockerfile.router
    container_name: mobile-core
    hostname: mobile-core
    cap_add:
      - NET_ADMIN
    sysctls:
      - net.ipv4.ip_forward=1
    networks:
      mobile_backhaul:
        ipv4_address: 10.70.1.1
      internet_core:
        ipv4_address: 10.100.0.4
    volumes:
      - ./scripts:/scripts:ro
    environment:
      # Mobile Core: Additional latency through mobile network
      - NETEM_DELAY=20ms
      - NETEM_JITTER=5ms
      - NETEM_LOSS=0.5%
      - NETEM_RATE=100mbit
      - INTERFACE=eth1
    command: ["/scripts/setup-impairment.sh"]

  # ============================================================
  # CHAOS AGENT - Dynamic network impairment
  # ============================================================
  chaos_agent:
    build:
      context: .
      dockerfile: Dockerfile.chaos
    container_name: chaos-agent
    hostname: chaos
    cap_add:
      - NET_ADMIN
    pid: host
    network_mode: host
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./scripts:/scripts:ro
      - ./scenarios:/scenarios:ro
    environment:
      - SCENARIO=realistic_internet
    depends_on:
      - client
    command: ["/scripts/chaos-agent.sh"]

  # ============================================================
  # METRICS & MONITORING
  # ============================================================
  prometheus:
    image: prom/prometheus:v2.48.0
    container_name: prometheus
    hostname: prometheus
    networks:
      internet_core:
        ipv4_address: 10.100.0.20
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - prometheus-data:/prometheus
    ports:
      - "9091:9090"
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'

  grafana:
    image: grafana/grafana:10.2.2
    container_name: grafana
    hostname: grafana
    networks:
      internet_core:
        ipv4_address: 10.100.0.21
    volumes:
      - ./grafana/dashboards:/etc/grafana/provisioning/dashboards:ro
      - ./grafana/datasources:/etc/grafana/provisioning/datasources:ro
      - grafana-data:/var/lib/grafana
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=triglav
      - GF_AUTH_ANONYMOUS_ENABLED=true
      - GF_AUTH_ANONYMOUS_ORG_ROLE=Viewer
    ports:
      - "3000:3000"

  # ============================================================
  # TEST RUNNER
  # ============================================================
  test_runner:
    build:
      context: .
      dockerfile: Dockerfile.test
    container_name: test-runner
    hostname: test-runner
    networks:
      internet_core:
        ipv4_address: 10.100.0.30
    volumes:
      - ./scripts:/scripts:ro
      - ./tests:/tests:ro
      - test-results:/results
    environment:
      - SERVER_ADDR=10.100.0.10:7443
      - CLIENT_ADDR=client
    depends_on:
      - client
      - server
    command: ["/scripts/run-tests.sh"]
    profiles:
      - test

# ============================================================
# NETWORKS
# ============================================================
networks:
  # Client LANs (one per "uplink type")
  wifi_lan:
    driver: bridge
    ipam:
      config:
        - subnet: 10.10.1.0/24
          gateway: 10.10.1.254

  ethernet_lan:
    driver: bridge
    ipam:
      config:
        - subnet: 10.20.1.0/24
          gateway: 10.20.1.254

  lte_lan:
    driver: bridge
    ipam:
      config:
        - subnet: 10.30.1.0/24
          gateway: 10.30.1.254

  # ISP networks
  isp_a:
    driver: bridge
    ipam:
      config:
        - subnet: 10.50.1.0/24

  isp_b:
    driver: bridge
    ipam:
      config:
        - subnet: 10.60.1.0/24

  mobile_backhaul:
    driver: bridge
    ipam:
      config:
        - subnet: 10.70.1.0/24

  # Internet core (where server lives)
  internet_core:
    driver: bridge
    ipam:
      config:
        - subnet: 10.100.0.0/24
          gateway: 10.100.0.1

# ============================================================
# VOLUMES
# ============================================================
volumes:
  server-data:
  client-data:
  prometheus-data:
  grafana-data:
  test-results: