7. 分类排队规则 (qdiscs)

通过分类排队规则,Linux 流量控制的灵活性和控制力可以得到充分发挥。请记住,分类排队规则可以附加过滤器,从而允许将数据包定向到特定的类和子队列。

有一些常用术语来描述直接附加到qdisc 和终端类的类。附加到qdisc 的类被称为根类,更广泛地称为内部类。特定排队规则中的任何终端类都被称为叶子类,这与类的树状结构类似。除了使用比喻性的语言将结构描绘成树之外,使用家庭关系语言也很常见。

7.1. HTB,分层令牌桶

HTB 使用令牌和桶的概念,以及基于类的系统和filters(过滤器),以实现对流量的复杂和精细控制。凭借复杂的借用模型,HTB 可以执行各种复杂的流量控制技术。立即使用 HTB 最简单的方法之一是整形

通过理解令牌,或者掌握TBF 的功能,HTB 应该只是一个逻辑步骤。这种排队规则允许用户定义所使用的令牌和桶的特性,并允许用户以任意方式嵌套这些桶。当与分类方案结合使用时,可以非常精细地控制流量。

下面是使用 tc 工具在命令行上使用 HTB 的语法的示例输出。虽然 tcng 的语法是一种独立的语言,但 HTB 的规则是相同的。

示例 10. tc 用于 HTB 的用法

Usage: ... qdisc add ... htb [default N] [r2q N]
 default  minor id of class to which unclassified packets are sent {0}
 r2q      DRR quantums are computed as rate in Bps/r2q {10}
 debug    string of 16 numbers each 0-3 {0}

... class add ... htb rate R1 burst B1 [prio P] [slot S] [pslot PS]
                      [ceil R2] [cburst B2] [mtu MTU] [quantum Q]
 rate     rate allocated to this class (class can still borrow)
 burst    max bytes burst which can be accumulated during idle period {computed}
 ceil     definite upper class rate (no borrows) {rate}
 cburst   burst but for ceil {computed}
 mtu      max packet size we create rate map for {1600}
 prio     priority of leaf; lower are served first {0}
 quantum  how much bytes to serve from leaf at once {use r2q}

TC HTB version 3.3
      

7.1.1. 软件要求

与几乎所有其他讨论的软件不同,HTB 是一种较新的排队规则,您的发行版可能没有使用 HTB 所需的所有工具和功能。内核必须支持 HTB;内核版本 2.4.20 及更高版本在标准发行版中支持它,尽管较早的内核版本需要打补丁。要启用用户空间对 HTB 的支持,请参阅 HTB 以获取 iproute2 补丁到 tc

7.1.2. 整形

HTB 最常见的应用之一是整形传输的流量到特定速率。

所有整形都发生在叶子类中。内部类或根类中不会发生整形,因为它们的存在只是为了说明借用模型应如何分配可用令牌。

7.1.3. 借用

HTB qdisc 的一个基本组成部分是借用机制。子类一旦超过rate(速率)就会从其父类借用令牌。子类将继续尝试借用,直到达到 ceil(上限),此时它将开始将数据包排队以进行传输,直到有更多令牌/ctoken 可用。由于只有两种主要类型的类可以使用 HTB 创建,下表和图表标识了各种可能的状态和借用机制的行为。

表 2. HTB 类状态和可能的动作

类类型类状态HTB 内部状态采取的动作
叶子类< 速率 (rate)HTB_CAN_SEND叶子类将出队排队的字节,最多到可用令牌(不超过 burst 数据包)
叶子类> 速率 (rate), < 上限 (ceil)HTB_MAY_BORROW叶子类将尝试从父类借用令牌/ctoken。如果令牌可用,它们将以quantum增量借出,叶子类将出队最多cburst字节
叶子类> 上限 (ceil)HTB_CANT_SEND不会出队数据包。这将导致数据包延迟,并将增加延迟以满足所需速率。
内部类,根类< 速率 (rate)HTB_CAN_SEND内部类将向子类借出令牌。
内部类,根类> 速率 (rate), < 上限 (ceil)HTB_MAY_BORROW内部类将尝试从父类借用令牌/ctoken,并以quantum每次请求的增量借给竞争的子类。
内部类,根类> 上限 (ceil)HTB_CANT_SEND内部类将不会尝试从其父类借用,也不会向子类借出令牌/ctoken。

