Skip to content

Latest commit

 

History

History

README.md

Leo Performance Testing Scripts

A comprehensive Python toolkit for running and managing leo performance testing (iperf-like tool) on local and remote machines. This suite provides tools to orchestrate performance tests with flexible configuration, result parsing, and analysis.

Overview

This project includes three main scripts:

  1. server.py - Runs leo in server mode locally or remotely
  2. client.py - Runs leo in client mode against a server
  3. orchestrator.py - Manages complete test workflows with server and client coordination

Features

  • ✅ Local and remote execution via SSH
  • ✅ Configurable test parameters via JSON
  • ✅ Automatic output parsing and result collection
  • ✅ Performance metrics analysis (throughput, connections, success rates)
  • ✅ JSON-based result export
  • ✅ Support for TCP and UDP profiling
  • ✅ Multiple concurrent test scenarios
  • ✅ Comprehensive logging

Installation

Prerequisites

  • Python 3.7+
  • Access to leo binary on target machines
  • SSH access for remote tests (optional)

Setup

  1. Clone or download the scripts to your project directory
  2. Install dependencies:
pip install paramiko  # For remote SSH execution

Or install from requirements:

pip install -r requirements.txt

Quick Start

1. Generate Sample Configuration

python client.py --create-config tcp_mixed.json

This creates a configuration file like:

{
  "connections_per_second": 100,
  "duration_seconds": 30,
  "connection_profiles": [
    {
      "connection_type": "upload",
      "protocol": "tcp",
      "percentage": 50,
      "duration_seconds": 30
    },
    {
      "connection_type": "download",
      "protocol": "tcp",
      "percentage": 50,
      "duration_seconds": 30
    }
  ]
}

2. Start Leo Server

Local Server

python server.py --local --port 5201 --interval 1 -V

Remote Server

python server.py --remote 192.168.1.100 --user root --key ~/.ssh/id_rsa --port 5201 -V

3. Run Performance Test (Client)

Local Client

python client.py --host 127.0.0.1 --config tcp_mixed.json --output results.json -V

Remote Client

python client.py --host 10.0.0.1 --remote 192.168.1.50 --user root --key ~/.ssh/id_rsa \
  --config tcp_mixed.json --output results.json -V

4. Complete Orchestrated Test

Local Test (Both on same machine)

python orchestrator.py --local --server-host 127.0.0.1 --config tcp_mixed.json --output-dir ./results

Distributed Test

python orchestrator.py \
  --server-host 10.0.0.1 --server-user root --server-key ~/.ssh/id_rsa \
  --client-host 10.0.0.2 --client-user root --client-key ~/.ssh/id_rsa \
  --config tcp_mixed.json --output-dir ./results

Configuration File Format

tcp_mixed.json Example

{
  "connections_per_second": 100,
  "duration_seconds": 30,
  "connection_profiles": [
    {
      "connection_type": "upload",
      "protocol": "tcp",
      "percentage": 50,
      "duration_seconds": 30
    },
    {
      "connection_type": "download",
      "protocol": "tcp",
      "percentage": 50,
      "duration_seconds": 30
    }
  ]
}

Configuration Parameters

  • connections_per_second: Rate of connection creation
  • duration_seconds: Total test duration
  • connection_profiles: Array of connection scenarios
    • connection_type: "upload", "download", or "bidirectional"
    • protocol: "tcp" or "udp"
    • percentage: Percentage of total connections
    • duration_seconds: Duration for this profile

Command Reference

server.py

python server.py [OPTIONS]

Options:
  --local                    Run server locally
  --remote HOST              Run server on remote host
  --port PORT                Leo server port (default: 5201)
  --interval SECONDS         Reporting interval (default: 1)
  --user USERNAME            SSH username (default: root)
  --key KEY_FILE             SSH private key
  --leo-path PATH            Path to leo binary (default: ./leo)
  --leo-path-remote PATH     Path to leo on remote host
  --ulimit LIMIT             File descriptor limit (default: 1048576)
  --verbose, -V              Enable verbose output

client.py

python client.py [OPTIONS]

Options:
  --host HOST                Server host (REQUIRED)
  --port PORT                Server port (default: 5201)
  --client-id ID             Client identifier (default: leo_client)
  --config FILE              Configuration JSON file
  --local                    Run client locally
  --remote HOST              Run client on remote host
  --user USERNAME            SSH username (default: root)
  --key KEY_FILE             SSH private key
  --leo-path PATH            Path to leo binary (default: ./leo)
  --leo-path-remote PATH     Path to leo on remote host
  --output FILE              Save results to JSON file
  --verbose, -V              Enable verbose output
  --create-config FILE       Create sample config and exit

orchestrator.py

python orchestrator.py [OPTIONS]

Options:
  --local                    Run local server and client
  --server-host HOST         Server host (REQUIRED)
  --server-port PORT         Server port (default: 5201)
  --server-user USER         Server SSH user (default: root)
  --server-key FILE          Server SSH key
  --client-host HOST         Client host
  --client-user USER         Client SSH user (default: root)
  --client-key FILE          Client SSH key
  --client-id ID             Client identifier (default: leo_client)
  --config FILE              Configuration file (REQUIRED)
  --output-dir DIR           Results directory (default: ./results)
  --leo-path PATH            Leo binary path (default: ./leo)
  --server-wait SECONDS      Wait before starting client (default: 5)
  --test-duration SECONDS    Max test duration (default: 300)

