Product Overview
Diaload is a high-performance Diameter Load Testing Simulator designed to evaluate routing capacity, connection stability, and performance limits. By simulating realistic traffic loads, it helps users benchmark network elements before deployment.
The simulator utilizes a distributed transaction engine capable of generating traffic rates of up to 400,000 Transactions Per Second (TPS) over SCTP connections.
System Architecture
The simulator is divided into two primary logical components to ensure clean scalability:
- Simulator Controller: The orchestration node. It processes your configurations, controls traffic runs, hosts the REST APIs, and displays telemetry on the Web HUD.
- Simulator Engine (Worker): The traffic generation nodes. These workers manage the physical network connections and execute the protocol state machines.
System Installation
Getting the simulator running requires configuring basic network prerequisites and deploying the nodes.
1. Operating System Prerequisites
Since the simulator uses the Stream Control Transmission Protocol (SCTP), make sure your Linux kernel has the SCTP module loaded:
# Load SCTP kernel module
sudo modprobe sctp
# Verify it was loaded successfully
lsmod | grep sctp
2. Containerized Deployment
The easiest way to run the controller and workers is via Docker Compose. Below is a standard container deployment structure:
services:
controller:
image: diaload-controller:latest
ports:
- "8080:8080"
command: ["/app/controller", "-db", "/app/controller.db", "-log-level", "INFO"]
engine:
image: diaload-engine:latest
cap_add:
- NET_ADMIN
command: ["/app/engine", "-mode", "worker", "-controller-url", "http://controller:8080"]
Workers require the NET_ADMIN capability in Docker to modify kernel socket buffer allocations and optimize networking parameters dynamically.
Scenario Modeling
Traffic generation is controlled by scenario configuration files. Each file defines a comprehensive blueprint of target systems, simulated network node topologies, protocol dictionaries, message formats, workflows, and execution rates.
1. Workload Profiles
The workload_profile block controls the pacing, volume, network impairment emulation, identities, and traffic composition of the execution:
"workload_profile": {
"target_tps": 1000,
"total_count": 50000,
"concurrency_cap": 1000,
"duration_seconds": 0,
"latency_ms": 10,
"jitter_ms": 2,
"packet_drop_pct": 0.5,
"imsi_start": 286330000000001,
"imsi_end": 286330000000100,
"msisdn_start": 905900000001,
"msisdn_end": 905900000100,
"destination_realm": "ims.mnc033.mcc286.3gppnetwork.org",
"location_pool": [
{
"mcc": "286",
"mnc": "33",
"tac": 10001,
"cell_id": 1000001
}
],
"traffic_mix": [
{
"name": "VoLTE_Full_Scenario",
"weight": 100,
"profile": "E2E_VoLTE_EPC_IMS_QoS_Change"
}
],
"trace_percentage": 10.0,
"interfaces": [
{ "name": "S6a", "application_id": 16777251 },
{ "name": "Cx", "application_id": 16777216 },
{ "name": "Sh", "application_id": 16777217 },
{ "name": "Gx", "application_id": 16777238 },
{ "name": "Rx", "application_id": 16777236 },
{ "name": "Ro", "application_id": 4 }
]
}
Each configuration field serves a specific control purpose:
target_tps: The desired throughput rate (Transactions Per Second) target for the grid.total_count: The total number of subscriber sessions to generate.concurrency_cap: The maximum number of concurrent active subscriber sessions permitted on a worker at any given time.duration_seconds: Maximum run duration (set to 0 for unlimited run time, wheretotal_countdictates termination).latency_ms: Injected latency delay (in milliseconds) added to outgoing requests.jitter_ms: Random variation range (in milliseconds) applied to the injected latency.packet_drop_pct: Simulated packet loss percentage to validate client/server retransmission behavior.imsi_start/imsi_end: The range of International Mobile Subscriber Identities (IMSI) allocated for simulation sessions.msisdn_start/msisdn_end: The range of Mobile Station International Subscriber Directory Numbers (MSISDN) allocated.destination_realm: The routing realm destination header injected into requests.location_pool: Array of geographical location parameters (Mobile Country Code, Mobile Network Code, Tracking Area Code, Cell ID) used to populate location-related AVPs dynamically.traffic_mix: Array specifying which workflows (profiles) to execute and their relative distribution weight percentage (adding up to 100%).trace_percentage: Percentage of simulated sessions to inspect via low-overhead detailed tracing.interfaces: List of active interfaces and their Application IDs initialized during the run.
2. Scenario Topology
The topology block maps logical roles (requester and responder) to node types for each protocol interface. This mapping determines which worker node acts as the client and which acts as the server for specific message exchanges:
"topology": {
"S6a": { "requestor": "MME", "responder": "HSS" },
"Cx": { "requestor": "CSCF", "responder": "HSS" },
"Gx": { "requestor": "PGW", "responder": "PCRF" },
"Rx": { "requestor": "PCSCF", "responder": "PCRF" },
"Ro": { "requestor": "TAS", "responder": "OCS" }
}
In this architecture, when a worker registers, the controller assigns it a role based on the topology. For instance, a worker acting as a PGW will initiate Gx CCR requests, while a worker acting as a PCRF will listen and reply with Gx CCAs.
3. Identity Pools
The identity_pools array configures target domains, realms, hostnames, and connection counts for each node type represented in the topology:
"identity_pools": [
{
"type": "PGW",
"hosts": [ "pgw-01.epc.mnc033.mcc286.3gppnetwork.org" ],
"realm": "epc.mnc033.mcc286.3gppnetwork.org",
"connection_count": 1
},
{
"type": "PCRF",
"hosts": [ "pcrf-01.epc.mnc033.mcc286.3gppnetwork.org" ],
"realm": "epc.mnc033.mcc286.3gppnetwork.org",
"connection_count": 1
}
]
4. AVP Dictionary
The dictionary defines the structure and types of Attribute-Value Pairs (AVPs) used in message payloads. It maps symbolic AVP names to their numeric codes, flag rules, and types:
"avp_dictionary": {
"Session-Id": { "code": 263, "flags": "M", "type": "UTF8String" },
"Subscription-Id": { "code": 443, "flags": "M", "type": "Grouped" },
"Subscription-Id-Type": { "code": 450, "flags": "M", "type": "Unsigned32" },
"Subscription-Id-Data": { "code": 444, "flags": "M", "type": "UTF8String" }
}
Supported types include UTF8String, OctetString, Unsigned32, Integer32, Address, and Grouped (nested AVPs).
5. Diameter Protocol & Interfaces
This section defines which Application IDs are associated with which interfaces, and maps Command Names (like CCR, CCA) to their Command Codes and message flags:
"diameter_protocol": {
"interfaces": {
"Gx": { "application_id": 16777238 }
},
"commands": {
"CCR": { "code": 272, "flags": "R" },
"CCA": { "code": 272, "flags": "A" }
}
}
6. Protocol Messages
Message templates describe the layout of specific request and response packets. Instead of hardcoding all values, templates can embed dynamic placeholders (prefixed with $) that are resolved at runtime for each active subscriber session:
"messages": {
"Gx_CCR_Init": {
"command": "CCR",
"interface": "Gx",
"avps": [
{ "name": "Session-Id", "value": "$session_id" },
{ "name": "Origin-Host", "value": "$origin_host" },
{ "name": "Origin-Realm", "value": "$origin_realm" },
{ "name": "Destination-Realm", "value": "$destination_realm" },
{ "name": "User-Name", "value": "$IMSI" },
{
"name": "Subscription-Id",
"avps": [
{ "name": "Subscription-Id-Type", "value": 0 },
{ "name": "Subscription-Id-Data", "value": "$MSISDN" }
]
}
]
}
}
Standard session variables include $session_id (cryptographically unique ID), $origin_host, $origin_realm, $destination_realm, $IMSI, and $MSISDN.
7. Workflows (Profiles)
Profiles organize messages and thinking pauses into a linear execution workflow that simulates a complete subscriber session lifecycle:
"profiles": {
"E2E_VoLTE_Extensive": {
"steps": [
"Cx_UAR",
"Wait_100ms",
"Cx_MAR",
"Wait_100ms",
"Cx_SAR",
"Wait_500ms",
"Gx_CCR_Init"
]
}
}
Pauses are defined using the Wait_<time> format (e.g. Wait_100ms, Wait_1s).
8. How All Components Tie Together
Diaload uses a compile-to-memory architecture to unify these components for native-speed execution without reflection overhead:
- Grammar & Dictionary: The
avp_dictionaryanddiameter_protocoldefine the validation schemas and binary encoders. - Packet Layout: The
messagescompile into static binary byte templates with designated placeholder offsets. - Call Flow: The
profilesbind messages and timer delays into sequential action trees. - Distributed Roles: The
topologyandidentity_poolsmap physical worker connections to hostnames and client/server roles. - Execution Engine: The
workload_profilespins up parallel session worker routines, increments subscriber identities (IMSIs/MSISDNs) for each loop, and throttles transaction output to meet the target TPS.
9. Visual Mapping Flow
Below is a visual diagram of how these configurations map together at runtime. This mapping determines how each worker node determines which actions to execute, reply to, or skip:
+--------------------------------------------------------------+
| 1. SCENARIO CONFIG |
| |
| "traffic_mix": [ |
| { "profile": "VoLTE_Full_Flow", "weight": 100 } |
| ] |
+--------------------------------------------------------------+
|
| (resolves profile from library/profiles)
v
+--------------------------------------------------------------+
| 2. PROFILE (library/profiles/) |
| |
| "VoLTE_Full_Flow": { |
| "steps": [ |
| "Gx_CCR_Init", <-------+ (maps step to message) |
| "Wait_100ms" | |
| ] | |
| } | |
+-----------------------------|--------------------------------+
|
v
+--------------------------------------------------------------+
| 3. MESSAGE (library/messages/) |
| |
| "Gx_CCR_Init": { |
| "interface": "Gx", <---+ (maps message to interface) |
| "command": "CCR" | |
| } | |
+-----------------------------|--------------------------------+
|
v
+--------------------------------------------------------------+
| 4. SCENARIO TOPOLOGY |
| |
| "topology": { |
| "Gx": { |
| "requestor": "PGW", <---+ (defines node roles) |
| "responder": "PCRF" | |
| } | |
| } | |
+---------------------------------|----------------------------+
|
v
+--------------------------------------------------------------+
| 5. WORKER EXECUTION DECISION |
| |
| Active Profile Loop (Synchronous Pacing): |
| - Am I the "requestor" (e.g. PGW)? |
| YES: Send Request -> Wait for Answer -> Next Step. |
| NO: Skip step & wait to stay in sync. |
| |
| Passive Telemetry Loop (Asynchronous Response): |
| - Did I receive a Request from peer? |
| - Am I the "responder" (e.g. PCRF)? |
| - YES: Generate matching Answer template & send reply. |
+--------------------------------------------------------------+
Diameter Interfaces
The simulator supports core 3GPP signaling interfaces. Each interface is defined by its Application-ID and message commands.
| Interface | Application ID | Primary Message Flows | Usage Context |
|---|---|---|---|
| Gx | 16777238 |
CCR / CCA (Init, Update, Term) | QoS Rules & Policy Enforcement |
| Rx | 16777236 |
AAR / AAA, STR / STA | Application Function Signaling |
| Cx | 16777216 |
UAR / UAA, SAR / SAA, MAR / MAA | HSS Subscriber Authentication |
| Sh | 16777217 |
UDR / UDA, PUR / PUA | HSS User Profile Management |
| Swx | 16777265 |
MAR / MAA, SAR / SAA | Non-3GPP Access Authentication |
| Ro | 4 |
CCR / CCA | Online Event & Session Charging |
Supported Command Codes
The table below lists the common Diameter command codes processed by the simulator:
257: Capabilities-Exchange-Request / Answer (CER / CEA)280: Device-Watchdog-Request / Answer (DWR / DWA)282: Disconnect-Peer-Request / Answer (DPR / DPA)272: Credit-Control-Request / Answer (CCR / CCA)
System Configuration
The simulator engine behavior is governed by parameters configured in the system.json file. These settings optimize queue thresholds, SCTP socket allocations, and timeouts:
| Parameter Name | Default Value | Description |
|---|---|---|
diameter_answer_timeout_ms |
5000 |
Timeout (in ms) for client waiting for an Answer before registering a transaction timeout. |
diameter_watchdog_consecutive_failures |
3 |
Consecutive unanswered Device Watchdog Requests (DWR) before a connection is considered dead. |
diameter_watchdog_interval_ms |
10000 |
Interval (in ms) at which the simulator sends keep-alive DWR messages. |
disconnect_cooldown_ms |
1000 |
Cooldown period (in ms) after a disconnect before reconnection is permitted. |
disconnect_grace_check_ms |
50 |
Grace check period (in ms) during connection shutdown. |
dpr_read_deadline_ms |
500 |
Read deadline (in ms) for parsing DPR packets during connection teardown. |
heartbeat_interval_ms |
5000 |
Interval (in ms) at which engine workers report state heartbeats to the controller. |
high_queue_cap |
1000 |
Capacity limit of the high-priority packet queue (used for watchdog and control traffic). |
http_disconnect_timeout_ms |
3000 |
HTTP request timeout (in ms) for reporting worker disconnect status to the controller. |
http_dispatch_timeout_ms |
3000 |
HTTP request timeout (in ms) for the controller to dispatch workload configurations. |
http_error_forwarder_timeout_ms |
3000 |
HTTP request timeout (in ms) for forwarding engine worker errors to the controller. |
http_heartbeat_timeout_ms |
2000 |
HTTP request timeout (in ms) for reporting worker heartbeats to the controller. |
http_registration_timeout_ms |
5000 |
HTTP request timeout (in ms) for registering workers with the controller. |
normal_queue_cap |
5000 |
Capacity limit of the normal priority packet queue (used for standard transaction traffic). |
payload_decode_buf_size |
8192 |
Pre-allocated buffer size (in bytes) used for encoding and decoding Diameter messages. |
sctp_buf_size |
65535 |
Socket buffer read and write size allocation (in bytes) for SCTP connections. |
sctp_dial_retry_delay_ms |
100 |
Retry delay (in ms) applied if the initial SCTP connection establishment fails. |
sctp_write_timeout_ms |
5000 |
Timeout duration (in ms) permitted for writing data chunks on an SCTP socket. |
session_msg_chan_cap |
500 |
Buffer capacity of the session message channel mapping answers to transaction runners. |
session_shard_count |
32 |
Shard partitions used in concurrent hashing maps to prevent worker lock contention. |
session_sync_trigger_cap |
100 |
Buffer capacity for session synchronization triggers. |
stop_safety_timeout_ms |
4000 |
Safety grace period (in ms) during traffic termination to complete in-flight transactions. |
sync_job_queue_cap |
100000 |
Queue size buffer limit for distributed control plane synchronization tasks. |
warmup_duration_ms |
1000 |
Warm-up period (in ms) given for connections to initialize before applying full load. |
worker_expiration_timeout_ms |
30000 |
Duration (in ms) after which the controller considers a worker disconnected if heartbeats fail. |
worker_remote_action_timeout_ms |
120000 |
Timeout limit (in ms) for workers to complete a synchronized remote transaction step. |
worker_sync_safety_timeout_ms |
60000 |
Safety timeout backup (in ms) for worker control plane synchronization loops. |
Load Math & Tuning
Achieving stable high-throughput performance requires understanding the relationship between concurrency and latency, as well as tuning system limits.
1. Concurrency Math (Little's Law)
In load testing, active concurrent connections ($L$) are dictated by the target transaction rate ($\lambda$) and the response time/latency of the peer ($W$):
Consider two different response time environments to see how this impacts hardware resources:
| Target Rate (TPS) | Average Peer Latency (ms) | Required Concurrent Connections |
|---|---|---|
| 5,000 TPS | 20 ms (0.02s) | 100 active connections |
| 5,000 TPS | 200 ms (0.2s) | 1,000 active connections |
| 5,000 TPS | 1,000 ms (1.0s) | 5,000 active connections |
If the peer network element responds slowly, the simulator must keep connections open longer to maintain the target rate, which increases RAM usage and active connection counts.
2. Operating System Socket Tuning
To scale beyond 10,000 concurrent sessions, you must increase Linux kernel receive/transmit buffers. Apply the following settings on your engine workers:
# Set maximum socket read buffer sizes
sudo sysctl -w net.core.rmem_max=26214400
sudo sysctl -w net.core.rmem_default=26214400
# Increase network device backlog limits
sudo sysctl -w net.core.netdev_max_backlog=20000
3. File Descriptor Limits
Each active socket requires a file descriptor. Update the limits on your host system to prevent too many open files errors:
# Increase maximum file descriptors in current session
ulimit -n 65535
Troubleshooting
Use these guides to resolve common errors and perform diagnostic captures.
1. Capturing Traffic
If you suspect parameter encoding errors, run a packet capture directly on the simulator host or within its Docker container:
# Capture SCTP traffic on eth0 and write to file
sudo tcpdump -i eth0 -w capture.pcap sctp
# Download and open in Wireshark
# Hint: Use the display filter 'diameter' to isolate protocol packets.
2. Common Operational Issues
Worker Registration Failure
Symptom: Engine worker fails to register with the controller, displaying a version_mismatch error.
Solution: Ensure the controller and worker nodes are running identical versions. You can check the versions by running the binaries with the version flag: ./diaload-controller -version.
Socket Failures or Packet Drops
Symptom: High error rate metrics showing socket write/read errors under high TPS loads.
Solution: The network interface buffers or operating system file limits are exhausted. Apply the system buffer allocations detailed in the Load Math & Tuning section.
3. Understanding System Logs
The simulator uses structured JSON logs to record system states, validation events, and active traffic transactions. Each log line is output in JSON format:
{
"timestamp": "2026-06-05T08:00:23Z",
"level": "ERROR",
"component": "scenario_parser",
"message": "Scenario validation failed: scenario_name is required",
"worker_id": "engine-01"
}
Error and Warning Logs
| Component | Level | Message / Meaning | Troubleshooting Action |
|---|---|---|---|
scenario_parser |
ERROR |
Configuration JSON decoding or validation syntax errors. | Correct structural formatting errors in your scenario configuration files. |
scenario_compiler |
ERROR |
Message or profile template compiles fail due to undefined AVPs or mismatch commands. | Ensure all workflows only call messages defined in the active protocol dictionaries. |
control_sync |
ERROR |
Synchronization trigger timeout between workers in a distributed grid setup. | Ensure low latency connectivity between workers, or increase worker_remote_action_timeout_ms in system.json. |
dynamic_send |
ERROR |
SCTP socket write errors or internal buffer transmit queue overflows. | The network path or file descriptors are exhausted. Apply the OS-level sysctl memory buffer and ulimit tuning guides. |
dynamic_recv |
ERROR |
Timeout waiting for peer answer (no reply within the answer timeout window). | The target peer under test failed to respond. Check target peer server logs. |
engine_server |
WARN |
Unhandled incoming request command code received from a peer. | Ensure you have defined templates to handle all request types initiated by the peer. |
Operational and Debugging Logs
To trace active transaction flow and session progress, set the log level to INFO or DEBUG. These logs help confirm exactly when messages are sent and received:
| Component | Level | Operational / Debug Message Meaning |
|---|---|---|
scenario_runner |
DEBUG |
Traces step-by-step subscriber lifecycle loops (starting, executing steps, and successfully completing profile runs). |
dynamic_recv |
DEBUG |
Confirms reception of a Diameter Answer packet (e.g. Answer for Gx_CCR_Init: Cmd 272) matching a sent request. |
engine_server |
INFO |
Logs capabilities exchange (CER/CEA) handshake success and peering connection states. |
library_loader |
INFO |
Displays dictionary parsing statistics (AVPs, commands, and profiles loaded) during engine startup. |
scenario_compiler |
INFO |
Logs progress of parsing and compiling scenario message layouts in memory. |
registry |
INFO |
Confirms grid worker registrations, scenario start/stop requests, and run archivals. |
license |
INFO |
Logs valid license parameter loading (customer metadata, max TPS, and worker node capacities). |
FAQ & Glossary
Frequently Asked Questions
Q: Can I run multiple workers on a single host machine?
A: Yes. However, make sure each worker is allocated a distinct SCTP local port range to prevent bind address collisions.
Q: What is SCTP multi-homing?
A: SCTP multi-homing allows a single connection to bind to multiple IP addresses, providing redundant paths. You can configure multi-homing by specifying comma-separated IP lists in the engine worker arguments.
Glossary of Terms
- AVP (Attribute-Value Pair): The basic unit of data inside a Diameter message, carrying parameters like identifiers or routing info.
- CEA/CER: Capabilities-Exchange-Answer / Request. The handshake sent upon initiating connection to exchange supported applications and capabilities.
- TPS (Transactions Per Second): The metric defining transaction throughput. In Diameter, this corresponds to Request-Answer pairs processed per second.
- UE (User Equipment): The simulated client entity (mobile phone, subscriber) represented in the simulator session profiles.