Automated Docker image builds for Cisco TRex traffic generator, based on Rocky Linux 9.
Images are published to the GitHub Container Registry:
ghcr.io/tshelter/trex:<version>
| Version | Pull command |
|---|---|
| v3.08 | docker pull ghcr.io/tshelter/trex:v3.08 |
| v3.02 | docker pull ghcr.io/tshelter/trex:v3.02 |
| v3.00 | docker pull ghcr.io/tshelter/trex:v3.00 |
TRex requires direct access to network interfaces and hugepages, so it must run with full privileges and host networking.
Add these to your ~/.bashrc or ~/.zshrc for convenient access:
TREX_IMAGE="ghcr.io/tshelter/trex:v3.08"
TREX_OPTS="--rm -it --privileged --network host --cap-add ALL --ulimit memlock=-1:-1 \
-v /dev/hugepages:/dev/hugepages \
-v /etc/trex_cfg.yaml:/etc/trex_cfg.yaml \
-v /sys:/sys \
-v /dev/vfio:/dev/vfio \
-v /lib/modules:/lib/modules:ro \
-v .:/cwd"
alias t-rex-64="docker run $TREX_OPTS $TREX_IMAGE t-rex-64"
alias trex-console="docker run $TREX_OPTS $TREX_IMAGE trex-console"
alias dpdk_nic_bind.py="docker run $TREX_OPTS $TREX_IMAGE dpdk_nic_bind.py"
alias dpdk_setup_ports.py="docker run $TREX_OPTS $TREX_IMAGE dpdk_setup_ports.py"Reload your shell (source ~/.bashrc) then use as if TRex were installed natively:
t-rex-64 -i # start server (interactive mode)
t-rex-64 -i --astf # start ASTF server
t-rex-64 -f cap2/sfr.yaml -m 100 # run sfr profile at 100 multiplier (≈100Gbps)
t-rex-64 --help # show all flags
trex-console # connect console to running server
trex-console -s 127.0.0.1 # connect to specific server
dpdk_nic_bind.py --status-dev net # show NIC driver bindings
dpdk_setup_ports.py -i # interactive config generatort-rex-64 -iOr with a custom config (e.g. memif):
t-rex-64 --cfg /etc/trex_memif.yamlOpen a second terminal:
trex-consoleThe interactive wizard generates /etc/trex_cfg.yaml from your actual hardware.
It must be run as root and has access to the host's PCI bus via the -v /sys:/sys mount.
dpdk_nic_bind.py -t+----+------+---------+-------------------+-------------------------------------+--------+-----------+----------+
| ID | NUMA | PCI | MAC | Name | Driver | Linux IF | Active |
+====+======+=========+===================+=====================================+========+===========+==========+
| 0 | 0 | 4b:00.0 | 7c:c2:55:4b:2f:96 | I350 Gigabit Network Connection | igb | enp75s0f0 | *Active* |
+----+------+---------+-------------------+-------------------------------------+--------+-----------+----------+
| 2 | 1 | b1:00.0 | 6c:fe:54:80:04:8e | Ethernet Controller E810-C for QSFP | ice | ens1f0np0 | |
+----+------+---------+-------------------+-------------------------------------+--------+-----------+----------+
| 3 | 1 | b1:00.1 | 6c:fe:54:80:04:8f | Ethernet Controller E810-C for QSFP | ice | ens1f1np1 | |
+----+------+---------+-------------------+-------------------------------------+--------+-----------+----------+
TRex configuration utility works with interfaces bound to their kernel driver (e.g. ice).
If you previously used vfio-pci, rebind first:
dpdk_nic_bind.py --bind ice b1:00.0 b1:00.1dpdk_setup_ports.py -iAnnotated session:
By default, IP based configuration file will be created.
Do you want to use MAC based config? (y/N) <-- N for IP-based (recommended for loopback/L2),
y for MAC-based (use when ARP may not work)
Enter list of interfaces separated by space (for example: 1 3) : 2 3
<-- select by ID, PCI, or Linux IF name;
choose pairs on the same NUMA for best performance
For interface 2, assuming loopback to its dual interface 3.
Putting IP 1.1.1.1, default gw 2.2.2.2 Change it?(y/N).
<-- default IPs are fine for loopback/L2;
see "L3 topology" below if routed
Save the config to file? (Y/n)
Default filename is /etc/trex_cfg.yaml
Press ENTER to confirm or enter new file:
Generated by the wizard for loopback or same-L2-domain setups. Default IPs
(1.1.1.1 / 2.2.2.2) are fine — no changes needed.
- version: 2
interfaces: ['b1:00.0', 'b1:00.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
platform:
master_thread_id: 0
latency_thread_id: 1
dual_if:
- socket: 1
threads: [24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47]Use this when the network between TRex and the DUT may not forward ARP
(e.g. strict L3, broken underlay). Select y at the wizard prompt.
- version: 2
interfaces: ['b1:00.0', 'b1:00.1']
port_info:
- dest_mac: 6c:fe:54:80:04:8f # MAC of the DUT or peer interface
src_mac: 6c:fe:54:80:04:8e
- dest_mac: 6c:fe:54:80:04:8e
src_mac: 6c:fe:54:80:04:8f
platform:
master_thread_id: 0
latency_thread_id: 1
dual_if:
- socket: 1
threads: [24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47]When TRex connects to the DUT via a routed network, you must use real interface IPs and configure routes on the router for TRex's traffic subnets.
TRex port 0 Router TRex port 1
10.0.0.2/24 ──────► 10.0.0.1/24 10.1.1.1/24 ◄────── 10.1.1.2/24
TRex generates traffic from 16.0.0.0/8 (client side) and 48.0.0.0/8
(server side) by default. Add these routes on the router:
16.0.0.0/8 via 10.0.0.2 (towards TRex port 0)
48.0.0.0/8 via 10.1.1.2 (towards TRex port 1)
If you use custom profiles with different subnets, add matching routes.
The dual_port_mask: "1.0.0.0" option shifts IP subnets for each additional
port pair — account for this when computing routes.
Config for the L3 case:
- version: 2
interfaces: ['b1:00.0', 'b1:00.1']
port_info:
- ip: 10.0.0.2
default_gw: 10.0.0.1
- ip: 10.1.1.2
default_gw: 10.1.1.1Use memif virtual interfaces to run TRex without a physical NIC — useful for testing on a local machine or in a VM.
- port_limit: 2
version: 2
interfaces: ["--vdev=net_memif0,id=0,role=master", "--vdev=net_memif1,id=0,role=slave"]
port_info:
- ip: 1.1.1.1
default_gw: 2.2.2.2
- ip: 2.2.2.2
default_gw: 1.1.1.1Run with:
t-rex-64 --cfg /etc/trex_memif.yamlPass the config file directly with --cfg; the default /etc/trex_cfg.yaml
is not used in this case.
- Base image:
rockylinux:9.3.20231119-minimal - TRex path:
/root/trex - Working directory:
/root/trex - PATH: includes
/root/trex - Packages added:
procps-ng,pciutils,iproute - Firmware: Intel E810 ice DDP (
/lib/firmware/intel/ice/ddp/ice.pkg) — fetched at build time, not the fulllinux-firmwareRPM - Architecture:
linux/amd64
Builds are triggered automatically on push when Dockerfile, versions.json, or the workflow file changes. You can also trigger a build manually from the Actions tab.
Use Run workflow → enter space-separated versions:
v3.06 v3.07 v3.08
Leave the field empty to build all versions listed in versions.json.
Edit versions.json:
["v3.00", "v3.02", "v3.08"]TRex tarballs are cached between runs — subsequent builds skip the download (~250 MB per version).
# Download the tarball first
curl -k -L -o trex.tar.gz https://trex-tgn.cisco.com/trex/release/v3.08.tar.gz
# Build
docker build --build-arg TREX_VERSION=v3.08 -t trex:v3.08 .