Juniper製のオープンソースパケットジェネレータ WARP17を試してみた

# はじめに

[WARP17](https://github.com/Juniper/warp17)はJuniperがオープンソースとして公開している高機能なパケットジェネレータです。サーバから10Gbpsの負荷を流せるオープンソースのパケットジェネレーターを探していたところ@kazubuさんから紹介してもらいました。試してみたところさすがJuniperが作っているだけあって完成度の高いソフトであると感じましたので、私が試した限りの構築ノウハウを共有したいと思います。


# WARP17の特徴

- DPDK対応なのでサーバのスペックを最大限生かしてトラフィックを生成可能
- 流れているトラフィック量をリアルタイムにモニター可能(Juniperのmonitorコマンドのイメージ)
- L7通信を擬似可能(現状はhttpのみ。今後拡張予定)なので色々な検証に応用できそう。
- 試験の自動化を行うためのPython/Perl API機能有り。

また、以下のように様々な検証構成を組むことができる高い柔軟性があります(構成名は私が勝手に付けただけです)。

- 単体構成
![network1.PNG](https://qiita-image-store.s3.amazonaws.com/0/165176/01557da8-b7fa-7e37-b30a-0b5a69514057.png)

- セパレート構成
![network2.PNG](https://qiita-image-store.s3.amazonaws.com/0/165176/ce6c2942-0cdf-9890-f72a-9140d4ce9c0e.png)

- 仮想マシン構成(VMware, KVM)
![network6.PNG](https://qiita-image-store.s3.amazonaws.com/0/165176/2cf97817-4d98-57a9-4412-2c01588ec63e.png)

スイッチをはさんだ図になっていますがもちろんセグメント越えもできます。

今回は上記の全構成を紹介したいと思いますので長文ご容赦ください。また、WARP17は使用するポート数によってオプションのチューニング内容が変わりますので、単体構成については2ポート、4ポート、8ポートの3パターンについて紹介します。

# サーバのスペック

- PowerEdge R630  
  - CPU
        - ｲﾝﾃﾙ Xeon E5-2695 v4 2.1GHz,HT,18C/36T x 2枚
  - メモリー
        - 192GB
  - OS
        - ubuntu-16.04.2 LTS (GNU/Linux 4.4.0-62-generic x86_64)

40Gbps以上のトラフィックを一台で送受信しない限りは上記のスペックは必須ではありません。今回紹介する内容からは省いていますが、本環境で単体構成における10Gbpsの下限となるスペックについて確認したところ、UDPで大容量ファイルを落とすような片方向のスループットが出やすいシナリオを使うことで、4core/20GBメモリーの割り当てでも10Gbpsが生成できました。また、セパレート構成にして複数マシンに負荷を分散することで、必要なスペックを半減できる可能性もあります。

# インストール
手順は[WARP17のReadme](https://github.com/Juniper/warp17)とほぼ同じですが、Ubuntu14.04ではなく16.02で構築したので若干の差異があります。DPDKについては[slankさんのブログ](http://blog.slankdev.net/2016/05/08/dpdk-setup/)が分かりやすいので、DPDKを初めて触る人はWARP17構築前に一度目を通しておくことをお勧めします。

**DPDKのインストール**

```
testerman@tester1:~$ sudo apt-get update
testerman@tester1:~$ sudo apt-get upgrade
testerman@tester1:~$ sudo apt-get install build-essential python libncurses5-dev

testerman@tester1:~$ wget http://dpdk.org/browse/dpdk/snapshot/dpdk-16.11.tar.xz
→DPDKの最新版は17.02ですが、WARP17がコンパイルエラーになったので、サイト例の通り16.11で進めます。

testerman@tester1:~$ tar xf dpdk-16.11.tar.xz
testerman@tester1:~$ cd dpdk-16.11/
testerman@tester1:~/dpdk-16.11$ make install T=x86_64-native-linuxapp-gcc
(省略)
Installation cannot run with T defined and DESTDIR undefined
→上記メッセージが表示されますが、x86_64-native-linuxapp-gccディレクトリは正常に作成されており
igb_uio.koもロードできるのでこのまま進めました。

testerman@tester1:~/dpdk-16.11$ sudo modprobe uio
testerman@tester1:~/dpdk-16.11$ sudo insmod x86_64-native-linuxapp-gcc/kmod/igb_uio.ko
testerman@tester1:~/dpdk-16.11$ sudo vi /etc/default/grub
(省略)
GRUB_CMDLINE_LINUX="default_hugepagesz=1G hugepagesz=1G hugepages=32"
→まずは2ポートを使った試験を行うため、サイト例にあわせて32GBのメモリーを使用します。
hugepagesには後述のWARP17実行時に指定するメモリー量よりも大きい値を指定する必要があります。
試験のつど修正するのも大変なので、可能なら大きい値を指定しておいても良いかもしれません。

testerman@tester1:~/dpdk-16.11$ sudo update-grub
testerman@tester1:~/dpdk-16.11$ sudo reboot

testerman@tester1:~$ sudo mkdir /mnt/huge_1GB
testerman@tester1:~$ sudo vi /etc/fstab
(省略)
nodev           /mnt/huge_1GB   hugetlbfs pagesize=1GB  0       0
→末尾に追記します。

testerman@tester1:~$ sudo mount -a
testerman@tester1:~$ export RTE_SDK=/home/testerman/dpdk-16.11
testerman@tester1:~$ export RTE_TARGET=x86_64-native-linuxapp-gcc
```

**Google Protocol Buffersのインストール**

```
testerman@tester1:~$ mkdir deb && cd $_
testerman@tester1:~/deb$ wget http://mirrors.kernel.org/ubuntu/pool/universe/p/protobuf-c/libprotobuf-c0_0.15-1build1_amd64.deb
testerman@tester1:~/deb$ wget http://mirrors.kernel.org/ubuntu/pool/universe/p/protobuf-c/libprotobuf-c0-dev_0.15-1build1_amd64.deb
testerman@tester1:~/deb$ wget http://mirrors.kernel.org/ubuntu/pool/main/p/protobuf/libprotobuf8_2.5.0-9ubuntu1_amd64.deb
testerman@tester1:~/deb$ wget http://mirrors.kernel.org/ubuntu/pool/main/p/protobuf/libprotoc8_2.5.0-9ubuntu1_amd64.deb
testerman@tester1:~/deb$ wget http://mirrors.kernel.org/ubuntu/pool/universe/p/protobuf-c/protobuf-c-compiler_0.15-1build1_amd64.deb

testerman@tester1:~/deb$ sudo dpkg -i libprotobuf-c0_0.15-1build1_amd64.deb
testerman@tester1:~/deb$ sudo dpkg -i libprotobuf-c0-dev_0.15-1build1_amd64.deb
testerman@tester1:~/deb$ sudo dpkg -i libprotobuf8_2.5.0-9ubuntu1_amd64.deb
testerman@tester1:~/deb$ sudo dpkg -i libprotoc8_2.5.0-9ubuntu1_amd64.deb
testerman@tester1:~/deb$ sudo dpkg -i protobuf-c-compiler_0.15-1build1_amd64.deb
```

**WARP17のインストール**

```
testerman@tester1:~$ sudo apt-get install protobuf-compiler libprotobuf-dev python-protobuf
testerman@tester1:~$ git clone https://github.com/Juniper/warp17.git
testerman@tester1:~$ cd warp17/
testerman@tester1:~/warp17$ make
testerman@tester1:~/warp17$ sudo chown root build/warp17
testerman@tester1:~/warp17$ sudo chmod u+s build/warp17
```

**Python virtualenvのインストール**

私は試せていませんが、Python APIを使って試験の自動化が可能なようです。
自動化しない場合は実施不要ですが、念のため手順を記載しておきます。

```
testerman@tester1:~/warp17$ sudo apt-get install python-pip
testerman@tester1:~/warp17$ sudo pip install virtualenv
testerman@tester1:~/warp17$ virtualenv warp17-venv
testerman@tester1:~/warp17$ source warp17-venv/bin/activate
(warp17-venv) testerman@tester1:~/warp17$ pip install -r python/requirements.txt
(warp17-venv) testerman@tester1:~/warp17$ source warp17-venv/bin/activate
(warp17-venv) testerman@tester1:~/warp17$ deactivate
```

# 検証1: 単体構成 2ポート試験

まずはサーバ1台で2ポートを使用した試験を行ってみます。本環境ではUbuntu上でenp130s0f0とenp130s0f1という名前の付いた2ポートを試験対象として設定していきます。
![network3.PNG](https://qiita-image-store.s3.amazonaws.com/0/165176/fe899fb8-64e0-1222-5017-302220911102.png)

## セットアップ

WARP17が使用するポートをバインドします。この作業を終えるとOSからはポートが見えなくなりますので、比較のために作業前後の状態を取得しています(出力結果から不要な部分は削っています。)。

```
testerman@tester1:~$ ip link show
(省略)
8: enp129s0f0: <BROADCAST,MULTICAST> (省略) link/ether xx:xx:xx:xx:xx:60 (省略)
9: enp129s0f1: <BROADCAST,MULTICAST> (省略) link/ether xx:xx:xx:xx:xx:62 (省略)
10: enp130s0f0: <BROADCAST,MULTICAST> (省略) link/ether xx:xx:xx:xx:xx:98 (省略)
11: enp130s0f1: <BROADCAST,MULTICAST> (省略) link/ether xx:xx:xx:xx:xx:9a (省略)

testerman@tester1:~/warp17$ $RTE_SDK/tools/dpdk-setup.sh
------------------------------------------------------------------------------
 RTE_SDK exported as /home/testerman/dpdk-16.11
------------------------------------------------------------------------------
----------------------------------------------------------
 Step 1: Select the DPDK environment to build
----------------------------------------------------------
[1] arm-armv7a-linuxapp-gcc
[2] arm64-armv8a-linuxapp-gcc
[3] arm64-dpaa2-linuxapp-gcc
[4] arm64-thunderx-linuxapp-gcc
[5] arm64-xgene1-linuxapp-gcc
[6] i686-native-linuxapp-gcc
[7] i686-native-linuxapp-icc
[8] ppc_64-power8-linuxapp-gcc
[9] tile-tilegx-linuxapp-gcc
[10] x86_64-native-bsdapp-clang
[11] x86_64-native-bsdapp-gcc
[12] x86_64-native-linuxapp-clang
[13] x86_64-native-linuxapp-gcc
[14] x86_64-native-linuxapp-icc
[15] x86_x32-native-linuxapp-gcc

----------------------------------------------------------
 Step 2: Setup linuxapp environment
----------------------------------------------------------
[16] Insert IGB UIO module
[17] Insert VFIO module
[18] Insert KNI module
[19] Setup hugepage mappings for non-NUMA systems
[20] Setup hugepage mappings for NUMA systems
[21] Display current Ethernet/Crypto device settings
[22] Bind Ethernet/Crypto device to IGB UIO module
[23] Bind Ethernet/Crypto device to VFIO module
[24] Setup VFIO permissions

----------------------------------------------------------
 Step 3: Run test application for linuxapp environment
----------------------------------------------------------
[25] Run test application ($RTE_TARGET/app/test)
[26] Run testpmd application in interactive mode ($RTE_TARGET/app/testpmd)

----------------------------------------------------------
 Step 4: Other tools
----------------------------------------------------------
[27] List hugepage info from /proc/meminfo

----------------------------------------------------------
 Step 5: Uninstall and system cleanup
----------------------------------------------------------
[28] Unbind devices from IGB UIO or VFIO driver
[29] Remove IGB UIO module
[30] Remove VFIO module
[31] Remove KNI module
[32] Remove hugepage mappings

[33] Exit Script

Option: 16
Unloading any existing DPDK UIO module
Loading DPDK UIO module
→まずigb_uioカーネルモジュールを読み込みます。続いてポートをバインドします。

(省略)
Option: 22

Network devices using DPDK-compatible driver
============================================
<none>

Network devices using kernel driver
===================================
0000:01:00.0 'Ethernet Controller 10-Gigabit X540-AT2' if=eno1 drv=ixgbe unused=igb_uio
0000:01:00.1 'Ethernet Controller 10-Gigabit X540-AT2' if=eno2 drv=ixgbe unused=igb_uio
0000:03:00.0 'Ethernet Controller 10-Gigabit X540-AT2' if=enp3s0f0 drv=ixgbe unused=igb_uio
0000:03:00.1 'Ethernet Controller 10-Gigabit X540-AT2' if=enp3s0f1 drv=ixgbe unused=igb_uio
0000:05:00.0 'I350 Gigabit Network Connection' if=eno3 drv=igb unused=igb_uio
0000:05:00.1 'I350 Gigabit Network Connection' if=eno4 drv=igb unused=igb_uio
0000:81:00.0 'Ethernet Controller 10-Gigabit X540-AT2' if=enp129s0f0 drv=ixgbe unused=igb_uio
0000:81:00.1 'Ethernet Controller 10-Gigabit X540-AT2' if=enp129s0f1 drv=ixgbe unused=igb_uio
0000:82:00.0 'Ethernet Controller 10-Gigabit X540-AT2' if=enp130s0f0 drv=ixgbe unused=igb_uio
0000:82:00.1 'Ethernet Controller 10-Gigabit X540-AT2' if=enp130s0f1 drv=ixgbe unused=igb_uio

(省略)

Enter PCI address of device to bind to IGB UIO driver: 82:00.0
OK

(省略)

Enter PCI address of device to bind to IGB UIO driver: 82:00.1
OK

→enp130s0f0とenp130s0f1に合致するPCIスロット番号を入れます。最終的に以下のようになればDPDKが2ポートをバインドできています。

Network devices using DPDK-compatible driver
============================================
0000:82:00.0 'Ethernet Controller 10-Gigabit X540-AT2' drv=igb_uio unused=ixgbe
0000:82:00.1 'Ethernet Controller 10-Gigabit X540-AT2' drv=igb_uio unused=ixgbe

Network devices using kernel driver
===================================
0000:01:00.0 'Ethernet Controller 10-Gigabit X540-AT2' if=eno1 drv=ixgbe unused=igb_uio
0000:01:00.1 'Ethernet Controller 10-Gigabit X540-AT2' if=eno2 drv=ixgbe unused=igb_uio
0000:03:00.0 'Ethernet Controller 10-Gigabit X540-AT2' if=enp3s0f0 drv=ixgbe unused=igb_uio
0000:03:00.1 'Ethernet Controller 10-Gigabit X540-AT2' if=enp3s0f1 drv=ixgbe unused=igb_uio
0000:05:00.0 'I350 Gigabit Network Connection' if=eno3 drv=igb unused=igb_uio
0000:05:00.1 'I350 Gigabit Network Connection' if=eno4 drv=igb unused=igb_uio
0000:81:00.0 'Ethernet Controller 10-Gigabit X540-AT2' if=enp129s0f0 drv=ixgbe unused=igb_uio
0000:81:00.1 'Ethernet Controller 10-Gigabit X540-AT2' if=enp129s0f1 drv=ixgbe unused=igb_uio

testerman@tester1:~$ ip link show
(省略)
8: enp129s0f0: <BROADCAST,MULTICAST> (省略) link/ether xx:xx:xx:xx:xx:60 (省略)
9: enp129s0f1: <BROADCAST,MULTICAST> (省略) link/ether xx:xx:xx:xx:xx:62 (省略)
→OS側からenp130s0f0,enp130s0f1が見えなくなります。
```

## オプション解説

以上でテスターを実行する準備は整いましたが、warp17プログラム実行時のオプションは実際に使用される環境に合わせてチューニングが必要です。あくまで本環境での例にはなりますが、以下のようなオプションで試験を行いましたのでこちらをベースに少し丁寧に(若干くどいかもしれませんが)説明していきます。

```
/home/testerman/warp17/build/warp17 -c AAAA -n 6 -m 32768 -- --qmap-default max-q --tcb-pool-sz 20000 --cmd-file /home/testerman/warp17/examples/test_5_raw_10M_sessions.cfg
```

`-c <hex_mask>`
パケット生成に使うcoreを指定するための16進数のマスクです。
以下の通り、AAAAを指定したら、core 1,3,5,7,9,11,13,15を使用します。

```
 Bitmask:   1  0  1  0      1   0  1  0     1  0  1  0     1  0  1  0 => 0xAAAA
    core:  15 14 13 12     11  10  9  8     7  6  5  4     3  2  1  0
```

指定したマスクのうち2bitは管理用に使用されるようなので試験で使用したいcoreから2bitを余分に指定する必要があります。

スペックに余裕があるのであればあまり悩む必要はありませんが、スペックを最大限生かすためにはマスクの指定時に以下の2つの条件を意識する必要があります。

*条件1. 使用するポートと同じsocket上のcoreを選定する*

まず、使用するポートがどのsocketにマップしているのか調べます。[DPDKのサイト](http://dpdk.org/doc/guides/linux_gsg/nic_perf_intel_platform.html)によると、通常PCIスロット番号が0x:00.xはsocket 0、8x:00.x はsocket 1のようなので、今回の検証で使用するenp130s0f0とenp130s0f1はsocket 1のようです。なお、正確にはWARP17を実行した際の表示結果からも確認できます。

次に、CPU構成の詳細を調べます。以下の実行結果より、socket1の論理CPUは1～71の奇数であることが分かります。

```
testerman@tester1:~$ lscpu | grep "CPU(s)"
CPU(s):                72
On-line CPU(s) list:   0-71
NUMA node0 CPU(s):     0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70
NUMA node1 CPU(s):     1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59,61,63,65,67,69,71
```

*条件2. 同一core上の論理CPUを指定しない*

[DPDKのサイト](http://dpdk.org/doc/guides/linux_gsg/nic_perf_intel_platform.html)に、同一core上の論理CPUを2つ以上使わないように注意書きがありますので、本検証環境でのCPUの詳細構成を確認してみます。

```
testerman@tester1:~/warp17$  egrep "processor|physical id|core id|^$" /proc/cpuinfo
processor       : 0
physical id     : 0
core id         : 0

processor       : 1
physical id     : 1
core id         : 0
(省略)
```

[こちらのサイト](http://d.hatena.ne.jp/kakurasan/20110117/p1)にprocessor、physical id、core idについてのわかりやすい説明がありましたので引用します。
> ・同一の物理CPU(CPUソケット単位)では「physical id」の値が同じ(異なる値のものは物理CPUが分かれている)
> ・「core id」はどのCPUコアかを示す値で、Hyper Threading Technology (HTTもしくはHT)が有効なIntel製CPUにおいて「core id」が同一で「processor」が異なる2つの項目は物理コアが同じな論理CPUどうし
> ・「cpu cores」の値は物理コアの数となる(ただし、AMD製のBulldozer系CPU/APUではコア2つ分のまとまりである「モジュール」単位で数える)

上記を参考にすると、本環境ではphysical id = 1(socket 1)でまず絞り込み、次にcore idが同一の2セット(同一の物理core上にある論理CPU)のうち若番を選定すれば良さそうです。結果として1, 3, 5, (省略), 33, 35(奇数)のprocessor番号が特定できました。

つまり本環境でsocket 1上のポートからパケットを生成するために使用できるCPUとしては、最大で`0xAAAAAAAAA(= 101010101010101010101010101010101010b)`が指定可能ということになります。

`-n <chan_no>`
メモリーチャネル数を指定します。以下のコマンドで確認可能なようですが本環境では何も表示されませんでしたので、物理的なメモリー本数(本環境では32GBメモリーを6本使っているので6)を指定しました。

```
$ dmidecode | grep Channel
    Bank Locator: P0_Node0_Channel0_Dimm0
    Bank Locator: P0_Node0_Channel1_Dimm0
    Bank Locator: P0_Node0_Channel2_Dimm0
    Bank Locator: P0_Node0_Channel3_Dimm0  <<<< the system has 4 channels (0-3)
```

`-m <mem_in_MB>`
割当メモリー量を指定します。先ほど設定したhugepages以下の値を指定する必要があります。

`--qmap-default max-q`
WARP17のサイトには試験で使用する各物理ポート毎の送信キュー数を最大化する設定と説明があります。2ポート検証および4ポート検証では-cオプションでsocket 1のcoreのみを指定しているので、qmap-default max-qを指定しておけば問題ありません。一方、後述の8ポート検証を行う際は使用するポートがsocket 0とsocket 1に分かれますので、-cオプションで両socketを含めたマスク値を指定することになります。この場合、qmap-defaultオプションではなくではなく-qmapオプションを使用し、ポート単位で同一socket上のcoreを指定する必要があります(8ポート検証のところで再度解説します)。

`--tcb-pool-sz <size>`
TCB数を指定します(単位はK)。WARP17のサイト例では32Mを指定していますが、2ポート検証ではメモリー不足のエラーが出ました。WARP17のサイトによると、以下で紹介するCLIコマンドリストのサンプルを動かすのに最低限必要な量はクライアント側とサーバ側で合わせて20Mと説明がありますので20Mに落としています。

`--cmd-file <CLIコマンドリストファイル>`
アプリケーション開始後に実行されるCLIコマンドリストです。以下に設定例があるので活用します(長くなるのでサンプルからコメント行を除いています)。ここでファイルを指定せずにCLIモードでコマンドを手動入力することも可能です。

```
testerman@tester1:~/warp17/examples$ pwd
/home/testerman/warp17/examples
testerman@tester1:~/warp17/examples$ ls
perl                           test_2_raw_udp_connection.cfg  test_5_raw_10M_sessions.cfg
python                         test_3_http_multiple.cfg       test_6_http_40M_sessions.cfg
test_1_raw_tcp_connection.cfg  test_4_http_10M_sessions.cfg   test_7_routing_raw_8M_sessions_no_data.cfg
testerman@tester1:~/warp17/examples$ cat test_5_raw_10M_sessions.cfg
add tests l3_intf port 0 ip 10.0.0.1 mask 255.255.255.0
add tests l3_gw port 0 gw 10.0.0.253
add tests client tcp port 0 test-case-id 0 src 10.0.0.1 10.0.0.1 sport 10001 60000 dest 10.0.0.253 10.0.0.253 dport 6001 6200
set tests timeouts port 0 test-case-id 0 init 10
set tests timeouts port 0 test-case-id 0 uptime infinite
set tests timeouts port 0 test-case-id 0 downtime 10
set tests rate port 0 test-case-id 0 open 1000000
set tests rate port 0 test-case-id 0 send  900000
set tests criteria port 0 test-case-id 0 run-time 3600
set tests client raw port 0 test-case-id 0 data-req-plen 1000 data-resp-plen 4000
add tests l3_intf port 1 ip 10.0.0.253 mask 255.255.255.0
add tests l3_gw port 1 gw 10.0.0.1
add tests server tcp port 1 test-case-id 0 src 10.0.0.253 10.0.0.253 sport 6001 6200
set tests server raw port 1 test-case-id 0 data-req-plen 1000 data-resp-plen 4000
start tests port 1
start tests port 0
show tests ui
```

上記のファイルにはport Xという指定がありますが、先ほどdpdk-setup.shでDPDKにバインドされているポートとして表示されていた順にport0、port1に割り当てられる仕様のようなので、本環境ではenp130s0f0がport 0、enp130s0f1がport 1になります。

上記のシナリオでは、それぞれのポートにIPアドレスを割り当て、port 0がクライアント側、port 1側がサーバ側になってTCPのrawデータを送受信する仕組みになっています。最大で秒間100万接続が生成されて、各クライアントがサーバに1000byteのリクエストデータを投げ、サーバがクライアントに4000byteのレスポンスを返して終了するという設定になっているようです。この辺りの動きは正確に追えていませんが、本気で使い込む方は詳細確認が必要だと思います。

## 試験実施

以上を踏まえ、先ほど説明した試験コマンドを実行します。先頭付近にPCIスロット番号とsocketの対応が表示されますので、想定とあっているかここで確認できます。

```
testerman@tester1:~$ /home/testerman/warp17/build/warp17 -c AAAA -n 6 -m 32768 -- --qmap-default max-q --tcb-pool-sz 20000 --cmd-file /home/testerman/warp17/examples/test_5_raw_10M_sessions.cfg
EAL: Detected 72 lcore(s)
EAL: Probing VFIO support...
EAL: PCI device 0000:01:00.0 on NUMA socket 0
EAL:   probe driver: 8086:1528 net_ixgbe
EAL: PCI device 0000:01:00.1 on NUMA socket 0
EAL:   probe driver: 8086:1528 net_ixgbe
EAL: PCI device 0000:03:00.0 on NUMA socket 0
EAL:   probe driver: 8086:1528 net_ixgbe
EAL: PCI device 0000:03:00.1 on NUMA socket 0
EAL:   probe driver: 8086:1528 net_ixgbe
EAL: PCI device 0000:05:00.0 on NUMA socket 0
EAL:   probe driver: 8086:1521 net_e1000_igb
EAL: PCI device 0000:05:00.1 on NUMA socket 0
EAL:   probe driver: 8086:1521 net_e1000_igb
EAL: PCI device 0000:81:00.0 on NUMA socket 1
EAL:   probe driver: 8086:1528 net_ixgbe
EAL: PCI device 0000:81:00.1 on NUMA socket 1
EAL:   probe driver: 8086:1528 net_ixgbe
EAL: PCI device 0000:82:00.0 on NUMA socket 1
EAL:   probe driver: 8086:1528 net_ixgbe
EAL: PCI device 0000:82:00.1 on NUMA socket 1
EAL:   probe driver: 8086:1528 net_ixgbe
warp17> USER1: Creating mempool global_pkt_mbuf-5 on core 5(size: 131072, obj_size: 2304, priv: 4 cache: 512)
USER1: Creating mempool global_pkt_mbuf_tx_hdr-5 on core 5(size: 87381, obj_size: 310, priv: 4 cache: 512)
(省略)

warp17>
```

ポートの準備とCLIコマンドリストの読み込みが終わると、リストの最後に指定した`show tests ui`コマンドにより以下のモニター画面が開き、リアルタイムにトラフィック量が更新されます。画面上部に回線使用率が表示され(赤丸)、B/sも確認可能(青丸)です。
![rate1-1.PNG](https://qiita-image-store.s3.amazonaws.com/0/165176/69e79d8a-cb97-4288-bd46-e64b938b70c5.png)

念のためスイッチでも10Gbpsが出ていることを確認します。

```
10GSW>show interfaces tengigabitethernet 1/25
(省略)
Rate info (interval 299 seconds):
     Input 4179.00 Mbits/sec,    1665252 packets/sec, 44.46% of line-rate
     Output 9801.00 Mbits/sec,    1432860 packets/sec, 99.90% of line-rate
Time since last interface status change: 00:08:32
```

2ポート検証では6core(8coreを指定していますが2coreは管理用のため)、メモリー32GBをWARP17に割り当てることで、TCPで10Gbps出せることが確認できました。

試験を終えるにはqキーを押してモニターからCLIモードに移り、以下の流れで各ポートのテストを順番に止めて行きます。

```
warp17> stop tests port 0
warp17> stop tests port 1
warp17> exit
testerman@tester1:~$
```

# 検証2: 単体構成 4ポート試験

次は4ポートで試験を行います。
![network4.PNG](https://qiita-image-store.s3.amazonaws.com/0/165176/bdf1d06c-71ea-d8d4-7bfb-ce54d64bb195.png)

## セットアップ
32GBではメモリーが不足するため2倍の64GBを割り当てます。

```
testerman@tester1:~$ sudo vi /etc/default/grub
(省略)
GRUB_CMDLINE_LINUX="default_hugepagesz=1G hugepagesz=1G hugepages=64"

testerman@tester1:~$ sudo update-grub
testerman@tester1:~$ sudo reboot

(再起動)

testerman@tester1:~$ export RTE_SDK=/home/testerman/dpdk-16.11
testerman@tester1:~$ export RTE_TARGET=x86_64-native-linuxapp-gcc
```

今回使用する4ポートをDPDKにバインドします。

```
testerman@tester1:~$ $RTE_SDK/tools/dpdk-setup.sh
(省略)
Network devices using DPDK-compatible driver
============================================
0000:81:00.0 'Ethernet Controller 10-Gigabit X540-AT2' drv=igb_uio unused=ixgbe
0000:81:00.1 'Ethernet Controller 10-Gigabit X540-AT2' drv=igb_uio unused=ixgbe
0000:82:00.0 'Ethernet Controller 10-Gigabit X540-AT2' drv=igb_uio unused=ixgbe
0000:82:00.1 'Ethernet Controller 10-Gigabit X540-AT2' drv=igb_uio unused=ixgbe

Network devices using kernel driver
===================================
0000:01:00.0 'Ethernet Controller 10-Gigabit X540-AT2' if=eno1 drv=ixgbe unused=igb_uio
0000:01:00.1 'Ethernet Controller 10-Gigabit X540-AT2' if=eno2 drv=ixgbe unused=igb_uio
0000:03:00.0 'Ethernet Controller 10-Gigabit X540-AT2' if=enp3s0f0 drv=ixgbe unused=igb_uio
0000:03:00.1 'Ethernet Controller 10-Gigabit X540-AT2' if=enp3s0f1 drv=ixgbe unused=igb_uio
0000:05:00.0 'I350 Gigabit Network Connection' if=eno3 drv=igb unused=igb_uio
0000:05:00.1 'I350 Gigabit Network Connection' if=eno4 drv=igb unused=igb_uio
```

先ほど使用した2ポート検証でのCLIコマンドリストファイルを4ポート用に追記します。

```
testerman@tester1:~/warp17/examples$ pwd
/home/testerman/warp17/examples
testerman@tester1:~/warp17/examples$ cp test_5_raw_10M_sessions.cfg test_11_raw_10M_sessions_4port.cfg
testerman@tester1:~/warp17/examples$ vi test_11_raw_10M_sessions_4port.cfg

add tests l3_intf port 0 ip 10.0.0.1 mask 255.255.255.0
add tests l3_gw port 0 gw 10.0.0.253
add tests client tcp port 0 test-case-id 0 src 10.0.0.1 10.0.0.1 sport 10001 60000 dest 10.0.0.253 10.0.0.253 dport 6001 6200
set tests timeouts port 0 test-case-id 0 init 10
set tests timeouts port 0 test-case-id 0 uptime infinite
set tests timeouts port 0 test-case-id 0 downtime 10
set tests rate port 0 test-case-id 0 open 1000000
set tests rate port 0 test-case-id 0 send 900000
set tests criteria port 0 test-case-id 0 run-time 3600
set tests client raw port 0 test-case-id 0 data-req-plen 1000 data-resp-plen 4000
add tests l3_intf port 1 ip 10.0.0.253 mask 255.255.255.0
add tests l3_gw port 1 gw 10.0.0.1
add tests server tcp port 1 test-case-id 0 src 10.0.0.253 10.0.0.253 sport 6001 6200
set tests server raw port 1 test-case-id 0 data-req-plen 1000 data-resp-plen 4000
start tests port 1
start tests port 0

add tests l3_intf port 2 ip 10.0.1.1 mask 255.255.255.0
add tests l3_gw port 2 gw 10.0.1.253
add tests client tcp port 2 test-case-id 1 src 10.0.1.1 10.0.1.1 sport 10001 60000 dest 10.0.1.253 10.0.1.253 dport 6001 6200
set tests timeouts port 2 test-case-id 1 init 10
set tests timeouts port 2 test-case-id 1 uptime infinite
set tests timeouts port 2 test-case-id 1 downtime 10
set tests rate port 2 test-case-id 1 open 1000000
set tests rate port 2 test-case-id 1 send 900000
set tests criteria port 2 test-case-id 1 run-time 3600
set tests client raw port 2 test-case-id 1 data-req-plen 1000 data-resp-plen 4000
add tests l3_intf port 3 ip 10.0.1.253 mask 255.255.255.0
add tests l3_gw port 3 gw 10.0.1.1
add tests server tcp port 3 test-case-id 1 src 10.0.1.253 10.0.1.253 sport 6001 6200
set tests server raw port 3 test-case-id 1 data-req-plen 1000 data-resp-plen 4000
start tests port 3
start tests port 2

show tests ui
```

## 試験実施

以下でシミュレーションを開始します。2ポート検証では管理用を除くと6coreで10Gbpsが出せましたが、4ポートでは12coreにしても回線仕様率が80%程度までしかいかなかったため16coreを割り当てました(管理ポートも含めると18core)。今回指定した4ポートは全てsocket 1上ですので、-cにAAAAAAAAA、qmap-default max-qを指定しています。

```
testerman@tester1:~/warp17/examples$ cd
testerman@tester1:~$ /home/testerman/warp17/build/warp17 -c AAAAAAAAA -n 6 -m 65536 -- --qmap-default max-q --tcb-pool-sz 40000 --cmd-file /home/testerman/warp17/examples/test_11_raw_10M_sessions_4port.cfg
(省略)
```

4ポートの場合、モニター画面のスペース不足のため、上部の回線仕様率などの一部の情報が見えなくなります。
![rate2-2.PNG](https://qiita-image-store.s3.amazonaws.com/0/165176/a27c14e3-4e3c-00b4-0bec-60865800c72f.png)

そこでスイッチでも確認してみたところ、2ポートで10Gbps出ていることが確認できました(もう一台のスイッチの確認結果は割愛します)。

```
10GSW1>show interfaces tengigabitethernet 1/25
(省略)
Rate info (interval 299 seconds):
     Input 3064.00 Mbits/sec,    1420229 packets/sec, 32.91% of line-rate
     Output 9677.00 Mbits/sec,    1407973 packets/sec, 99.02% of line-rate

10GSW1>show interfaces tengigabitethernet 1/27
(省略)
Rate info (interval 299 seconds):
     Input 3112.00 Mbits/sec,    1429250 packets/sec, 33.41% of line-rate
     Output 9708.00 Mbits/sec,    1409497 packets/sec, 99.33% of line-rate
```

止め方は先ほどと同じです。

```
warp17> stop tests port 0
warp17> stop tests port 1
warp17> stop tests port 2
warp17> stop tests port 3
```

# 検証3: 単体構成 8ポート試験

TCPでは各ポート3Gbps程度しか出ませんでしたので、本検証ではプロトコルをUDPに変更し、サーバから送信するファイルサイズを4000byteから1000000byte(1MB)に変更することでスループットが上がりやすくしています。
![network5.PNG](https://qiita-image-store.s3.amazonaws.com/0/165176/d5ec1dc5-bf7b-4877-a187-23911c4899df.png)

## セットアップ

```
testerman@tester1:~$ sudo vi /etc/default/grub
(省略)
GRUB_CMDLINE_LINUX="default_hugepagesz=1G hugepagesz=1G hugepages=128"

testerman@tester1:~$ sudo update-grub
testerman@tester1:~$ sudo reboot

testerman@tester1:~$ export RTE_SDK=/home/testerman/dpdk-16.11
testerman@tester1:~$ export RTE_TARGET=x86_64-native-linuxapp-gcc
testerman@tester1:~$ $RTE_SDK/tools/dpdk-setup.sh
(省略)

Network devices using DPDK-compatible driver
============================================
0000:01:00.0 'Ethernet Controller 10-Gigabit X540-AT2' drv=igb_uio unused=ixgbe
0000:01:00.1 'Ethernet Controller 10-Gigabit X540-AT2' drv=igb_uio unused=ixgbe
0000:03:00.0 'Ethernet Controller 10-Gigabit X540-AT2' drv=igb_uio unused=ixgbe
0000:03:00.1 'Ethernet Controller 10-Gigabit X540-AT2' drv=igb_uio unused=ixgbe
0000:81:00.0 'Ethernet Controller 10-Gigabit X540-AT2' drv=igb_uio unused=ixgbe
0000:81:00.1 'Ethernet Controller 10-Gigabit X540-AT2' drv=igb_uio unused=ixgbe
0000:82:00.0 'Ethernet Controller 10-Gigabit X540-AT2' drv=igb_uio unused=ixgbe
0000:82:00.1 'Ethernet Controller 10-Gigabit X540-AT2' drv=igb_uio unused=ixgbe

Network devices using kernel driver
===================================
0000:05:00.0 'I350 Gigabit Network Connection' if=eno3 drv=igb unused=igb_uio
0000:05:00.1 'I350 Gigabit Network Connection' if=eno4 drv=igb unused=igb_uio
→管理ポートをDPDKにバインドするとサーバにアクセスできなくなりますのでご注意下さい。

testerman@tester1:~$ cd warp17/examples/
testerman@tester1:~/warp17/examples$ cp test_11_raw_10M_sessions_4port.cfg test_12_raw_10M_sessions_8port-udp.cfg
testerman@tester1:~/warp17/examples$ vi test_12_raw_10M_sessions_8port-udp.cfg
add tests l3_intf port 0 ip 10.0.0.1 mask 255.255.255.0
add tests l3_gw port 0 gw 10.0.0.253
add tests client udp port 0 test-case-id 0 src 10.0.0.1 10.0.0.1 sport 10001 60000 dest 10.0.0.253 10.0.0.253 dport 6001 6200
set tests timeouts port 0 test-case-id 0 init 10
set tests timeouts port 0 test-case-id 0 uptime infinite
set tests timeouts port 0 test-case-id 0 downtime 10
set tests rate port 0 test-case-id 0 open 1000000
set tests rate port 0 test-case-id 0 send 900000
set tests criteria port 0 test-case-id 0 run-time 3600
set tests client raw port 0 test-case-id 0 data-req-plen 1000 data-resp-plen 1000000
add tests l3_intf port 1 ip 10.0.0.253 mask 255.255.255.0
add tests l3_gw port 1 gw 10.0.0.1
add tests server udp port 1 test-case-id 0 src 10.0.0.253 10.0.0.253 sport 6001 6200
set tests server raw port 1 test-case-id 0 data-req-plen 1000 data-resp-plen 1000000
start tests port 1
start tests port 0

add tests l3_intf port 2 ip 10.0.1.1 mask 255.255.255.0
add tests l3_gw port 2 gw 10.0.1.253
add tests client udp port 2 test-case-id 1 src 10.0.1.1 10.0.1.1 sport 10001 60000 dest 10.0.1.253 10.0.1.253 dport 6001 6200
set tests timeouts port 2 test-case-id 1 init 10
set tests timeouts port 2 test-case-id 1 uptime infinite
set tests timeouts port 2 test-case-id 1 downtime 10
set tests rate port 2 test-case-id 1 open 1000000
set tests rate port 2 test-case-id 1 send 900000
set tests criteria port 2 test-case-id 1 run-time 3600
set tests client raw port 2 test-case-id 1 data-req-plen 1000 data-resp-plen 1000000
add tests l3_intf port 3 ip 10.0.1.253 mask 255.255.255.0
add tests l3_gw port 3 gw 10.0.1.1
add tests server udp port 3 test-case-id 1 src 10.0.1.253 10.0.1.253 sport 6001 6200
set tests server raw port 3 test-case-id 1 data-req-plen 1000 data-resp-plen 1000000
start tests port 3
start tests port 2

add tests l3_intf port 4 ip 10.0.2.1 mask 255.255.255.0
add tests l3_gw port 4 gw 10.0.2.253
add tests client udp port 4 test-case-id 2 src 10.0.2.1 10.0.2.1 sport 10001 60000 dest 10.0.2.253 10.0.2.253 dport 6001 6200
set tests timeouts port 4 test-case-id 2 init 10
set tests timeouts port 4 test-case-id 2 uptime infinite
set tests timeouts port 4 test-case-id 2 downtime 10
set tests rate port 4 test-case-id 2 open 1000000
set tests rate port 4 test-case-id 2 send 900000
set tests criteria port 4 test-case-id 2 run-time 3600
set tests client raw port 4 test-case-id 2 data-req-plen 1000 data-resp-plen 1000000
add tests l3_intf port 5 ip 10.0.2.253 mask 255.255.255.0
add tests l3_gw port 5 gw 10.0.2.1
add tests server udp port 5 test-case-id 2 src 10.0.2.253 10.0.2.253 sport 6001 6200
set tests server raw port 5 test-case-id 2 data-req-plen 1000 data-resp-plen 1000000
start tests port 5
start tests port 4

add tests l3_intf port 6 ip 10.0.3.1 mask 255.255.255.0
add tests l3_gw port 6 gw 10.0.3.253
add tests client udp port 6 test-case-id 3 src 10.0.3.1 10.0.3.1 sport 10001 60000 dest 10.0.3.253 10.0.3.253 dport 6001 6200
set tests timeouts port 6 test-case-id 3 init 10
set tests timeouts port 6 test-case-id 3 uptime infinite
set tests timeouts port 6 test-case-id 3 downtime 10
set tests rate port 6 test-case-id 3 open 1000000
set tests rate port 6 test-case-id 3 send 900000
set tests criteria port 6 test-case-id 3 run-time 3600
set tests client raw port 6 test-case-id 3 data-req-plen 1000 data-resp-plen 1000000
add tests l3_intf port 7 ip 10.0.3.253 mask 255.255.255.0
add tests l3_gw port 7 gw 10.0.3.1
add tests server udp port 7 test-case-id 3 src 10.0.3.253 10.0.3.253 sport 6001 6200
set tests server raw port 7 test-case-id 3 data-req-plen 1000 data-resp-plen 1000000
start tests port 7
start tests port 6

show tests ui
```

## オプション解説

2ポート試験の--qmap-defaultオプションの解説にも記載しましたが、-cで指定するcoreが複数CPUにまたがる場合はqmap-defaultオプションの代わりに-qmapオプションを使用する必要があります。

`--qmap <port>.<hex_mask>`
各ポートを制御するcoreをマスクで指定するオプションです。ただし、同じsocket上のポートであればマスクを共用することも可能なようです。本検証環境では、port0～3はsocket0、port4～7はsocket1なので、socket0に属するポートは全て555555550、socket1に属するポートは全てAAAAAAAA0を指定します(0～3bitを0にしているのは管理用coreを確保するため)。また、-cオプションにはsocket0、socket1、管理用coreを全て含むマスク(FFFFFFFFF)を指定しています。

```
socket0:  0  1  0  1    0  1  0  1    0  1  0  1    0  1  0  1    0  1  0  1    0  1  0  1    0  1  0  1    0  1  0  1   0  0  0  0 => 0x555555550
socket1:  1  0  1  0    1  0  1  0    1  0  1  0    1  0  1  0    1  0  1  0    1  0  1  0    1  0  1  0    1  0  1  0   0  0  0  0 => 0xAAAAAAAA0
 core:   35 34 33 32   31 30 29 28   27 26 25 24   23 22 21 20   19 18 17 16   15 14 13 12   11 10  9  8    7  6  5  4   3  2  1  0
```

## 試験実施
以上を踏まえると実行コマンドは以下のようになります。プロトコルをUDPに変えたので、tcb-pool-szがucb-pool-szに変わっている点に注意して下さい。また、エラー対応でucb-pool-szのサイズも131072に上げています。

```
testerman@tester1:~/warp17/examples$ /home/testerman/warp17/build/warp17 -c FFFFFFFFF -n 6 -m 131072 -- --qmap 0.555555550 --qmap 1.555555550 --qmap 2.555555550 --qmap 3.555555550 --qmap 4.AAAAAAAA0 --qmap 5.AAAAAAAA0 --qmap 6.AAAAAAAA0 --qmap 7.AAAAAAAA0 --ucb-pool-sz 131072 --cmd-file /home/testerman/warp17/examples/test_12_raw_10M_sessions_8port-udp.cfg
(省略)
```

ポート数が多いとモニター画面を見てもレートがほとんど見えなくなります(4Kディスプレイなら見れるかもしれません･･･)。
![rate5.PNG](https://qiita-image-store.s3.amazonaws.com/0/165176/77ac1655-9c27-5f4a-2ecb-d3813d64666a.png)

そこでスイッチでも10Gbpsが出ていることを確認します。

```
10GSW#sho int tengigabitethernet 1/25-1/31 | grep rate

     Input 579.00 Mbits/sec,      69255 packets/sec, 5.90% of line-rate
     Output 9862.00 Mbits/sec,     844811 packets/sec, 99.90% of line-rate

     Input 518.00 Mbits/sec,      61913 packets/sec, 5.27% of line-rate
     Output 9862.00 Mbits/sec,     844812 packets/sec, 99.90% of line-rate

     Input 500.00 Mbits/sec,      59819 packets/sec, 5.10% of line-rate
     Output 9893.00 Mbits/sec,     847445 packets/sec, 99.90% of line-rate

     Input 507.00 Mbits/sec,      60613 packets/sec, 5.16% of line-rate
     Output 9893.00 Mbits/sec,     847448 packets/sec, 99.90% of line-rate
```

UDPかつ片方向とはいえ、4ポートでトータル40Gbpsが出ています！


# 検証4: セパレート構成試験
新たにtester1と同スペックの別サーバであるtester2を追加して、tester2をクライアント、tester1をサーバに役割を分けて、TCPで負荷をかけてみます。
![network7.png](https://qiita-image-store.s3.amazonaws.com/0/165176/2ae4d619-3c4d-5b00-e7a7-cdecf6532160.png)

## セットアップ
tester2のインストール手順は割愛しますので、先ほどのtester1の手順を参考にして下さい。クライアントとサーバにマシンが分かれるので割り当てるリソースは半分で済むはず?なので、事前にhugepagesを16GB(2ポート構成で割り当てた半分)にします。

```
testerman@tester1:~$ sudo vi /etc/default/grub
(省略)
GRUB_CMDLINE_LINUX="default_hugepagesz=1G hugepagesz=1G hugepages=16"

testerman@tester1:~$ sudo update-grub
testerman@tester1:~$ sudo reboot

testerman@tester2:~$ sudo vi /etc/default/grub
(省略)
GRUB_CMDLINE_LINUX="default_hugepagesz=1G hugepagesz=1G hugepages=16"

testerman@tester2:~$ sudo update-grub
testerman@tester2:~$ sudo reboot
```

**ポートのバインド**

```
testerman@tester2:~$ export RTE_SDK=/home/testerman/dpdk-16.11
testerman@tester2:~$ export RTE_TARGET=x86_64-native-linuxapp-gcc
testerman@tester2:~$ /home/testerman/dpdk-16.11/tools/dpdk-setup.sh
(省略)

Network devices using DPDK-compatible driver
============================================
0000:81:00.0 'Ethernet Controller 10-Gigabit X540-AT2' drv=igb_uio unused=

Network devices using kernel driver
===================================
0000:01:00.0 'Ethernet Controller 10-Gigabit X540-AT2' if=em1 drv=ixgbe unused=igb_uio
0000:01:00.1 'Ethernet Controller 10-Gigabit X540-AT2' if=em2 drv=ixgbe unused=igb_uio
0000:04:00.0 'Ethernet Controller 10-Gigabit X540-AT2' if=p3p1 drv=ixgbe unused=igb_uio
0000:04:00.1 'Ethernet Controller 10-Gigabit X540-AT2' if=p3p2 drv=ixgbe unused=igb_uio
0000:07:00.0 'I350 Gigabit Network Connection' if=em3 drv=igb unused=igb_uio
0000:07:00.1 'I350 Gigabit Network Connection' if=em4 drv=igb unused=igb_uio
0000:81:00.1 'Ethernet Controller 10-Gigabit X540-AT2' if=p2p2 drv=ixgbe unused=igb_uio
0000:83:00.0 'Ethernet Controller 10-Gigabit X540-AT2' if=p1p1 drv=ixgbe unused=igb_uio
0000:83:00.1 'Ethernet Controller 10-Gigabit X540-AT2' if=p1p2 drv=ixgbe unused=igb_uio



testerman@tester1:~$ export RTE_SDK=/home/testerman/dpdk-16.11
testerman@tester1:~$ export RTE_TARGET=x86_64-native-linuxapp-gcc
testerman@tester1:~$ /home/testerman/dpdk-16.11/tools/dpdk-setup.sh
(省略)

Network devices using DPDK-compatible driver
============================================
0000:81:00.0 'Ethernet Controller 10-Gigabit X540-AT2' drv=igb_uio unused=ixgbe

Network devices using kernel driver
===================================
0000:01:00.0 'Ethernet Controller 10-Gigabit X540-AT2' if=eno1 drv=ixgbe unused=igb_uio
0000:01:00.1 'Ethernet Controller 10-Gigabit X540-AT2' if=eno2 drv=ixgbe unused=igb_uio
0000:03:00.0 'Ethernet Controller 10-Gigabit X540-AT2' if=enp3s0f0 drv=ixgbe unused=igb_uio
0000:03:00.1 'Ethernet Controller 10-Gigabit X540-AT2' if=enp3s0f1 drv=ixgbe unused=igb_uio
0000:05:00.0 'I350 Gigabit Network Connection' if=eno3 drv=igb unused=igb_uio
0000:05:00.1 'I350 Gigabit Network Connection' if=eno4 drv=igb unused=igb_uio
0000:81:00.1 'Ethernet Controller 10-Gigabit X540-AT2' if=enp129s0f1 drv=ixgbe unused=igb_uio
0000:82:00.0 'Ethernet Controller 10-Gigabit X540-AT2' if=enp130s0f0 drv=ixgbe unused=igb_uio
0000:82:00.1 'Ethernet Controller 10-Gigabit X540-AT2' if=enp130s0f1 drv=ixgbe unused=igb_uio
```

**CLIコマンドリスト作成**
クライアント側であるtester2は、CLIコマンドリストのサンプルのport 1の行(サーバに関する設定)をコメントアウトしてそのまま利用します。サーバ側であるtester1は、CLIコマンドリストのサンプルのport 0の行(クライアントに関する設定)をコメントアウトし、port 1をport 0に修正します(セパレート構成では1ポートしかバインドせずport0しか存在しないため)。

```
testerman@tester2:~/warp17/examples$ cp test_5_raw_10M_sessions.cfg test_5_raw_10M_sessions_client.cfg
testerman@tester2:~/warp17/examples$ vi test_5_raw_10M_sessions_client.cfg
add tests l3_intf port 0 ip 10.0.0.1 mask 255.255.255.0
add tests l3_gw port 0 gw 10.0.0.253
add tests client tcp port 0 test-case-id 0 src 10.0.0.1 10.0.0.1 sport 10001 60000 dest 10.0.0.253 10.0.0.253 dport 6001 6200
set tests timeouts port 0 test-case-id 0 init 10
set tests timeouts port 0 test-case-id 0 uptime infinite
set tests timeouts port 0 test-case-id 0 downtime 10
set tests rate port 0 test-case-id 0 open 1000000
set tests rate port 0 test-case-id 0 send  900000
set tests criteria port 0 test-case-id 0 run-time 3600
set tests client raw port 0 test-case-id 0 data-req-plen 1000 data-resp-plen 4000
#add tests l3_intf port 1 ip 10.0.0.253 mask 255.255.255.0
#add tests l3_gw port 1 gw 10.0.0.1
#add tests server tcp port 1 test-case-id 0 src 10.0.0.253 10.0.0.253 sport 6001 6200
#set tests server raw port 1 test-case-id 0 data-req-plen 1000 data-resp-plen 4000
#start tests port 1
start tests port 0
show tests ui


testerman@tester1:~/warp17/examples$ cp test_5_raw_10M_sessions.cfg test_5_raw_10M_sessions_server.cfg
testerman@tester1:~/warp17/examples$ vi test_5_raw_10M_sessions_server.cfg
#add tests l3_intf port 0 ip 10.0.0.1 mask 255.255.255.0
#add tests l3_gw port 0 gw 10.0.0.253
#add tests client tcp port 0 test-case-id 0 src 10.0.0.1 10.0.0.1 sport 10001 60000 dest 10.0.0.253 10.0.0.253 dport 6001 6200
#set tests timeouts port 0 test-case-id 0 init 10
#set tests timeouts port 0 test-case-id 0 uptime infinite
#set tests timeouts port 0 test-case-id 0 downtime 10
#set tests rate port 0 test-case-id 0 open 1000000
#set tests rate port 0 test-case-id 0 send  900000
#set tests criteria port 0 test-case-id 0 run-time 3600
#set tests client raw port 0 test-case-id 0 data-req-plen 1000 data-resp-plen 4000
add tests l3_intf port 0 ip 10.0.0.253 mask 255.255.255.0
add tests l3_gw port 0 gw 10.0.0.1
add tests server tcp port 0 test-case-id 0 src 10.0.0.253 10.0.0.253 sport 6001 6200
set tests server raw port 0 test-case-id 0 data-req-plen 1000 data-resp-plen 4000
#start tests port 1
start tests port 0
show tests ui
```

## 試験実施

クライアント・サーバ共に、CPUを5core(管理用含む)、メモリーを16GB割り当てます。まずはサーバを起動してモニター画面起動後にクライアントを起動します。

```
testerman@tester1:~$ /home/testerman/warp17/build/warp17 -c 2AA -n 1 -m 16384 -- --qmap-default max-q --tcb-pool-sz 5000 --cmd-file /home/testerman/warp17/examples/test_5_raw_10M_sessions_server.cfg
```

モニター画面の起動後、クライアントを起動します。

```
testerman@tester2:~$ /home/testerman/warp17/build/warp17 -c 2AA -n 1 -m 16384 -- --qmap-default max-q --tcb-pool-sz 5000 --cmd-file /home/testerman/warp17/examples/test_5_raw_10M_sessions_client.cfg
```

以下のモニター画面から10Gbpsトラフィックが流れていることが確認できます。クライアントとサーバで役割を分けることで、1台当たりのリソース数を減らして10Gbpsを流せることが確認できました。

クライアント側でのモニター画面
![rate6(CL側).PNG](https://qiita-image-store.s3.amazonaws.com/0/165176/61e54669-fceb-4355-48f3-4722cfcd95d3.png)

サーバ側でのモニター画面
![rate6(SV側).PNG](https://qiita-image-store.s3.amazonaws.com/0/165176/c1c201ce-9b3c-b496-2cb9-7f1f04a32982.png)


# 検証5: 仮想マシン(VMware)試験

[WARP17のサイト](https://github.com/Juniper/warp17/blob/dev/common/ovf/README.md)ではVMwareの10G利用の手順がありませんでしたので紹介したいと思います。
![network9.PNG](https://qiita-image-store.s3.amazonaws.com/0/165176/37449ec2-990e-ee81-5576-1f2d38ce15ed.png)

ESXiのインストール、warp17のovfファイルのデプロイ、仮想マシン(Ubuntu14.04でした)の初期設定手順については割愛します。なお、[こちら](http://warp17.net/downloads/)からVMware用のOVFテンプレートをダウンロードできます。

以降はセットアップの完了した仮想マシンにSSH接続したところからの手順になります。デプロイした仮想マシンのログインID、パスワードはどちらもwarp17です。

## セットアップ

デプロイしただけの状態ですと、仮想マシンから10Gポートは見えません。

```
warp17@warp17:~$ $RTE_SDK/tools/dpdk-devbind.py --status

Network devices using DPDK-compatible driver
============================================
<none>

Network devices using kernel driver
===================================
0000:02:01.0 '82545EM Gigabit Ethernet Controller (Copper)' if=eth0 drv=e1000 unused=igb_uio
0000:02:02.0 '82545EM Gigabit Ethernet Controller (Copper)' if=eth1 drv=e1000 unused=igb_uio
0000:02:03.0 '82545EM Gigabit Ethernet Controller (Copper)' if=eth2 drv=e1000 unused=igb_uio
(省略)
→これらのポートは仮想マシンのデプロイ時点で作られていますが、1GbpsなのでDPDKでのバインド対象にはしません。
```

仮想マシンから10Gポートを直接扱えるように、ESXiにアクセスして2本の10GポートのPCIパススルーの有効化を行い(赤丸の状態にします)、ホストOSを再起動します。ESXi 6.5(非vCenter環境)を使用していますが、他のバージョンでも同様の設定があると思いますので適宜読み替えて下さい。ちなみに同じ10Gアダプター上の別ポートがグレーアウトされており選択できませんでした。恐らくSR-IOVを使えば改善される気がしますが、今回は踏み込まず検証を進めます。
![1-PCIパススルー.PNG](https://qiita-image-store.s3.amazonaws.com/0/165176/857e4e7c-6b5e-1e8f-92ce-2f6e04278dfa.png)

仮想マシンにPCIデバイスを追加する場合、RAMに割り当てた値と同じメモリー量を予約しないとエラーになりますので、仮想マシンの設定の編集にてメモリを16384MBに設定します。
![2-メモリー予約.PNG](https://qiita-image-store.s3.amazonaws.com/0/165176/96c9a71a-5989-5375-ec5d-37e5a33e8461.png)

同じく仮想マシンの設定の編集にて「その他のデバイスの追加」からPCIデバイスとして先ほどパススルーの有効化を行った2ポートを追加します。以下の通り、別のPCIスロット番号のデバイスが正常に追加されていればOKです。
![4-PCIデバイス追加後.PNG](https://qiita-image-store.s3.amazonaws.com/0/165176/90cacbc4-8656-a5f7-bdfa-f1e626e71187.png)

仮想マシンを起動してPCIデバイスが追加されているか確認します。

```
warp17@warp17:~$ $RTE_SDK/tools/dpdk-devbind.py --status

Network devices using DPDK-compatible driver
============================================
<none>

Network devices using kernel driver
===================================
0000:02:01.0 '82545EM Gigabit Ethernet Controller (Copper)' if=eth0 drv=e1000 unused=igb_uio
0000:02:02.0 '82545EM Gigabit Ethernet Controller (Copper)' if=eth1 drv=e1000 unused=igb_uio
0000:02:03.0 '82545EM Gigabit Ethernet Controller (Copper)' if=eth3 drv=e1000 unused=igb_uio
0000:03:00.0 'Ethernet Controller 10-Gigabit X540-AT2' if=eth2 drv=ixgbe unused=igb_uio
0000:0b:00.0 'Ethernet Controller 10-Gigabit X540-AT2' if=eth4 drv=ixgbe unused=igb_uio
(省略)
→10-Gigabitのデバイスが追加されました。

warp17@warp17:~$ sudo vi /etc/default/grub
GRUB_CMDLINE_LINUX="default_hugepagesz=1G hugepagesz=1G hugepages=32"
→10Gbps試験を行うためにhugepagesを12から32に増やします。

warp17@warp17:~$ sudo update-grub
warp17@warp17:~$ sudo shutdown -h now
```

余裕をもって10Gbpsを流せるように仮想マシンのCPUを4coreから8coreに、メモリーを32768に増やし、あわせてメモリーの予約値も32768に修正します(特にこれらのリソースの値に意味はありません)

完了したら仮想マシンを起動して10Gポートをバインドします。

```
warp17@warp17:~$ $RTE_SDK/tools/dpdk-devbind.py --status

Network devices using DPDK-compatible driver
============================================
<none>

Network devices using kernel driver
===================================
0000:02:01.0 '82545EM Gigabit Ethernet Controller (Copper)' if=eth0 drv=e1000 unused=igb_uio
0000:02:02.0 '82545EM Gigabit Ethernet Controller (Copper)' if=eth2 drv=e1000 unused=igb_uio
0000:02:03.0 '82545EM Gigabit Ethernet Controller (Copper)' if=eth3 drv=e1000 unused=igb_uio
0000:03:00.0 'Ethernet Controller 10-Gigabit X540-AT2' if=rename3 drv=ixgbe unused=igb_uio
0000:0b:00.0 'Ethernet Controller 10-Gigabit X540-AT2' if=eth4 drv=ixgbe unused=igb_uio
(省略)

warp17@warp17:~$ sudo $RTE_SDK/tools/dpdk-devbind.py -b igb_uio 03:00.0
warp17@warp17:~$ sudo $RTE_SDK/tools/dpdk-devbind.py -b igb_uio 0b:00.0
→10Gポートをバインドします。

warp17@warp17:~$ $RTE_SDK/tools/dpdk-devbind.py --status

Network devices using DPDK-compatible driver
============================================
0000:03:00.0 'Ethernet Controller 10-Gigabit X540-AT2' drv=igb_uio unused=
0000:0b:00.0 'Ethernet Controller 10-Gigabit X540-AT2' drv=igb_uio unused=

Network devices using kernel driver
===================================
0000:02:01.0 '82545EM Gigabit Ethernet Controller (Copper)' if=eth0 drv=e1000 unused=igb_uio
0000:02:02.0 '82545EM Gigabit Ethernet Controller (Copper)' if=eth2 drv=e1000 unused=igb_uio
0000:02:03.0 '82545EM Gigabit Ethernet Controller (Copper)' if=eth3 drv=e1000 unused=igb_uio
(省略)
→仮想マシンから10G物理ポートが正常にバインドされました。
```

## 試験実施

メモリーを32GB割り当てると以下のようなエラーが出ますので少し値を下げます。
`EAL: Not enough memory available! Requested: 32768MB, available: 29696MB`

```
warp17@warp17:~$ sudo ./warp17/build/warp17 -c FF -m 29696 -- --qmap-default max-q --tcb-pool-sz 20480 --cmd-file /home/warp17/warp17/examples/test_5_raw_10M_sessions.cfg
```

以下の通り、10Gbps出ています。クライアントからサーバへの通信も10Gbps出ていますのでSYN flood攻撃みたいになってる気がします。
![rate(VMware).PNG](https://qiita-image-store.s3.amazonaws.com/0/165176/a88729cc-6347-31de-0f00-86907689c219.png)

スイッチでも10Gbpsが出ていることを確認します。

```
10GSW1# show interfaces tengigabitethernet 1/37 | grep rate
Queueing strategy: fifo
     Input 9739.00 Mbits/sec,    1675056 packets/sec, 99.90% of line-rate
     Output 9809.00 Mbits/sec,    1290207 packets/sec, 99.90% of line-rate

10GSW2# sho int tengigabitethernet 1/37 | grep rate
Queueing strategy: fifo
     Input 9831.00 Mbits/sec,    1285030 packets/sec, 99.90% of line-rate
     Output 9771.00 Mbits/sec,    1660177 packets/sec, 99.90% of line-rate
```

仮想マシンでも普通に10Gbpsが出ることが確認できました。


# 検証6: 仮想マシン(KVM)試験
KVMについては[WARP17のサイト](https://github.com/Juniper/warp17/blob/dev/common/ovf/README.md#warp17-virtual-machine)にも記載されていますが、若干の追加作業がありましたのであわせて紹介します。物理サーバのスペックはこれまで検証でつかった機器と同じですが、ホストOSはovfテンプレートにあわせてUbuntu14.04にしています。

![network8.PNG](https://qiita-image-store.s3.amazonaws.com/0/165176/6aa2a06f-d12c-decc-ddc7-6f4af20d2b98.png)

## セットアップ

PCIパススルーの設定を行います。VMwareの際はXX:00.0とXX:00.1の片方しかパススルー設定できませんでしたが、KVMでは両方をパススルーさせることが可能です。

```
testerman@tester2:~$ sudo vi /etc/default/grub
(省略)
GRUB_CMDLINE_LINUX_DEFAULT=""
GRUB_CMDLINE_LINUX="intel_iommu=on"
→intel_iommu=onを追記し、IOMMU機能を有効化します。

testerman@tester2:~$ sudo update-grub
testerman@tester2:~$ sudo reboot

testerman@host1:~$ sudo dmesg | grep IOMMU
[    0.000000] DMAR: IOMMU enabled
→IOMMU enabledを確認します。

testerman@tester2:~$ lspci -nn | grep 10-Gigabit
(省略)
83:00.0 Ethernet controller [0200]: Intel Corporation Ethernet Controller 10-Gigabit X540-AT2 [8086:1528] (rev 01)
83:00.1 Ethernet controller [0200]: Intel Corporation Ethernet Controller 10-Gigabit X540-AT2 [8086:1528] (rev 01)
→KVM仮想マシンに渡す10GポートのPCIスロット番号を決めます。

testerman@tester2:~$ sudo su
root@tester2:~# modprobe pci-stub
root@tester2:~# echo "8086 1528" > /sys/bus/pci/drivers/pci-stub/new_id
root@tester2:~# echo 0000:83:00.0 > /sys/bus/pci/devices/0000:83:00.0/driver/unbind
root@tester2:~# echo 0000:83:00.1 > /sys/bus/pci/devices/0000:83:00.1/driver/unbind
root@tester2:~# echo 0000:83:00.0 > /sys/bus/pci/drivers/pci-stub/bind
root@tester2:~# echo 0000:83:00.1 > /sys/bus/pci/drivers/pci-stub/bind
```

[こちら](http://warp17.net/downloads/)からVMware用のOVFファイルをダウンロードしてきてconvert後、仮想マシンを起動します。

```
root@tester2:/home/testerman# tar -xvf WARP17-v1.4.ova
WARP17-v1.4.ovf
WARP17-v1.4.mf
WARP17-v1.4-disk1.vmdk
root@tester2:/home/testerman# apt-get install qemu-utils
root@tester2:/home/testerman# qemu-img convert -O qcow2 -c WARP17-v1.4-disk1.vmdk WARP17-v1.4-disk1.qcow2
root@tester2:/home/testerman# apt-get install qemu-system-x86
root@tester2:/home/testerman# qemu-system-x86_64 -enable-kvm -cpu host -smp 16 -hda WARP17-v1.4-disk1.qcow2 -m 32768   -display vnc=:0 -redir tcp:2222::22   -net nic,model=e1000 -net user,name=mynet0 -device pci-assign,romfile=,host=83:00.0 -device pci-assign,romfile=,host=83:00.1 -daemonize
```

別ターミナルよりtester2経由で仮想マシンにログインします。

```
testerman@tester2:~$ ssh -p 2222 warp17@localhost
warp17@localhost's password:warp17

warp17@warp17:~$ sudo vi /etc/default/grub
(省略)
GRUB_CMDLINE_LINUX="default_hugepagesz=1G hugepagesz=1G hugepages=32"
→10Gbpsが流せるように12から32に修正します。

warp17@warp17:~$ sudo update-grub
warp17@warp17:~$ sudo reboot
warp17@warp17:~$ Connection to localhost closed by remote host.
Connection to localhost closed.
testerman@tester2:~$

しばらくしたら再度仮想マシンにログインして10Gポートをバインドします。

testerman@tester2:~$ ssh -p 2222 warp17@localhost
warp17@warp17:~$ $RTE_SDK/tools/dpdk-devbind.py --status

Network devices using DPDK-compatible driver
============================================
<none>

Network devices using kernel driver
===================================
0000:00:03.0 '82540EM Gigabit Ethernet Controller' if=eth0 drv=e1000 unused=igb_uio
0000:00:04.0 'Ethernet Controller 10-Gigabit X540-AT2' if=eth1 drv=ixgbe unused=igb_uio
0000:00:05.0 'Ethernet Controller 10-Gigabit X540-AT2' if=eth2 drv=ixgbe unused=igb_uio
(省略)

warp17@warp17:~$ sudo $RTE_SDK/tools/dpdk-devbind.py -b igb_uio 00:04.0
warp17@warp17:~$ sudo $RTE_SDK/tools/dpdk-devbind.py -b igb_uio 00:05.0
warp17@warp17:~$ $RTE_SDK/tools/dpdk-devbind.py --status

Network devices using DPDK-compatible driver
============================================
0000:00:04.0 'Ethernet Controller 10-Gigabit X540-AT2' drv=igb_uio unused=
0000:00:05.0 'Ethernet Controller 10-Gigabit X540-AT2' drv=igb_uio unused=

Network devices using kernel driver
===================================
0000:00:03.0 '82540EM Gigabit Ethernet Controller' if=eth0 drv=e1000 unused=igb_uio
(省略)
→仮想マシンから10G物理ポートが正常にバインドされました。
```

## 試験実施

VMwareの時と同様にメモリーを32GB割り当てると以下のようなエラーが出ますので少し値を下げます。
`EAL: Not enough memory available! Requested: 32768MB, available: 29696MB`

```
warp17@warp17:~$ sudo ./warp17/build/warp17 -c FFFF -m 29696 -- --qmap-default max-q --tcb-pool-sz 20480 --cmd-file /home/warp17/warp17/examples/test_5_raw_10M_sessions.cfg
```

10Gbpsが流れています。
![rate7(VM).PNG](https://qiita-image-store.s3.amazonaws.com/0/165176/e53e5a92-16e5-1188-631e-eecdfe9a26ef.png)


# 最後に
今回、単体構成(2ポート、4ポート、8ポート)、セパレート構成、VMware、KVMのどの構成でも、WARP17を使用して10Gbpsが流せることが確認できました。10Gbpsだけ試してみるぐらいの予定でしたが面白くなってどっぷりつかってしまいました。@kazubuさん、juniperさん、どうもありがとうございました。