(大事なことを書くことを忘れていた。回線遅延シミュレーションを安価に行うには、古来、FreeBSD上で動作するDummyNetを使うとか、Linux用だとNISTNetを使うなどがいわれている。いずれも古い話で、NISTNetはカーネル2.6xの上ではコンパイルすらとおらない。そこで)
Linuxにnetemというパッケージが導入されている。その解説訳を書いておく。なお、F君から「リアルのデバイスじゃないと動かないっす」という情報が入っている。
netemはネットワークエミュレーションの機能をネットワーク上のプロトコルテストなどのために提供される。今のバージョンは遅延とパケットロスと順序変更(パケット再送)が可能である。
もし、2.6以上のディストレイビューション(Fedora, OpenSuse, Gentoo, Debian, Mandriva, Ubuntu)であるならば、netemはすでにiproute2の一部としてカーネルに導入されている。。netemカーネルコンポーネントは
Networking –>
Networking Options –>
Qos and/or fair queuing –>
Network emulator
にある。
Netemはtcコマンドでコントロール可能でありiproute2パッケージ内にある。tcコマンドは/usr/lib/tcディレクトリーにライブラリやデータファイルがある。
例:
WANの遅延のエミュレーション
これはもっとも簡単な例で、タンに遅延時間を入れるだけですべてのパケットは遅延する。
# tc qdisc add dev eth0 root netem delay 100ms
ここでpingを打つと100m秒以上に増加しているはずだ。遅延はカーネルのクロック解像度により制限される(HZ).ほとんどの2.4システムでシステムクロックは10m秒きざみの100HZまでの遅延を許している。2.6システムではこの値は構成パラメータにより、100から100hzの範囲で変更できる。
次の例はqdiscを再ロードしないで変更する。
実際のWANのようにばらけた遅延値を示す。
# tc qdisc change dev eth0 root netem delay 100ms 10ms
この設定で、100m秒プラスマイナス10m秒のランダムな遅延を「だいたい」作り出す。
遅延の範囲
一般的に遅延は単一なものではない。散らばり具合は正規分布だったり違ったものだったりするものだろう。netemは単一でない分散をテーブルによって可能である。
# tc qdisc chnage dev eth0 root netem delay 100ms 20ms distribution normal
分布を定義するテーブル(normal, pareto,paretonormal)はiproute2のコンパイルの一部として生成されており、/usr/lib/tc内にある。ユーザーが変更することは可能である。
パケットロス
ランダムにパケットをロスさっせることがtcコマンドでできる。ゼロでない非常に小さい値を設定するとする
2^32 = 0.0000000232%
# tc qdisc change dev eth0 root netem loss 0.1%
これは1%の1/10の確率でパケットをおとす。
同時に別のオプションも設定できる。これは、パケットバーストロスをランダムにシミュレートする。
# tc qdisc change dev eth0 root netem loss 0.3% 25%
これは0.3%のパケットロスと、最後のパケットの確率を25%の確率で加味することで、今の確率を決める。
Probn = 0.25 * Probn-1 + 0.75 * Random
注意:ロスはローカルでおきる(ブリッジやルータ上ではない)つまりロスの検知はより上位のアプリケーションでないと検知できない。これは本来、TCPがデータ再送の原因となるが、あたかもロスしていないかのように働く。もし、プロトコルテストをしたいならば、netemをブリッジやルータ上で動かすべきである。
パケット重複
パケット重複はパケットロスと同じように設定できる。
# tc qdisc change dev eth0 root netem duplicate 1%
パケット破壊
ランダムなノイズをシミュレーションできる(2.6.16以上)。これはパケット内のランダムなオフセットの1ビットを破壊する。
# tc qdisc change dev eth0 root netem corrupt 0.1%
パケット再送要求
再送要求をする方法はふたつある。ひとつ目は、gapを使ってn番目のパケットごとに再送要求する方法である。
# tc qdisc change dev eth0 root netem gap5 delay 10ms
これは5回目(10回目、15回目,,,)パケットはすぐに送られ、他のパケットは10m秒待たされる。結果的に再送要求が起きる。これはベースプロトコルテストには便利である。
二つ目の方法は、より現実に近いreorderパラメータを使う方法である。これは一定のパーセント、パケットの順序エラーが起きる。
# tc qdisc change dev eth0 root netem delay 10ms reorder 25% 50%
この例は、(50%に関連付けられた)25%のパケットがすぐに送られる、他は10m秒待たされる。netemの当たらしいバージョンではランダムな遅延時間を設けるとパケットの順序がかわり再送要求がおきる。以下は再送要求が起きる例
# tc qdisc change dev eth0 root netem delay 100ms 75ms
もし最初のパケットがランダムな遅延で100m秒(100m秒ベース-0m秒差)となったとする、二番目のパケットが1m秒後に送り出され50m秒(100m秒ベース-50m秒差)、待ったら2番目が先に送りだされる。netemの中にキューされており、スケジュールどおりに送りだされる。
注意:
・ランダムな再送要求は思わぬ結果をもたらすことがある
・再送要求の方法がどれでも、いくらかの遅延は必要である
・遅延時間がパケットが送られる時間より短い場合は再送要求はおきない
レートのコントロール
レートのコントロールはnetemにはそなわっていないが、かわりの方法がある。ここではToken Bucketフィルター(TBF)を使って出力を制限する方法を述べる。
# tc qdisc add dev eth0 root handle 1:0 netem delay 100ms
# tc qdisc add dev eth0 parent 1:1 handle 10: tbr rate 256kbit buffer 1600 limit 3000
# tc -s qdisc L sev eth0
qdisc netem 1: limit 1000 delay 100.0ms
Sent 0 bytes 0 pkts (dropped 0, overlimites 0 )
qdisc tbf 10: rate 256kbit burst 1599b lat 26.6ms
Sent 0 bytes 0 pakts (dropped 0, overlimites 0 )
オプションのバッファと制限がデフォルトより大きいことに注意。
さらなる詳細は別で、
FAQ(めんどくさいので抄訳)
入ってくるトラフィックにはどう使えばいいのでしょうか?
Intermediate Functional Block psedo-deveic(IFG)を使う。このネットワークデバイスは入ってくるパケットをキューするためにある。
# modprobe ifb
# ip link set dev ifb0 up
# tc qdisc add dev eth0 ingress
# tc filter ad dev eth0 parent ffff; protocol ip u32 match u32 0 0 flowid 1:1 action mirred egress redirect dev ifb0
# tc qdisc add dev ib0 root netem delay 750ms
他の方法としては、イーサのブリッジとして他のマシンをnetemをいれて使うことです。
http://www.linux-foundation.org/en/Net:Netem