9.6. フィルタによるパケットのクラス選別

あるパケットをどのクラスが処理すべきかを決めるには、 いわゆる「クラス選別チェイン」がその度ごとに呼び出されます。 このチェインは、その決断を行うクラスフルな qdisc に属する すべてのフィルタからなります。

ではまた木を。実際には木ではないのですが。

                    root 1:
                      |
                    _1:1_
                   /  |  \
                  /   |   \
                 /    |    \
               10:   11:   12:
              /   \       /   \
           10:1  10:2   12:1  12:2

パケットのエンキューイングをする際、 それぞれの枝でどのような命令をすべきか、 フィルタチェインに問い合わせがいきます。 よくある設定は、1:1 のフィルタがパケットを 12: に向け、 12: のフィルタがそのパケットを 12:2 に送る、といったようなものです。

この後者の規則を直接 1:1 に所属させることもできますが、 より特殊なテストはチェインの先に置く方が、効率的になります。

なお、パケットを「上向き」にフィルタすることはできません。 また HTB では、すべてのフィルタは root に所属させなければなりません。

もう一度。パケットのエンキューは下に向かってのみ行われます。 それらのパケットがデキューされる際には、 インターフェースのある上の方に上がっていくわけです。 枝の先の方に行ってもネットワークアダプタはありません。

9.6.1. シンプルなフィルタの例

クラス選別器の章で説明する通り、 非常に複雑な文法が利用でき、文字通りあらゆるものにマッチが可能です。 まずは、わかりやすい例から始めましょう。 幸いこれらは簡単です。

ここでは '10:' という PRIO qdisc があるといます。ここには 3 つのクラスがあり、 ポート 22 からのトラフィックを最も優先度の高いバンドに割り当てたいとしましょう。 このときのフィルタは次のようになります。

# tc filter add dev eth0 protocol ip parent 10: prio 1 u32 match \ 
  ip dport 22 0xffff flowid 10:1
# tc filter add dev eth0 protocol ip parent 10: prio 1 u32 match \
  ip sport 80 0xffff flowid 10:1
# tc filter add dev eth0 protocol ip parent 10: prio 2 flowid 10:2

何をやってるのでしょうか? ここでは: eth0 の node 10: に、優先度 1 の u32 フィルタを加えています。 このフィルタは IP 送信先ポートが 22 (だけ) にマッチし、バンド 10:1 へ送ります。 次の行では発信元ポートが 80 のパケットについて同じことをやっています。 最後の行では、マッチしなかったものはすべて、 次に優先度の高いバンド 10:2 に送っています。 (訳注: 0xffff はマッチの前に取る AND マスクです)

ここには 'eth0' またはそのインターフェースの名前が必要です。 各インターフェースは、それぞれ他と重ならないかたちで割り当てられた、 ハンドルの名前空間を保持しているからです。

IP アドレスで選別するには、次のようにします。
# tc filter add dev eth0 parent 10:0 protocol ip prio 1 u32 \ 
  match ip dst 4.3.2.1/32 flowid 10:1
# tc filter add dev eth0 parent 10:0 protocol ip prio 1 u32 \
  match ip src 1.2.3.4/32 flowid 10:1
# tc filter add dev eth0 protocol ip parent 10: prio 2      \
  flowid 10:2

これは 4.3.2.1 へのトラフィックと、1.2.3.4 からのトラフィックに 最高の優先度のキューに入れ、その他を 2 番目のキューに入れています。

マッチ条件は連結できます。1.2.3.4 のポート 80 から来たトラフィックに マッチさせるには、次のようにします。
# tc filter add dev eth0 parent 10:0 protocol ip prio 1 u32 match ip src 4.3.2.1/32 \
  match ip sport 80 0xffff flowid 10:1

9.6.2. 通常必要なフィルタコマンドすべて

ここで説明する帯域制限コマンドは、たいていこの前置きから始まっています:
# tc filter add dev eth0 parent 1:0 protocol ip prio 1 u32 ..
これらはいわゆる 'u32' マッチで、パケットのどの部分にもマッチします。

発信元/送信先アドレスによるマッチ

発信元マスクは 'match ip src 1.2.3.0/24'、 送信先マスクは 'match ip src 4.3.2.0/24' です。 単一のホストにマッチさせるには、/32 を用いるかマスクを省略します。

発信元/送信先ポートによるマッチ (ip プロトコルは問わない)

発信元は 'match ip sport 80 0xffff'、 送信先は 'match ip dport 0xffff'。

ip プロトコル (tcp, udp, icmp, gre, ipsec)

/etc/protocols の番号を用います。 例えば icmp は 1 ですから、'match ip protocol 1 0xff'。

fwmark によるマッチ

ipchains か iptables でパケットに印を付けて、 その印をインターフェース間のルーティングで利用することもできます。 これは例えば、eth0 から入ってきたパケットだけを eth1 で絞る場合などにとても便利です。文法は次の通り:
# tc filter add dev eth1 protocol ip parent 1:0 prio 1 handle 6 fw flowid 1:1
これは u32 マッチではないことに注意。

印を付けるには次のようにします。
# iptables -A PREROUTING -t mangle -i eth0 -j MARK --set-mark 6
この番号 6 は任意に変更できます。

tc フィルタの文法全部を理解するのが面倒なら、 iptables を使うことにして、fwmark による選別だけを覚えてください。

TOS フィールドによるマッチ

対話的な、minimum delay のトラフィックを選別するには:
# tc filter add dev ppp0 parent 1:0 protocol ip prio 10 u32 \
      match ip tos 0x10 0xff \
     flowid 1:4
バルクトラフィックには 0x08 0xff を用います。

フィルタコマンドについてもっと知りたい人は、 高度なフィルタの章を見てください。