Cisco's TRexのLayer 3 modeを試してみました
概要
TRexはCisco謹製のオープンソースのDPDKトラフィックジェネレータです。 TRexでは、Scapyやpcap fileからパケットを生成します。また、Stateless/Statefullともにサポートしています。
TRexの導入からLayer3 modeでトラフィックを流してみたので、備忘録としてまとめておきます。
検証環境
TRexサーバとDUT (Device Under Test: 測定対象) を直接接続した、最小単位の構成にしました。
TRexサーバとDUTの環境は次のとおりです。2台ともVMware ESXi 6.7上の仮想マシンで動作させました。NICのアダプタタイプはすべてVMXNET3です。
TRexは推奨であるCentOS 7.4に導入しました (参考)。 DUTは何でもよいのですが、今回はUbuntu 18.04にしました。
検証環境の図の矢印のとおりに、TRexサーバで生成したトラフィックを一方のポートからトラフィックを送信し、もう一方のポートで受信させます。
環境構築
TRexの導入
基本的には公式のInstallation Guideにしたがって導入を進めていきます。
まずTRexを適当な場所にダウンロードして解凍します。今回利用するTRexのバージョンは v2.53
です。
TRex:~$ sudo su - TRex:~# mkdir -p /opt/trex TRex:~# curl -LO http://trex-tgn.cisco.com/trex/release/latest TRex:~# cd /opt/trex TRex:~# tar xvf latest
次にDPDKのセットアップをしていきます。
セットアップに必要なツールをインストールします。
TRex:~# yum install -y pciutils kernel-devel-`uname -r` TRex:~# yum group install "Development tools"
そして、TRexが提供するPythonスクリプトファイルを -i
の対話形式オプションで実行します。
次の内容を入力します。
- 記事のタイトルどおりLayer 3 modeを利用
ens224
(ID: 1) とens256
(ID: 2) をTRexのポートとして利用- 検証環境の図のとおりにIPアドレスとデフォルトゲートウェイを設定
あとは必要なカーネルモジュールのロードなどをこのスクリプトが実施してくれます。
TRex:~# cd /opt/trex/v.2.53 TRex:~# ./dpdk_setup_ports.py -i By default, IP based configuration file will be created. Do you want to use MAC based config? (y/N)N +----+------+---------+-------------------+-----------------------------+---------+----------+----------+ | ID | NUMA | PCI | MAC | Name | Driver | Linux IF | Active | +====+======+=========+===================+=============================+=========+==========+==========+ | 0 | -1 | 0b:00.0 | 00:0c:29:84:3f:d4 | VMXNET3 Ethernet Controller | vmxnet3 | ens192 | *Active* | +----+------+---------+-------------------+-----------------------------+---------+----------+----------+ | 1 | -1 | 13:00.0 | 00:0c:29:84:3f:de | VMXNET3 Ethernet Controller | vmxnet3 | ens224 | | +----+------+---------+-------------------+-----------------------------+---------+----------+----------+ | 2 | -1 | 1b:00.0 | 00:0c:29:84:3f:e8 | VMXNET3 Ethernet Controller | vmxnet3 | ens256 | | +----+------+---------+-------------------+-----------------------------+---------+----------+----------+ Please choose even number of interfaces from the list above, either by ID , PCI or Linux IF Stateful will use order of interfaces: Client1 Server1 Client2 Server2 etc. for flows. Stateless can be in any order. Enter list of interfaces separated by space (for example: 1 3) : 1 2 For interface 1, assuming loopback to it's dual interface 2. Putting IP 1.1.1.1, default gw 2.2.2.2 Change it?(y/N).y Please enter IP address for interface 1: 1.1.1.1 Please enter default gateway for interface 1: 1.1.1.3 For interface 2, assuming loopback to it's dual interface 1. Putting IP 2.2.2.2, default gw 1.1.1.1 Change it?(y/N).y Please enter IP address for interface 2: 2.2.2.2 Please enter default gateway for interface 2: 2.2.2.3 Print preview of generated config? (Y/n)Y ### Config file generated by dpdk_setup_ports.py ### - version: 2 interfaces: ['13:00.0', '1b:00.0'] port_info: - ip: 1.1.1.1 default_gw: 1.1.1.3 - ip: 2.2.2.2 default_gw: 2.2.2.3 platform: master_thread_id: 0 latency_thread_id: 1 dual_if: - socket: 0 threads: [2,3] Save the config to file? (Y/n)Y Default filename is /etc/trex_cfg.yaml Press ENTER to confirm or enter new file: Saved to /etc/trex_cfg.yaml.
これでTRexを動かす準備が完了しました。
DUTの設定
検証環境の構成に従って、IPアドレスを設定しておきます。
DUT:~# cat /etc/netplan/50-cloud-init.yaml network: version: 2 ethernets: ens192: addresses: - 1.1.1.3/24 ens224: addresses: - 2.2.2.3/24 DUT:~# netplan apply
TRexを動かす
以降のコマンド入力はTRexを配置したディレクトリ ( /opt/trex/v2.53
) で実施しています。
TRexの起動
TRexサーバの起動
動作確認のために、対話形式でTRexを起動します。
TRex:~# ./t-rex-64 -i
TRexが起動すると、TRexで利用するインタフェースがDPDKで利用されるようになり、
ip address show
しても見えなくなります。
この状態でTRexサーバのそれぞれにインタフェースにDUTからpingしてみると、
TRexとDUTの間で疎通が確認できます。
DUT:~# ping -c 1 1.1.1.1 PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data. 64 bytes from 1.1.1.1: icmp_seq=1 ttl=128 time=47.0 ms --- 1.1.1.1 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 47.008/47.008/47.008/0.000 ms DUT:~# ping -c 1 2.2.2.2 PING 2.2.2.2 (2.2.2.2) 56(84) bytes of data. 64 bytes from 2.2.2.2: icmp_seq=1 ttl=128 time=8.70 ms --- 2.2.2.2 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 8.703/8.703/8.703/0.000 ms
TRexコンソールの起動
./t-rex-64 -i
でTRexサーバが起動している状態で別のターミナルを起動し、TRex consoleからTRexサーバに接続します。
TRex:~# ./trex-console
そのTRexコンソールからPythonで作成したパケットを流してみます。
TRexコンソールからStatelessトラフィック1フローを流す
トラフィックの生成ファイル
stl/
配下にTRexのStateless traffic用のサンプルファイルがいくつも配置されています。
stl/udp_1pkt.py
というシンプルなUDPパケットを送信するファイルを今回の環境用に書き換えます。
書き換えたPythonファイルは次のとおりです。
stl/udp_1pkt_2.py
from trex_stl_lib.api import * class STLS1(object): def __init__ (self): self.fsize = 64; def create_pkt_base (self): return Ether()/IP(src="1.1.1.1",dst="2.2.2.2")/UDP(dport=50000,sport=50001) def create_stream (self): # Create base packet and pad it to size size = self.fsize - 4; # HW will add 4 bytes ethernet FCS base_pkt = self.create_pkt_base () pad = max(0, size - len(base_pkt)) * 'x' pkt = STLPktBuilder(pkt = base_pkt/pad, vm = []) return STLStream(packet = pkt, mode = STLTXCont()) def get_streams (self, direction = 0, **kwargs): # create 1 stream return [ self.create_stream() ] # dynamic load - used for trex console or simulator def register(): return STLS1()
不要な箇所は削り、シンプルにしています。
Scapyで次のようなパケットを生成しています。
Ethernetフレームの最小サイズは64バイトであるため、
L7で64バイトになるようデータとして xxxxxxx
を詰めておきます。
トラフィックは送信し続けるモード ( STLTXCont()
) にしておきます。
パケットの確認
TRexでトラフィックを流す前に、作成したPythonファイルで生成されるパケットをpcapファイルに出力して動作確認します。
TRexでは、 stl-sim
が準備されているため、それを利用します。
TRex:~# ./stl-sim -f stl/udp_1pkt_2.py -o /usr/tmp/udp_1pkt_2.pcap executing command: '/opt/trex/v2.53/bp-sim-64-debug --pcap --sl --cores 1 --limit 5000 -f /tmp/tmpNYMdGQ -o /usr/tmp/udp_1pkt_2.pcap' set dpdk queues mode to ONE_QUE General info: ------------ image type: debug I/O output: /usr/tmp/udp_1pkt_2.pcap packet limit: 5000 core recording: merge all Configuration info: ------------------- ports: 2 cores: 1 Port Config: ------------ stream count: 1 max PPS : 1.00 pps max BPS L1 : 672.00 bps max BPS L2 : 512.00 bps line util. : 0.00 % Starting simulation... Simulation summary: ------------------- core index 0 ----------------- simulated packets : 5000 non active packets : 0 on-wire packets : 5000 Total: ----------------- simulated packets : 5000 non active packets : 0 on-wire packets : 5000 written 5000 packets to '/usr/tmp/udp_1pkt_2.pcap'
生成されたファイルをWiresharkで開くと、想定したとおりのパケットが確認できます。
TRexコンソールからトラフィックを流す
先ほどから起動している trex-console
から stl/udp_1pkt_2.py
を動かしてみます。
100k bpsでトラフィックを流してみます。送信ポートは ID: 0 (IPアドレス 1.1.1.1
を割り当て中) を指定します。
trex>start -p 0 -m 100kbps -f stl/udp_1pkt_2.py -p 0 Removing all streams from port(s) [0]: [SUCCESS] Attaching 1 streams to port(s) [0]: [SUCCESS] Starting traffic on port(s) [0]: [SUCCESS] 9.53 [ms]
TRexサーバ側で、送信 (Tx) と受信 (Rx) がそれぞれ100K bps前後になっていることが確認できます。
-Per port stats table ports | 0 | 1 ----------------------------------------------------------------------------------------- opackets | 770824266 | 65986289 obytes | 49332753176 | 4223122610 ipackets | 8 | 470350760 ibytes | 664 | 30102450602 ierrors | 0 | 7498 oerrors | 0 | 0 Tx Bw | 100.06 Kbps | 0.00 bps -Global stats enabled Cpu Utilization : 0.0 % Platform_factor : 1.0 Total-Tx : 100.06 Kbps Total-Rx : 100.06 Kbps Total-PPS : 195.43 pps Total-CPS : 0.00 cps Expected-PPS : 0.00 pps Expected-CPS : 0.00 cps Expected-BPS : 0.00 bps Active-flows : 0 Clients : 0 Socket-util : 0.0000 % Open-flows : 0 Servers : 0 Socket : 0 Socket/Clients : -nan Total_queue_full : 203155427 drop-rate : 0.00 bps current time : 7247.9 sec test duration : 0.0 sec
DUTの ens224
で tcpdump
すると、パケットが転送されている様子が確認されます。
DUT:~# tcpdump -i ens224 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on ens224, link-type EN10MB (Ethernet), capture size 262144 bytes 15:23:06.048913 ARP, Request who-has 2.2.2.2 tell test-ubuntu-01, length 28 15:23:06.049366 ARP, Reply 2.2.2.2 is-at 00:0c:29:84:3f:e8 (oui Unknown), length 46 15:23:06.960427 IP one.one.one.one.50001 > 2.2.2.2.50000: UDP, length 18 15:23:06.960449 IP one.one.one.one.50001 > 2.2.2.2.50000: UDP, length 18 15:23:07.960437 IP one.one.one.one.50001 > 2.2.2.2.50000: UDP, length 18 15:23:07.960466 IP one.one.one.one.50001 > 2.2.2.2.50000: UDP, length 18
また、TRexコンソールでも、 tui
によって送受信レート等を確認できます。
trex>tui Global Statistitcs connection : localhost, Port 4501 total_tx_L2 : 99.96 Kb/sec version : STL @ v2.53 total_tx_L1 : 131.2 Kb/sec cpu_util. : 0.05% @ 1 cores (1 per port) total_rx : 99.96 Kb/sec rx_cpu_util. : 0.0% / 195.24 pkt/sec total_pps : 195.24 pkt/sec async_util. : 0.05% / 1.47 KB/sec drop_rate : 0 b/sec queue_full : 0 pkts Port Statistics port | 0 | 1 | total -----------+-------------------+-------------------+------------------ owner | root | root | link | UP | UP | state | TRANSMITTING | IDLE | speed | 10 Gb/s | 10 Gb/s | CPU util. | 0.05% | 0.0% | -- | | | Tx bps L2 | 99.96 Kbps | 0 bps | 99.96 Kbps Tx bps L1 | 131.2 Kbps | 0.01 bps | 131.2 Kbps Tx pps | 195.24 pps | 0 pps | 195.24 pps Line Util. | 0 % | 0 % | --- | | | Rx bps | 0 bps | 99.96 Kbps | 99.96 Kbps Rx pps | 0 pps | 195.24 pps | 195.24 pps ---- | | | opackets | 33906 | 6 | 33912 ipackets | 0 | 33912 | 33912 obytes | 2169984 | 384 | 2170368 ibytes | 0 | 2170368 | 2170368 tx-pkts | 33.91 Kpkts | 6 pkts | 33.91 Kpkts rx-pkts | 0 pkts | 33.91 Kpkts | 33.91 Kpkts tx-bytes | 2.17 MB | 384 B | 2.17 MB rx-bytes | 0 B | 2.17 MB | 2.17 MB ----- | | | oerrors | 0 | 0 | 0 ierrors | 0 | 0 | 0 status: / Press 'ESC' for navigation panel... status:
TRexコンソールで開始したトラフィックは、 stop
コマンドで停止します。
trex>stop Stopping traffic on port(s) [0]: [SUCCESS] 2.83 [ms]
次に複数フローを流してみます。 その前に、起動しているTRexサーバとTRexコンソールを一旦終了しておきます。
TRexコンソールからStatelessトラフィックを複数フローを流す
これまではTRexで1フローのみ ( 1.1.1.1
から 2.2.2.2
宛) でトラフィックを流してきました。
次は複数のフローを流してみます。
YAMLファイルを記述することで、詳細な設定でTRexサーバを動かすことができます。
今回は、予め用意されている cap2/dns_tw.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 tw : # set timer wheel configuration options buckets : 32768 levels : 2 bucket_time_usec : 20.0 cap_info : - name: cap2/dns.pcap cps : 1.0 ipg : 10000 rtt : 10000 w : 1
pcapファイルで用意されたトラフィックを流していきます。
Layer3 modeで 1.1.1.0/24
から 2.2.2.0/24
宛にトラフィックを流すことはできない
(参考:http://trex-tgn.cisco.com/trex/doc/trex_config_guide.html#slide-3) ようです。
なので、TRexのIPアドレスとclients/serversのIPアドレスプレフィックスは別のものを利用します
(参考:http://trex-tgn.cisco.com/trex/doc/trex_config_guide.html#slide-2)。
TRexサーバが流すトラフィックをDUTで中継できるように、DUTに経路情報を追加します。
DUT:~# ip -4 route add 16.0.0.0/24 via 1.1.1.1 dev ens192 DUT:~# ip -4 route add 48.0.0.0/24 via 2.2.2.2 dev ens224
t-rex-64
から直接TRexでトラフィックを生成していきます。今回もID: 0のポートからトラフィックを流します。
TRex:~# ./t-rex-64 -p 0 -m 100kbps -f cap2/dns_tw.yaml -Per port stats table ports | 0 | 1 ----------------------------------------------------------------------------------------- opackets | 190 | 191 obytes | 16150 | 16227 ipackets | 96 | 95 ibytes | 8899 | 7315 ierrors | 0 | 0 oerrors | 0 | 0 Tx Bw | 33.70 Kbps | 33.33 Kbps -Global stats enabled Cpu Utilization : 0.0 % Platform_factor : 1.0 Total-Tx : 67.03 Kbps Total-Rx : 33.58 Kbps Total-PPS : 98.53 pps Total-CPS : 49.51 cps Expected-PPS : 200.00 pps Expected-CPS : 100.00 cps Expected-BPS : 136.00 Kbps Active-flows : 1 Clients : 511 Socket-util : 0.0003 % Open-flows : 191 Servers : 255 Socket : 111 Socket/Clients : 0.2 drop-rate : 33.45 Kbps current time : 3.0 sec test duration : 3597.0 sec
最後に、DUTの ens224
で tcpdump
もしてみます。
DUT:~# tcpdump -i ens224 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on ens224, link-type EN10MB (Ethernet), capture size 262144 bytes 17:28:03.426173 ARP, Reverse Request who-is 00:0c:29:84:3f:e8 (oui Unknown) tell 00:0c:29:84:3f:e8 (oui Unknown), length 46 17:28:03.426187 ARP, Reverse Request who-is 00:0c:29:84:3f:e8 (oui Unknown) tell 00:0c:29:84:3f:e8 (oui Unknown), length 46 17:28:04.425679 ARP, Reverse Request who-is 00:0c:29:84:3f:e8 (oui Unknown) tell 00:0c:29:84:3f:e8 (oui Unknown), length 46 17:28:04.425690 IP 0.0.0.0 > all-systems.mcast.net: igmp query v3 [max resp time 1.0s] 17:28:04.434847 ARP, Request who-has 2.2.2.2 (01:03:05:07:09:00 (oui Unknown)) tell 2.2.2.2, length 46 17:28:04.434855 ARP, Request who-has test-ubuntu-01 (01:03:05:07:09:01 (oui Unknown)) tell 2.2.2.2, length 46 17:28:04.434863 ARP, Reply test-ubuntu-01 is-at 00:0c:29:e8:81:6d (oui Unknown), length 28 17:28:04.548155 IP bpe-ssl.ams.hpecore.net.41668 > 48.0.0.1.domain: 48 A? www.cisco.com. (31) 17:28:04.557095 IP 48.0.0.1.domain > bpe-ssl.ams.hpecore.net.41668: 48* 1/0/0 A 100.100.100.100 (47) 17:28:04.558116 IP 16.0.0.2.59073 > 48.0.0.2.domain: 48 A? www.cisco.com. (31) 17:28:04.568080 IP 16.0.0.3.10942 > 48.0.0.3.domain: 48 A? www.cisco.com. (31) 17:28:04.577086 IP 48.0.0.3.domain > 16.0.0.3.10942: 48* 1/0/0 A 100.100.100.100 (47) 17:28:04.578092 IP 16.0.0.4.28347 > 48.0.0.4.domain: 48 A? www.cisco.com. (31) 17:28:04.588079 IP 16.0.0.5.45752 > 48.0.0.5.domain: 48 A? www.cisco.com. (31) 17:28:04.597085 IP 48.0.0.5.domain > 16.0.0.5.45752: 48* 1/0/0 A 100.100.100.100 (47)