trafgenの使い方

# はじめに
trafgenは、**IPアドレスやポート番号をランダム、もしくは、インクリメント**させながら、ネットワークに負荷をかけることができるツールです。trafgenを利用すれば、より実用的なワークロードでの性能評価が可能になると考えられますが、trafgenの利用に関する情報は少なく、webに公開されている情報を元に利用してみると、躓くことがあります。
本稿では、trafgenの利用方法を紹介します。


# 1. trafgenとは

trafgenは、[netsniff-ng](http://netsniff-ng.org/
)に含まれるツールの一つで、マルチスレッドで動作する低レベルのゼロコピー・パケットジェネレイターです。**drnd()やdinc()といった関数**を用いることで、IPアドレスやポート番号などを変更しながら、ネットワークの性能評価ができます。netsniff-ngには、ifppsといったスループットやpps(packet per second)をリアルタイムで表示するツールも用意されています。
例えば、ubuntuの場合は、aptでインストールできます。
```
# sudo apt-get install netsniff-ng 
```

# 2. trafgenの利用例

## 2.1 設定ファイルの準備
### 2.1.1 テンプレートの自動生成
下記コマンドで、設定ファイルのテンプレートを自動生成させます。
公開されている情報の中には、簡略化されたテンプレートを自前で用意する例もありますが、構築したネットワークの状況によってはパケットが疎通しないことがあります。基本的には、テンプレートを作成して、それを修正する手順が最も安全と言えます。
```
# trafgen -e > sample.cfg
```
自動生成されたテンプレートは以下です。
```
# cat sample.cfg
/* Note: dynamic elements make trafgen slower! */
#include <stddef.h>

{
  /* MAC Destination */
  fill(0xff, ETH_ALEN),
  /* MAC Source */
  0x00, 0x02, 0xb3, drnd(3),
  /* IPv4 Protocol */
  c16(ETH_P_IP),
  /* IPv4 Version, IHL, TOS */
  0b01000101, 0,
  /* IPv4 Total Len */
  c16(59),
  /* IPv4 Ident */
  drnd(2),
  /* IPv4 Flags, Frag Off */
  0b01000000, 0,
  /* IPv4 TTL */
  64,
  /* Proto TCP */
  0x06,
  /* IPv4 Checksum (IP header from, to) */
  csumip(14, 33),
  /* Source IP */
  drnd(4),
  /* Dest IP */
  drnd(4),
  /* TCP Source Port */
  drnd(2),
  /* TCP Dest Port */
  c16(80),
  /* TCP Sequence Number */
  drnd(4),
  /* TCP Ackn. Number */
  c32(0),
  /* TCP Header length + TCP SYN/ECN Flag */
  c16((8 << 12) | TCP_FLAG_SYN | TCP_FLAG_ECE)
  /* Window Size */
  c16(16),
  /* TCP Checksum (offset IP, offset TCP) */
  csumtcp(14, 34),
  /* TCP Options */
  0x00, 0x00, 0x01, 0x01, 0x08, 0x0a, 0x06,
  0x91, 0x68, 0x7d, 0x06, 0x91, 0x68, 0x6f,
  /* Data blob */
  "gotcha!",
}
```
### 2.1.2 テンプレートの修正
IPアドレスやポート番号などを適切な値に書き換えます。
値を書き換える際には、ランダム関数（drn）とインクリメント関数（dinc）を利用することができます。

## 2.2 trafgenの実行
今回は、物理マシン2台(tx-host, rx-host)を直接結線し、trafgenによるネットワークの負荷掛けを行いました。
それぞれのインターフェース名は、enp3s0f1とenp1sとなっています。
tx-host上で、trafgenでネットワーク負荷掛けをし、rx-host上で、ifppsを用いてリアルタイムな測定をします。
実行結果は以下です。
```:tx-host
# sudo trafgen -d enp3s0f1 --cpp --conf sample.cfg -n 1000000
     8 packets to schedule
   544 bytes in total
Running! Hang up with ^C!


     1000000 packets outgoing
    68000000 bytes outgoing
           9 sec, 57697 usec on CPU0 (125000 packets)
           9 sec, 36054 usec on CPU1 (125000 packets)
           9 sec, 55131 usec on CPU2 (125000 packets)
          12 sec, 88467 usec on CPU3 (125000 packets)
           9 sec, 50743 usec on CPU4 (125000 packets)
          12 sec, 94213 usec on CPU5 (125000 packets)
          12 sec, 75100 usec on CPU6 (125000 packets)
           9 sec, 51505 usec on CPU7 (125000 packets)
```
```: rx-host
# ifpps -d enp1s0 
  5.15.0-46-generic, x86_64, enp1s0 (atl1c 100Mbit/s link:yes), t=1000ms, cpus=4/4

  rx:            2.637 MiB/t      40656 pkts/t      40670 drops/t          0 errors/t  
  tx:            0.000 MiB/t          0 pkts/t          0 drops/t          0 errors/t  

  rx:          196.750 MiB      3032909 pkts      3040580 drops            0 errors
  tx:            0.254 MiB         1185 pkts            0 drops            0 errors

  sys:            2114 cs/t         214 procs           2 running          0 iowait

  mem:           3866M total      3445M used         958M active       2076M inactive
  swap:          2047M total         2M used           0M cached

  cpu0 +:         0.0% usr/t      11.0% sys/t       89.0% idl/t         0.0% iow/t
  cpu1 |:         0.0% usr/t       0.0% sys/t      100.0% idl/t         0.0% iow/t
  cpu2 |:         0.0% usr/t       0.0% sys/t      100.0% idl/t         0.0% iow/t
  cpu3 -:         0.0% usr/t       0.0% sys/t      100.0% idl/t         0.0% iow/t
  avg:            0.0%             2.0%             98.0%               0.0%

  cpu3 +:          950 irqs/t                 0 sirq rx/t                 1 sirq tx/t
  cpu0 |:            0 irqs/t                 0 sirq rx/t                 0 sirq tx/t
  cpu1 |:            0 irqs/t                 0 sirq rx/t                 0 sirq tx/t
  cpu2 -:            0 irqs/t                 0 sirq rx/t                 0 sirq tx/t
```
ifppsの結果を確認すると、40656 pkts/t となっており、40 Kpps程度しかネットワークに負荷を掛けられていませんでした。物理マシンのスペックが問題の一つである可能性もありますが、trafgenを単に利用するだけでは、十分な負荷を掛けられない場合がありそうです。
より高負荷なネットワークの性能評価を実施したい場合は、[DPDK](https://www.dpdk.org/)などの技術の利用を検討すると良いと言えます。DPDKでは、プロトコルスタックをユーザスペースで実施するためのライブラリを提供しており、パケット処理におけるユーザスペースとカーネルスペース間でのコンテキストスイッチの回数を削減することで、パケット処理を高速化させることができます。


# 3. まとめ
自動生成されたテンプレートを用いて、trafgenを利用する方法を紹介しました。また、trafgenをそのまま利用すると、ネットワークへの負荷を十分に掛けられない可能性があることを示しました。

# 参考文献

https://man7.org/linux/man-pages/man8/trafgen.8.html

https://levelup.gitconnected.com/building-a-high-performance-linux-based-traffic-generator-with-dpdk-93bb9904416c