该图表标识了借用令牌的流向以及令牌如何向父类收费的方式。为了使借用模型正常工作,每个类都必须准确计算自身及其所有子类使用的令牌数量。因此,在子类或叶子类中使用的任何令牌都会向每个父类收费,直到到达根类。

任何希望借用令牌的子类都将向其父类请求令牌,如果父类也超过了其速率 (rate)速率 (rate),将请求从其父类借用,直到找到令牌或到达根类。因此,令牌的借用流向叶子类,而令牌使用的收费流向根类。

请注意,在此图中,有多个 HTB 根类。每个根类都可以模拟一个虚拟电路。

7.1.4. HTB 类参数

default(默认)

每个 HTB qdisc 对象的可选参数,default(默认)default(默认)为 0,这将导致任何未分类的流量以硬件速度出队,完全绕过附加到qdisc 的任何类。

速率 (rate)

rate(速率)

上限 (ceil)

用于设置限制传输流量的最小期望速度。这可以被认为是承诺信息速率 (CIR) 的等效值,或给定叶子类的保证带宽。

ceil(上限)

用于设置限制传输流量的最大期望速度。借用模型应说明如何使用此参数。这可以被认为是"突发带宽"的等效值。ceil(上限)burst

cburst

这是 rate(速率)桶的大小(参见 令牌和桶)。HTB 将出队cburst字节,然后等待更多令牌的到达。

quantum

cburstquantum这是 ceil(上限)桶的大小(参见 令牌和桶)。HTB 将出队

字节,然后等待更多 ctoken 的到达。

quantum字节,然后等待更多 ctoken 的到达。这是 HTB 用来控制借用的关键参数。通常,正确的

quantum

由 HTB 计算,而不是由用户指定。调整此参数可能会对争用下的借用和整形产生巨大影响,因为它既用于在超过 rate(速率)(但在 ceil(上限)以下)的子类之间拆分流量,也用于从这些相同的类传输数据包。

r2q

同样,通常为用户计算,

  • r2q

  • 是 HTB 的一个提示,以帮助确定特定类的最佳 quantum速率 (rate)mtu上限 (ceil)mtu速率 (rate)最大传输单元 (MTU),应设置为 MTU 或更高。速率 (rate)prio上限 (ceil) - 速率 (rate)prio

    优先级。

  • 7.1.5. 规则quantum以下是一些使用 HTB 的通用指南,这些指南来自 http://docum.org/LARTC 邮件列表。这些规则只是对初学者的建议,旨在最大限度地发挥 HTB 的优势,直到更好地理解 HTB 的实际应用。速率 (rate)使用 HTB 的整形仅发生在叶子类中。另请参见 第 7.1.2 节上限 (ceil).

  • 7.1.5. 规则quantum由于 HTB 除了叶子类之外,不在任何类中进行整形,因此叶子类的quantumrate(速率)之和不应超过父类的

  • ceil(上限)。理想情况下,子类的quantumrate(速率)之和应与父类的quantumrate(速率)匹配,从而允许父类在子类之间分配剩余带宽(

  • ceil(上限))。

  • 在采用 HTB 时,这个关键概念值得重复。只有叶子类实际整形数据包;数据包仅在这些叶子类中延迟。内部类(一直到根类)的存在是为了定义借用/借出如何发生(另请参见 第 7.1.3 节)。

quantum(量子)

仅当类超过

rate(速率)但低于

ceil(上限)时才使用。

mtu(MTU)

rate(速率)但低于

应设置为 MTU 或更高。即使 mtu(MTU)

太小,HTB 也至少会在每次服务机会中出队一个数据包。在这种情况下,它将无法准确计算实际消耗的带宽[1]

quantum(量子)

[1]

父类以 quantum(量子)的增量向子类借出令牌,因此为了获得最大的粒度和最瞬时均匀分配的带宽,quantumquantum(量子)