Cisco IOS、IOS-XEのFTP転送速度実験
はじめに
Cisco機器のOSバージョンアップでBinaryファイルをFTP転送する時、いつも「めっちゃ遅いな」と感じているのですが、TCP/IP周りの実装がどうなっているのか知りたくなったので実験してみました。
まず比較対象としてLinux(Ubuntu)、その後Cisco IOS-XEとIOSでFTP転送を行い、パケット解析を行いました。さらに、TCP設定変更による速度チューニングも行ってみました。
1. 事前準備
1-1. NW構成
ubuntu-2をFTPサーバとし、csr1(IOS-XE)とiosv-1(IOS)をFTPクライアントとしました。wan-em-0はWAN Emulatorです。1対1でしか接続できないため、実験時は交互に接続切替を行いました。
上のunmanaged-switch-0、ext-conn-0は、外部の物理環境からキャプチャファイルを取得するための環境です。取得時はubuntu-2とunmanaged-switch-0間を接続しました。
1-2. UbuntuでのFTPサーバ構築
以下記事を参考にvsftpdをインストールしました。バージョンは3.0.3です。設定ファイル(/etc/vsftpd.conf)はデフォルトのままにしました。
1-3. FTP転送用ファイルの生成
以下記事を参考に、中身がランダムなファイルを生成し、FTPサーバのホームディレクトリ(/home/ubuntu)に格納しました。ファイルサイズは50MB、ファイル名はtest_50mb.txtとしました。
$ head -c 50m /dev/urandom > test_50mb.txt
1-4. WAN Emulatorの設定
以下記事を参考に、Port Settingsで遅延、パケットロス、帯域制限を発生させ、FTPサーバ~クライアント間のTCP設定による挙動の違いが見えやすいようにしました。
項目 | 値 |
---|---|
Latency(ms) | 50(行きと戻りで合計100) |
Jitter(ms) | 0 |
Loss(%) | 0.01(約10000回に1回パケットロス) |
Bandwidth(kbit) | 50000 |
https://sig9.hatenablog.com/entry/2020/06/22/000000 |
1-5. パケットキャプチャ設定
CML Personal 2.1にもパケットキャプチャ機能はありますが、有効化によりFTP転送速度が遅くなったり、CMLのキャプチャ結果表示画面がフリーズしてしまったりしたので、FTPサーバ側でtcpdumpを行いました。
sudo tcpdump -i ens2 -w capture.pcap
2. UbuntuがFTPクライアントの場合
2-1. TCP設定確認
(1) TCP輻輳制御アルゴリズム
Ubuntu(18.04)の場合、Loss-based輻輳制御アルゴリズムの一つである「CUBIC」をデフォルトで採用しているようです。Linux2.6.19以降やWindows10で標準搭載されているもので、従来のNew Renoが抱えていた、ロングファットパイプ(広帯域/高遅延環境)で帯域を有効活用出来ない課題に対応したアルゴリズムです。
ubuntu@ubuntu:~$ sudo sysctl net.ipv4.tcp_congestion_control
net.ipv4.tcp_congestion_control = cubic
(2) TCPオプション
下記FTPデータ通信の3way handshake時にやり取りされるオプション設定を確認しました。
Window scale
TCPの標準仕様では、Windowサイズ(ACKを待たずに一度に送信できるデータ量)は64KB(2の16乗)までですが、広帯域の場合これでは不十分なため、Window scaleオプションで値を大きく出来ます。今回は「7」が提示され、8MB(2の16+7=23乗)まで利用可能になっていました。
SACK
TCPの標準仕様では、パケットロス発生時、ロストしたパケット以降全て再送が必要です。SACK(Selective ACK)の有効化により、ロストしたパケットのみ再送すれば良くなります。
2-2. 転送結果
(1) 転送時間計測
以下の通り、FTPクライアントからBinaryモード、PassiveモードでファイルのGETを行いました。
ubuntu@ubuntu:~$ ftp 192.168.100.196
Connected to 192.168.100.196.
220 (vsFTPd 3.0.3)
Name (192.168.100.196:ubuntu): ubuntu
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> bi
200 Switching to Binary mode.
ftp> passive
Passive mode on.
ftp> get test_50mb.txt
local: test_50mb.txt remote: test_50mb.txt
227 Entering Passive Mode (192,168,100,196,176,3).
150 Opening BINARY mode data connection for test_50mb.txt (52428800 bytes).
226 Transfer complete.
52428800 bytes received in 17.54 secs (2.8504 MB/s)
ftp> exit
221 Goodbye.
3回実施したところ、以下の結果になりました。感覚的には「遅延・パケロスも発生させているし、まあこんなものかな」くらいの転送速度でした。(ちなみに両方発生させない場合は1~3秒くらいで転送完了しました。)
回数 | 転送時間(s) | 転送速度(MB/s) |
---|---|---|
1 | 17.54 | 2.8504 |
2 | 27.05 | 1.8487 |
3 | 12.34 | 4.0524 |
平均 | 18.98 | 2.9172 |
(2) 入出力グラフ
1回目のキャプチャデータをWiresharkで読み込み、FTPサーバからのデータ転送パケット(ip.src_host==<FTPサーバのアドレス> && tcp.srcport==<FTPサーバのポート番号>)のみをフィルタし、100ms間隔で入出力グラフを出力してみました。ちょっと見づらいですが、安定時は25~35Mbpsの間を推移しています。
(3) 時間/シーケンスグラフ(tcptrace)
同じくWireshakで、TCPストリームグラフから「時間/シーケンス(tcptrace)」を選択し、FTPサーバからのデータ転送パケットのシーケンス番号推移を確認しました。
上の緑の線は、FTPクライアントから返ってきたACKパケットの確認応答番号に、受信Windowサイズを加えた値です。重なって見えづらいですが、下の茶色の線は、ACKパケットの確認応答番号の値です。2つの線の差分から、Windowサイズの推移を確認できます。安定時は2.95×100000B前後でした。
真ん中の青い点は、FTPサーバから送信したパケットのシーケンス番号の値のようです。
5秒、8.5秒、16.5秒付近で赤くなっているのは、確認応答番号が同じACKパケットが返ってきている状態(Duplicate ACK)を示し、今回パケットロスが発生した箇所です。
(4) スループットグラフ
さらにTCPストリームグラフの「スループット」を選択し、FTPサーバからクライアントへの転送能力を計測しました。この値は実際の転送速度ではなく、受信Windowサイズを往復遅延時間(RTT)で割った値です。
最初の値が小さいのは、TCP輻輳制御のスロースタートによるものです。途中で値が小さくなっているのは、パケットロスによるWindowサイズ減少と関係していると考えられます。
(5) 往復遅延時間グラフ
基本的に100msで推移していますが、パケットロスしている時間帯で、おそらく再送によりRTTが大きくなっています。
3. Cisco IOS-XEがFTPクライアントの場合
3-1. TCP設定確認
(1) TCP輻輳制御アルゴリズム
IOS-XE(16.11.1b)の場合、Loss-based輻輳制御アルゴリズムの一つである「New Reno」を採用しているようです。インターネット普及前の、回線速度や信頼性が今より低い時代に適したアルゴリズムです。
Router# debug ip tcp congestion
Router# show log
(省略)
*Mar 20 04:28:18.769: Setting New Reno as congestion control algorithm
デフォルトは「New Reno」ですが、アプリケーションで「 Binary Increase Congestion Control(BIC)」も使用できるようです。
(2) TCPオプション
下記FTPデータ通信の3way handshake時にやり取りされるオプション設定を確認しました。UbuntuがFTPクライアントの場合と異なり、Window scaleやSACKのやり取りはされていませんでした。
3-2. 転送結果
(1) 転送時間計測
以下コマンドでIOSからFTPサーバ上のファイルをGETしました。モードはデフォルトはPassiveです。
Router#$ubuntu:xxx@192.168.100.196/test_50mb.txt bootflash:/test_50mb.txt
Destination filename [test_50mb.txt]?
Accessing ftp://*:*@192.168.100.196/test_50mb.txt...!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
[OK - 52428800/4096 bytes]
52428800 bytes copied in 345.601 secs (151703 bytes/sec)
3回実施したところ、所要時間はUbuntuの約18倍でした!やっぱり遅い!
回数 | 転送時間(s) | 転送速度(B/s) |
---|---|---|
1 | 345.601 | 151703 |
2 | 345.567 | 151718 |
3 | 346.743 | 151204 |
平均 | 345.970 | 151542 |
(2) 入出力グラフ
Ubuntuの場合と同様、1回目のキャプチャデータをWiresharkで読み込み、FTPサーバからのデータ転送パケットを1s間隔で出力してみました。安定時は1.25Mbps前後でした。
(3) 時間/シーケンスグラフ(tcptrace)
グラフを拡大すると、約100ms毎に、Windowサイズ分のパケットを送信し切って、次のパケットを送信するまで待っている箇所があります(緑線が横這いになっている箇所)。安定時のWindowサイズは14924B前後でした。
(4) スループットグラフ
(5) 往復遅延時間グラフ
ここまでで、IOS-XEのFTP転送速度が遅い理由の一つとして、Windowサイズが小さい事が分かったので、IOS-XE側のTCP設定を変更し、どの程度変化するか確認してみました。
4. Cisco IOS-XEのTCP設定を変更した場合
4-1. TCP設定確認
(1) IOS-XE TCP設定
以下サイトを参考に、ip tcp window-sizeコマンドでWindowサイズをデフォルトの4128Bから2500000Bに変更しました。値は適当ですが、64KB以上を指定するとWindow scaleが適用されるようです。ついでにip tcp selective-ackコマンドでSACKも有効化しました。
Router(config)#ip tcp window-size 2500000
Router(config)#ip tcp selective-ack
(2) TCPオプション
TCP設定変更前と比較すると、SACKとWindow scaleオプションが追加されています。Windowサイズは、65535×64(Window scale分)=4194240Bになっていました。
4-2. 転送結果
(1) 転送時間計測
3回実施したところ、TCP設定変更前の約1/10になりました!
回数 | 転送時間(s) | 転送速度(B/s) |
---|---|---|
1 | 31.914 | 1642815 |
2 | 35.501 | 1476826 |
3 | 30.600 | 1713359 |
平均 | 32.67 | 1611000 |
(2) 入出力グラフ
安定時は15Mbps前後でした。
(3) 時間/シーケンスグラフ(tcptrace)
見づらいですが6秒、13.5秒、31秒付近の赤い箇所でパケットロスが見られました。
(4) スループットグラフ
Ubuntuの時と同様、パケットロス発生時にスループット低下がみられますが、TCP設定変更前と比べると高い値で推移しています。
(5) 往復遅延時間グラフ
IOS-XEの場合は、TCP設定変更による転送速度の高速化が見られました。次はIOSで同様の設定を行ってみます。
5. Cisco IOSがFTPクライアントの場合
5-1. TCP設定確認
(1) TCP輻輳制御アルゴリズム
IOS(15.8(3)M2)でも「New Reno」を採用しているようです。
Router# debug ip tcp congestion
他の機器からTelnetログイン ↓
Router# show log
(省略)
*Mar 14 15:14:10.798: Setting New Reno as congestion control algorithm
(2) TCPオプション
こちらもIOS-XEと同様、Window scaleやSACKのやり取りはされていませんでした。
5-2. 転送結果
(1) 転送時間計測
Router#copy ftp://ubuntu:xxx@192.168.100.196/test_50mb.txt flash0:/test_50mb.txt
Destination filename [test_50mb.txt]?
Accessing ftp://*:*@192.168.100.196/test_50mb.txt...
Loading test_50mb.txt !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
[OK - 52428800/4096 bytes]
52428800 bytes copied in 628.761 secs (83384 bytes/sec)
3回実施したところ、所要時間はIOS-XEよりさらに遅く、Ubuntuの約30倍でした。
回数 | 転送時間(s) | 転送速度(B/s) |
---|---|---|
1 | 628.761 | 83384 |
2 | 646.168 | 81138 |
3 | 643.862 | 81429 |
平均 | 639.597 | 81984 |
(2) 入出力グラフ
安定時は600Kbps前後でした。
(3) 時間/シーケンスグラフ(tcptrace)
グラフを拡大すると、約800ms毎に、Windowサイズ分のパケットを送信し切って、次のパケットを送信するまで100ms程度待っている箇所があります(緑線が横這いになっている箇所)。安定時のWindowサイズは10544B、12004B程度でした。
(4) スループットグラフ
(5) 往復遅延時間グラフ
6. Cisco IOSのTCP設定を変更した場合
6-1. TCP設定確認
(1) IOS-XE TCP設定
IOS-XEと同じ設定を追加しました。
(2) TCPオプション
IOS-XEと同様、SACKとWindow scaleオプションが追加されていました。Windowサイズも65535×64(Window scale分)=4194240Bになっていました。
6-2. 転送結果
(1) 転送時間計測
IOSの場合、設定変更前後で大きな違いはなく、6%程度早くなりました。
回数 | 転送時間(s) | 転送速度(B/s) |
---|---|---|
1 | 604.506 | 86730 |
2 | 602.020 | 87088 |
3 | 602.453 | 87026 |
平均 | 602.993 | 86948 |
(2) 入出力グラフ
開始直後は4Mbps程度まで出ていますが、その後は設定変更前と同様でした。
(3) 時間/シーケンスグラフ(tcptrace)
緑と茶色の線の差分を見ると、開始当初のWindowサイズは2500000Bですが、徐々に減少していき、5秒後くらいに設定変更前と同様の値になりました。
(4) スループットグラフ
(5) 往復遅延時間グラフ
最後に
今回の実験条件では、IOS-XE、IOSともにTCP輻輳制御アルゴリズムは古い「New Reno」を使用しているものの、IOS-XEはTCPのWindowサイズ変更で高速化が可能な事が分かりました。一方でIOSは、原因は良く分かりませんが、変更してもほぼ効果はありませんでした。
今後ラボ環境でIOS-XEにファイル転送する時は、TCP設定追加を検討したいと思います。
おしまい。
Discussion