本文書で概説している方法は、他の Linux 構成でも動作するはずですが、 次の構成以外は未確認のままです。
Red Hat Linux 7.3
QoS サポートをすべて有効にし(モジュールでも構いません)、 次のパッチを当てた、2.4.18-5 カーネル(当該パッチは、 やがては将来のカーネルに取り込まれるかもしれません)。
HTB キュー - http://luxik.cdi.cz/~devik/qos/htb/
注意:Mandrake (8.1, 8.2) で出荷しているバージョン 2.4.18-3 以降のカーネルには、 HTB に関する当該パッチは既に当ててあるという連絡を受けました。
IMQ デバイス - http://luxik.cdi.cz/~patrick/imq/
iptables v1.2.6a 以降(Red Hat 7.3 で配布しているバージョンの iptables には、 length モジュールがありません)。
説明が込み入らないように、 本文書でネットワークデバイスや設定について触れる際は、 すべて以下のネットワーク接続図に従います。
<-- 128Kbit/s --------------- <--10Mbit --> インターネット <--------------------> | ADSL モデム | <-------------------- 1.5Mbit/s --> --------------- | | eth0 V ------------------ | | | Linux ルーター | | | ------------------ | .. | eth1..ethN | | V V ローカルネットワーク |
パケットキューというのは、 データがすぐにはネットワークデバイスに向けて送れない場合に、 そのデータを保持しておくバケツです。たいていのパケットキューは、 特に他の方法を使うように設定されていない限り、 FIFO(ファースト・イン、ファースト・アウト)という方式を使っています。 これが何を意味するかというと、 あるデバイス用のパケットキューが完全に飽和している場合に、 一番新しくキューに置かれたパケットが送出されるのは、 その時点でキューにある他のすべてのパケットが送出されてからだということです。
ADSL モデムでは、帯域は下りが通常 1.5Mbit/s、 上りが通常 128Kbit/s というように、 非対称になっています。これは回線速度のことですが、 Linux ルーター PC と ADSL モデム間のインタフェースは、 普通 10Mbit/s かそれ以上になっています。 ローカルネットワーク側のインタフェースも 10Mbit/s だったら、 ローカルネットワークからインターネットへ送るパケットは、 普通ルーターでは「キューイングしません」。 パケットは、ローカルネットワークから受けとった時と同じ速度で、 eth0 から送出されます。でも、反対向きのパケットは ADSL モデムでキューに溜ります。 というのは、パケットは 10Mbit/s でやってきますが、 出ていくのは 128Kbit/s にすぎないからです。 やがては ADSL モデムのパケットキューは飽和し、 そこにやってくるどんなパケットも、 それ以上は知らない間に落ちてしまいます。 TCP はこの問題を処理するよう設計されており、 適宜転送ウィンドウサイズを調整して、 可能な帯域をフルに活用します。
TCP とパケットキューを組み合せると、 帯域がもっとも効果的に使えるようになる一方で、 副作用として FIFO キューにたまるデータ量が増えるので、 対話的なトラフィックの遅延が増大しないとも限りません。
FIFO に幾分似てはいますが別の種類のキューに、 n バンドの優先順位づけキューというのがあります。 パケットを並べるキューが一つしかないのではなく、 n バンドの優先順位づけキューには n 個の FIFO キューがあり、 パケットはその種類に従って、どれかにキューイングされます。 各々のキューには優先順位があり、 パケットは常にもっとも優先順位の高いキューから取り出します。 この方式を使うと、 FTP のパケットを telnet のパケットよりも優先順位の低いキューに置けるので、 FTP のアップロード中でも、 telnet のパケットはたった一つでもキューに割り込んで、 即座に送出されます。
本文書では、階層化トークンバケット(HTB) という、 Linux の新しいキューを使うように改訂しました。 HTB キューは先に述べた n バンドのキューとたいへん似ていますが、 各クラスで転送率を制限できるようになっています。 さらに、他のクラスの下位にトラフィックのクラスを設定し、 クラス階層が作れるようになっています。 しかし HTB を余すところなく解説するというのは、 本文書で扱うべき事ではありません。 詳細な情報は http://www.lartc.org を参照して下さい。
ADSL モデムに対する内向きのトラフィックは、 外向きのトラフィックとほとんど同じ方法でキューに溜りますが、 そのキューは ISP 側にあります。 このため、パケットのキューイング方法とか、 どういった種類のトラフィックを優先的に扱うかといったことに関して、 直接制御することはおそらくできません。 遅延を低く抑える唯一の方法は、データをあまり高速で送らないようにすることです。 ですが、残念なことに、パケットの到着速度を直接制御する方法はありません。 でも、トラフィックの大多数はおそらく TCP ですから、 送信側の速度を抑える方法はいくつかあります。
意図的に内向きのパケットを落とす - TCP はリンクの輻輳を避ける一方で、 可能な帯域をフルに活用するよう設計されています。 つまり、バルクデータの転送中、TCP は最終的にパケットが落ちるまで、 次々とデータを送出します。すると、TCP はパケットが落ちたのを検出して、 転送ウィンドウを縮小します。転送が続いている間は、 ずっとこのサイクルを繰り返し、できる限りデータの高速転送を保証するのです。
通知された受信ウィンドウサイズを操作する - TCP の転送中、 受信側は確認応答 (ACK) パケットを返し続けます。 この ACK パケットには、通知されたウィンドウサイズが入っています。 これによって、未受信データの最大量を送信側に明示します。 ですから、外向きの ACK パケットのウィンドウサイズを操作すれば、 送信側を意図的にスピードダウンさせることができるのです。 現時点では、Linux でこの種のフロー制御を実装した(フリーな)ものはありません (でも筆者はこの機能の実装作業を続けると思います!)。