CUBE SUGAR CONTAINER

技術系のこと書きます。

Linux TC (Traffic Control) の netem (Network Emulator) で劣悪なネットワーク環境を再現する

今回は Linux TC (Traffic Control) に実装されている netem (Network Emulator) という qdisc (Queueing Discipline) を使って、劣悪なネットワーク環境を再現する方法について書いてみる。 Linux TC は、文字通り Linux のトラフィックを制御するための機能で、qdisc という形で様々な制御のやり方が実装されている。 その中でも netem という qdisc には、意図的にフレームの送出にディレイを入れたりドロップするといった機能が備わっている。 これを使うと、実際に環境を用意してテストするのがなかなか難しいようなネットワークの状況を再現できる。

使った環境は次のとおり。

$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=22.04
DISTRIB_CODENAME=jammy
DISTRIB_DESCRIPTION="Ubuntu 22.04.1 LTS"
$ uname -srm
Linux 5.15.0-53-generic aarch64
$ tc -V
tc utility, iproute2-5.15.0, libbpf 0.5.0
$ iperf3 -v
iperf 3.9 (cJSON 1.7.13)
Linux jammy 5.15.0-53-generic #59-Ubuntu SMP Mon Oct 17 18:55:29 UTC 2022 aarch64
Optional features available: CPU affinity setting, IPv6 flow label, SCTP, TCP congestion algorithm setting, sendfile / zerocopy, socket pacing, authentication

もくじ

下準備

まずは、使用するパッケージをインストールする。

$ sudo apt-get -y install iproute2 iputils-ping iperf3

今回は Network Namespace で作った仮想的なネットワーク環境で netem の機能を試す。 あらかじめ、ns1ns2 という Network Namespace を作っておく。

$ sudo ip netns add ns1
$ sudo ip netns add ns2

次に Virtual Ethernet インターフェイスで veth0veth1 を作って Network Namespace 同士をつなぐ。

$ sudo ip link add veth0 type veth peer name veth1
$ sudo ip link set veth0 netns ns1
$ sudo ip link set veth1 netns ns2
$ sudo ip netns exec ns1 ip link set veth0 up
$ sudo ip netns exec ns2 ip link set veth1 up

それぞれのインターフェイスに IP アドレスとして 192.0.2.1/24192.0.2.2/24 を付与する。

$ sudo ip netns exec ns1 ip address add 192.0.2.1/24 dev veth0
$ sudo ip netns exec ns2 ip address add 192.0.2.2/24 dev veth1

これで、ひとまず IP で疎通がある状態になった。 RTT に遅延はほとんどなく 100us を下回っている。

$ sudo ip netns exec ns1 ping -c 3 192.0.2.2 -I 192.0.2.1
PING 192.0.2.2 (192.0.2.2) from 192.0.2.1 : 56(84) bytes of data.
64 bytes from 192.0.2.2: icmp_seq=1 ttl=64 time=0.097 ms
64 bytes from 192.0.2.2: icmp_seq=2 ttl=64 time=0.085 ms
64 bytes from 192.0.2.2: icmp_seq=3 ttl=64 time=0.081 ms

--- 192.0.2.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2137ms
rtt min/avg/max/mdev = 0.081/0.087/0.097/0.006 ms

何もしない状態で iperf3 を使って帯域幅を確認しておく。 まずは、新しくターミナルを開いて ns2 の方でサーバを立ち上げる。

$ sudo ip netns exec ns2 iperf3 -s
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------

そして ns1 の方でクライアントを立ち上げる。 次のとおり、70Gbps ほど出ている。

