私はlinux-htb QDiscとlinux tc QDiscのキューイングメカニズムを全体的に理解しようとしています。
私が収集できるもの:TX中に、パケットはLinux tc内のキューに保存されます。デフォルトでは、このキューはtxqueuelenが1000のpfifo_fast QDiscに従います。パケットスケジューラはこのキューからパケットを取り出し、それをTXドライバキュー(リングバッファ)に配置します。
linux-htbを使用すると、デフォルトのキューだけがtxqueuelenを継承します。 [協会]。私の質問:ツリーを検討してください(速度は括弧()の中にkbits / secで指定されています)。
1: root qdisc (class htb)
(100)
/ | \
/ | \
/ | \
1:1 1:2 1:3 parent qdiscs (class htb)
(30) (10) (60)
各親HTBクラス(1:1、1:2、1:3)ごとに内部キューが保持されますか?それでは、キューの長さはどのくらいですか?そうでない場合、実際に保持されるキューの数と目的は何ですか?キューの長さはどのくらいですか?
キューイング規約(QDisc)とはどういう意味ですか?使用されたデータ構造(キュー)の属性ですか?それともパケットスケジューラの属性ですか?それとも両方の組み合わせですか?
HTB QDiscのソースコードを読み込んでいます[協会]、直接キューであることを発見しました。直接キューとは何ですか?
可能であれば、関連ソースへのリンクを提供してください。
ベストアンサー1
私は直接ソースコードを読んで研究したことがあるので、私の質問に答えます。私が直接研究作業を行っていない場合は、Frostschutzとsourcejediの答えが大きな助けになります。私の知識は正確に見えます(詳細はありませんが出発点を提供します)。残りの研究は直接行ってください。 )。
いくつかの理論:キュー規約には、クラス型とクラス型ではない2種類があります。
エレガント(sourcejediの答えによると)規律は柔軟です。これにより、サブクラスqdiscsを添付し、可能であれば他のクラスと帯域幅を共有できます。リーフクラスには、クラスのないqdisc(デフォルト/デフォルトqdisc)が接続されています(デフォルトqdiscとも呼ばれます)。これらのデフォルトのqdiscによって管理されるキューは、パケットがキューに追加され、キューから除外される場所です。パケットは、そのクラスに対応するアルゴリズムによって、これらのクラスからキューから除外され、キューに追加されます。 qdiscに似たものの例には、HTBとCBQがあります。
階級のないqdiscはデフォルトまたはデフォルトのqdiscであり、サブqdiscを接続できず、帯域幅を共有できないという点で厳密です。簡単に言えば、彼らはそれ自体です。これらのqdiscには、qdiscに対応するアルゴリズムに従ってパケットをキューに入れるか、キューから取り出すキューがあります。クラスレスqdiscの例:pfifo、bfifo、pfifo_fast(デフォルトではLinux tcで使用)、tbf、sfqなど
質問の例ツリーでは、各リーフhtbクラス1:1、1:2、および1:3にはデフォルトのqdiscが添付されており、デフォルトではpfifo(pfifo_fastではありません)です。リーフに取り付けられているデフォルトのqdiscは、 tc
次のようにユーザースペースユーティリティを使用して変更できます。
tc qdisc add dev eth0 parent 1:11 handle 30: pfifo limit 5
tc qdisc add dev eth0 parent 1:12 handle 40: sfq perturb 10
これについての詳細は、以下で確認できます。HTB Linuxキュールールマニュアル。したがって、ツリーは実際には次のようになります。
1: root qdisc (class htb)
(100)
/ | \
/ | \
/ | \
1:1 1:2 1:3 parent qdiscs (class htb)
(30) (10) (60)
|| || || -----> pfifo qdiscs (queue length: txqueuelen (default, can be changed by tc utitlity))
txqueuelenパラメーターはインターフェース固有のパラメーターです。つまり、パラメータはインタフェースの属性であり、使用または変更される可能性iproute2
がありますifconfig
。デフォルトでは、その値は1000です。次の方法で200に変更する方法の例は次のとおりですiproute2
。
ip link set eth0 txqueuelen 200
リーフノードが作成されると(HTB qdiscのコンテキストでは)、pfifo qdiscはデフォルトでリーフクラスにリンクされます。この pfifo はインターフェイスの txqueuelen キュー制限で初期化されます。これは関数で見つけることがhtb_change_class()
できます。sch_htb.c、1395行:
/* create leaf qdisc early because it uses kmalloc(GFP_KERNEL)
* so that can't be used inside of sch_tree_lock
* -- thanks to Karlis Peisenieks
*/
new_q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
classid, NULL);
pfifoキューのデフォルトキューの長さについては、次を参照してください。sch_fifo.c、61行目:
u32 limit = qdisc_dev(sch)->tx_queue_len;
カーネルがパケットをキューに入れたり、キューから取り除こうとすると、ルートqdisc(クラスがあるかクラスがない可能性がある)と直接対話します。ルートqdiscが分類され、子がある場合は、まずパケットを分類します(パケットを送信する子を決定します)。これを達成するためのカーネルソースコード:sch_htb.c、209行:
static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch,
int *qerr)
コメントを読んだ後、関数が次のいずれかを返すことを簡単に推論できます。
パケットをドロップする必要がある場合はNULLを返します。
-1:パケットがdirect_queueに待機する必要がある場合
リーフノード(パケットが実際に終了するデフォルトのqdiscを含む)この関数は、パケットがキューに入れる必要があるリーフノードを返すまで、ツリー内のすべての内部ノード(クラス)を検索します。
キューから削除すると、各クラスはqdiscに関連するアルゴリズムに従ってキューから削除する子を決定し、子はリーフクラスに関連付けられているデフォルトのqdiscからパケットがキューから削除されるまで同じことを行います。これはまた、サブクラスの割合が親クラスの割合を超えないようにする。 (パケットが通過するかどうかは親が決定するためです。)HTBはDequeueingソースについて学んだことがないため、ソースを提供できません。
直接キューに入れる:HTB qdisc によって保持される特殊な内部 FIFO キューで、パケットはハードウェア速度でキューから除外されます。キューの長さは txqueuelen です。 HTBがパケットをsub-qdiscの1つに分類できず、デフォルト値が指定されていない場合、パケットは直接キューに入ります。
だから私の質問に対する答えは次のとおりです。
はい、リーフノードなので、デフォルトではpfifoキューで、インターフェイスのキュー長txqueuelenはデフォルトで1000で変更できます。
キューイングの分野は、1つのパッケージに結合されたアルゴリズムとキューのようなものです!私に尋ねると、キューイングルールはキュータイプとパケットスケジューラの属性です(ここで、パケットスケジューラはパケットをキューに入れるか減算するアルゴリズムを表します)。たとえば、キューはpfifoまたはbfifoタイプです。キューに入れると減算するために使用されるアルゴリズムは同じですが、キューの長さはバイトfifo(bfifo)で測定されます。バイト制限に達すると、パケットは bfifo から廃棄されます。デフォルトのバイト制限は次のように計算されます
mtu*txqueuelen
。たとえば、パケットがキューに追加されると、パケット長が現在のキュー長に追加されます。同様に、パケットがキューから削除されると、キュー長からパケット長が減算されます。上記ですでに答えています。
人々が確認できるいくつかのソースは次のとおりです。