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.
This project includes three main scripts:
- server.py - Runs leo in server mode locally or remotely
- client.py - Runs leo in client mode against a server
- orchestrator.py - Manages complete test workflows with server and client coordination
- ✅ 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
- Python 3.7+
- Access to leo binary on target machines
- SSH access for remote tests (optional)
- Clone or download the scripts to your project directory
- Install dependencies:
pip install paramiko # For remote SSH executionOr install from requirements:
pip install -r requirements.txtpython client.py --create-config tcp_mixed.jsonThis 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
}
]
}python server.py --local --port 5201 --interval 1 -Vpython server.py --remote 192.168.1.100 --user root --key ~/.ssh/id_rsa --port 5201 -Vpython client.py --host 127.0.0.1 --config tcp_mixed.json --output results.json -Vpython 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 -Vpython orchestrator.py --local --server-host 127.0.0.1 --config tcp_mixed.json --output-dir ./resultspython 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{
"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
}
]
}- 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
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 outputpython 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 exitpython 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)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
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
}
},
...
]
}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%
================================================================================
-
Start server:
python server.py --local -V
-
In another terminal, run test:
python client.py --host 127.0.0.1 --config tcp_mixed.json --output test_results.json -V
-
Start remote server:
python server.py --remote 10.0.0.1 --user root --key ~/.ssh/server_key -V -
Run client test locally:
python client.py --host 10.0.0.1 --config tcp_mixed.json --output test_results.json -V
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 60Solution: Ensure leo binary is in the correct path or specify with --leo-path:
python server.py --local --leo-path /usr/local/bin/leoSolution: 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_rsaSolution: Change the port:
python server.py --local --port 5202 -V
python client.py --host 127.0.0.1 --port 5202 --config tcp_mixed.json -VSolution: Install paramiko for remote execution:
pip install paramikoSolution: Increase system file descriptor limit before starting server:
# Adjust the ulimit
python server.py --local --ulimit 2097152 -V-
Increase File Descriptors: Use appropriate
--ulimitvalue:python server.py --local --ulimit 2097152 -V
-
Adjust Connections Per Second: Modify in config file:
"connections_per_second": 1000
-
Monitor System Resources: Run in separate terminal:
watch -n 1 'ps aux | grep leo' -
Multiple Clients: Run multiple client tests against same server for load testing
Logs are saved in the results directory:
server_TIMESTAMP.log- Server execution logclient_TIMESTAMP.log- Client execution log
Enable verbose output with -V flag for detailed logs.
Terminal 1 - Server:
python server.py --local -VTerminal 2 - Client 1:
python client.py --host 127.0.0.1 --client-id client1 --config tcp_mixed.json -VTerminal 3 - Client 2:
python client.py --host 127.0.0.1 --client-id client2 --config tcp_mixed.json -VCreate 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- Python 3.7+: Core runtime
- paramiko: SSH client library (optional, for remote execution)
These scripts are provided as-is for performance testing with leo.
To enhance these scripts:
- Add new metrics parsing
- Support additional protocols
- Implement result visualization
- Add database storage support
For issues or questions:
- Check the Troubleshooting section
- Review command help:
python script.py --help - Enable verbose output with
-Vflag - Check log files in results directory