TRex is Cisco's open-source, high-performance network traffic generator built on top of Intel DPDK. It generates realistic network traffic at line rate — up to 200+ Gbps on commodity hardware — for testing routers, firewalls, load balancers, IDS/IPS, and other network infrastructure. TRex operates in three distinct modes: Stateless (STL) for raw packet streams, Advanced Stateful (ASTF) for realistic TCP/UDP application traffic, and Emulation (EMU) for protocol-level client simulation.
This guide covers everything you need to install, configure, and operate TRex across all three modes, including the interactive console, Python automation API, traffic profiles, and real-world workflow recipes.
Note
For architecture details, deployment planning, security hardening, performance tuning internals, and contributor workflows, see the TRex Admin Guide.
Table of Contents
- 1. Quick Start
- 2. Installation
- 3. Configuration
- 4. Core Usage
- 5. Common Tasks
- 6. Troubleshooting
- 7. FAQ
1. Quick Start
This section gets you from zero to generating traffic in the shortest path possible. You will need a Linux machine with at least two DPDK-compatible network interfaces.
1.1 Minimum Requirements
| Requirement | Minimum |
|---|---|
| OS | Linux (Ubuntu 18.04+, CentOS 7+) |
| Kernel | 2.6.32+ |
| CPU | x86_64 with SSE 4.2 |
| RAM | 4 GB (8+ GB recommended) |
| NICs | 2 DPDK-compatible ports (Intel X710, XL710, E810, ixgbe, i40e, etc.) |
| Hugepages | 1024 x 2MB (or equivalent 1GB pages) |
1.2 Five-Minute Quick Start
Step 1: Download and extract TRex.
wget --no-cache --no-check-certificate https://trex-tgn.cisco.com/trex/release/latest
tar -xzvf latest
cd v3.0x # version directory
Step 2: Set up hugepages and bind NICs.
sudo ./dpdk_setup_ports.py -i
This interactive script walks you through configuring hugepages and binding network interfaces to DPDK-compatible drivers (igb_uio, vfio-pci).
Step 3: Create a minimal config file.
# /etc/trex_cfg.yaml
- port_limit: 2
version: 2
interfaces: ["03:00.0", "03:00.1"]
port_info:
- dest_mac: "00:00:00:01:00:00"
src_mac: "00:00:00:02:00:00"
- dest_mac: "00:00:00:02:00:00"
src_mac: "00:00:00:01:00:00"
Replace the PCI addresses and MAC addresses with your actual hardware values.
Step 4: Start the TRex server in stateless mode.
sudo ./t-rex-64 -i --cfg /etc/trex_cfg.yaml
Step 5: Connect the console and send traffic.
In a second terminal:
./trex-console
trex> start -f stl/bench.py -m 1gbps -p 0
trex> stats
trex> stop -a
You are now generating 1 Gbps of stateless traffic on port 0.
Tip
Use
./t-rex-64 --helpto see all server flags andtrex-console -hfor console options. The console supports tab completion for commands and arguments.
2. Installation
2.1 Supported Platforms
TRex runs on Linux x86_64 systems. The primary build system is waf, with separate build configurations for DPDK-based builds (linux_dpdk/ws_main.py) and non-DPDK builds (linux/ws_main.py).
2.2 Pre-Built Binary Installation
The fastest path. Download the latest release tarball:
mkdir /opt/trex
cd /opt/trex
wget --no-cache --no-check-certificate https://trex-tgn.cisco.com/trex/release/latest
tar -xzvf latest
The extracted directory contains:
t-rex-64— the main TRex binarybp_sim— alias/alternate name for the same binarytrex-console— the interactive Python consolescripts/— profiles, automation libraries, config examplesdpdk_setup_ports.py— NIC binding and hugepage setup utility
2.3 Building from Source
If you need a custom build (e.g., specific DPDK patches, debug builds):
git clone https://github.com/cisco-system-traffic-generator/trex-core.git
cd trex-core
# DPDK-based build (production)
cd linux_dpdk
./b configure
./b build
# Non-DPDK build (simulation/testing)
cd linux
./b configure
./b build
The build system uses waf. The CXX environment variable selects the C++ compiler:
export CXX=g++-9
cd linux_dpdk && ./b configure && ./b build
Important
The
BUILD_NUMenvironment variable is used internally for build numbering. TheUSERenvironment variable is read by the build system for paths. These are the only environment variables TRex uses — there are no runtime env-var knobs for traffic generation behavior.
2.4 Hugepage Configuration
TRex requires Linux hugepages for DPDK memory. Configure them before starting TRex:
Temporary (until reboot):
# 2MB hugepages
echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
# Mount hugepage filesystem
mkdir -p /mnt/huge
mount -t hugetlbfs nodev /mnt/huge
Persistent (survives reboot):
Add to /etc/default/grub:
GRUB_CMDLINE_LINUX="default_hugepagesz=1G hugepagesz=1G hugepages=4"
Then run update-grub and reboot. Verify:
grep Huge /proc/meminfo
cat /proc/cmdline | grep huge
2.5 NIC Binding with dpdk_setup_ports.py
The dpdk_setup_ports.py script manages binding NICs to DPDK-compatible drivers:
# Interactive setup (recommended for first time)
sudo ./dpdk_setup_ports.py -i
# Show current NIC status
sudo ./dpdk_setup_ports.py -s
# Auto-configure based on existing /etc/trex_cfg.yaml
sudo ./dpdk_setup_ports.py
Warning
Binding a NIC to DPDK removes it from the Linux kernel network stack. Do not bind your management interface. Always keep at least one interface on the kernel driver for SSH/management access.
2.6 Python Client Library Installation
The TRex Python client library lives in scripts/automation/trex_control_plane/. To use it from external scripts:
# Add to your Python path
export PYTHONPATH=/opt/trex/v3.0x/scripts/automation/trex_control_plane/interactive
# Or install the package
cd scripts/automation/trex_control_plane
pip install .
Verify the import:
from trex.stl.trex_stl_lib.api import *
print("STL API loaded successfully")
2.7 VM / Lab Installation
For testing in a VM where you lack physical NICs, TRex can run with virtual interfaces (e.g., virtio, vmxnet3). Key differences:
- Set
port_bandwidth_gb: 1in your config (VMs cannot do line rate) - Use
--softwaremode if the virtual NIC lacks DPDK support - Hugepages still required inside the VM
- port_limit: 2
version: 2
interfaces: ["03:00.0", "03:00.1"]
port_bandwidth_gb: 1
port_info:
- ip: 1.1.1.1
default_gw: 2.2.2.2
- ip: 2.2.2.2
default_gw: 1.1.1.1
3. Configuration
3.1 Config File Location and Format
TRex configuration is a YAML file, typically stored at /etc/trex_cfg.yaml. You can specify an alternate location with the --cfg flag:
sudo ./t-rex-64 -i --cfg /path/to/my_config.yaml
Example config files are in scripts/cfg/. The config is a YAML list (note the leading dash) where each item configures a TRex instance.
3.2 Complete Config Reference
| Key | Type | Default | Description |
|---|---|---|---|
port_limit |
int | — | Number of ports (2 or 4) |
version |
int | 2 | Config file version (always 2) |
interfaces |
list[str] | — | PCI addresses, e.g. ["03:00.0","03:00.1"] |
port_info |
list[obj] | — | Per-port MAC or IP configuration |
port_bandwidth_gb |
int | auto | Port bandwidth: 1 (VM), 10 (10G NIC), 40 (XL710) |
enable_zmq_pub |
bool | false | Enable ZMQ publisher for stats |
zmq_pub_port |
int | 4500 | ZMQ publisher port |
zmq_rpc_port |
int | 4501 | ZMQ RPC port (console connects here) |
telnet_port |
int | 4502 | Telnet access port |
prefix |
str | — | Instance prefix for multi-instance setups |
limit_memory |
int | — | Memory limit in MB |
c |
int | — | Number of datapath cores |
scan_only_1g |
bool | false | Only scan 1G interfaces |
Port info — MAC-based (loopback or direct cable):
port_info:
- dest_mac: "00:00:00:01:00:00"
src_mac: "00:00:00:02:00:00"
- dest_mac: "00:00:00:02:00:00"
src_mac: "00:00:00:01:00:00"
Port info — IP-based (routed setup through DUT):
port_info:
- ip: 10.0.0.1
default_gw: 10.0.0.2
- ip: 10.1.0.1
default_gw: 10.1.0.2
3.3 Platform Section — CPU Pinning
For production deployments, pin TRex threads to specific CPU cores to avoid NUMA crossings and ensure deterministic performance:
- port_limit: 2
version: 2
interfaces: ["03:00.0", "03:00.1"]
port_info:
- ip: 10.0.0.1
default_gw: 10.0.0.2
- ip: 10.1.0.1
default_gw: 10.1.0.2
platform:
master_thread_id: 0
latency_thread_id: 1
dual_if:
- socket: 0
threads: [2, 3, 4, 5]
| Platform Key | Type | Description |
|---|---|---|
platform.master_thread_id |
int | CPU core for the master (control) thread |
platform.latency_thread_id |
int | CPU core for the latency measurement thread |
platform.dual_if[].socket |
int | NUMA socket for this interface pair |
platform.dual_if[].threads |
list[int] | CPU cores for datapath threads |
Tip
Run
lscpuandcat /proc/cpuinfoto identify NUMA topology. Place TRex threads on the same NUMA node as the NICs for best performance. Uselstopofrom thehwlocpackage for a visual map.
3.4 Memory Section
memory:
dp_flows: 1048576
| Key | Type | Description |
|---|---|---|
memory.dp_flows |
int | Number of datapath flow entries |
3.5 Multi-Instance Configuration
Run multiple TRex instances on the same server using the prefix key and different ports:
# Instance A — /etc/trex_cfg_a.yaml
- port_limit: 2
version: 2
prefix: instance_a
interfaces: ["03:00.0", "03:00.1"]
zmq_pub_port: 4500
zmq_rpc_port: 4501
telnet_port: 4502
port_info:
- dest_mac: "00:00:00:01:00:00"
src_mac: "00:00:00:02:00:00"
- dest_mac: "00:00:00:02:00:00"
src_mac: "00:00:00:01:00:00"
# Instance B — /etc/trex_cfg_b.yaml
- port_limit: 2
version: 2
prefix: instance_b
interfaces: ["05:00.0", "05:00.1"]
zmq_pub_port: 4510
zmq_rpc_port: 4511
telnet_port: 4512
port_info:
- dest_mac: "00:00:00:03:00:00"
src_mac: "00:00:00:04:00:00"
- dest_mac: "00:00:00:04:00:00"
src_mac: "00:00:00:03:00:00"
3.6 Example Configs by Scenario
Lab / VM — Two virtual NICs, minimal resources:
- port_limit: 2
version: 2
interfaces: ["03:00.0", "03:00.1"]
port_bandwidth_gb: 1
limit_memory: 1024
c: 1
port_info:
- ip: 1.1.1.1
default_gw: 2.2.2.2
- ip: 2.2.2.2
default_gw: 1.1.1.1
Production — Four XL710 40G ports, pinned CPUs:
- port_limit: 4
version: 2
interfaces: ["03:00.0", "03:00.1", "05:00.0", "05:00.1"]
port_bandwidth_gb: 40
enable_zmq_pub: true
zmq_pub_port: 4500
port_info:
- ip: 10.0.0.1
default_gw: 10.0.0.2
- ip: 10.1.0.1
default_gw: 10.1.0.2
- ip: 10.2.0.1
default_gw: 10.2.0.2
- ip: 10.3.0.1
default_gw: 10.3.0.2
platform:
master_thread_id: 0
latency_thread_id: 1
dual_if:
- socket: 0
threads: [2, 3, 4, 5, 6, 7]
- socket: 1
threads: [8, 9, 10, 11, 12, 13]
4. Core Usage
4.1 The TRex Binary (t-rex-64)
The t-rex-64 binary is the TRex server/daemon. It manages DPDK, NIC ports, and the datapath. All traffic generation commands flow through this process.
4.1.1 Server Startup Flags
| Flag | Description |
|---|---|
-i |
Interactive mode — wait for console/API connections |
--cfg <file> |
Path to YAML config file |
-f <file> |
Traffic profile file (for direct/batch mode) |
-o <file> |
Output capture file (.erf format) |
-d <seconds> |
Duration to run |
-v [1-3] |
Verbosity level (1=basic, 2=detailed, 3=debug) |
--pcap |
Enable pcap export |
--ipv6 |
Enable IPv6 mode |
--sl |
Stateless mode |
--tcp_cfg |
ASTF mode |
--ut |
Unit test mode |
--cores <N> |
Number of datapath cores (1-8) |
--core_index <N> |
Use a specific core index |
--limit <N> |
Packet limit (stop after N packets) |
--dry |
Dry run — parse profile but do not send traffic |
--full |
Full ASTF simulation |
ASTF simulator-specific flags:
| Flag | Description |
|---|---|
--shaper-rate <bps> |
Traffic shaper rate |
--shaper-size <bytes> |
Traffic shaper buffer size |
--rtt <usec> |
Simulated round-trip time |
--drop <rate> |
Simulated packet drop rate |
4.1.2 Starting TRex in Different Modes
Stateless interactive (most common):
sudo ./t-rex-64 -i --sl --cfg /etc/trex_cfg.yaml
ASTF interactive:
sudo ./t-rex-64 -i --tcp_cfg --cfg /etc/trex_cfg.yaml
Batch mode (run a profile for a duration, then exit):
sudo ./t-rex-64 -f stl/bench.py -d 60 --cfg /etc/trex_cfg.yaml
Dry run (validate a profile without sending traffic):
sudo ./t-rex-64 -f stl/bench.py --dry
Packet capture to file:
sudo ./t-rex-64 -f stl/bench.py -d 30 -o capture.erf --pcap
4.2 The TRex Console (trex-console)
The interactive console is a Python-based CLI that connects to a running TRex server via ZMQ.
./trex-console
4.2.1 Console Connection Options
# Connect to remote TRex server
./trex-console -s 192.168.1.100
# Connect to specific RPC port
./trex-console -s 192.168.1.100 -p 4501
# Connect in read-only mode
./trex-console --readonly
4.2.2 Essential Console Commands
Server & Port Management:
| Command | Description |
|---|---|
connect |
Connect/reconnect to TRex server |
disconnect |
Disconnect from server |
acquire |
Acquire port ownership |
release |
Release port ownership |
reset |
Reset all ports to idle |
portattr |
Show/set port attributes |
l1_config |
Layer 1 port configuration |
Traffic Control:
| Command | Description |
|---|---|
start |
Start traffic on port(s) |
stop |
Stop traffic on port(s) |
pause |
Pause traffic |
resume |
Resume paused traffic |
update |
Update multiplier on running traffic |
push |
Push a pcap file |
Monitoring & Stats:
| Command | Description |
|---|---|
stats |
Show port statistics |
streams |
Show configured streams |
tui |
Full-screen text UI dashboard |
clear |
Clear statistics |
Capture & Debug:
| Command | Description |
|---|---|
capture |
Start/stop/show packet captures |
resolve |
Resolve ARP for port(s) |
ping |
Ping from TRex port |
scan6 |
IPv6 neighbor discovery scan |
Utility:
| Command | Description |
|---|---|
history |
Show command history |
verbose |
Set verbosity level |
quit |
Exit the console |
4.2.3 Console Start Command Syntax
The start command is the primary way to begin traffic generation:
start -f <profile> [-m <multiplier>] [-p <ports>] [-d <duration>] [--force]
[-t <key>=<val> ...] [--total] [--dry]
Multiplier formats:
| Format | Example | Meaning |
|---|---|---|
| Raw | -m 1000 |
1000 pps per stream |
| pps | -m 10kpps |
10,000 packets/sec |
| bps | -m 1gbps |
1 Gbps |
| percentage | -m 50% |
50% of line rate |
Examples:
# Start a profile at 1 Gbps on port 0
trex> start -f stl/bench.py -m 1gbps -p 0
# Start on both ports at 10,000 pps for 60 seconds
trex> start -f stl/bench.py -m 10kpps -p 0 1 -d 60
# Start with profile tunables
trex> start -f stl/bench.py -m 1gbps -t size=256 vm=var1
# Update running traffic to 2 Gbps
trex> update -m 2gbps -p 0
# Stop all ports
trex> stop -a
4.3 Console Plugins
The console supports plugins for specialized testing scenarios.
4.3.1 IPv6 Neighbor Discovery Plugin
trex> plugins load IPv6ND
trex> ipv6nd start -p 0
Sends IPv6 Router Solicitation and processes Router Advertisements. Useful for testing IPv6 network equipment.
4.3.2 BIRD Routing Plugin
trex> plugins load bird
Integrates with the BIRD routing daemon for testing routing protocols (BGP, OSPF, etc.) alongside traffic generation.
4.3.3 Wireless Testing Plugins
# Generic wireless testing
trex> plugins load wireless
# Wireless LAN Controller testing
trex> plugins load wlc
These plugins add specialized commands for testing wireless network infrastructure, including association, authentication, and data forwarding.
4.4 Python API
The Python API provides full programmatic control over TRex. Use it for automated testing, CI/CD integration, and custom traffic generation scripts.
4.4.1 STL API
from trex.stl.trex_stl_lib.api import *
# Connect to TRex server
client = STLClient(server="127.0.0.1")
client.connect()
# Acquire ports
client.acquire(ports=[0, 1])
client.reset(ports=[0, 1])
# Load a profile
profile = STLProfile.load("stl/bench.py", size=64)
client.add_streams(profile.get_streams(), ports=[0])
# Start traffic at 1 Gbps for 30 seconds
client.start(ports=[0], mult="1gbps", duration=30)
# Wait for traffic to finish
client.wait_on_traffic(ports=[0])
# Get stats
stats = client.get_stats()
print(f"TX packets: {stats[0]['opackets']}")
print(f"RX packets: {stats[1]['ipackets']}")
print(f"TX rate: {stats[0]['tx_bps']:.2f} bps")
# Disconnect
client.disconnect()
4.4.2 ASTF API
from trex.astf.trex_astf_lib.api import *
client = ASTFClient(server="127.0.0.1")
client.connect()
client.acquire(ports=[0, 1])
client.reset()
# Load an ASTF profile
client.load_profile("astf/http_simple.py")
# Start the ASTF traffic
client.start(mult=1, duration=60)
client.wait_on_traffic()
# Get ASTF-specific stats
stats = client.get_traffic_stats()
print(f"Total flows: {stats['total']['m_active_flows']}")
client.stop()
client.disconnect()
4.4.3 Key TRexClient Methods
The TRexClient base class provides 93+ methods. The most commonly used:
| Method | Description |
|---|---|
connect() |
Connect to TRex server |
disconnect() |
Disconnect |
acquire(ports) |
Acquire port ownership |
release(ports) |
Release ports |
reset(ports) |
Reset ports to defaults |
add_streams(streams, ports) |
Add stream objects to ports |
remove_all_streams(ports) |
Remove all streams |
start(ports, mult, duration) |
Start traffic |
stop(ports) |
Stop traffic |
update(ports, mult) |
Change rate on running traffic |
pause(ports) |
Pause traffic |
resume(ports) |
Resume traffic |
wait_on_traffic(ports) |
Block until traffic finishes |
get_stats() |
Get port statistics |
clear_stats(ports) |
Clear statistics |
set_port_attr(...) |
Set port attributes (promiscuous, etc.) |
push_remote(pcap, ports) |
Push a pcap file to hardware |
set_rx_queue(port, size) |
Enable RX packet queue |
get_rx_queue_pkts(port) |
Get captured RX packets |
ping_ip(port, dst_ip) |
Ping from a TRex port |
resolve(ports) |
ARP resolution |
4.4.4 Exception Handling
from trex.stl.trex_stl_lib.api import *
client = STLClient()
try:
client.connect()
client.acquire(ports=[0])
client.start(ports=[0], mult="1gbps")
except TRexError as e:
print(f"General TRex error: {e}")
except TRexTimeoutError as e:
print(f"Connection/operation timeout: {e}")
except TRexArgumentError as e:
print(f"Invalid argument: {e}")
except TRexTypeError as e:
print(f"Type mismatch: {e}")
finally:
client.disconnect()
5. Common Tasks
5.1 Stateless (STL) Workflows
Recipe 1: Simple Single-Stream UDP at Fixed Rate
# Start TRex in stateless mode
sudo ./t-rex-64 -i --sl --cfg /etc/trex_cfg.yaml
# In console:
trex> start -f stl/udp_1pkt_simple.py -m 100kpps -p 0
trex> tui
# Watch real-time stats, press 'q' to exit TUI
trex> stop -a
Recipe 2: Benchmark with Variable Packet Sizes
# 64-byte packets at maximum rate
trex> start -f stl/bench.py -m 100% -p 0 -t size=64
# IMIX (Internet Mix) distribution
trex> start -f stl/bench.py -m 50% -p 0 -t size=imix
IMIX generates a realistic distribution of packet sizes (64B, 594B, 1518B) in proportions matching real-world internet traffic.
Recipe 3: Multi-Stream with Field Engine (Variable Source IPs)
trex> start -f stl/bench.py -m 1gbps -p 0 -t vm=var1
The vm=var1 tunable enables the field engine to vary the source IP address across a range, creating multiple flows for load balancer and firewall testing.
Recipe 4: Bidirectional Traffic
# Send from both port 0 and port 1
trex> start -f stl/bench.py -m 1gbps -p 0 1
Recipe 5: Pcap Replay
Push a recorded pcap file as a traffic stream:
trex> push --port 0 -f /path/to/capture.pcap -m 1gbps --duration 60
Or use the pcap profile:
trex> start -f stl/pcap.py -m 1gbps -p 0 -t pcap_file=/path/to/capture.pcap
Recipe 6: Flow Stats and Latency Measurement
# With per-flow statistics
trex> start -f stl/bench.py -m 1gbps -p 0 -t flow=fs pg_id=7
# With flow-stats latency (measures per-flow latency)
trex> start -f stl/bench.py -m 100kpps -p 0 -t flow=fsl pg_id=7
Note
Flow-stats latency (
fsl) adds timestamping to each packet group. This has slightly higher overhead than basic flow stats (fs). Use-t flow=no-fsto disable flow stats entirely for maximum throughput.
Recipe 7: Gradual Rate Ramp-Up
trex> start -f stl/bench.py -m 100kpps -p 0
# ... wait a few seconds
trex> update -m 500kpps -p 0
# ... wait
trex> update -m 1mpps -p 0
# ... wait
trex> update -m 5mpps -p 0
Recipe 8: Cache-Based Streams (High PPS)
For maximum packets-per-second, use cached streams that pre-compute packets in memory:
trex> start -f stl/bench.py -m 100% -p 0 -t cache_size=1024
Recipe 9: Duration-Limited Test Run
# Run for exactly 120 seconds, then stop
trex> start -f stl/bench.py -m 1gbps -p 0 -d 120
Recipe 10: Capture Packets for Analysis
# Start a capture on port 1 (RX side)
trex> capture monitor start --rx 1 --limit 1000
# Start traffic
trex> start -f stl/bench.py -m 10kpps -p 0
# Save captured packets
trex> capture monitor save /tmp/captured.pcap
trex> capture monitor stop
5.2 Advanced Stateful (ASTF) Workflows
ASTF mode generates realistic TCP and UDP application-layer traffic. TRex acts as both client and server, establishing full TCP connections, performing handshakes, and transferring application data.
Recipe 11: HTTP Traffic Generation
# Start TRex in ASTF mode
sudo ./t-rex-64 -i --tcp_cfg --cfg /etc/trex_cfg.yaml
# In console:
trex> start -f astf/http_simple.py -m 1
trex> stats
trex> stop
The multiplier (-m) in ASTF mode controls the rate of new connections per second relative to the profile's base CPS.
Recipe 12: HTTP with Custom Response Size
trex> start -f astf/http_simple.py -m 1 -t size=4096
Recipe 13: FTP Traffic
trex> start -f astf/ftp_simple.py -m 1
Recipe 14: UDP Application Traffic
trex> start -f astf/udp1.py -m 10
Recipe 15: ASTF with TCP Tuning
# Custom MSS and window size
trex> start -f astf/http_simple.py -m 1 -t mss=1460 win=65535
# With TCP keepalive
trex> start -f astf/http_simple.py -m 1 -t tcp_ka=60
# With HTTP pipelining
trex> start -f astf/http_simple.py -m 1 -t pipe=4
Recipe 16: ASTF Simulation (Offline)
Test ASTF profiles without NICs using the simulator:
sudo ./t-rex-64 -f astf/http_simple.py --tcp_cfg --full -o sim_output.erf
With network impairments:
sudo ./t-rex-64 -f astf/http_simple.py --tcp_cfg --full \
--rtt 50000 --drop 0.01 -o sim_output.erf
Recipe 17: ASTF Traffic Shaping Simulation
sudo ./t-rex-64 -f astf/http_simple.py --tcp_cfg --full \
--shaper-rate 1000000000 --shaper-size 65536 -o shaped_output.erf
5.3 Emulation (EMU) Workflows
EMU mode emulates network clients at the protocol level — DHCP, DNS, ARP, IGMP, and more. Each emulated client has its own MAC, IP, and protocol state.
Recipe 18: DHCP Client Emulation
# Using EMU profile
from trex.emu.trex_emu_profile import *
# Or via console:
trex> start -f emu/dhcp_profile.py -t clients=100
Common EMU tunables:
| Tunable | Description |
|---|---|
--ns |
Namespace identifier |
--clients |
Number of emulated clients |
--mac |
Base MAC address |
--4 |
IPv4 mode |
--6 |
IPv6 mode |
--dg |
Default gateway |
Recipe 19: DNS Client Emulation
trex> start -f emu/dns_profile.py -t clients=50
Recipe 20: mDNS (Multicast DNS) Emulation
trex> start -f emu/mdns_profile.py -t clients=20
Recipe 21: IGMP Multicast Group Joins
trex> start -f emu/igmpv4_profile.py -t clients=100
Recipe 22: IPFIX Flow Export Emulation
trex> start -f emu/ipfix_profile.py
Recipe 23: ARP Emulation
trex> start -f emu/arp_profile.py -t clients=200
Recipe 24: AppSim (Application Simulation)
trex> start -f emu/appsim_profile.py
5.4 Profile Writing
Recipe 25: Writing a Custom STL Profile
STL profiles are Python classes that inherit from the TRex profile base:
from trex.stl.trex_stl_lib.api import *
class STLS1(object):
def get_streams(self, tunables, **kwargs):
size = tunables.get('size', 64)
# Build a UDP packet
pkt = STLPktBuilder(
pkt=Ether() / IP(src="16.0.0.1", dst="48.0.0.1") /
UDP(dport=12, sport=1025) /
Raw(b'\x00' * (size - 42))
)
# Single continuous stream
return [STLStream(
packet=pkt,
mode=STLTXCont(pps=1000)
)]
def get_tunables(self):
return {'size': 64}
def register():
return STLS1()
Run it:
trex> start -f my_profile.py -m 1gbps -p 0 -t size=128
Recipe 26: Multi-Stream Profile with Bursts
from trex.stl.trex_stl_lib.api import *
class STLMultiBurst(object):
def get_streams(self, tunables, **kwargs):
pkt_small = STLPktBuilder(
pkt=Ether() / IP(src="16.0.0.1", dst="48.0.0.1") /
UDP() / Raw(b'\x00' * 22)
)
pkt_large = STLPktBuilder(
pkt=Ether() / IP(src="16.0.0.1", dst="48.0.0.1") /
UDP() / Raw(b'\x00' * 1400)
)
return [
# Stream 1: continuous small packets
STLStream(
packet=pkt_small,
mode=STLTXCont(pps=5000),
name="small_continuous"
),
# Stream 2: burst of 100 large packets every second
STLStream(
packet=pkt_large,
mode=STLTXMultiBurst(
pkts_per_burst=100,
ibg=1000000.0, # inter-burst gap in usec
count=0 # infinite
),
name="large_bursts"
),
]
def register():
return STLMultiBurst()
Recipe 27: Profile with Field Engine (IP Range Sweep)
from trex.stl.trex_stl_lib.api import *
class STLVarIP(object):
def get_streams(self, tunables, **kwargs):
pkt = Ether() / IP(src="16.0.0.1", dst="48.0.0.1") / UDP() / Raw(b'\x00' * 22)
vm = STLScVmRaw([
STLVmFlowVar(name="src_ip",
min_value="10.0.0.1",
max_value="10.0.0.254",
size=4, op="inc"),
STLVmWrFlowVar(fv_name="src_ip", pkt_offset="IP.src"),
STLVmFixIpv4(offset="IP")
])
return [STLStream(
packet=STLPktBuilder(pkt=pkt, vm=vm),
mode=STLTXCont(pps=1000)
)]
def register():
return STLVarIP()
Recipe 28: Writing a Custom ASTF Profile
from trex.astf.trex_astf_lib.api import *
class Prof1(object):
def get_profile(self, tunables, **kwargs):
size = tunables.get('size', 1024)
# Client program: connect, send request, receive response
prog_c = ASTFProgram()
prog_c.send(b"GET /index.html HTTP/1.1\r\nHost: test\r\n\r\n")
prog_c.recv(size)
# Server program: receive request, send response
prog_s = ASTFProgram()
prog_s.recv(1)
prog_s.send(b"HTTP/1.1 200 OK\r\nContent-Length: " +
str(size).encode() + b"\r\n\r\n" + b"A" * size)
# Create the template
template = ASTFTCPClientTemplate(
program=prog_c,
ip_gen=ASTFIPGenDist(
ip_range=ASTFIPRange(ip_start="16.0.0.1",
ip_end="16.0.0.254"),
dist="seq"
),
port=80
)
server_template = ASTFTCPServerTemplate(program=prog_s)
cap = ASTFCapInfo(cps=100)
return ASTFProfile(
default_ip_gen=ASTFIPGenGlobal(
ip_offset="1.0.0.0"),
cap_list=[cap],
templates=[ASTFTemplate(
client_template=template,
server_template=server_template)]
)
def register():
return Prof1()
5.5 Automation & Scripting
Recipe 29: Automated Throughput Test
from trex.stl.trex_stl_lib.api import *
import time
def find_max_rate(server="127.0.0.1", profile="stl/bench.py",
target_loss_pct=0.1, duration=30):
"""Binary search for maximum rate with acceptable loss."""
client = STLClient(server=server)
client.connect()
client.acquire(ports=[0, 1])
low, high = 1, 100 # percentage of line rate
best = 0
try:
while high - low > 1:
mid = (low + high) // 2
client.reset(ports=[0, 1])
client.clear_stats()
prof = STLProfile.load(profile)
client.add_streams(prof.get_streams(), ports=[0])
client.start(ports=[0], mult=f"{mid}%", duration=duration)
client.wait_on_traffic(ports=[0])
stats = client.get_stats()
tx = stats[0]["opackets"]
rx = stats[1]["ipackets"]
loss_pct = ((tx - rx) / tx * 100) if tx > 0 else 100
print(f"Rate: {mid}% | TX: {tx} | RX: {rx} | Loss: {loss_pct:.3f}%")
if loss_pct <= target_loss_pct:
best = mid
low = mid
else:
high = mid
print(f"Maximum rate with <={target_loss_pct}% loss: {best}%")
finally:
client.stop(ports=[0])
client.disconnect()
return best
if __name__ == "__main__":
find_max_rate()
Recipe 30: Latency Monitoring Script
from trex.stl.trex_stl_lib.api import *
import time, json
def monitor_latency(server="127.0.0.1", profile="stl/bench.py",
rate="1gbps", duration=60, interval=5):
"""Collect latency measurements over time."""
client = STLClient(server=server)
client.connect()
client.acquire(ports=[0, 1])
client.reset(ports=[0, 1])
results = []
try:
prof = STLProfile.load(profile)
client.add_streams(prof.get_streams(), ports=[0])
client.start(ports=[0], mult=rate, duration=duration)
elapsed = 0
while elapsed < duration:
time.sleep(interval)
elapsed += interval
stats = client.get_stats()
sample = {
"time": elapsed,
"tx_pps": stats[0].get("tx_pps", 0),
"rx_pps": stats[1].get("rx_pps", 0),
"tx_bps": stats[0].get("tx_bps", 0),
}
results.append(sample)
print(json.dumps(sample))
client.wait_on_traffic(ports=[0])
finally:
client.disconnect()
return results
if __name__ == "__main__":
monitor_latency()
Recipe 31: Multi-Profile Sequential Test
from trex.stl.trex_stl_lib.api import *
profiles = [
("stl/bench.py", {"size": 64}, "1gbps", 30),
("stl/bench.py", {"size": 256}, "1gbps", 30),
("stl/bench.py", {"size": 512}, "1gbps", 30),
("stl/bench.py", {"size": 1518}, "1gbps", 30),
("stl/bench.py", {"size": "imix"}, "1gbps", 30),
]
client = STLClient()
client.connect()
client.acquire(ports=[0, 1])
for profile_path, tunables, rate, duration in profiles:
print(f"\n--- Testing {profile_path} with {tunables} at {rate} ---")
client.reset(ports=[0, 1])
client.clear_stats()
prof = STLProfile.load(profile_path, **tunables)
client.add_streams(prof.get_streams(), ports=[0])
client.start(ports=[0], mult=rate, duration=duration)
client.wait_on_traffic(ports=[0])
stats = client.get_stats()
tx = stats[0]["opackets"]
rx = stats[1]["ipackets"]
loss = ((tx - rx) / tx * 100) if tx > 0 else 0
print(f"TX: {tx:,} | RX: {rx:,} | Loss: {loss:.4f}%")
client.disconnect()
5.6 IPv6 Workflows
Recipe 32: IPv6 Traffic Generation
# Start TRex with IPv6 mode
sudo ./t-rex-64 -i --sl --ipv6 --cfg /etc/trex_cfg.yaml
In the console, use the scan6 command to discover IPv6 neighbors:
trex> scan6 -p 0
trex> start -f stl/bench.py -m 1gbps -p 0
Recipe 33: IPv6 Neighbor Discovery via Plugin
trex> plugins load IPv6ND
trex> ipv6nd start -p 0
trex> ipv6nd show -p 0
5.7 PCAP-Based Workflows
Recipe 34: Replay a Pcap at Line Rate
trex> push -f /path/to/traffic.pcap --port 0 -m 100% -d 60
Recipe 35: Convert Pcap to STL Profile
from trex.stl.trex_stl_lib.api import *
class STLPcap(object):
def get_streams(self, tunables, **kwargs):
pcap_file = tunables.get('pcap_file', 'input.pcap')
return STLProfile.load_pcap(pcap_file, ipg_usec=10.0)
def register():
return STLPcap()
5.8 Port Configuration Workflows
Recipe 36: Set Port to Promiscuous Mode
client.set_port_attr(ports=[0], promiscuous=True)
Or in the console:
trex> portattr --port 0 --prom on
Recipe 37: ARP Resolution Before Traffic
trex> resolve -p 0 1
This sends ARP requests from TRex ports to discover the destination MAC address based on the default_gw in your config.
Recipe 38: Viewing Port Info
trex> portattr -a
5.9 Statistics & Monitoring
Recipe 39: Real-Time TUI Dashboard
trex> tui
The TUI provides a live-updating dashboard showing:
- Per-port TX/RX rates (pps, bps)
- Total transmitted/received packets
- Drop counters and error counters
- Active stream information
Press q to exit the TUI.
Recipe 40: Export Statistics to JSON
import json
client = STLClient()
client.connect()
# ... start traffic ...
stats = client.get_stats()
with open("trex_stats.json", "w") as f:
json.dump(stats, f, indent=2, default=str)
Recipe 41: ZMQ Statistics Subscription
If enable_zmq_pub: true in your config, external tools can subscribe to the stats stream:
import zmq, json
context = zmq.Context()
socket = context.socket(zmq.SUB)
socket.connect("tcp://127.0.0.1:4500")
socket.setsockopt_string(zmq.SUBSCRIBE, "")
while True:
msg = socket.recv_json()
print(json.dumps(msg, indent=2))
5.10 Network Equipment Testing Workflows
Recipe 42: Firewall Rule Testing
Generate traffic matching specific firewall rules to verify pass/block behavior:
from trex.stl.trex_stl_lib.api import *
class FirewallTest(object):
def get_streams(self, tunables, **kwargs):
# HTTP traffic (should be allowed)
http = STLStream(
packet=STLPktBuilder(
pkt=Ether() / IP(src="10.0.0.1", dst="192.168.1.1") /
TCP(dport=80) / Raw(b"GET / HTTP/1.1\r\n\r\n")
),
mode=STLTXCont(pps=100),
name="http_allowed"
)
# SSH traffic (should be blocked)
ssh = STLStream(
packet=STLPktBuilder(
pkt=Ether() / IP(src="10.0.0.1", dst="192.168.1.1") /
TCP(dport=22) / Raw(b"\x00" * 20)
),
mode=STLTXCont(pps=100),
name="ssh_blocked"
)
return [http, ssh]
def register():
return FirewallTest()
Recipe 43: Load Balancer Distribution Testing
Generate traffic from many source IPs to verify load balancer hash distribution:
from trex.stl.trex_stl_lib.api import *
class LBTest(object):
def get_streams(self, tunables, **kwargs):
pkt = Ether() / IP(src="10.0.0.1", dst="192.168.1.100") / \
TCP(dport=80) / Raw(b"\x00" * 100)
vm = STLScVmRaw([
STLVmFlowVar(name="src", min_value="10.0.0.1",
max_value="10.0.255.254", size=4, op="random"),
STLVmWrFlowVar(fv_name="src", pkt_offset="IP.src"),
STLVmFixIpv4(offset="IP"),
])
return [STLStream(
packet=STLPktBuilder(pkt=pkt, vm=vm),
mode=STLTXCont(pps=10000)
)]
def register():
return LBTest()
Recipe 44: Router Throughput Testing (RFC 2544 Style)
from trex.stl.trex_stl_lib.api import *
FRAME_SIZES = [64, 128, 256, 512, 1024, 1280, 1518]
client = STLClient()
client.connect()
client.acquire(ports=[0, 1])
for size in FRAME_SIZES:
client.reset(ports=[0, 1])
client.clear_stats()
prof = STLProfile.load("stl/bench.py", size=size)
client.add_streams(prof.get_streams(), ports=[0])
client.start(ports=[0], mult="100%", duration=60)
client.wait_on_traffic(ports=[0])
stats = client.get_stats()
tx = stats[0]["opackets"]
rx = stats[1]["ipackets"]
throughput_pps = stats[0].get("tx_pps", 0)
loss = ((tx - rx) / tx * 100) if tx > 0 else 0
print(f"Frame: {size}B | PPS: {throughput_pps:,.0f} | Loss: {loss:.4f}%")
client.disconnect()
Recipe 45: IDS/IPS Evasion Testing with Mixed Traffic
# Generate a mix of traffic types
trex> start -f stl/imix.py -m 5gbps -p 0
The IMIX profile generates a realistic distribution of packet sizes that mirrors real-world traffic patterns, exercising DPI engines across multiple packet boundaries.
5.11 Advanced Profile Techniques
Recipe 46: Chained Streams (Sequential Traffic Patterns)
from trex.stl.trex_stl_lib.api import *
class STLChained(object):
def get_streams(self, tunables, **kwargs):
# Stream 1: burst of 1000 small packets, then trigger stream 2
s1 = STLStream(
packet=STLPktBuilder(
pkt=Ether() / IP() / UDP() / Raw(b'\x00' * 22)
),
mode=STLTXSingleBurst(total_pkts=1000, pps=10000),
name="burst_small",
next="burst_large"
)
# Stream 2: burst of 500 large packets, then trigger stream 3
s2 = STLStream(
packet=STLPktBuilder(
pkt=Ether() / IP() / UDP() / Raw(b'\x00' * 1400)
),
mode=STLTXSingleBurst(total_pkts=500, pps=5000),
name="burst_large",
next="burst_small",
self_start=False
)
return [s1, s2]
def register():
return STLChained()
Recipe 47: YAML-Based Profile (Alternative to Python)
For simple stream definitions, YAML profiles can be used:
# simple_udp.yaml
- name: udp_stream
stream:
self_start: true
packet:
binary: stl/udp_64B_no_crc.pcap
mode:
type: continuous
pps: 1000
trex> start -f simple_udp.yaml -m 1gbps -p 0
5.12 Packet Capture & Analysis
Recipe 48: Capture and Save Packets
# Start monitoring RX on port 1
trex> capture monitor start --rx 1 --limit 500
# Generate traffic
trex> start -f stl/bench.py -m 10kpps -p 0 -d 10
# View capture status
trex> capture monitor show
# Save to pcap
trex> capture monitor save /tmp/rx_capture.pcap
# Stop capture
trex> capture monitor stop
Recipe 49: Record and Replay
# Step 1: Capture live traffic with tcpdump on another machine
tcpdump -i eth0 -w recorded.pcap -c 10000
# Step 2: Replay on TRex at high rate
trex> push -f recorded.pcap --port 0 -m 10gbps -d 300
Recipe 50: Dry Run Profile Validation
# Validate profile syntax and packet construction without sending
sudo ./t-rex-64 -f stl/my_profile.py --dry -v 2
6. Troubleshooting
6.1 Installation & Startup Issues
Error: Could not find requested interface during DPDK setup
Cause: The PCI address in your config does not match any NIC on the system, or the NIC is not bound to a DPDK-compatible driver.
Solution:
- List all NICs and their current driver bindings:
sudo ./dpdk_setup_ports.py -s - Verify PCI addresses match your config file.
- Rebind the interfaces:
sudo ./dpdk_setup_ports.py -i
Prevention: Always run dpdk_setup_ports.py -s after system changes (kernel updates, NIC changes) to confirm bindings. (Related: GitHub issue #919)
Error: failure in ixgbe_dev_start() or NIC driver start failure
Cause: The DPDK driver cannot initialize the NIC. Common with ixgbe NICs when the kernel driver is still loaded or IOMMU settings conflict.
Solution:
- Unload the kernel driver:
sudo modprobe -r ixgbe - Check IOMMU settings in BIOS and GRUB:
cat /proc/cmdline | grep iommu - Try
vfio-pciinstead ofigb_uio:sudo modprobe vfio-pci sudo ./dpdk_setup_ports.py -i
Prevention: Use vfio-pci as the default DPDK driver on modern kernels (4.x+). It has better IOMMU support. (Related: GitHub issue #934)
Error: no Driver_str in dpdk_setup_ports.py
Cause: The NIC's driver string cannot be detected, usually because the interface is in an unexpected state or uses an unsupported chipset.
Solution:
- Check
lspci -vfor the NIC's kernel driver. - Manually specify the driver in
dpdk_setup_ports.py. - Ensure the DPDK-compatible driver module is loaded:
sudo modprobe igb_uio # or sudo modprobe vfio-pci
Prevention: Stick to well-tested NIC families: Intel X710, XL710, E810, 82599 (ixgbe), i40e. (Related: GitHub issue #1135)
Error: X710 NIC card can't bind driver on Ubuntu 20.04
Cause: Kernel version and DPDK driver compatibility issue with i40e NICs.
Solution:
- Update to the latest TRex release.
- Use
vfio-pcidriver with IOMMU enabled:# Add to GRUB_CMDLINE_LINUX: intel_iommu=on iommu=pt - Rebuild GRUB and reboot:
sudo update-grub && sudo reboot
Prevention: Always enable IOMMU when using vfio-pci. (Related: GitHub issue #1127)
Error: Unable to start ./t-rex-64 in ASTF mode
Cause: Missing ASTF configuration, wrong flags, or port setup issues.
Solution:
- Ensure you are using
--tcp_cfgflag (not--sl):sudo ./t-rex-64 -i --tcp_cfg --cfg /etc/trex_cfg.yaml - Verify port_info uses IP-based config (ASTF needs IP, not just MAC):
port_info: - ip: 10.0.0.1 default_gw: 10.0.0.2 - ip: 10.1.0.1 default_gw: 10.1.0.2 - Check that ARP resolution succeeds:
trex> resolve
Prevention: ASTF mode requires IP-based port configuration so that the TCP/IP stack can function. MAC-only config works for STL but not ASTF. (Related: GitHub issue #1183)
6.2 Traffic Generation Issues
Error: Packets truncated to 64 bytes with Intel E810 NICs using STL VM
Cause: Known issue with E810 NICs and the field engine (VM) in STL mode where packets get truncated.
Solution:
- Update to the latest TRex release.
- If the issue persists, try disabling hardware offloads:
trex> portattr --port 0 --prom on - As a workaround, use a cache-based approach instead of VM for packet variation.
Prevention: Test with the --dry flag first to verify expected packet sizes. (Related: GitHub issue #1205)
Error: TRex attempting to set MTU to 65518
Cause: A profile or configuration is requesting jumbo frames beyond the NIC's capability.
Solution:
- Verify your profile does not request packets larger than 9000 bytes.
- Check NIC firmware supports the requested MTU.
- Set explicit MTU in port attributes:
trex> portattr --port 0 --mtu 1500
Prevention: Set explicit MTU values in port configuration rather than relying on auto-detection. (Related: GitHub issue #1204)
Error: Stop traffic causes TRex abnormalities
Cause: Stopping traffic abruptly during certain profile types can leave internal state in an inconsistent condition.
Solution:
- Use
stop -ato stop all ports cleanly. - Follow with
resetto clear all state:trex> stop -a trex> reset - If the server becomes unresponsive, restart:
# Kill and restart sudo killall t-rex-64 sudo ./t-rex-64 -i --sl --cfg /etc/trex_cfg.yaml
Prevention: Avoid stopping mid-burst on complex chained stream profiles. Use duration-limited runs (-d) when possible. (Related: GitHub issue #1207)
Error: Method not found 'ctx_stop_autotriggers'
Cause: Version mismatch between the TRex console/client and the TRex server. The client is calling an API method that does not exist on the server version.
Solution:
- Ensure console and server are the same TRex version.
- Update both to the latest release.
- If using a remote console, verify the connection is to the correct server.
Prevention: Always update console and server together. (Related: GitHub issue #1208)
6.3 Performance Issues
Error: Cannot reach expected throughput (e.g., only 10 Gbps on a 40G NIC)
Cause: Insufficient CPU cores assigned, NUMA mismatch, or missing hugepages.
Solution:
- Add more datapath cores:
c: 4 # or more - Pin threads to the correct NUMA node (see Section 3.3).
- Verify hugepages are allocated:
grep Huge /proc/meminfo - Set
port_bandwidth_gbto match your NIC:port_bandwidth_gb: 40 # for XL710
Prevention: Always configure CPU pinning for production deployments. One core is rarely sufficient for rates above 10 Gbps.
Error: High CPU usage but low packet rate
Cause: Small packets (64B) require more CPU cycles per unit of bandwidth. The field engine (VM) also adds CPU overhead per packet.
Solution:
- Use
cache_sizeto pre-compute packets:trex> start -f stl/bench.py -m 100% -t cache_size=4096 - Reduce field engine complexity.
- Add more datapath cores.
Prevention: For maximum PPS with small packets, minimize field engine usage and maximize cache size.
Error: TRex cannot effectively use 400G network cards
Cause: Current DPDK support and TRex architecture have limitations at 400G speeds.
Solution:
- Use multiple datapath cores (maximum 8):
c: 8 platform: master_thread_id: 0 latency_thread_id: 1 dual_if: - socket: 0 threads: [2, 3, 4, 5, 6, 7, 8, 9] - Use pre-cached streams to minimize per-packet CPU work.
- Monitor for TRex updates with improved 400G support.
Prevention: For 400G testing, plan for potential rate limitations and test incrementally. (Related: GitHub issue #1185)
6.4 ARP & Connectivity Issues
Error: Gratuitous ARP broken
Cause: Known regression in certain TRex versions affecting gratuitous ARP handling.
Solution:
- Update to the latest TRex release.
- Manually set destination MACs in config as a workaround:
port_info: - dest_mac: "aa:bb:cc:dd:ee:ff" src_mac: "11:22:33:44:55:66" - Use the
resolveconsole command to manually trigger ARP.
Prevention: Test ARP behavior after every TRex upgrade. (Related: GitHub issue #1162)
Error: ARP resolution fails — no response from DUT
Cause: The DUT (device under test) is not responding to ARP requests from TRex ports.
Solution:
- Verify IP configuration in port_info matches the DUT's expected subnet.
- Check that the DUT has an ARP entry or responds to ARP:
trex> ping -p 0 -d 10.0.0.2 - Set promiscuous mode:
trex> portattr --port 0 --prom on - Fall back to static MAC addresses in config.
Prevention: Always verify L2/L3 connectivity before running traffic tests.
6.5 Console & API Issues
Error: Cannot connect to TRex server from console
Cause: Server not running, wrong port, or firewall blocking ZMQ.
Solution:
- Verify the server is running:
ps aux | grep t-rex-64 - Check the ZMQ RPC port (default 4501):
ss -tlnp | grep 4501 - Connect with explicit server/port:
./trex-console -s 127.0.0.1 -p 4501
Prevention: Use zmq_rpc_port in config to set a known port. Ensure no firewall blocks the ZMQ ports.
Error: Port ownership conflict — port is already owned by another user
Cause: Another console or API session has acquired the ports.
Solution:
- Use
--forceto take ownership:trex> acquire --force - Or from the API:
client.acquire(ports=[0, 1], force=True)
Prevention: Always release ports and disconnect cleanly when done.
6.6 Profile Issues
Error: Profile fails to load — Python import error
Cause: The profile script has a Python syntax error or missing import.
Solution:
- Test the profile with dry run:
sudo ./t-rex-64 -f stl/my_profile.py --dry -v 2 - Validate Python syntax:
python3 -c "import py_compile; py_compile.compile('stl/my_profile.py', doraise=True)" - Ensure the profile has a
register()function returning the profile class.
Prevention: Always test profiles with --dry before using in production.
Error: Profile tunables not taking effect
Cause: The tunable names in -t key=value do not match the profile's get_tunables() definition.
Solution:
- Check the profile source for available tunables.
- Use exact tunable names as defined in the profile:
trex> start -f stl/bench.py -m 1gbps -t size=128 vm=var1
Prevention: Document tunables in profile source comments.
6.7 Build Issues
Error: Build fails with waf errors
Cause: Missing build dependencies or wrong compiler version.
Solution:
- Install required packages:
sudo apt install build-essential g++ python3 zlib1g-dev libpcap-dev - Set the compiler:
export CXX=g++-9 - Clean and rebuild:
cd linux_dpdk ./b clean ./b configure ./b build
Prevention: Use the pre-built binaries unless you specifically need a custom build.
6.8 Memory Issues
Error: EAL: No free hugepages reported or Cannot allocate memory
Cause: Hugepages not configured or exhausted by other DPDK applications.
Solution:
- Check hugepage availability:
grep Huge /proc/meminfo - Allocate more hugepages:
echo 2048 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages - Use
limit_memoryin config to cap TRex memory:limit_memory: 2048 # MB
Prevention: Set hugepages at boot via kernel command line for reliability.
Error: Out of datapath flow entries
Cause: The memory.dp_flows value is too low for the traffic profile.
Solution:
Increase dp_flows in config:
memory:
dp_flows: 4194304 # 4M flows
Prevention: Size dp_flows based on your expected concurrent flow count. Rule of thumb: 2x your expected peak.
7. FAQ
General
Q: What operating systems does TRex support? TRex runs on Linux x86_64 only. It requires kernel 2.6.32 or newer. Ubuntu 18.04+, CentOS 7+, and RHEL 7+ are commonly used.
Q: Does TRex require special hardware? TRex requires DPDK-compatible NICs (Intel X710, XL710, E810, 82599 ixgbe, i40e are best supported). Hugepage-capable RAM is required. Any modern x86_64 CPU with SSE 4.2 works.
Q: Can TRex run in a virtual machine?
Yes, with virtual NICs (virtio, vmxnet3). Performance is limited — expect 1-5 Gbps depending on the hypervisor. Set port_bandwidth_gb: 1 in config.
Q: What is the maximum throughput TRex can achieve? TRex can generate 200+ Gbps on appropriate hardware. Actual throughput depends on NIC count, CPU cores, packet size, and field engine complexity.
Q: Is TRex free? Yes, TRex is fully open-source under the Apache 2.0 license.
Modes
Q: What is the difference between STL, ASTF, and STF modes? STL (Stateless) generates raw packet streams — maximum PPS, no connection state. ASTF (Advanced Stateful) creates full TCP/UDP connections with application-layer data exchange. STF (Stateful) is the legacy stateful mode using YAML/pcap templates (use ASTF for new work).
Q: When should I use STL vs. ASTF? Use STL for throughput/PPS testing, packet-level testing, and when you need maximum rate. Use ASTF for testing firewalls, proxies, load balancers, and any device that tracks connections or inspects application-layer content.
Q: What is EMU mode? EMU (Emulation) simulates protocol-level clients — DHCP, DNS, ARP, IGMP, etc. Use it when you need devices to respond to protocol interactions, not just forward packets.
Q: Can I run STL and ASTF simultaneously?
No, you must start the TRex server in one mode (--sl for STL or --tcp_cfg for ASTF). To switch, stop the server and restart in the other mode.
Configuration
Q: Where should I put the config file?
The default location is /etc/trex_cfg.yaml. Use --cfg /path/to/file.yaml to specify an alternate location.
Q: How do I find my NIC PCI addresses?
Run lspci | grep -i ethernet or sudo ./dpdk_setup_ports.py -s.
Q: Can I use more than 4 ports?
The port_limit config supports 2 or 4 ports. For more ports, run multiple TRex instances with different prefix values.
Q: What is the prefix config option for?
It enables running multiple TRex instances on the same machine. Each instance needs a unique prefix, unique ports (zmq_pub_port, zmq_rpc_port, telnet_port), and unique NIC interfaces.
Q: What does port_bandwidth_gb do?
It tells TRex the link speed so it can correctly calculate percentage-based rates. Set to 1 for VMs, 10 for 10G NICs, 40 for XL710 40G NICs.
Q: How do I configure CPU pinning?
Use the platform section with master_thread_id, latency_thread_id, and dual_if[].threads. Pin all threads to the same NUMA node as the NICs for optimal performance. See Section 3.3.
Traffic Profiles
Q: What profile formats does TRex support? Python (recommended) and YAML. Python profiles are more flexible with support for tunables, field engines, and complex logic.
Q: What are tunables?
Tunables are runtime parameters passed to profiles via -t key=value. They let you customize packet size, flow count, protocol options, etc., without editing the profile source.
Q: What is the field engine (VM)?
The field engine varies packet fields (IP addresses, ports, etc.) at line rate without CPU overhead per-packet. It is configured via STLScVmRaw with flow variables and write instructions.
Q: What is IMIX?
Internet Mix — a standardized distribution of packet sizes (64B, 594B, 1518B) that approximates real-world internet traffic. Use -t size=imix with the bench profile.
Q: What is the cache_size tunable?
It pre-computes N packets in memory and replays them, bypassing per-packet construction. Dramatically increases PPS for profiles with field engines. Higher values use more memory but allow more packet variation.
Q: How do chained streams work?
Streams can reference a next stream by name. When a burst stream finishes, TRex starts the next stream. This creates sequential traffic patterns (e.g., handshake then data).
Q: Can I replay pcap files?
Yes. Use push -f file.pcap in the console or STLProfile.load_pcap() in the API. TRex replays packets from the pcap at the specified rate.
Console & API
Q: Can I connect to a remote TRex server?
Yes. Use ./trex-console -s <server_ip> or STLClient(server="<server_ip>") in the API.
Q: What is read-only mode?
Connect with --readonly to view stats without the ability to start/stop traffic. Useful for monitoring while someone else controls traffic.
Q: How do I take over ports from another session?
Use acquire --force in the console or client.acquire(ports=[0], force=True) in the API.
Q: What happens if the console disconnects during a test? Traffic continues running on the server. Reconnect and re-acquire ports to regain control.
Q: Can I automate TRex from CI/CD? Yes. Use the Python API in test scripts. Start the TRex server before the test suite, run traffic, collect stats, and assert thresholds.
Performance
Q: How many CPU cores does TRex need? Minimum: 1 master + 1 latency + 1 datapath = 3 cores. For high throughput, allocate 4-8 datapath cores plus the master and latency threads.
Q: How do I maximize packets per second?
Use small packets (64B), maximize datapath cores, use cache_size to pre-compute packets, disable field engine if not needed, and pin threads to the correct NUMA node.
Q: Why is my latency high? Common causes: NUMA mismatch (threads and NICs on different sockets), CPU contention from other processes, insufficient hugepages causing TLB misses, or a misconfigured DUT.
Q: How much memory does TRex need?
Base: 1-2 GB for the DPDK memory pool. Add more for large flow tables (memory.dp_flows), large cache sizes, and ASTF connection state. Use limit_memory to cap usage.
Troubleshooting
Q: TRex starts but no packets appear on the wire. What should I check?
- Verify NICs are bound to DPDK (
dpdk_setup_ports.py -s). 2. Check that dest_mac or default_gw is correct. 3. Runresolveto ARP. 4. Tryportattr --prom onon the receiving side. 5. Check for cable/fiber issues.
Q: How do I check if TRex is running?
ps aux | grep t-rex-64 or try connecting the console.
Q: How do I cleanly shut down TRex?
From the console: stop -a then quit. Then kill the server process: sudo killall t-rex-64.
Q: My NIC is supported by DPDK but TRex does not start. What now?
Check TRex release notes for NIC-specific requirements. Some NICs need firmware updates. Try both igb_uio and vfio-pci drivers. Enable IOMMU if using vfio-pci.
Q: How do I debug a profile that produces unexpected traffic?
Use --dry -v 2 to see the packet structure without sending. Use packet capture (capture monitor) to examine actual packets on the wire. Check field engine variables with -v 3.
Q: The TUI shows TX but zero RX. Is that normal? It depends on your setup. If you have a loopback cable (port 0 to port 1), you should see RX on port 1. If traffic goes through a DUT, the DUT may be dropping packets. Check DUT logs and counters.
Q: How do I report a bug?
File an issue at https://github.com/cisco-system-traffic-generator/trex-core/issues with your TRex version, OS, NIC model, config file, profile, and exact error message.
Caution
When reporting issues, never include sensitive network information (real production IPs, credentials, internal hostnames) in public GitHub issues. Sanitize configs before posting.