次の節では、何が遅延の原因なのか、どうすればそれを修正できるかを、 より詳しく説明します。もしこの魔法の動作原理に関心がなければ、 次は飛ばして直接スクリプトに向かっても問題ありません。
ではどうしましょう? これらのキューは制御できないのですから、 殺してしまわなければなりません。キューは Linux ルータに移動するのです。 ありがたいことに、これは可能です。
さて、これらを行うと、下りのキューを完全に (短いバーストを除いて) 無効にでき、 下りのキューの管理にも、Linux の持つ能力をすべて利用できるようになります。
これらをすべて設定すれば、 オランダの xs4all における excellent ADSL 接続では、 次のような測定結果が得られます。
基本的な遅延: round-trip min/avg/max = 14.4/17.1/21.7 ms トラフィック調整器なし、ダウンロード中: round-trip min/avg/max = 560.9/573.6/586.4 ms トラフィック調整器なし、アップロード中: round-trip min/avg/max = 2041.4/2332.1/2427.6 ms トラフィック調整器あり、220kbit/s のアップロード中: round-trip min/avg/max = 15.7/51.8/79.9 ms トラフィック調整器あり、850kbit/s のダウンロード中: round-trip min/avg/max = 20.4/46.9/74.0 ms |
すべてのカーネルで動作します。 CBQ qdisc の内部に 2 つの確率的不偏キューを置き、 複数のバルクストリームがお互いを完全に殺してしまわないようにしています。
下りトラフィックはトークンバケツフィルタを用いた tc フィルタで制限しています。
#!/bin/bash # 自宅のインターネット接続用の究極設定 # # # 次のパラメータを、実際のダウンロード・アップロード速度より # 少々小さくしてください (キロバイト単位) DOWNLINK=800 UPLINK=220 DEV=ppp0 # 既存の下り・上りの qdisc を削除。エラーは隠す。 tc qdisc del dev $DEV root 2> /dev/null > /dev/null tc qdisc del dev $DEV ingress 2> /dev/null > /dev/null ###### 上り # root CBQ をインストール tc qdisc add dev $DEV root handle 1: cbq avpkt 1000 bandwidth 10mbit # あらゆる物を $UPLINK 速度の内部に収める - これは DSL モデムの # 巨大なキューを無効にし、遅延が出ないようにします: # メインクラス tc class add dev $DEV parent 1: classid 1:1 cbq rate ${UPLINK}kbit \ allot 1500 prio 5 bounded isolated # 高優先度クラス 1:10 tc class add dev $DEV parent 1:1 classid 1:10 cbq rate ${UPLINK}kbit \ allot 1600 prio 1 avpkt 1000 # バルクおよびデフォルトのクラス 1:20。ややトラフィックが少なく、 # 優先度が低くなります tc class add dev $DEV parent 1:1 classid 1:20 cbq rate $[9*$UPLINK/10]kbit \ allot 1600 prio 2 avpkt 1000 # 両者に確率的不偏キューをあてがいます tc qdisc add dev $DEV parent 1:10 handle 10: sfq perturb 10 tc qdisc add dev $DEV parent 1:20 handle 20: sfq perturb 10 # ここからフィルタ # TOS が Minimum Delay (scp 以外の ssh) のものを 1:10 へ: tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 \ match ip tos 0x10 0xff flowid 1:10 # ICMP (ip プロトコル 1) を対話的クラス 1:10 へ。 # 測定と相手への通知ができるようになります: tc filter add dev $DEV parent 1:0 protocol ip prio 11 u32 \ match ip protocol 1 0xff flowid 1:10 # アップロード時のダウンロードを高速化するために、ACK パケットを # 対話的クラスへ: tc filter add dev $DEV parent 1: protocol ip prio 12 u32 \ match ip protocol 6 0xff \ match u8 0x05 0x0f at 0 \ match u16 0x0000 0xffc0 at 2 \ match u8 0x10 0xff at 33 \ flowid 1:10 # 残りは「非対話的」つまり「バルク」なので 1:20 へ tc filter add dev $DEV parent 1: protocol ip prio 13 u32 \ match ip dst 0.0.0.0/0 flowid 1:20 ###### 下り # ダウンロードを実際の速度よりも少々遅くして、ISP でのキューを # 無効にする。調整してできるだけ大きくしてください。 # ISP は大きなサイズのダウンロードを高速化するために「巨大」な # キューを持つことが多い # # 入口監視制限を追加: tc qdisc add dev $DEV handle ffff: ingress # 「すべて」(0.0.0.0/0) をこちらへフィルタし、速すぎるものは # 破棄する: tc filter add dev $DEV parent ffff: protocol ip prio 50 u32 match ip src \ 0.0.0.0/0 police rate ${DOWNLINK}kbit burst 10k drop flowid :1 |
このスクリプトは素晴らしい HTB キューを用い、すべての目的を達成しています。 HTB の章を見てください。カーネルへのパッチ当て作業に十分見合います!
#!/bin/bash # 自宅のインターネット接続用の究極設定 # # # 次のパラメータを、実際のダウンロード・アップロード速度より # 少々小さくしてください (キロバイト単位) DOWNLINK=800 UPLINK=220 DEV=ppp0 # 既存の下り・上りの qdisc を削除。エラーは隠す。 tc qdisc del dev $DEV root 2> /dev/null > /dev/null tc qdisc del dev $DEV ingress 2> /dev/null > /dev/null ###### 上り # root HTB をインストールし、デフォルトのトラフィックを 1:20 へ: tc qdisc add dev $DEV root handle 1: htb default 20 # あらゆる物を $UPLINK 速度の内部に収める - これは DSL モデムの # 巨大なキューを無効にし、遅延が出ないようにします: tc class add dev $DEV parent 1: classid 1:1 htb rate ${UPLINK}kbit burst 6k # 高優先度クラス 1:10 tc class add dev $DEV parent 1:1 classid 1:10 htb rate ${UPLINK}kbit \ burst 6k prio 1 # バルクおよびデフォルトのクラス 1:20。ややトラフィックが少なく、 # 優先度が低くなります tc class add dev $DEV parent 1:1 classid 1:20 htb rate $[9*$UPLINK/10]kbit \ burst 6k prio 2 # 両者に確率的不偏キューをあてがいます tc qdisc add dev $DEV parent 1:10 handle 10: sfq perturb 10 tc qdisc add dev $DEV parent 1:20 handle 20: sfq perturb 10 # TOS が Minimum Delay (scp 以外の ssh) のものを 1:10 へ: tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 \ match ip tos 0x10 0xff flowid 1:10 # ICMP (ip プロトコル 1) を対話的クラス 1:10 へ。 # 測定と相手への通知ができるようになります: tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 \ match ip protocol 1 0xff flowid 1:10 # アップロード時のダウンロードを高速化するために、ACK パケットを # 対話的クラスへ: tc filter add dev $DEV parent 1: protocol ip prio 10 u32 \ match ip protocol 6 0xff \ match u8 0x05 0x0f at 0 \ match u16 0x0000 0xffc0 at 2 \ match u8 0x10 0xff at 33 \ flowid 1:10 # 残りは「非対話的」つまり「バルク」なので 1:20 へ ###### 下り # ダウンロードを実際の速度よりも少々遅くして、ISP でのキューを # 無効にする。調整してできるだけ大きくしてください。 # ISP は大きなサイズのダウンロードを高速化するために「巨大」な # キューを持つことが多い # # 入口監視制限を追加: tc qdisc add dev $DEV handle ffff: ingress # 「すべて」(0.0.0.0/0) をこちらへフィルタし、速すぎるものは # 破棄する: tc filter add dev $DEV parent ffff: protocol ip prio 50 u32 match ip src \ 0.0.0.0/0 police rate ${DOWNLINK}kbit burst 10k drop flowid :1 |