TRex 是基于 DPDK 的一个开源、低成本的流量生成器,支持生成 L3~7 流量,提供有状态、无状态两种模式。
TRex 架构
TRex 之所以能够产生相比其他流量生成器更大的流量,原因是使用了 DPDK。
传统的工具,比如 iperf,如果想要生成包,需要走 Linux 内核,经过绑定的 socket API、 TCP/IP 栈、设备驱动这样一套完整的流程,最终才能到达物理网卡。
而 TRex 使用 DPDK,这意味着它可以绕过 Linux 内核态协议栈,直接控制物理网卡,应用单独实现包处理过程,不用经历内核/用户态切换、内存拷贝、冗余的 TCP/IP 协议栈等步骤。
安装
进入安装目录,比如
/opt/trex
下载 TRex 压缩包
1
wget --no-cache --no-check-certificate https://trex-tgn.cisco.com/trex/release/latest
解压 TRex 压缩包
1
tar -xzvf latest
网卡配置
TRex 需要 DPDK 绑定网卡,通过 TRex 提供的脚本可以查看或修改网卡
查看网卡状态
1 | root@ubuntu:/opt/trex/v3.05# ./dpdk_setup_ports.py -s |
- 当前三张网卡都绑定在 kernel 下,DPDK 未绑定网卡
Active
的网卡为 ssh 使用的管理网卡,不可以设置在 TRex 配置文件中,分配给 DPDK
在运行 TRex 时,会自动将 TRex 配置文件中interfaces
网卡绑定 DPDK
TRex 配置
Yaml 格式配置文件,用来配置 TRex 服务器,包括:
- 每个网卡的源、目的 IP 和 MAC 地址
- 屏蔽网卡,保证 TRex 不使用管理网卡作为流量网卡
在运行 TRex 服务器时,通过 --cfg
配置,如果未设置,则使用默认路径/etc/trex_cfg.yaml
,TRex 提供了一些示例 TRex 配置文件在 $TREX_ROOT/cfg
配置项
port_limit
:(必选)网卡数量,绑定 DPDK 的网卡数量,必须和interfaces
中的网卡数量对应version
:(必选)必须是 2interfaces
:(必选)TRex 使用的网卡 PCI,顺序有意义,对应port_info
中的顺序- 必须是偶数个,成对存在,按顺序分别为 clinet 和 server 网卡
- 如是奇数个网卡,可以使用
dummy
填充,但每对网卡对必须有非dummy
的网卡 - 通过
./dpdk_setup_ports.py -s
查看网卡 PCI - 不能填入 ssh 使用的网卡
c
:分配给每个网卡对的线程数,会被运行时的命令行参数-c
覆盖services_core
:(非必选)用来跑 scapy、PyBird、Emu 这些 service 的核,如果未设置,则会采用以下逻辑- low_end 开启,使用 low_end_core
- low_end 未开启,使用 master_thread_id
- low_end 未开启,使用 master_thread_id,使用 core 0
port_info
:(必选)- 网卡信息,每项按顺序对应
interfaces
中的网卡 - (必选)对于每张网卡,都必须要设置目的 MAC 地址,有两种设置方式:
- 直接设置
dest_mac
- 设置
default_gw
,在未设置dest_mac
时,TRex 会对default_gw
这个 IP 发送 ARP 请求,使用回复的结果作为目的 MAC 地址
- 直接设置
dest_mac
:目的 MAC 地址,该网卡打流将打往这个 MAC 地址default_gw
:默认网关,用于生成目的 MAC 地址src_mac
:(非必选)该网卡生成流量的源 MAC 地址,如果未设置,将使用该网卡的 MAC 地址作为源 MAC 地址
- 网卡信息,每项按顺序对应
platform
:(非必选)master_thread_id
:控制线程使用的线程 idlatency_thread_id
:RX 线程使用的线程 id,用来计算延迟dual_if
:- 与
interfaces
中的网卡对一一对应 socket
:该网卡对被分配的 NUMA 节点threads
:该网卡对用来发包的线程 id
- 与
示例
1 | - port_limit : 2 |
Traffic 模版配置
Stateful 模式时需配置 Traffic 模版,用以生成流量。
运行 TRex 时,通过配置-f <file>
参数来设置流量模版 yaml 文件。
配置项
duration
:测试持续时间,即打多久的流量,单位 s。会被运行时的命令行参数-d
覆盖generator
:生成流量的 IP 依据
clients_start
、clients_end
、servers_start
、servers_end
、dual_port_mask
clients_start
、clients_end
、servers_start
、servers_end
分别设置了 client 和 server 的 IP 池,该范围即限定了 client 和 server 的总数dual_port_mask
设置网卡对的偏移量,使得可以为每个网卡对配置不同的静态路由,如需要发送同样的范围,则设置为0.0.0.0
下面示例中,如果 TRex 配置设置了两个网卡对(4张网卡),则分配 IP 如下
- ```powershell
port pair-0 (0,1) —> C (16.0.0.1-16.0.0.128 ) <-> S( 48.0.0.1 - 48.0.0.128)
port pair-1 (2,3) —> C (17.0.0.129-17.0.0.255 ) <-> S( 49.0.0.129 - 49.0.0.255) + mask (“1.0.0.0”)1
2
3
4
5
6
7
8
9
10
- client 和 server 数量即为设置范围的数量,都是 255,不会因为网卡数量而变化
- 网卡对偏移量为`dual_port_mask`,第二对网卡对比第一对偏移 `1.0.0.0`
- 如果 `dual_port_mask` 设置为`0.0.0.0`,依旧设置 TRex 配置两个网卡对(4张网卡),则分配 IP 如下
- ```powershell
port pair-0 (0,1) --> C (16.0.0.1-16.0.0.128 ) <-> S( 48.0.0.1 - 48.0.0.128)
port pair-1 (2,3) --> C (16.0.0.129-16.0.0.255 ) <-> S( 48.0.0.129 - 48.0.0.255)
- ```powershell
生成流量的 IP 范围
- client IP 范围:网卡对中的 client 发送流量的源 IP、网卡对中的 server 发送流量的目的 IP
- server IP 范围:网卡对中的 client 发送流量的目的 IP、网卡对中的 server 发送流量的源 IP
clients_per_gb
:已废弃min_clients
:已废弃cap_info
name
:pcap文件,流量模版文件- 只允许单数据流
- 生成流量时使用该流量模版,并将 IP 替换为 client 和 server 的 IP 池中的 IP
cps
:每秒连接数,实际连接数需乘以运行时设置的-m
ipg
:报文间隙,单位 msrtt
:设置与ipg
相同的值w
:定义一个burst中该template生成几个flow,默认为 1
示例
1 | - duration : 10.0 |
运行命令行参数
通过./t-rex-64
运行 TRex 服务器,添加参数设置有状态/无状态以及其他选项
1 | ./t-rex-64 [mode] <options> |
使用 ./t-rex-64 -h
查看细节
设置 mode:
-f <file>
:运行有状态模式,需设置流量模版 yaml 文件-i
:运行无状态模式
可选参数:
--cfg <file>
:TRex 配置文件,如果未设置,则使用默认路径/etc/trex_cfg.yaml
-c <num>
:给每个网卡对分配的线程数,会覆盖 TRex 配置中的c
-m <num>
:流量放大倍数,生成基础流量大小乘以这个倍数的流量-d
:持续时间,单位 s,默认3600s
Stateful 示例
使用下面测试交换机性能示例来理解 Stateful 运行模式。
该示例配置有一台 TRex 机器和一台交换机。
- Trex 机器有两张网卡绑定 DPDK,port 1 作为模拟 client 的网卡,port 2 作为模拟 server 的网卡
- 交换机配置有两条静态路由,如下图所示,可以将
16.0.0.0/8
的包传到 TRex 的 port 0,将48.0.0.0/8
的包传到 TRex 的 port 1
根据下面配置,运行 TRex 有状态模式 ./t-rex-64 -f traffic.yaml
,打流流程如下
- Port 0 发包
- TRex 配置中的
interfaces
网卡对中的前一张网卡 port 0 作为 client 发包 - 发包使用 Traffic 模版配置中的
cap_info
中的第一个包,也就是其中的 DNS query 请求 - 发送的包中的源目的 IP 会随机被替换为 Traffic 模版中的配置的范围,其中,源 IP 范围
16.0.0.1
(clients_start) ~16.0.0.255
(clients_end),目的 IP 范围48.0.0.1
(servers_start) ~48.0.255.255
(servers_end) - 包被发往 TRex 配置中设置的 port 0 网卡的目的 MAC 地址
dest_mac
,本示例即通过默认网卡default_gw
得到的目的 MAC 地址
- TRex 配置中的
- Port 1 收包
- 交换机 port 2 收到 TRex 机器 port 1 发来的目的 IP 为
48.0.0.1
~48.0.255.255
的包,根据路由,将其通过 port 3 转发到 TRex 机器的 port 1 - TRex 配置中的
interfaces
网卡对中的后一张网卡 port 1 作为 server 收包
- 交换机 port 2 收到 TRex 机器 port 1 发来的目的 IP 为
- Port 1 发包
- TRex 配置中的
interfaces
网卡对中的后一张网卡 port 1 作为 server 发包 - 发包使用 Traffic 模版配置中的
cap_info
中的第二个包,也就是其中的 DNS response 回复 - 发送的包中的源目的 IP 会随机被替换为 Traffic 模版中的配置的范围,其中,源 IP 范围
48.0.0.1
(servers_start) ~48.0.255.255
(servers_end),目的 IP 范围16.0.0.1
(clients_start) ~16.0.0.255
(clients_end) - 包被发往 TRex 配置中设置的 port 1 网卡的目的 MAC 地址
dest_mac
,本示例即通过默认网卡default_gw
得到的目的 MAC 地址
- TRex 配置中的
- Port 0 收包
- 交换机 port 3 收到 TRex 机器 port 2 发来的目的 IP 为
16.0.0.1
~16.0.0.255
的包,根据路由,将其通过 port 2 转发到 TRex 机器的 port 0 - TRex 配置中的
interfaces
网卡对中的后一张网卡 port 0 作为 server 收包
- 交换机 port 3 收到 TRex 机器 port 2 发来的目的 IP 为
TRex 配置
1 | - port_limit : 2 #对应下面的网卡数量 |
Traffic 模版配置
1 | - duration : 10.0 |
pcap 包模版
1 | root@ubuntu:/opt/trex/v3.05# tcpdump -r cap2/dns.pcap |
示例
Stateful
在 Linux 虚拟机上演示 Stateful 模式简单示例,直接将流量从 ens37 打到 ens38,再从 ens38 回复到 ens37,配置如下
初始网卡信息
1 | root@ubuntu:/opt/trex/v3.05# ./dpdk_setup_ports.py -s |
1 | root@ubuntu:/opt/trex/v3.05# ip a |
TRex 配置
1 | - port_limit : 2 |
Traffic 配置
1 | - duration : 10.0 |
运行
1 | ./t-rex-64 -f /opt/trex/config/traffic.yaml -d 10 |
运行过程中,实时状态显示如下
1 | -Per port stats table #两张网卡当前的状态 |
最终结果
1 | ================== |
问题记录
初始化 EAL 环境失败
如运行 TRex 遇到下面 EAL 环境报错,则需设置大页
1 | root@ubuntu:/opt/trex/v3.05# ./t-rex-64 -f /opt/trex/config/traffic.yaml |
设置 1024 个 2048kB 大页,即写入 1024 到 hugepages-2048kB 下的 nr_hugepages 文件(初始为 0)
1 | root@ubuntu:/opt/trex/v3.05# echo 1024 | tee /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages |
重新运行,即可正常