$ sudo ip netns exec ns1 iperf3 -c 192.0.2.2
Connecting to host 192.0.2.2, port 5201
[  5] local 192.0.2.1 port 60428 connected to 192.0.2.2 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec  8.26 GBytes  70.9 Gbits/sec    0   3.07 MBytes       
[  5]   1.00-2.00   sec  8.68 GBytes  74.6 Gbits/sec    0   3.07 MBytes       
[  5]   2.00-3.00   sec  8.63 GBytes  74.1 Gbits/sec    0   3.07 MBytes       
[  5]   3.00-4.00   sec  8.72 GBytes  74.9 Gbits/sec    0   3.07 MBytes       
[  5]   4.00-5.00   sec  8.71 GBytes  74.8 Gbits/sec    0   3.07 MBytes       
[  5]   5.00-6.00   sec  8.60 GBytes  73.9 Gbits/sec    0   3.07 MBytes       
[  5]   6.00-7.00   sec  8.70 GBytes  74.8 Gbits/sec    0   3.07 MBytes       
[  5]   7.00-8.00   sec  8.62 GBytes  74.1 Gbits/sec    0   3.07 MBytes       
[  5]   8.00-9.00   sec  8.72 GBytes  74.9 Gbits/sec    0   3.07 MBytes       
[  5]   9.00-10.00  sec  8.73 GBytes  75.0 Gbits/sec    0   3.07 MBytes       
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  86.4 GBytes  74.2 Gbits/sec    0             sender
[  5]   0.00-10.04  sec  86.4 GBytes  73.9 Gbits/sec                  receiver

iperf Done.

サーバは、ひとまず立ち上げたままにしておこう。

レイテンシを大きくする

まずは、モバイルネットワークだったり通信先が地球の反対側にあるような、レイテンシの大きな状況を再現してみる。

Linux TC は tc(8) というコマンドを使って操作する。 そして、Linux TC の qdisc はネットワークインターフェイスに設定される。 試しに tc qdisc show サブコマンドを使って ns2veth1 インターフェイスに設定されている qdisc を確認してみよう。

$ sudo ip netns exec ns2 \
    tc qdisc show dev veth1
qdisc noqueue 0: root refcnt 2

当然だけど、初期状態ではインターフェイスに何も qdisc が設定されていない。

ここで、tc qdisc add サブコマンドを使って ns2veth1 に netem qdisc を設定してみよう。 qdisc の名前である netem の後ろには、その qdisc 固有のパラメータを指定する。 delay 200ms 100ms というのは、100ms のジッターのある 200ms のディレイを挿入する、という意味になる。

$ sudo ip netns exec ns2 \
    tc qdisc add dev veth1 root \
    netem delay 200ms 100ms

なお、netem の前に入っている root は「そのインターフェイスのルートの qdisc を設定する」という意味になる。 というのも、1 つのインターフェイスには複数の qdisc を親子関係のあるツリー構造で設定できるため。 そのため、操作する位置を指定する必要がある。 ただし、今回は簡単のために qdisc の位置は root しか扱わない。

さて、再度 tc qdisc show サブコマンドで確認すると、今度は qdisc として netem が設定されていることがわかる。

$ sudo ip netns exec ns2 \
    tc qdisc show dev veth1
qdisc netem 8002: root refcnt 2 limit 1000 delay 200ms  100ms

この状態で、最初に確認したのと同じように ping(8) を使ってみよう。 すると、今度は RTT が 200 ~ 300ms 前後にまで増加している。

$ sudo ip netns exec ns1 ping -c 10 192.0.2.2 -I 192.0.2.1
PING 192.0.2.2 (192.0.2.2) from 192.0.2.1 : 56(84) bytes of data.
64 bytes from 192.0.2.2: icmp_seq=1 ttl=64 time=300 ms
64 bytes from 192.0.2.2: icmp_seq=2 ttl=64 time=326 ms
64 bytes from 192.0.2.2: icmp_seq=3 ttl=64 time=287 ms
64 bytes from 192.0.2.2: icmp_seq=4 ttl=64 time=292 ms
64 bytes from 192.0.2.2: icmp_seq=5 ttl=64 time=202 ms
64 bytes from 192.0.2.2: icmp_seq=6 ttl=64 time=303 ms
64 bytes from 192.0.2.2: icmp_seq=7 ttl=64 time=262 ms
64 bytes from 192.0.2.2: icmp_seq=8 ttl=64 time=292 ms
64 bytes from 192.0.2.2: icmp_seq=9 ttl=64 time=216 ms
64 bytes from 192.0.2.2: icmp_seq=10 ttl=64 time=298 ms

--- 192.0.2.2 ping statistics ---
10 packets transmitted, 10 received, 0% packet loss, time 9389ms
rtt min/avg/max/mdev = 202.402/277.962/326.268/37.638 ms

