iperf での帯域測定検証(tcpモード vs udpモードなど)

# 1. 目的
- iperf(iperf3) を使ってスループットの測定を行うことがあるが、以下のような疑問があった。
    - tcpモードとudpモードのどちらを使ったほうがよいのか？
    - パラメータ（ウィンドウサイズなど）を変えることにより結果にどれだけ影響があるのか？
    - FTPなど、他の方法でのスループット測定とどう違うのか？
- 特に気になった点を実機検証することにより、あらためて自分なりの測定ルールを確立する。

# 2. やったこと
- 3種類のネットワーク環境を用意する。
    - 環境1(有線LAN): PC(Win10) -- L2SW(1G対応) -- PC(Win11)　(ping RTT 1ms未満)
    - 環境2(モバイルアクセス): PC(Win11) -- インターネット -- AWS東京リージョン(Win2019) (ping RTT 60ms程度)
    - 環境3(リージョン間): AWS東京リージョン(Win2019) -- インターネット -- AWSサンパウロリージョン(Win2019) (ping RTT 250ms程度)
- 以下のパターンでの測定を行い、結果を比較する。
    - iperf tcpモード
    - iperf tcpモード(ウィンドウサイズ変更)
    - iperf udpモード
    - FTP

# 3. 結果概要

## 3.1 測定結果概要
- tcpモードとudpモードの使い分け
    - iperf(udpモード)では低帯域(同一環境でのtcpモードでの実績値を下回る値)を設定してもロスが発生する。udpモードでロスがない状態を維持しつつ、tcpモードよりも高いスループットを出すのは難しく、普通に帯域を測定したい場合はtcpモードでよいのではないか。

- tcpモードのウィンドウサイズ
    - 遅延が小さいネットワーク環境の場合、iperf(tcpモード)でのウィンドウサイズ設定の影響も小さい。そのため、iperf(tcpモード)のデフォルト設定のまま測定しても高いスループットが得られると考えられる。一方、遅延が大きい環境で高いスループットを出そうとする場合はウィンドウサイズの調整が必要。

- iperfとFTPの使い分け
    - iperf(tcpモード,デフォルト設定)と、FTPでは、遅延が小さいネットワークの場合スループットに大差なかったが、遅延が大きいネットワークの場合は、FTPのほうが高スループットとなった（FTPはウィンドウサイズが可変で、結果として大きくなるからと想定）。iperf(tcpモード,デフォルト設定)での測定結果をベースラインとして、アプリケーション(FTPなど)によってはそれ以上のスループットが出る可能性がある、と考えるようにしたい。

## 3.2 iperf測定手順の使い分け方針 
- 今回検証した結果から、今後以下のようなユースケースにおいて、（あくまで自分ルールとして）以下の方針にすることとした。

||ユースケース|方法|備考|
|---|---|---|---|
|1|大まかなスループットの値を把握したい。|tcpモード(デフォルト設定)|様々なネットワーク環境を公平に測定するには環境ごとにパラメータを変えないほうがよい。またデフォルトの設定で実施したほうが結果が他者に説明しやすい。|
|2|そのネットワーク環境での最大スループットを把握したい。|tcpモード(ウィンドウサイズ変更) |「最大XXMbps出たよ！」のようになるべく大きい値を出したい場合は、パラメータ調整などに手間をかける必要あり。udpモードはロスが出ない中での最大値を探る必要あるが、tcpモード以上の値が出しづらかった。|
|3|スループット測定ではなく、回線に負荷をかけたい。|udpモード | 「-b 10M」 のように帯域を指定して負荷トラフィックの出力が可能。送信側で指定した量のトラフィックを出していても、受信側までエンド-エンドで届いているとは限らないので、あくまで送信側に近いネットワーク区間の回線に負荷をかける用途。
|4|ジッタを測定したい。|udpモード|ジッタはudpモードでしか測定できない。ロスが起こらない程度の少量の帯域を指定して実施する。

# 4. 構成図

