mahimahi というネットワークをエミュレーションするツールには、LinkShellという帯域のエミュレーションをするツールが含まれています。
LinkShellを使うとトレースファイルをもとにネットワークの上りと下りの帯域のエミュレーションができます。LinkShellでは動的に変動する帯域や固定された帯域のエミュレーションを行えます。
簡単な使い方
早速試してみます。以下のようにファイルを用意すると12Mbpsの帯域をエミュレーションできます。
1
帯域の測定には、iperf3を使います。
$ mm-link 12Mbps.trace 12Mbps.trace -- iperf3 -c 192.168.11.13
Connecting to host 192.168.11.13, port 5201
[ 4] local 100.64.0.2 port 40690 connected to 192.168.11.13 port 5201
[ ID] Interval Transfer Bandwidth Retr Cwnd
[ 4] 0.00-1.00 sec 2.00 MBytes 16.7 Mbits/sec 0 115 KBytes
[ 4] 1.00-2.00 sec 1.80 MBytes 15.1 Mbits/sec 0 185 KBytes
[ 4] 2.00-3.00 sec 1.74 MBytes 14.6 Mbits/sec 0 256 KBytes
[ 4] 3.00-4.00 sec 1.74 MBytes 14.6 Mbits/sec 0 327 KBytes
[ 4] 4.00-5.00 sec 1.80 MBytes 15.1 Mbits/sec 0 397 KBytes
[ 4] 5.00-6.05 sec 1.49 MBytes 12.0 Mbits/sec 0 458 KBytes
[ 4] 6.05-7.00 sec 1.80 MBytes 15.8 Mbits/sec 0 532 KBytes
[ 4] 7.00-8.00 sec 1.74 MBytes 14.6 Mbits/sec 0 601 KBytes
[ 4] 8.00-9.01 sec 1.74 MBytes 14.5 Mbits/sec 0 672 KBytes
[ 4] 9.01-10.00 sec 1.43 MBytes 12.1 Mbits/sec 0 742 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bandwidth Retr
[ 4] 0.00-10.00 sec 17.3 MBytes 14.5 Mbits/sec 0 sender
[ 4] 0.00-10.00 sec 14.4 MBytes 12.1 Mbits/sec receiver
iperf Done.
結果は [ 4] 0.00-10.00 sec 14.4 MBytes 12.1 Mbits/sec receiver
となっており、おおむね12Mbpsとなっていることが確認できました。
原理
LinkShellでは、トレースファイルに基づいてエミュレーションを行います。トレースファイルのそれぞれの行は合計1500バイトのパケットを送信するタイミングを表しています。単位はmsecです。
例えば先ほどの例のように1行に1
が書かれたトレースファイルがあるとします。
1
トレースファイルは最後まで読み込まれたら先頭に戻って繰り返し使用されます。なので、上記のトレースファイルを使用すると、1000msec * 1500byte * 8bit = 12,000,000 = 12Mbps のエミュレーションができます。
また、同じタイムスタンプを複数書くことも可能です。
例えば、以下のように2行に1
を書くと、24Mbpsのエミュレーションが可能になります。
1
1
$ mm-link 24Mbps.trace 24Mbps.trace -- iperf3 -c 192.168.11.13
Connecting to host 192.168.11.13, port 5201
[ 4] local 100.64.0.2 port 32994 connected to 192.168.11.13 port 5201
[ ID] Interval Transfer Bandwidth Retr Cwnd
[ 4] 0.00-1.00 sec 3.68 MBytes 30.8 Mbits/sec 0 164 KBytes
[ 4] 1.00-2.00 sec 3.48 MBytes 29.2 Mbits/sec 0 305 KBytes
[ 4] 2.00-3.00 sec 3.54 MBytes 29.7 Mbits/sec 0 447 KBytes
[ 4] 3.00-4.00 sec 3.48 MBytes 29.2 Mbits/sec 0 588 KBytes
[ 4] 4.00-5.00 sec 3.29 MBytes 27.6 Mbits/sec 0 730 KBytes
[ 4] 5.00-6.00 sec 2.67 MBytes 22.4 Mbits/sec 0 871 KBytes
[ 4] 6.00-7.00 sec 2.73 MBytes 22.9 Mbits/sec 0 1012 KBytes
[ 4] 7.00-8.00 sec 2.67 MBytes 22.4 Mbits/sec 0 1.13 MBytes
[ 4] 8.00-9.00 sec 2.73 MBytes 22.9 Mbits/sec 0 1.26 MBytes
[ 4] 9.00-10.00 sec 2.67 MBytes 22.4 Mbits/sec 0 1.40 MBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bandwidth Retr
[ 4] 0.00-10.00 sec 31.0 MBytes 26.0 Mbits/sec 0 sender
[ 4] 0.00-10.00 sec 29.0 MBytes 24.3 Mbits/sec receiver
iperf Done.
オプション
引数無しで mm-link
を実行するとオプションが確認できます。
$ mm-link
Usage: mm-link UPLINK-TRACE DOWNLINK-TRACE [OPTION]... [COMMAND]
Options = --once
--uplink-log=FILENAME --downlink-log=FILENAME
--meter-uplink --meter-uplink-delay
--meter-downlink --meter-downlink-delay
--meter-all
--uplink-queue=QUEUE_TYPE --downlink-queue=QUEUE_TYPE
--uplink-queue-args=QUEUE_ARGS --downlink-queue-args=QUEUE_ARGS
QUEUE_TYPE = infinite | droptail | drophead | codel | pie
QUEUE_ARGS = "NAME=NUMBER[, NAME2=NUMBER2, ...]"
(with NAME = bytes | packets | target | interval | qdelay_ref | max_burst)
target, interval, qdelay_ref, max_burst are in milli-second
Died on std::runtime_error: invalid arguments
--once
トレースファイルを1度だけ実行します
--uplink-log=FILENAME
uplinkのログファイルを生成します。
downlink-log=FILENAME
downlinkのログファイルを生成します。
--meter-uplink
このオプションを付けると、uplinkのエミュレーションされた帯域、uplinkで送信しようとしているデータ量、実際に送信しているデータ量をリアルタイムでモニタリングできます。
赤で囲まれた場所がトレースファイルの帯域で、青い線が送信しようとしているデータ量になります。赤い線が実際に送信できているデータ量です
--meter-uplink-delay
uplinkのqueueing delayをリアルタイムでモニタリングできます。
--meter-downlink
このオプションを付けると、downlinkのエミュレーションされた帯域、downlinkで送信しようとしているデータ量、実際に送信しているデータ量をリアルタイムでモニタリングできます。
--meter-downlink-delay
downlinkのqueueing delayをリアルタイムでモニタリングできます。
--meter-all
--meter-uplink
--meter-uplink-delay
--meter-downlink --meter-downlink-delay
の4つを同時に表示します。
--uplink-queue=QUEUE_TYPE
uplinkのキューの種類を定義します。キューの種類は以下の5種類があります。
QUEUE_TYPE = infinite | droptail | drophead | codel | pie
droptail
はキューのサイズを超えるパケットはキューに入れずに捨てます。逆に、drophead
の場合は、キューの先頭から要素を捨てます。
codel
やpie
は Active Queue Managementの手法のCoDel、PIEをそれぞれ表しています。
--uplink-queue-args=QUEUE_ARGS
--uplink-queue-args
ではキューの振る舞いを定義します。以下のようなオプションが存在しています。
QUEUE_ARGS = "NAME=NUMBER[, NAME2=NUMBER2, ...]"
(with NAME = bytes | packets | target | interval | qdelay_ref | max_burst)
target, interval, qdelay_ref, max_burst are in milli-second
bytes
、packets
は、キューの種類をdroptail
、drophead
としているときに使えます。それぞれバイト長、パケット数でキューの上限を設定します。
target
、interval
はCoDel用のオプションのようです。
qdelay_ref
、max_burst
はPIE用のオプションのようです。
動的な帯域制御の例
LinkShellの特徴の一つに、動的な帯域変更のエミュレーションがあります。
実際に用意されているトレースファイルを https://github.com/ravinet/mahimahi/tree/master/traces から選んでiperf3を実行してみます。aptでインストールした場合は、/usr/share/mahimahi/traces/
にあります
今回は、ATT-LTE-driving-2016.up
と ATT-LTE-driving-2016.down
を使ってみました。
iperf3の結果は以下のようになります
$ mm-link /usr/share/mahimahi/traces/ATT-LTE-driving-2016.up /usr/share/mahimahi/traces/ATT-LTE-driving-2016.down --meter-uplink -- iperf3 -c 192.168.11.13 -b 6M
Connecting to host 192.168.11.13, port 5201
[ 4] local 100.64.0.2 port 40788 connected to 192.168.11.13 port 5201
[ ID] Interval Transfer Bandwidth Retr Cwnd
[ 4] 0.00-1.00 sec 594 KBytes 4.86 Mbits/sec 1 1.41 KBytes
[ 4] 1.00-2.00 sec 445 KBytes 3.65 Mbits/sec 1 59.4 KBytes
[ 4] 2.00-3.01 sec 573 KBytes 4.67 Mbits/sec 0 62.2 KBytes
[ 4] 3.01-4.00 sec 0.00 Bytes 0.00 bits/sec 2 1.41 KBytes
[ 4] 4.00-5.00 sec 0.00 Bytes 0.00 bits/sec 1 1.41 KBytes
[ 4] 5.00-6.00 sec 382 KBytes 3.13 Mbits/sec 0 70.7 KBytes
[ 4] 6.00-7.00 sec 573 KBytes 4.69 Mbits/sec 0 82.0 KBytes
[ 4] 7.00-8.00 sec 445 KBytes 3.65 Mbits/sec 0 87.7 KBytes
[ 4] 8.00-9.00 sec 63.6 KBytes 521 Kbits/sec 1 87.7 KBytes
[ 4] 9.00-10.00 sec 445 KBytes 3.64 Mbits/sec 0 97.6 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bandwidth Retr
[ 4] 0.00-10.00 sec 3.44 MBytes 2.88 Mbits/sec 6 sender
[ 4] 0.00-10.00 sec 2.94 MBytes 2.46 Mbits/sec receiver
iperf Done.
モニタリングの結果は以下のようになりました。実際に動的な帯域のシミュレーションができていることが分かります。
参考