どうやら、ちゃんとディレイが入ったようだ。 これこそが netem の効果というわけ。

実験し終わったら、設定していた qdisc をインターフェイスから削除しよう。

$ sudo ip netns exec ns2 \
    tc qdisc delete dev veth1 root

ここからは、同じように次の流れで各機能を説明していく。

  1. qdisc を設定する
  2. 動作を確認する
  3. qdisc を削除する

また、それぞれの設定を基本的には単独で試していくけど、実際には複数を組み合わせることもできる。

パケットロスを生じさせる

続いてはいわゆるパケロス 1 を起こしてみよう。 先ほどと同じように ns2veth1 に qdisc を設定する。 この点は、後述するすべての実験において変わらない。 変わるのは netem の設定が loss random 30% となっている点だ。

$ sudo ip netns exec ns2 \
    tc qdisc add dev veth1 root \
    netem loss random 30%

確認すると、ちゃんと qdisc が設定されている。 これで 30% の確率でパケットロスが生じるはず。

$ sudo ip netns exec ns2 \
    tc qdisc show dev veth1
qdisc netem 8002: root refcnt 5 limit 1000 loss 30%

実際に ping を打って試してみよう。

$ sudo ip netns exec ns1 \
    ping -c 10 192.0.2.2 -I 192.0.2.1
PING 192.0.2.2 (192.0.2.2) from 192.0.2.1 : 56(84) bytes of data.
64 bytes from 192.0.2.2: icmp_seq=2 ttl=64 time=0.138 ms
64 bytes from 192.0.2.2: icmp_seq=3 ttl=64 time=0.101 ms
64 bytes from 192.0.2.2: icmp_seq=4 ttl=64 time=0.162 ms
64 bytes from 192.0.2.2: icmp_seq=5 ttl=64 time=0.150 ms
64 bytes from 192.0.2.2: icmp_seq=6 ttl=64 time=0.114 ms
64 bytes from 192.0.2.2: icmp_seq=7 ttl=64 time=0.093 ms
64 bytes from 192.0.2.2: icmp_seq=8 ttl=64 time=0.110 ms

--- 192.0.2.2 ping statistics ---
10 packets transmitted, 7 received, 30% packet loss, time 9255ms
rtt min/avg/max/mdev = 0.093/0.124/0.162/0.024 ms

実行する毎に結果は変わるものの、上記ではちゃんと 30% のパケットが失われた。 なお、設定しているのが ns2 のインターフェイスなので、失われているのは戻りの ICMP Echo Reply になる。

実験し終わったら qdisc を削除する。

$ sudo ip netns exec ns2 \
    tc qdisc delete dev veth1 root

データを破損させる

続いてはフレームのデータを破損させる。 これはようするにビットを化けさせるということ。 引き起こされる事象は、破損が生じた箇所によって異なる。 以下では corrupt 50% と設定することで 50% の確率でフレームのいずれかのビットが化けることになる。

$ sudo ip netns exec ns2 \
    tc qdisc add dev veth1 root \
    netem corrupt 50%
$ sudo ip netns exec ns2 \
    tc qdisc show dev veth1
qdisc netem 8005: root refcnt 2 limit 1000 corrupt 50%

この状況で ping を打ってみよう。

