Skip to content

Wlinee で擬似的にネットワークへ遅延やロスを発生させる

2004 年の書籍ですが、いまどきのソケットプログラミング―遊んで学ぶ、TCP/IPネットワークの奥義 をお書きになっている 波多さん 作の Wlinee を使うと、ネットワーク上で遅延やロスを発生させたり、帯域を一定の状態にポリシング出来ます。Wlinee を使うと、遅延やロスの多い、品質の悪い回線を Windows で手軽にエミュレート出来ますので、悪条件化でのネットワークテストを実施することが出来ます。Wlinee は下図のように、遅延やロスを挿入したい位置へ Wlinee PC を物理的に割り入れる(挟む)構成にして利用しますので、必然的にふたつの NIC がインストールされた Windows PC が必要となります。

file

今回は Windows XP SP3(32bit)環境に Wlinee をインストールしてみました。尚、波多さんは Wlinee 以前に Linux で動作する Linee もお書きになっています。

事前準備

Wlinee を動作させるには、以下のふたつが事前に必要となりますので、予めインストールしておきます。.NET Framework 3.5 であれば 2.0 を含んでいます(最新の 4.0 は下位バージョンを含んでいません)。

Wlinee のインストール

Wlinee は Sourceforge のプロジェクトページ からインストーラをダウンロード出来ます。インストーラがあるので、インストール自体は簡単です。.NET Framework 2.0 と WinPcap がインストールされていれば、起動するはずです。起動画面は以下の通りです。

file

使い方

利用方法は概ね、以下の通りです。

  1. 上部の Interface0 と Interface1 から、ブリッジを構成したいふたつのインターフェイスを選択する。ふたつのインターフェイスのうち、IP アドレスの設定は片側のみに行い、もう片側のインターフェイスは DHCP 設定にしておく
  2. インターフェイスの選択が完了したら右上の "Set Interface" をクリックする("Set Interface" をクリックするまで、次項の "Start" がグレーアウトしており、クリック出来ません)
  3. Policing, FrameLoss, Delay のうち、実施したい制御を選択する
  4. 下部の "Start" を選択する
  5. Policing, FrameLoss, Delay それぞれのパラメータを書き換えた場合は下部の "Param Set" をクリックするだけでリアルタイムに反映される(Wlinee を再起動する必要はない)
  6. トラフィック制御を停止するには下部の "Stop" をクリックする

攪乱パラメータについては Wlinee の使い方 に記載がありました。以下は抜粋です。

  • Policing
    • 最大スループット。FastEthernetでありながら、100Kbpsしか疎通できない細い回線をエミュレートします。
  • FrameLoss - Random
    • そのインタフェースでフレームを受信するたびに、その確率で2値乱数を発生し、あたり値が出たらフレームを疎通させません。結果的に、フレームが廃棄されたように見えます。
  • FrameLoss - Burst
    • 1秒間のうち指定された時間だけ、連続的にフレーム疎通を停止します。
  • Delay - Constant
    • そのインタフェースで受信されたすべてのフレームに一定時間の遅延を入れます
  • Delay - Uniformal
    • その値が平均となる一様乱数を発生させて、その値をフレーム遅延とします。
  • Dleay - Gaussian
    • 指定された平均と分散をもつ正規分布特性をもつ乱数を発生させて、その値をフレーム遅延とします。

また、「いずれの遅延特性にせよ、Wlinee内部ではフレームの順序入れ替えは発生しません。前のフレームを追い越す遅延乱数が発生することがありますが、その場合には前のフレームが送出されたあとに該当フレームが連続して送出されます。」だそうです。

遅延のテスト

実際に Ping でテストしてみます。PC から Server へ Ping を実行したままの状態で、リアルタイムに遅延を挿入してみました。テスト開始時点で予め Wlinee は起動してあります。

1
2
3
4
5
6
7
8
>  ping -t 192.168.1.100

192.168.1.100 に ping を送信しています 32 バイトのデータ:
192.168.1.100 からの応答: バイト数 =32 時間 <1ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 <1ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 <1ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 <1ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 <1ms TTL=64

同セグメントで直結された構成なので、RTT(Round Trip Time)も 1msec 以下で応答があります。ここで "Constant 100msec" の遅延を挿入してみます。

1
2
3
4
5
192.168.1.100 からの応答: バイト数 =32 時間 =84ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 =84ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 =93ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 =84ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 =84ms TTL=64

ほぼ一定の遅延が挿入されていることが分かります(厳密に 100msec ではありませんが、これは仕方無いかと...)。次は "Uniformal 1,000msec" の遅延を挿入してみます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
192.168.1.100 からの応答: バイト数 =32 時間 =773ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 =469ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 =343ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 =1557ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 =860ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 =227ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 =1224ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 =581ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 =1525ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 =711ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 =1434ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 =1574ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 =1520ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 =497ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 =986ms TTL=64

平均 1,000msec の遅延が挿入されていることが分かります。

ロスのテスト

ロスについてもテストしてみます。"Random 50%" でロスを発生させてみました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
> ping -w 100 -t 192.168.1.100

192.168.1.100 に ping を送信しています 32 バイトのデータ:
要求がタイムアウトしました。
192.168.1.100 からの応答: バイト数 =32 時間 <1ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 <1ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 <1ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 <1ms TTL=64
要求がタイムアウトしました。
要求がタイムアウトしました。
要求がタイムアウトしました。
192.168.1.100 からの応答: バイト数 =32 時間 =1ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 <1ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 <1ms TTL=64
要求がタイムアウトしました。
192.168.1.100 からの応答: バイト数 =32 時間 <1ms TTL=64
要求がタイムアウトしました。
192.168.1.100 からの応答: バイト数 =32 時間 <1ms TTL=64
要求がタイムアウトしました。
要求がタイムアウトしました。
要求がタイムアウトしました。
要求がタイムアウトしました。
192.168.1.100 からの応答: バイト数 =32 時間 <1ms TTL=64

概ね、成功と失敗が半々程度のようです。

「遅延」と「ロス」の同時設定テスト

最後に「遅延の挿入」と「ロスの発生」を同時に設定して、テストしてみます。ロスは "Random 50%"、遅延は "Constant 100msec" で設定しました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
> ping -w 100 -t 192.168.1.100

192.168.1.100 に ping を送信しています 32 バイトのデータ:
192.168.1.100 からの応答: バイト数 =32 時間 =84ms TTL=64
要求がタイムアウトしました。
要求がタイムアウトしました。
要求がタイムアウトしました。
192.168.1.100 からの応答: バイト数 =32 時間 =86ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 =84ms TTL=64
要求がタイムアウトしました。
192.168.1.100 からの応答: バイト数 =32 時間 =84ms TTL=64
192.168.1.100 からの応答: バイト数 =32 時間 =84ms TTL=64
要求がタイムアウトしました。
要求がタイムアウトしました。
192.168.1.100 からの応答: バイト数 =32 時間 =84ms TTL=64
要求がタイムアウトしました。
要求がタイムアウトしました。
要求がタイムアウトしました。
192.168.1.100 からの応答: バイト数 =32 時間 =84ms TTL=64
要求がタイムアウトしました。
192.168.1.100 からの応答: バイト数 =32 時間 =84ms TTL=64
要求がタイムアウトしました。

設定通り、50% 程度のロスと、応答があったものにも 100msec 弱の遅延が発生していることが分かります。