Unix command > tc (ネットワークエミュレータ)

更新日 2015-09-26
広告

tcコマンドは、Linuxの通信を制御するためのコマンドです(Traffic Controlの略称)。例えば、特定の通信に対して、通信量の上限を設定したりできます。

FedoraやDebian、UbuntuなどのLinuxディストリビューションで利用できます。カーネルのバージョンが2.6以上であればデフォルトで利用できます。

netemというネットワークエミュレータを組み合わせることで、パケットロスや通信遅延をエミュレーションできます。詳細はLinux Foundationのサイトを参照してください。

概要

tcコマンドの背景にあるLinuxカーネルの仕組みは複雑です。以下、簡単にまとめますが、内容が間違っている可能性もあります。詳しくは、公式サイトをご覧ください。

tcコマンドは、qdiscとclassという概念を扱います。qdiscは、パケット出力時のスケジューラのことです。queuing disciplineの略です。

classful qdiscとclassless qdiscがあります。classful qdiscは、子classを持つことができます。

典型的には、まず、ネットワークインターフェース(eth0など)に対して、root qdiscを作成します。 このroot qdiscに、netemを組み合わせることで、遅延のエミュレーションが可能です。 root qdiscに子classを追加することで、特定のトラヒック(例えば、特定のアドレスに対するパケット)に対して遅延をかけたりもできます。

設定例

以下、いくつか例を示します。まず、eth0に、「100ms の遅延」を設定する例です。root権限が必要です。

$ tc qdisc add dev eth0 root netem delay 100ms
上で設定した内容を、「90ms から 110ms の遅延」に変更する例。
$ tc qdisc change dev eth0 root netem delay 100ms 10ms
さらに、上で設定した内容を、「25% の確率で、90ms から 110ms の遅延」に変更する例。
$ tc qdisc change dev eth0 root netem delay 100ms 10ms 25%
さらに、上で設定した内容を、「正規分布に基づいて、100ms ± 10ms の遅延」に変更する例。
$ tc qdisc change dev eth0 root netem delay 100ms 10ms distribution normal
正規分布に基づいて、100ms ±50ms の遅延をかけて、さらに0.5パーセントの確率でパケットロス。
$ sudo tc qdisc add dev eth0 root netem delay 100ms 50ms distribution normal loss 0.5%

フィルタを使う例

特定のトラヒックに対して遅延をかけるためにはフィルタを使う必要があります。 以下は、宛先IPアドレスが「192.168.0.100」を含むパケットのみ、遅延させる例です。
$ tc qdisc add dev eth0 root handle 1: prio
$ tc filter add dev eth0 protocol ip parent 1: prio 2 u32 match ip dst 0.0.0.0/0 flowid 1:2
$ tc qdisc add dev eth0 parent 1:1 handle 10: netem delay 100ms
$ tc filter add dev eth0 protocol ip parent 1: prio 1 u32 match ip dstw 192.168.0.100/32 flowid 1:1

まず、root qdiscを作成しています。名前は"1:"です。"prio"を指定すると、優先度付きの子classを3つ、自動的に作成します。このとき作成される子classは、それぞれ、1:1, 1:2, 1:3という識別子を持ちます。

次に、root qdiscに、フィルタをセットします。ここでは、「優先度2で、全てのパケットをclass 1:2に分類する」というフィルタをセットしています。これを設定しておかないと、全てのトラヒックに遅延がかかる場合があります。

3つ目のコマンドで、class 1:1に、「100ミリ秒の遅延をエミュレーションするqdisc」を追加しています。

最後に、root qdiscに、「優先度1(最優先)で、宛先が192.168.0.100のパケットはclass 1:1に分離する」というフィルタをセットします。これで、宛先が192.168.0.100のパケットは、3つ目のコマンドで設定した「遅延をエミュレーションするqdisc」に処理されることになります。

アドレスとポートをフィルタの条件に加えるときは、以下のように続けて書きます。

$ tc filter add dev eth0 protocol ip parent 1: prio 1 u32 match ip dst 192.168.0.100/32 match ip dport 80 0xffff flowid 1:1

これで、「宛先ポートが80番」という条件が追加されます。

受信パケットの制御

ここまで説明した例は、すべて、送信パケットに遅延をかける例でした。受信パケットを制御する場合は、ifbモジュールを使う必要があります。
$ modprobe ifb
$ modprobe act_mirred
qdiscをセットするための仮想NICを起動します。
$ ip link set dev ifb0 up
物理NIC eth0に、ingress qdiscをセットします。
# tc qdisc add dev eth0 ingress handle ffff:
eth0が受信する全てのパケットを、ifb0に転送するためのフィルタをセットします。
$ tc filter add dev eth0 parent ffff: protocol ip u32 match u32 0 0 flowid 1:1 action mirred egress redirect dev ifb0
そして、ifb0にroot qdiscを作成します。
$ tc qdisc add dev ifb0 root handle 1: prio
このあとは、ifb0に作成したroot qdiscを使い、送信パケットを制御したときと同じように設定できます。 ただし、完全に設定をクリアするときは、eth0とifb0の両方をクリアすることをお忘れなく。
$ tc qdisc del dev eth0 ingress handle ffff:
$ tc qdisc del dev ifb0 root

その他

eth0に設定されている内容を一覧表示する例。
$ tc qdisc show dev eth0
eth0の設定されている内容を削除する例。
$ tc qdisc del dev eth0 root
広告
お問い合わせは sweng.tips@gmail.com まで。
inserted by FC2 system