$ sudo ip netns exec ns1     ping -c 10 192.0.2.2 -I 192.0.2.1
PING 192.0.2.2 (192.0.2.2) from 192.0.2.1 : 56(84) bytes of data.
ping: Warning: time of day goes back (-9007199254740929us), taking countermeasures
ping: Warning: time of day goes back (-9007199254740648us), taking countermeasures
64 bytes from 192.0.2.2: icmp_seq=1 ttl=64 time=0.000 ms
64 bytes from 192.0.2.2: icmp_seq=2 ttl=64 time=0.184 ms
64 bytes from 192.0.2.2: icmp_seq=3 ttl=64 time=0.178 ms
wrong data byte #29 should be 0x1d but was 0x19
#16    10 11 12 13 14 15 16 17 18 19 1a 1b 1c 19 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 
#48    30 31 32 33 34 35 36 37 
64 bytes from 192.0.2.2: icmp_seq=4 ttl=64 time=0.201 ms
64 bytes from 192.0.2.2: icmp_seq=5 ttl=64 time=0.190 ms
64 bytes from 192.0.2.2: icmp_seq=6 ttl=64 time=0.112 ms
wrong data byte #36 should be 0x24 but was 0x4
#16    10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 4 25 26 27 28 29 2a 2b 2c 2d 2e 2f 
#48    30 31 32 33 34 35 36 37 
64 bytes from 192.0.2.2: icmp_seq=7 ttl=64 time=0.209 ms
64 bytes from 192.0.2.2: icmp_seq=8 ttl=64 time=0.209 ms
wrong data byte #35 should be 0x23 but was 0x21
#16    10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 21 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 
#48    30 31 32 33 34 35 36 37 
64 bytes from 192.0.2.2: icmp_seq=9 ttl=64 time=0.214 ms
wrong data byte #53 should be 0x35 but was 0x75
#16    10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 
#48    30 31 32 33 34 75 36 37 
64 bytes from 192.0.2.2: icmp_seq=10 ttl=64 time=0.220 ms
wrong data byte #45 should be 0x2d but was 0x29
#16    10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 29 2e 2f 
#48    30 31 32 33 34 35 36 37 

--- 192.0.2.2 ping statistics ---
10 packets transmitted, 10 received, 0% packet loss, time 9401ms
rtt min/avg/max/mdev = 0.000/0.171/0.220/0.064 ms

上記では、どうやらフレームやパケットのヘッダ部分が破損することはなかったようだ。 というのも、ヘッダが破損すればチェックサムの不一致によって破棄されるはずなので。 その代わり、ICMP のペイロードが破損したことで wrong data というエラーが記録されている。 たとえば icmp_seq=3 においては、0x1d であるはずの箇所が 0x19 だったらしい。

実験が終わったら qdisc を削除する。

$ sudo ip netns exec ns2 \
    tc qdisc delete dev veth1 root

パケットを重複させる

続いてはパケットを重複させてみる。 これには duplicate という設定を使う。 以下では 50% の確率でパケット (フレーム) が重複するようになっている。

$ sudo ip netns exec ns2 \
    tc qdisc add dev veth1 root \
    netem duplicate 50%
$ sudo ip netns exec ns2 \
    tc qdisc show dev veth1
qdisc netem 800b: root refcnt 5 limit 1000 duplicate 50%

ping を打ってみよう。

$ sudo ip netns exec ns1     ping -c 10 192.0.2.2 -I 192.0.2.1
PING 192.0.2.2 (192.0.2.2) from 192.0.2.1 : 56(84) bytes of data.
64 bytes from 192.0.2.2: icmp_seq=1 ttl=64 time=0.163 ms
64 bytes from 192.0.2.2: icmp_seq=1 ttl=64 time=0.164 ms (DUP!)
64 bytes from 192.0.2.2: icmp_seq=2 ttl=64 time=0.150 ms
64 bytes from 192.0.2.2: icmp_seq=3 ttl=64 time=0.171 ms
64 bytes from 192.0.2.2: icmp_seq=3 ttl=64 time=0.172 ms (DUP!)
64 bytes from 192.0.2.2: icmp_seq=4 ttl=64 time=0.156 ms
64 bytes from 192.0.2.2: icmp_seq=4 ttl=64 time=0.158 ms (DUP!)
64 bytes from 192.0.2.2: icmp_seq=5 ttl=64 time=0.160 ms
64 bytes from 192.0.2.2: icmp_seq=5 ttl=64 time=0.161 ms (DUP!)
64 bytes from 192.0.2.2: icmp_seq=6 ttl=64 time=0.086 ms
64 bytes from 192.0.2.2: icmp_seq=7 ttl=64 time=0.159 ms
64 bytes from 192.0.2.2: icmp_seq=8 ttl=64 time=0.109 ms
64 bytes from 192.0.2.2: icmp_seq=9 ttl=64 time=0.141 ms
64 bytes from 192.0.2.2: icmp_seq=9 ttl=64 time=0.142 ms (DUP!)
64 bytes from 192.0.2.2: icmp_seq=10 ttl=64 time=0.091 ms

--- 192.0.2.2 ping statistics ---
10 packets transmitted, 10 received, +5 duplicates, 0% packet loss, time 9359ms
rtt min/avg/max/mdev = 0.086/0.145/0.172/0.026 ms