Output and Results

Console Output

During test execution, you'll see real-time metrics:

[rms1]      1.0-46.0     sec | Connections: 3697/4482 | TCP: 3697/4482 
(UP:1553/2213 DN:2144/2269 BI:0/0 IN:0/0) | UDP: 0/0 
(UP:0/0 DN:0/0 BI:0/0 IN:0/0) | TCP TX:143.7 Mbps RX:34.5 Mbps | 
UDP TX:0.0 bps RX:0.0 bps

JSON Results File

Example results.json:

{
  "client_id": "leo_client",
  "server_host": "10.0.0.1",
  "server_port": 5201,
  "test_start": "2024-06-19T10:30:45.123456",
  "total_results": 30,
  "results": [
    {
      "timestamp": "2024-06-19T10:30:46.123456",
      "time_range": "1.0-2.0",
      "connections": "100/150",
      "tcp": {
        "completed": 100,
        "total": 150,
        "upload": "50/75",
        "download": "50/75",
        "tx_mbps": 143.7,
        "rx_mbps": 34.5
      },
      "udp": {
        "completed": 0,
        "total": 0,
        "tx_bps": 0.0,
        "rx_bps": 0.0
      }
    },
    ...
  ]
}

Summary Report

After test completion, a summary is printed:

================================================================================
Performance Test Summary for Client: leo_client
================================================================================

Test Duration: 30 seconds

TCP Throughput:
  TX: Avg=125.6 Mbps, Max=164.5 Mbps
  RX: Avg=28.3 Mbps, Max=34.5 Mbps

Connections:
  Max Connections: 3921

Final Status (at 1.0-30.0 sec):
  Total Connections: 3921/4982
  Success Rate: 78.7%
================================================================================

Typical Workflow

Scenario 1: Local Performance Testing

  1. Start server:

    python server.py --local -V
  2. In another terminal, run test:

    python client.py --host 127.0.0.1 --config tcp_mixed.json --output test_results.json -V

Scenario 2: Remote Server, Local Client

  1. Start remote server:

    python server.py --remote 10.0.0.1 --user root --key ~/.ssh/server_key -V
  2. Run client test locally:

    python client.py --host 10.0.0.1 --config tcp_mixed.json --output test_results.json -V

Scenario 3: Fully Automated with Orchestrator

python orchestrator.py \
  --server-host 10.0.0.1 --server-user root --server-key ~/.ssh/id_rsa \
  --config tcp_mixed.json \
  --output-dir ./results \
  --test-duration 60

Troubleshooting

Issue: "leo executable not found"

Solution: Ensure leo binary is in the correct path or specify with --leo-path:

python server.py --local --leo-path /usr/local/bin/leo

Issue: SSH Connection Refused

Solution: Check SSH access and key permissions:

# Verify SSH access
ssh -i ~/.ssh/id_rsa [email protected] echo "SSH OK"

# Check key permissions
chmod 600 ~/.ssh/id_rsa

Issue: Port Already in Use

Solution: Change the port:

python server.py --local --port 5202 -V
python client.py --host 127.0.0.1 --port 5202 --config tcp_mixed.json -V

Issue: "paramiko library not found"

Solution: Install paramiko for remote execution:

pip install paramiko

Issue: Too many open files

Solution: Increase system file descriptor limit before starting server:

# Adjust the ulimit
python server.py --local --ulimit 2097152 -V

Performance Tips

  1. Increase File Descriptors: Use appropriate --ulimit value:

    python server.py --local --ulimit 2097152 -V
  2. Adjust Connections Per Second: Modify in config file:

    "connections_per_second": 1000
  3. Monitor System Resources: Run in separate terminal:

    watch -n 1 'ps aux | grep leo'
  4. Multiple Clients: Run multiple client tests against same server for load testing

Logs and Debugging

Logs are saved in the results directory:

  • server_TIMESTAMP.log - Server execution log
  • client_TIMESTAMP.log - Client execution log

Enable verbose output with -V flag for detailed logs.

Advanced Usage

Starting Multiple Clients Against One Server

Terminal 1 - Server:

python server.py --local -V

Terminal 2 - Client 1:

python client.py --host 127.0.0.1 --client-id client1 --config tcp_mixed.json -V

Terminal 3 - Client 2:

python client.py --host 127.0.0.1 --client-id client2 --config tcp_mixed.json -V

Custom Configuration Profiles

Create aggressive.json:

{
  "connections_per_second": 500,
  "duration_seconds": 60,
  "connection_profiles": [
    {
      "connection_type": "upload",
      "protocol": "tcp",
      "percentage": 100,
      "duration_seconds": 60
    }
  ]
}

Then run:

python client.py --host 10.0.0.1 --config aggressive.json -V

Dependencies

  • Python 3.7+: Core runtime
  • paramiko: SSH client library (optional, for remote execution)

License

These scripts are provided as-is for performance testing with leo.

Contributing

To enhance these scripts:

  1. Add new metrics parsing
  2. Support additional protocols
  3. Implement result visualization
  4. Add database storage support

Support

For issues or questions:

  1. Check the Troubleshooting section
  2. Review command help: python script.py --help
  3. Enable verbose output with -V flag
  4. Check log files in results directory