![iperf構成図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/292b0843-57af-ffe2-e3ca-81a36f2749d9.png)


# 5. 事前環境構築
- 今回は全てWindows版のiperf3(64bit版、ver3.1.3)を[公式サイト](https://iperf.fr/iperf-download.php)からダウンロードして使用する。
- 自宅環境について、L2SWは1Gbps対応のものを用意。PCに接続して用いるUSB LANアダプタを100Mbps/1Gbps対応のものを
差し替えて物理的な帯域を変更する。
- AWSでの主な設定は以下の通り。
    - インスタンスタイプ: t3.medium
    - FTPサーバはIISを使用。FTPサーバの設定手順は以下を参照。
        - IIS FTP設定手順： [windows server 2019へFTPサーバ機能を追加してみた](https://blog.denet.co.jp/i-added-ftp-server-function-to-windows-server-2019/)　
        - NAT(EIP)対応：　[FTP Firewall Support <firewallSupport>](https://docs.microsoft.com/en-us/iis/configuration/system.applicationhost/sites/site/ftpserver/firewallsupport)
- PC(Windows 10)のFTP有効化は以下を参照。
    - [Windows10でFTPサーバーを構築・設定する手順をやさしく解説](https://proengineer.internous.co.jp/content/columnfeature/19899)
- FTPクライアントは[Filezilla 3.58.0](https://filezilla-project.org/index.php)を使用。

# 6. 測定試験

## 6.1 測定方法
### 6.1.1 iperf3の設定
- iperf3のインストール方法、基本的な使い方やパラメータの説明は以下のサイトなどを参照する。
    - [iperf3コマンドの使い方](https://hana-shin.hatenablog.com/entry/2022/01/16/121553#3-%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E6%96%B9%E6%B3%95)
    - [iperf3コマンド使い方、オプション一覧](https://qiita.com/yokoc1322/items/bfd8b6e69d6bdb3bb1c6)

### 6.1.2 iperf3サーバ側設定
- サーバ側は普通に待ち受け設定する。

```
# iperf3 -s 
```

### 6.1.3 iperf3クライアント側設定、実行例

- クライアント側は 「-t 30」(実行時間30秒)、「--get-server-output」(サーバ側での結果出力をクライアント側にも出力」を今回の検証でのデフォルト値として常時指定する。(--get-server-outputを付けているのは、秒単位のジッタ値など、サーバ側でしか出力されない値もあるため）
- udpモードは帯域を指定しないとデフォルトで1Mbpsになるため、「-b 10M」などのように帯域を設定する。
- 今回は全てクライアント側からのデータ送信とする。(-R オプションによる逆方向の測定は行わない） 

```
### tcpモードの例
# iperf3 -c dstip -t 30 --get-server-output -w 60K
### udpモードの例
# iperf3 -c dstip -t 30 --get-server-output -u -b 10M 
```

- 測定結果表へ記載する「xxMbps」の値は、コマンド実行結果のうち、「sender」の左の値(以下例では94.8Mbps)を使用する。

```
c:\work\iperf-3.1.3-win64>iperf3 -c 192.168.0.2 --get-server-output -t 30
Connecting to host 192.168.0.2, port 5201
[  4] local 192.168.0.1 port 49975 connected to 192.168.0.2 port 5201
[ ID] Interval           Transfer     Bandwidth
[  4]   0.00-1.00   sec  11.1 MBytes  93.1 Mbits/sec
[  4]   1.00-2.00   sec  11.4 MBytes  95.2 Mbits/sec
～中略～
[  4]  28.00-29.00  sec  11.2 MBytes  94.1 Mbits/sec
[  4]  29.00-30.00  sec  11.4 MBytes  95.7 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth
[  4]   0.00-30.00  sec   339 MBytes  94.8 Mbits/sec                  sender
[  4]   0.00-30.00  sec   339 MBytes  94.7 Mbits/sec                  receiver
```
- 「iperfで表示している値の量のパケットを本当に送受信しているのか？」は、Windows(PC/サーバ)のパフォーマンスモニタを表示し、パフォーマンスモニタのイーサネットの送信/受信値がiperfの結果と同等となっていることを確認する。以下例はudpモード(10Mbps指定)での通信中の受信側の画面。概ねiperfでの値と同等となっていた。

![PFモニタ画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/580f1e3a-a58a-b975-2873-20a134dcbb0d.png)

### 6.1.4 FTP

- FTPのスループットについては、クライアントにFileZilla、サーバにIIS(FTP Site)を用いて、100MBのファイル1個をアップロードする際の所要時間をIISのログから確認する（最小単位が秒のため、あまり正確な値ではない）。以下のIISのログファイル例だと、100MBのファイルのアップロードに03:48:46～03:49:21までの35秒かかっており、100MB/8sec で、22.8Mbpsとなる。

```
2022-02-22 03:48:46 x.x.x.x EC2AMAZ-ENBK37O\ftpuser 10.0.0.17 21 TYPE A 200 0 0 20 8 0 5a4a4d3a-43c0-4371-a6e3-d9f50ddfdbdc -
2022-02-22 03:48:46 x.x.x.x EC2AMAZ-ENBK37O\ftpuser 10.0.0.17 21 PASV - 227 0 0 51 6 0 5a4a4d3a-43c0-4371-a6e3-d9f50ddfdbdc -
2022-02-22 03:48:46 x.x.x.x EC2AMAZ-ENBK37O\ftpuser 10.0.0.17 49730 DataChannelOpened - - 0 0 0 0 0 5a4a4d3a-43c0-4371-a6e3-d9f50ddfdbdc -
2022-02-22 03:49:21 x.x.x.x EC2AMAZ-ENBK37O\ftpuser 10.0.0.17 49730 DataChannelClosed - - 0 0 0 100000000 0 5a4a4d3a-43c0-4371-a6e3-d9f50ddfdbdc -
2022-02-22 03:49:21 x.x.x.x EC2AMAZ-ENBK37O\ftpuser 10.0.0.17 21 STOR 100MB 226 0 0 65 100000012 35579 5a4a4d3a-43c0-4371-a6e3-d9f50ddfdbdc /100MB
```

### 6.1.5 TCPウィンドウサイズについて
- 「-w」オプションによるウィンドウサイズ設定が実際にどのように反映されるかについて、iperf3/FTPのパケットをWireSharkで見ることにより確認した。
- nesuke様のサイト「[【図解】TCP window size の仕組み〜MSS(MTU)との違い,calculated window size,unknown factor,受信バッファの設定変更～](https://milestone-of-se.nesuke.com/nw-basic/tcp-udp/window-size-mss-mtu/)」にWireSharkの見方の解説があり、それを参考に各設定パターンでのウィンドウサイズ関連値を確認した。
- ウィンドウサイズにどういった値を設定するのが適切なのか理解できてはいないが、検証パターンとしてデフォルト状態(-w の引数なし)の時よりもウィンドウサイズが小さい値、大きい値の両方を取れるよう60Kと100Mという値を設定した。

- iperf3の-wオプション指定によるウィンドウサイズの挙動は以下の通り。「Calculated Window Size」(Window Size * Window size scaling factor) がウィンドウサイズの値となる。双方向同じ値となり、またコマンド実行中常時固定の値となる。なお-w オプションを指定しない場合、以下表のとおり、ウィンドウサイズは約213KBとなる。
    
|値|デフォルト<br>クライアント発|デフォルト<br>サーバ発|-w 60K<br>クライアント発|-w 60K<br>サーバ発|-w 100M<br>クライアント発 |-w 100M<br>サーバ発|
|--|--:|--:|--:|--:|--:|--:|
|Window Size|53248|53248|61440|61440|51200|51200|
|Calculated Window Size|212992|212992|61440|61440|104857600|104857600|
|Window size scaling factor|4|4|1|1|2048|2048|

- FTPのウィンドウサイズの挙動は以下の通り。FTPアプリケーションによりウィンドウサイズの調整が行われているようで、サーバ発のパケットのCalculated Windows Sizeの値が変化しており、ファイルのアップロード時のウィンドウサイズが大きくなるようになっている。このため、パケロスによる再送などがなければ、iperf(tcpモード、デフォルト設定)よりはスループットが上がる可能性があると考えられる。

|値|通信開始直後<br>クライアント発|通信開始直後<br>サーバ発|通信終了直前<br>クライアント発|通信終了直前<br>サーバ発|
|--|--:|--:|--:|--:|
|Window Size|1026|8223|1026|64094|
|Calculated Window Size|262656|2105088|262656|13848064|
|Window size scaling factor|256|256|256|256|



## 6.2 有線LAN環境での測定

- まず、物理的な帯域が把握できる有線LAN環境で基本動作を確認する。基本的にはエンド-エンドで1Gbpsだが、片方のPCのLANアダプタを100Mbps対応のものに変更することで物理帯域を100Mbpsとしての測定も実施。遅延(ping RTT)は<1ms。

|#|物理帯域|方法|クライアント側コマンド|結果|補足(UDPの場合のlost率/Jitter値)|
|--|--|--|--|--|--|
|1|100M|tcp(デフォルト)| iperf3 -c dstip --get-server-output -t 30| 94.8Mbps |
|2|100M|tcp(-w 60K)| iperf3 -c dstip --get-server-output -t 30 -w 60K| 94.9Mbps |
|3|100M|tcp(-w 100M)| iperf3 -c dstip --get-server-output -t 30 -w 100M| 94.8Mbps | senderの値(clientでの結果)が異常値(100Mbpsを超えてしまった)のため、receiverの値(Serverでの結果)である94.8Mbpsを採用。
|4|100M|udp(1M)     | iperf3 -c dstip --get-server-output -t 30 -u -b 1M| 1.00Mbps |lost: 0%<br>Jitter: 0.254ms|
|5|100M|udp(10M)     | iperf3 -c dstip --get-server-output -t 30 -u -b 50M| 9.97Mbps |lost: 46%<br>Jitter: 0.841ms|
|6|100M|FTP||100Mbps|100MBのファイルを8秒でアップロード完了<br>※ログが秒単位のため概算値
|7|1G|tcp(デフォルト)| iperf3 -c dstip --get-server-output -t 30| 942Mbps |
|8|1G|tcp(-w 60K)| iperf3 -c dstip --get-server-output -t 30 -w 60K| 390Mbps |
|9|1G|tcp(-w 100M)| iperf3 -c dstip --get-server-output -t 30 -w 100M| 977Mbps | 
|10|1G|udp(1M)     | iperf3 -c dstip --get-server-output -t 30 -u -b 1M| 1.00Mbps |lost: 0% <br> Jitter: 0.265ms
|11|1G|udp(10M)     | iperf3 -c dstip --get-server-output -t 30 -u -b 10M| 9.97Mbps |lost: 3.5% <br> Jitter: 0.523ms
|13|1G|udp(50M)     | iperf3 -c dstip --get-server-output -t 30 -u -b 50M| 49.9Mbps |lost: 14% <br> Jitter: 0.127ms
|14|1G|udp(500M)     | iperf3 -c dstip --get-server-output -t 30 -u -b 500M| 500Mbps |lost: 74% <br> Jitter: 266.360ms
|15|1G|FTP||1Gbps|100MBファイルを1秒でアップロード完了<br>※ログが秒単位のため概算値

- 有線LAN環境では遅延が小さいため、デフォルトのtcpモードのままでも、ほぼワイヤーレートの値が出せている。
- udpモードにした場合、送信側では指定の帯域で出力しているが、受信側できちんと受けとれず、割と低い値の時からロスが発生してしまった。udpモードではロスがない状態でないと「エンド-エンドでの帯域が測れた」とはいいづらいため、スループットの最大値はtcpモードより低くなってしまった。
- tcpモード(デフォルト)とFTPは、どちらもワイヤレートでの送信が可能で、あまり差がなかった。

## 6.3 自宅～AWS東京リージョンでの測定

- 自宅からインターネット経由でのAWS東京リージョンへのアクセス環境(モバイルルータ使用)での測定を実施する。遅延(ping RTT)は60ms程度。

|#|方法|クライアント側コマンド|結果|補足|
|--|--|--|--|--|
|1|tcp(デフォルト)| iperf3 -c dstip --get-server-output -t 30| 16.2Mbps |
|2|tcp(-w 60k)  | iperf3 -c dstip --get-server-output -t 30 -w 60K| 10.8Mbps |
|3|tcp(-w 100M)  | iperf3 -c dstip --get-server-output -t 30 -w 100M| 20.6Mbps | senderの値(clientでの結果)が異常値(最初の1秒の結果が846Mbps)のため、receiverの値(Serverでの結果)である20.6Mbpsを採用。
|4|FTP||22.8Mbps|100MBのファイルを35秒でアップロード完了<br>※ログが秒単位のため概算値
|5|udp(1M)     | iperf3 -c dstip --get-server-output -t 30 -u -b 1M| 1.00Mbps |lost: 0% <br> Jitter: 7.690ms
|6|udp(10M)         | iperf3 -c dstip --get-server-output -t 30 -u -b 10M| 10.0Mbps |lost: 0.044% <br> Jitter: 2.358ms
|7|udp(50M)         | iperf3 -c dstip --get-server-output -t 30 -u -b 50M| 49.8Mbps |lost: 66%<br> Jitter: 5.988ms

- iperf(tcpモード,デフォルト値)よりもFTPのほうが若干高スループットとなった。
- モバイル回線を使っていることからか、他のネットワーク環境と比較しジッタの値が大きくなっている。

## 6.4 AWS東京リージョン～AWSサンパウロリージョン間での測定

- 最後に、恒常的に遅延がある環境として、クライアントをAWSサンパウロリージョン、サーバをAWS東京リージョンに設置した(VPCピアリングなどではなく、それぞれのインスタンスにEIPを付与してインターネット経由)。遅延(ping RTT)は250ms程度。

|#|方法|クライアント側コマンド|結果|補足|
|--|--|--|--|--|
|1|tcp(デフォルト)| iperf3 -c dstip --get-server-output -t 30| 5.80Mbps |
|2|tcp(-w 60k)  | iperf3 -c dstip --get-server-output -t 30 -w 60K| 1.90Mbps |
|3|tcp(-w 100M)  | iperf3 -c dstip --get-server-output -t 30 -w 100M| 51.6Mbps | senderの値(clientでの結果)が異常値(最初の1秒の結果が834Mbps)のため、receiverの値(Serverでの結果)である51.6Mbpsを採用。
|4|FTP||57.1Mbps|100MBのファイルを14秒でアップロード完了<br>※ログが秒単位のため概算値
|5|udp(1M)     | iperf3 -c dstip --get-server-output -t 30 -u -b 1M| 1.00Mbps |lost: 0% <br> Jitter: 0.115ms
|6|udp(10M)         | iperf3 -c dstip --get-server-output -t 30 -u -b 10M| 9.97Mbps |lost: 0% <br> Jitter: 0.029ms
|7|udp(50M)         | iperf3 -c dstip --get-server-output -t 30 -u -b 50M| 49.9Mbps |lost: 78%<br> Jitter: 0.025ms

- 遅延が大きい環境のため、iperf(tcpモード)はウィンドウサイズ設定の影響が大きくなっている。

# 7.所感
- iperfはパラメータが多く全貌が分かったわけでは全然ないが、基本的な動作について測定データを基にした再確認を行うことができた。各種環境での測定を行う中で知識のアップデートを行いたい。
- 「マスタリングTCP/IP」のような本を読むなど、ネットワークの基礎を学びなおしたほうがいいのかなという気持ちになった。