上記で (DUP!) という表示が、重複したパケットの到着を表している。

実験が終わったら qdisc を削除する。

$ sudo ip netns exec ns2 \
    tc qdisc delete dev veth1 root

パケットの順序を入れ替える

続いてはパケットの順序を入れ替えてみる。 いわゆるリオーダと呼ばれる事象だ。 以下では reorder 25% の設定で 25% の確率でパケットの順序を入れ替えている。 ただし、reorder を設定するときは delay の設定も必ず必要になるため 2s のディレイを入れている。

$ sudo ip netns exec ns2 \
    tc qdisc add dev veth1 root \
    netem delay 2s reorder 25%
$ sudo ip netns exec ns2 \
    tc qdisc show dev veth1
qdisc netem 8007: root refcnt 2 limit 1000 delay 2s reorder 25% gap 1

ディレイも組み合わせる必要があるのは、リオーダを実装しているメカニズムに起因している。 基本的な考え方は次のとおり。

  1. あるフレームが netem qdisc にキューイングされる
  2. ディレイによって (1) のフレームの送出 (デキュー) が遅延される
  3. 別のフレームが netem qdisc にキューイングされる
  4. 一定の確率で (3) のフレームが netem qdisc から即座に送出される
  5. ディレイが完了した上で (1) のフレームが送出される

実際に ping を使って試してみよう。

$ sudo ip netns exec ns1 \
    ping -c 10 192.0.2.2 -I 192.0.2.1
PING 192.0.2.2 (192.0.2.2) from 192.0.2.1 : 56(84) bytes of data.
64 bytes from 192.0.2.2: icmp_seq=2 ttl=64 time=0.128 ms
64 bytes from 192.0.2.2: icmp_seq=1 ttl=64 time=2041 ms
64 bytes from 192.0.2.2: icmp_seq=3 ttl=64 time=2024 ms
64 bytes from 192.0.2.2: icmp_seq=4 ttl=64 time=2002 ms
64 bytes from 192.0.2.2: icmp_seq=6 ttl=64 time=0.073 ms
64 bytes from 192.0.2.2: icmp_seq=5 ttl=64 time=2010 ms
64 bytes from 192.0.2.2: icmp_seq=7 ttl=64 time=2047 ms
64 bytes from 192.0.2.2: icmp_seq=8 ttl=64 time=2046 ms
64 bytes from 192.0.2.2: icmp_seq=9 ttl=64 time=2041 ms
64 bytes from 192.0.2.2: icmp_seq=10 ttl=64 time=2027 ms

--- 192.0.2.2 ping statistics ---
10 packets transmitted, 10 received, 0% packet loss, time 9344ms
rtt min/avg/max/mdev = 0.073/1623.841/2046.608/811.998 ms, pipe 2

上記において icmp_seq=2icmp_seq=6 は順序が入れ替わっている。 また、TTL が順序の入れ替わっていないものに比べると極端に短いことも確認できる。 これは、前述した動作原理によって引き起こされている。

実験が終わったら qdisc の設定を削除する。

$ sudo ip netns exec ns2 \
    tc qdisc delete dev veth1 root

帯域幅を狭くする

続いては帯域幅を狭くしてみる。 これには rate を設定すれば良い。 以下では帯域幅を 1Mbps に制限している。 limit はキューの大きさで、これが小さいと流量が大きいときに恐らくキュー溢れが生じて安定しないため念の為大きくしている。

$ sudo ip netns exec ns2 \
    tc qdisc add dev veth1 root \
    netem rate 1mbit limit 100k
$ sudo ip netns exec ns2 \
    tc qdisc show dev veth1
qdisc netem 8001: root refcnt 2 limit 102400 rate 1Mbit

iperf3 を使って帯域幅を確認しよう。 サーバをもし止めてしまっていたときはもう一度立ち上げ直す。 実行時のポイントとしては -R オプションを使って、サーバからクライアントへダウンロードする方向でトラフィックを流しているところ。 というのも netem はフレームの送出 (egress) に作用するため。 クライアントからサーバへのアップロードの方向にトラフィックを流すと、帯域幅が制限される ns2 の egress は TCP の ACK がチョロチョロと流れるだけなので意味がない。

