私は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
。たとえば、パケットがキューに追加されると、パケット長が現在のキュー長に追加されます。同様に、パケットがキューから削除されると、キュー長からパケット長が減算されます。上記ですでに答えています。
人々が確認できるいくつかのソースは次のとおりです。
答え2
婦人声明:質問が多すぎます。私は10年間HTBを使用していませんか?だから自信を持って答えることができません。しかし、これまでの答えはまったくありませんので、これはまだ役に立ちます。
各親HTBクラス(1:1、1:2、1:3)ごとに内部キューが保持されますか?
それらはそれぞれ qdisc キュー構造で表されるリーフクラスなので、内部キューとみなされると仮定します。キューの長さがわからない。申し訳ありません。
struct htb_class_leaf {
int deficit[TC_HTB_MAXDEPTH];
struct Qdisc *q;
} leaf;
Qdisc構造はinclude/net/sch_generic.hで定義されています。
キューイング規約(QDisc)とはどういう意味ですか?
状況によって異なりますが、デフォルトではパケットがキューに追加され、キューから除外されるカーネル API です。したがって、QDiscは、着信パケットが再送信される(または完全に破棄される)順序(またはタイミング)をある程度制御できます。これは、HTB、SFQ、PRIOなどのQDiscが優先順位付けや帯域幅制限などのさまざまな方法でトラフィックを形成する方法です。
Generally, queueing discipline ("qdisc") is a black box,
which is able to enqueue packets and to dequeue them (when
device is ready to send something) in order and at times
determined by algorithm hidden in it.
HTBはそのようないくつかのアルゴリズムの1つにすぎません。
直接キューとは何ですか?
API の一部ではなく内部的に処理されるため、HTB アルゴリズムの一部と考えることができます。
意図的にパケットを分類するX:0
か、基本クラスが存在しない場合、HTBはそのパケットを別々のキューに入れることを決定し、キューから削除するときにそのパケットを最初に送信しようとします。
* [...] If we end up with classid MAJOR:0 we enqueue the skb into special
* internal fifo (direct). These packets then go directly thru. If we still
* have no valid leaf we try to use MAJOR:default leaf. It still unsuccessful
* then finish and return direct queue.
...そしてこれは直接パケットを最初にキューから削除する場所です。。
これは通常誤った設定(存在しないクラスへのパケット転送)の結果ですが、HTB開発者はこの場合、すべてのトラフィックを破棄するのではなく、すべてのトラフィックを通過する必要があると判断しました(邪魔になりすぎます)。
答え3
いくつかの高速ファジーメモリベースの検索:
HTBは柔軟です。デフォルトでは、各リーフクラスにはFIFOがあり、おそらくFIFOのデフォルト設定を使用できます。ただし、リーフクラスにはPFIFOまたはFQ_CODELを使用することもできます。ここでは、「オプションでリーフクラスへのキュールールの関連付け」を参照してください。http://luxik.cdi.cz/~devik/qos/htb/manual/userg.htm
私の考えでは、あなたが走ったらそれらを見ることができると思いますtc qdisc show
。
"この"直接"キューは、フィルタの1つがhtb qdiscの '0'クラスIDを明示的にターゲットにしている場合にのみ使用されます。https://lists.bufferbloat.net/pipermail/cerowrt-devel/2013-June/006507.html。直接キューはまだ形成されていません。明らかに、直接キューの長さを制御することが可能になりましたが、tcがそれをどのようにサポートするか(またはサポートするか)はわかりません。https://patchwork.ozlabs.org/patch/225546/
別の「パケットスケジューラ」があるとは言わない。パケットスケジューラはQDiscです(ただし、man tc-tbf
「トラフィックを予約しない」と主張します。これは、順序を再指定しないことを意味します。