分层令牌桶是tc中最强大的工具,没有之一,htb使用令牌桶的原理,结合分类、过滤器,可以实现非常复杂的流控,更重要的是,htb支持流量租借,当孩子节点流量不足或者也叫带宽不足但是父亲节点流量仍有冗余的情况下,孩子节点通过超发模式使用父亲的带宽资源

1. 令牌桶

令牌桶是HTB的基础,HTB主要是在令牌桶的原理之上支持了分层机制

令牌桶算法是网络流量整形和速率限制中最常使用的一种算法,令牌桶算法用来控制发送到网络上的数据的数目,并允许突发数据的发送

首先令牌桶有一个容量,这个容量是固定的,令牌桶可以自行以恒定的速率源源不断的产生令牌:

  1. 如果令牌被消耗速度跟不上产生速度,最终就会导致令牌桶中的令牌数不断增多,直至桶满,然后开始溢出,最后桶中的令牌绝对不会超出桶的容量
  2. 如果令牌被消耗的速度超过令牌产生的速度,那么桶中的令牌就会越来越少,最终桶就会变空

tc使用令牌来描述网络传输数据包的单位,使用令牌桶来控制数据包发送到网络上的传输速度,令牌可以用来表示网络数据包的大小,不同的数据包消耗的令牌数是不一样的

令牌桶的控制传输速率的基本原理就是:

  1. 数据包经过令牌桶时,如果桶中有足够的令牌,则发送数据包,同时减去响应的令牌数
  2. 如果桶中的令牌数不足,那么数据包就不能被发送,需要等待,直到令牌桶中有足够的令牌

2. 分层

分层是HTB中另一个重要的概念,这是CBQ没有的,CBQ不但复杂,而且因为和Linux内核机制不兼容导致多数情况下都无法按照预期进行优化。所以作者Martin Devera搞了一个HTB出来,HTB能够很好地满足这样一种场景:

你有一个固定速率的链路,希望分割给多种不同的用途使用,为每种用途做出带宽承诺并实现定量的带宽租借

htb可以创建分层的队列规则,不同的层级还可以继续创建子分层,从而形成一个拓扑型的流量控制,如下

3. 分类

HTB中的分类其实就是分层拓扑中的节点,不同的类有不同的带宽配置,详细的配置如下:

tc 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}

其中有几个比较关键的概念:

  1. rate:带宽速率,单位是bit/mbit/kbit/gbit或者bps/mbps/kbps/gbps
  2. ceil:上限带宽速率,单位与rate一致,ceil是实现HTB的流量租借的重要参数
  3. burst:突发数据包大小
  4. cburst:租借情况下的突发数据包大小

其中rate和ceil可以分别对应到Matrix中的软限和硬限,burst主要用来控制流量整形的精确度

4. 过滤器

内核只和根打交道,数据包是在根队列规定处入队和出队的:

  1. 数据包进入队列时,自上而下进入拓扑中的某个子节点
  2. 当内核决定把一个数据包发给网卡的时候,根队列规定会得到一个出队请求,然后它会把请求以递归的方式发送给所有的孩子,最终只有叶子节点才能执行真正的数据包出队操作

为了决定用哪个类处理数据包,必须调用所谓的分类选择器进行选择,这就是tc中的filter概念,filter会根据自身设定的规则,以决定当前数据包进入哪一个孩子节点,目前tc支持的分类器有fw,u32,route,cgroup等。它们主要的区别是:

  • fw 根据防火墙如何对这个数据包做标记进行判断
  • u32 根据数据包中的各个字段进行判断
  • route 根据数据如何被路由进行判断
  • cgroup 与net_cls子系统结合,根据进程pid来判断

5. 流量租借

流量租借是htb中非常核心的功能,htb拓扑中的孩子节点带宽耗尽之后,可以向父节点租借流量,如果父节点还有冗余的话。但是租借的流量最终不能超过设定的一个上线,如前面我们再tc的htb用法中看到的ceil参数,htb中每个节点都有两个很重要的参数:

  • rate 表示节点所拥有的带宽速率
  • ceil 表示节点的上限带宽速率

默认情况下,如果不指定ceil,则ceil取rate指,也就是ceil == rate,意思就是说突发流量不能超过rate,详细租借规则具体可以参考:http://www.tldp.org/HOWTO/Traffic-Control-HOWTO/classful-qdiscs.html#qc-htb

Leave a Comment