$ sudo ip netns exec ns1 iperf3 -R -c 192.0.2.2
Connecting to host 192.0.2.2, port 5201
Reverse mode, remote host 192.0.2.2 is sending
[  5] local 192.0.2.1 port 33828 connected to 192.0.2.2 port 5201
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-1.00   sec   130 KBytes  1.06 Mbits/sec                  
[  5]   1.00-2.00   sec   119 KBytes   971 Kbits/sec                  
[  5]   2.00-3.00   sec   117 KBytes   961 Kbits/sec                  
[  5]   3.00-4.01   sec   116 KBytes   940 Kbits/sec                  
[  5]   4.01-5.02   sec   119 KBytes   967 Kbits/sec                  
[  5]   5.02-6.01   sec   116 KBytes   960 Kbits/sec                  
[  5]   6.01-7.00   sec   115 KBytes   945 Kbits/sec                  
[  5]   7.00-8.00   sec   116 KBytes   950 Kbits/sec                  
[  5]   8.00-9.02   sec   119 KBytes   962 Kbits/sec                  
[  5]   9.02-10.05  sec   122 KBytes   965 Kbits/sec                  
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.18  sec  2.50 MBytes  2.06 Mbits/sec    0             sender
[  5]   0.00-10.05  sec  1.16 MBytes   968 Kbits/sec                  receiver

iperf Done.

上記から、ちゃんと1Mbps に帯域幅が制限されていることが確認できる。

終わったら qdisc の設定を削除しよう。

$ sudo ip netns exec ns2 \
    tc qdisc delete dev veth1 root

幅のあるディレイを加える

続いては、最初に実験したレイテンシを大きくするのと似ている。 ただし、今度はある程度の幅を持たせたランダム性のあるディレイを加える。 これには slot という設定を使えば良い。 以下では最小 100 最大 1000ms という幅のあるディレイを設定している。

$ sudo ip netns exec ns2 \
    tc qdisc add dev veth1 root \
    netem slot 100ms 1000ms
$ sudo ip netns exec ns2 \
    tc qdisc show dev veth1
qdisc netem 8008: root refcnt 2 limit 1000 slot 100ms 1s

ping で動作を確認してみよう。

$ sudo ip netns exec ns1 \
    ping -c 10 192.0.2.2 -I 192.0.2.1
PING 192.0.2.2 (192.0.2.2) from 192.0.2.1 : 56(84) bytes of data.
64 bytes from 192.0.2.2: icmp_seq=1 ttl=64 time=1160 ms
64 bytes from 192.0.2.2: icmp_seq=2 ttl=64 time=123 ms
64 bytes from 192.0.2.2: icmp_seq=3 ttl=64 time=260 ms
64 bytes from 192.0.2.2: icmp_seq=4 ttl=64 time=614 ms
64 bytes from 192.0.2.2: icmp_seq=5 ttl=64 time=695 ms
64 bytes from 192.0.2.2: icmp_seq=6 ttl=64 time=173 ms
64 bytes from 192.0.2.2: icmp_seq=7 ttl=64 time=674 ms
64 bytes from 192.0.2.2: icmp_seq=8 ttl=64 time=791 ms
64 bytes from 192.0.2.2: icmp_seq=9 ttl=64 time=546 ms
64 bytes from 192.0.2.2: icmp_seq=10 ttl=64 time=971 ms

--- 192.0.2.2 ping statistics ---
10 packets transmitted, 10 received, 0% packet loss, time 9130ms
rtt min/avg/max/mdev = 123.187/600.742/1159.726/320.913 ms, pipe 2

上記から 100 ~ 1000ms 前後のバラついたディレイが入っていることが確認できる。

終わったら qdisc の設定を削除する。

$ sudo ip netns exec ns2 \
    tc qdisc delete dev veth1 root

まとめ

今回は Linux TC の netem qdisc に実装されている機能を一通り試した。 この機能を使えば、実際に用意するのが難しいような、ネットワークでごく稀に生じる事象も再現できる。


  1. 厳密にはフレームのレベルで起こっている事象ではあるものの面倒なので以降を含めあえて曖昧に書いている部分がある