ネットワーク帯域上で必要な帯域をあらかじめ確保したり、必要以上のトラフィックを制限することを引っくるめて一般にQoS(Quality of Service)などと言うが、LinuxでIPのトラフィックコントロール(帯域制御)をするには、iprouteとtcを使う。

しかしこの設定は柔軟ではあるものの、直感的ではなく分かりづらい。こういうモノが必要な場合の大半は、アドレス帯毎に制限したいとかポート毎に制限したいとか、比較的目的がはっきりしているため、出来ればザックリと簡単に設定したいものだ。

そこで、CBQ.initというtcのwrapperとして使いやすいscriptがある。CBQというのはClass-Based Queuingと言って、トラフィック(パケット)をクラスとして定義し、それぞれに帯域上限値を設定しておく事で、上限値を超えたパケットを破棄するという方式だ。単純なqueueの優先順位付けの帯域制限方式と異なり、いつまで経ってもパケットがスケジューリングされず、事実上の通信断になってしまう事態を防ぐ事が出来る。

このCBQ.initをCentOS4で試してみた(たぶんCentOS5でもredhatでも同じでしょう)。必要なモジュールは最小構成でも用意されていたので、単純にscriptを設置するだけで良い。

まずはscriptをダウンロードし、適当はdirectoryに置いておく。redhat系のchkconfig形式のscriptのため、/etc/init.d/に置くなりlinkするなりしておくと、サービスとして管理することができる。分かりやすくするため、/etc/init.d/cbqというファイル名で設置してみた。

# chkconfig --add cbq
# chkconfig --list | grep cbq
cbq             0:off   1:off   2:off   3:off   4:off   5:off   6:off

こんな感じで見えれば正常。

あとは、script中のコメントに従って設定ファイルを用意する。設定ファイルもredhat系のdistributionならばおなじみの形式だ。設定ファイルの置き場はデフォルトでは/etc/sysconfig/cbq/なので、特に問題無ければここにすると良い。当然CentOSの標準構成には無いので作っておく。

# mkdir /etc/sysconfig/cbq/

設定ファイルは帯域制御したいクラス毎に、このdirectoryにファイルを置く。ファイル名の命名規則は以下のとおり。

cbq-lt;clsidgt;.lt;namegt;
  • clsidは帯域制御のクラスIDで、他のクラス(要は他の設定ファイル名)と重複してはいけない。0002からFFFFまでの値を指定する。
  • nameは任意の文字列。分かりやすい名前にでもしておく。

たとえば/etc/sysconfig/cbq/cbq-5963.for_httpsなどというファイルを作る。内容の例はこんな感じ。

DEVICE=eth0,1000Mbit,100Mbit
RATE=5Mbit
WEIGHT=500kbit
RULE=:443,
  • DEVICEには対象とするinterface名と、対応する物理NICのリンク速度、ウェイト(通常はリンク速度の1/10)を指定する。
  • RATEにはこのクラスへの割り当て帯域を指定する。
  • WEIGHTはウェイトを指定する。通常はRATEの1/10。
  • RULEは、[[saddr[/prefix]][:port[/mask]],][daddr[/prefix]][:port[/mask]]この形式で指定する。カンマ区切りで前半がソースアドレスとポート、後半がディスティネーションだ。特に指定しない(anyを指定する)場合は省略可能。

これがもっとも基本的で単純な使い方だ。上記の例だと、1Gbpsのインターフェイスeth0を通るパケットに対し、ソースポートが443であれば何れのソースアドレスでも、何れのディスティネーションでも5Mbpsの帯域とする、と言う意味。Webサーバなどに設定して、httpsの下り帯域を制限しているわけだ。

単なるwrapperとはいえ、設定出来る内容は多岐にわたり、かなりきめ細かい設定も出来る。scriptのコメントがとてもよく纏まっているので、いろいろ試してみると良い(CBQ.initという名前だけど、CBQ以外の制御もできる)。

chkconfigでサービスに登録してあれば、動作させるには

# service cbq start

だけで良い。動作状況の確認は以下のコマンドでできる。

# service cbq stats(帯域制御の状況を表示する)
# service cbq list(制御対象のリストを表示する)
# tc -s class ls dev eth0(tcで見る場合にはこんな感じ watchコマンドの引数にすると便利)

動作に問題が無ければ、chkconfigコマンドでonにしておけば、毎回OSのboot時に設定される。chkconfigを使わない場合は、そのままscriptの実行し、引数にstart,stop,stats,list等を指定すれば同じ結果になる。