TRex是思科研发的一款成熟的基于DPDK的网络测试工具。TRex是一款开源的发包工具,它跑在标准的intel处理芯片上,同时支持stateful和stateless模式,stateful可以描述L4~L7层的应用场景,而stateless主要用来进行定制包的发包。思科官方使用手册:TRex official manual。Github上思科TRex Traffic Generator代码仓库。目前主要利用TRex的DPDK高线速发包能力 Current Stateful TRex Feature sets (STF)
High scale of realistic traffic (number of clients, number of server, bandwidth)
Latency/Jitter measurements
Flow ordering checks
NAT, PAT dynamic translation learning
Learn TCP SYN sequence randomization - vASA/Firepower use case
Cluster mode for Controller tests
IPV6 inline replacement
Some cross flow support (e.g RTSP/SIP)
安装依赖项。
sudo apt-get update sudo apt-get install -y gcc g++ python git zlib1g-dev pciutils vim kmod strace wget
然后,下载最新的trex release。
cd $P4_HOME mkdir trex cd trex wget --no-cache http://trex-tgn.cisco.com/trex/release/latest tar -zxvf latest cd v2.75 # 本次下载的版本是v2.75
在ubuntu下面执行dpdk安装命令。
sudo apt-get update sudo apt-get install dpdk
配置dpdk网口。
cd $P4_HOME/trex/v2.75 sudo ./dpdk_setup_ports.py -s
返回结果显示,目前主机上Intel X710网卡有两个端口eth1和eth3。网卡还在使用内核驱动,还没绑定dpdk功能。等trex发包程序运行起来,X710网卡的两个网口会加载DPDK-compatible driver,比如igb_uio。
Network devices using DPDK-compatible driver ============================================ <none> Network devices using kernel driver =================================== 0000:00:1f.6 'Ethernet Connection (3) I219-LM' if=eth2 drv=e1000e unused=igb_uio,vfio-pci,uio_pci_generic 0000:02:00.0 'I210 Gigabit Network Connection' if=eth0 drv=igb unused=igb_uio,vfio-pci,uio_pci_generic *Active* 0000:d5:00.0 'Ethernet Controller X710 for 10GbE SFP+' if=eth1 drv=i40e unused=igb_uio,vfio-pci,uio_pci_generic 0000:d5:00.1 'Ethernet Controller X710 for 10GbE SFP+' if=eth3 drv=i40e unused=igb_uio,vfio-pci,uio_pci_generic
本次实验对系统的要求是:4核CPU以及4GB的内存 正在上传…重新上传取消 Trex主机的原理就是两个网口模仿发送者和接受者,从而进行通讯,产生报文。 正在上传…重新上传取消 本次实验中,trex主机的两个端口和交换机直连,两端口的ip地址分别为10.0.0.1和10.0.0.2。实验目的为在trex主机中对上诉DNS报文流量进行重放,当流量经过测试网络时,在交换机上捕获报文内容,流量最终回到trex主机。
编写 trex 配置文件, 配置文件的模板可以从 trex解压目录的 cfg 文件夹中找到。以cfg文件夹中的simple_cfg.yaml配置文件为例,将配置文件的内容修改为如下(主要是对interfaces的相关信息进行了修改)。
$ vim $P4_HOME/trex/v2.75/cfg/simple_cfg.yaml - port_limit : 2 version : 2 #List of interfaces. Change to suit your setup. Use ./dpdk_setup_ports.py -s to see available options interfaces : ["trex-eth0","trex-eth1"] port_info : # Port IPs. Change to suit your needs. In case of loopback, you can leave as is. - ip : 10.0.0.1 default_gw : 10.0.0.2 - ip : 10.0.0.2 default_gw : 10.0.0.1
注:YAML 是 "YAML Ain't a Markup Language"(YAML 不是一种标记语言)的递归缩写。在开发这种语言时,YAML 的意思其实是:"Yet Another Markup Language"(仍是一种标记语言)。YAML 的语法和其他高级语言类似,并且可以简单表达清单、散列表,标量等数据形态。可以用vi
来编辑和语法亮显yaml格式的配置文件。
在上面的trex配置文件中
interfaces 参数指定本次作为发送方和接收方的端口。
虚拟环境中, 在trex终端中使用
ifconfig
命令查看虚拟网卡的标识符和ip地址。在真实环境中可以在trex 解压目录下执行
./dpdk_setup_ports.py -s
,查看相应的设备代号。
cd $P4_HOME/trex/v2.75 sudo ./dpdk_setup_ports.py -s
port_info 参数是对两个网口的ip进行配置。其中
ip为这个网口本身的ip,
default_gw 为是这个网口直连设备的ip。在本次实验中,由于交换机是二层设备,所以trex-eth0的默认网关为trex-eth1的ip地址,trex-eth1的默认网关为trex-eth0的ip地址。
修改完成后可以执行以下命令直接拷贝配置文件的模板到/etc
文件夹下。
sudo cp $P4_HOME/trex/v2.75/cfg/simple_cfg.yaml /etc/trex_cfg.yaml
Trex 可以将实际网络中抓包生成的pcap文件做模板,快速生成各种协议的报文流。pcap可以说是一种通用的数据流格式,很多开源的项目都需要用到这种格式的文件。随着libpcap库成为UNIX系统上网络报文捕捉的标准库,pcap也成为了开源社区的标准记录网络报文的文件格式。详细内容参考Wireshark的libpcap文件格式的介绍文档。
Trex 有很多 pcap网络抓包记录的例子, 放在解压目录$P4_HOME/trex/v2.75
下的 cap2
文件夹。在重放pcap网络流量之前,首先需要准备 pcap文件以及对应的配置文件。这里以cap2/dns.yaml
为例。
duration : 10.0 generator : distribution : "seq" clients_start : "16.0.0.1" clients_end : "16.0.1.255" servers_start : "48.0.0.1" servers_end : "48.0.0.255" clients_per_gb : 201 min_clients : 101 dual_port_mask : "1.0.0.0" tcp_aging : 1 udp_aging : 1 cap_info : - name: cap2/dns.pcap cps : 1.0 ipg : 10000 rtt : 10000 w : 1
参数:
clients_start client_end 等参数都是指生成模拟流量的服务端和客户端的地址范围
name 为 pcap文件路径, 这个pcap文件是所有流成生的模板
cps 为每秒连接次数
ipg 报文间隙(microseconds)
w : Should be the same as ipg
在P4环境下的mininet文件夹中,找到 mininet/examples 目录。 执行 python miniedit.py
即可启动图形化miniedit 界面,绘制拓扑图,该实验的拓扑为trex主机和交换机s1直连。
cd $P4_HOME/mininet/mininet/examples python miniedit.py
在图形化界面的左端选择一个主机(host)和一个交换机(LegacySwitch)。鼠标右击主机(host),选择properties
,修改Hostname
为trex,在trex主机和交换机s1之间添加一条连接,在图形化界面的File
选项中选择Export Level 2 Script
导出 python 拓扑脚本文件。python脚本文件命名为edtopo
,导出的目录为Trex的解压目录v2.75文件夹中,导出完成后,退出图形化界面。
由于trex主机有两个端口,所以trex主机和交换机s1应该有两个连接。由于可视化过程中只能在trex主机和交换机s1之间添加一条连接,所以需要手动更改生成的python文件以添加连接。使用cd
命令切换到trex的解压目录v2.75文件夹下,并使用vim edtopo.py
修改生成的python文件,修改后的python文件如下所示(需要修改的部分已经在下面的程序中注明):
#!/usr/bin/python from mininet.net import Mininet from mininet.node import Controller, RemoteController, OVSController from mininet.node import CPULimitedHost, Host, Node from mininet.node import OVSKernelSwitch, UserSwitch from mininet.node import IVSSwitch from mininet.cli import CLI from mininet.log import setLogLevel, info from mininet.link import TCLink, Intf from subprocess import call def myNetwork(): net = Mininet( topo=None, build=False, ipBase='10.0.0.0/8') info( '*** Adding controller\n' ) info( '*** Add switches\n') s1 = net.addSwitch('s1', cls=OVSKernelSwitch, failMode='standalone') info( '*** Add hosts\n') trex = net.addHost('trex', cls=Host, ip='10.0.0.1', defaultRoute=None) info( '*** Add links\n') # 主要修改这里, 这里增加了一个链路,并且指定ip地址 net.addLink(trex, s1, params1={'ip':'10.0.0.1/8'}) net.addLink(trex, s1, params1={'ip':'10.0.0.2/8'}) info( '*** Starting network\n') net.build() info( '*** Starting controllers\n') for controller in net.controllers: controller.start() info( '*** Starting switches\n') net.get('s1').start([]) info( '*** Post configure switches and hosts\n') CLI(net) net.stop() if __name__ == '__main__': setLogLevel( 'info' ) myNetwork()
从上面的代码注意到修改的地方:
增加了一条 trex主机到交换机 s1 的链路
为trex主机的端口分配了ip地址, 这个需要根据测试的网络需要进行配置。
cd $P4_HOME/mininet/mininet/examples sudo python edtopo.py
xterm s1
tcpdump -i s1-eth1
xterm trex
cd $P4_HOME/trex/v2.75 ./t-rex-64 -f cap2/dns.yaml -d 30
其中,-f 参数后面就是 pcap配置文件的路径。30 代表测试时间(秒)。 最后,可以在交换机s1的终端看到对应的DNS请求和应答报文。
在上节中,已经实现Trex报文发生器的基本功能。在这一节中,分别使用Trex报文发生器和主机的模拟发包达到流量生成的目的,流量在生成后经过交换机s1,在交换机中统计相关数据。该实验的P4代码在交换机s1中部署了六个registers进行基于count-min sketch的包计数,其中前三个registers记录包个数packets_number,后三个registesr记录字节数bytes_number。
需要使用p4-utils提供控制面的一些功能。p4-utils是Mininet的扩展,以支持P4设备。原虚拟机中是没有的,在P4的目录下,使用如下安装命令:
git clone https://github.com/nsg-ethz/p4-utils.git cd p4-utils sudo ./install.sh cd .. #回到P4目录
编写 trex 配置文件, 进入到trex解压目录下(比如$P4_HOME/trex/v2.75),配置文件的模板可以从 cfg 文件夹中找到,以cfg文件夹中的simple_cfg.yaml配置文件为例,将配置文件的内容修改为如下(主要是对interfaces的相关信息进行了修改):
- port_limit : 2 version : 2 #List of interfaces. Change to suit your setup. Use ./dpdk_setup_ports.py -s to see available options interfaces : ["h1-eth0","h1-eth1"] port_info : # Port IPs. Change to suit your needs. In case of loopback, you can leave as is. - ip : 10.0.1.1 default_gw : 10.0.1.2 - ip : 10.0.1.2 default_gw : 10.0.1.1
其中 interfaces 参数指定本次作为发送方和接收方的端口,本例中就是唯一的主机h1的两个以太网端口。port_info参数是对两个网口的ip进行配置,其中ip为这个网口本身的ip,default_gw是为这个网口直连设备的ip。 使用以下命令将修改后的配置文件复制到etc下
sudo cp cfg/simple_cfg.yaml /etc/trex_cfg.yaml
Trex可以通过读取抓包生成的pcap文件快速生成各种协议的报文流,在此之前要准备pcap文件及对应配置文件。
pcap文件为在Trex解压目录的avl文件夹中,找到pcap文件夹下的delay_10_smtp_0.pcap文件;
配置文件为在Trex解压目录的cap2文件夹中,找到对应的pcap配置文件short_tcp.yaml。 配置文件的内容如下:
- duration : 40 generator : distribution : "seq" clients_start : "16.0.0.1" clients_end : "16.0.0.255" servers_start : "48.0.0.1" servers_end : "48.0.255.255" clients_per_gb : 201 min_clients : 101 dual_port_mask : "1.0.0.0" tcp_aging : 0 udp_aging : 0 cap_info : - name: avl/delay_10_smtp_0.pcap cps : 1.0 ipg : 10000 rtt : 10000 w : 1
cap_info下的name即为pcap文件所在位置
使用Trex发包的实验除了h1窗口中的发包指令与前面不同,其余操作步骤都与前一个例子相同。h1窗口中的发包指令不再使用send.py发送批量构造的虚拟包,而是利用Trex读取pcap文件,对其中的报文流进行重放发送。依然是从主机h1的eth0端口发出,经过交换机s1处理和转发后由主机h1的eth1端口接收。
打开两个控制台,使用cd
命令均进入到P4目录下的basic_p4_measurement中
在控制台一中输入sudo p4run
。
使用命令xterm h1
打开主机h1窗口
在主机h1中使用
cd
命令切换到Trex的解压目录v2.75文件夹下,输入命令(!!!但不执行)
./t-rex-64 -f cap2/short_tcp.yaml -d 30
其中,-f参数后面是pcap配置文件路径(这里用short_tcp.yaml文件),最后的30代表测试时间(秒)。
在控制台二中运行python cm-sketch-controller.py --option set_hashes
,这一步的目的是给交换机中的hash函数配置参数以及写入转发表规则。
继续在控制台二中运行sudo python cm-sketch-controller.py --option start_working
,可以在终端二中看到,屏幕每5秒会打印一次六个register的全部位置的值,每30秒会将当前的值保存到一个txt文件中,同时将所有register清零,以便重新开始计数。(由于没发包,当前显示全零)
在h1的窗口中按下回车,运行发包指令,在输出中可以看到发出数据包的统计信息,同时,在控制台二可以看到各个计数器的值。
在控制台一中使用exit
退出mininet