2012年2月21日星期二

tc-htb限速

HTB - Hierarchy Token Bucket,从字面意义上上,这个是分层次的,HTB的规则本质上是一个树形结构。HTB可以用来在一个物理链路上虚拟多个链路,并能合理的利用空闲带宽,限速的原理和TBF是一样的。HTB比CBQ更加灵活,但是CPU开销也更大,通常高速的链路会使用CBQ,一般而言HTB使用的更加广泛,比HTB更加强大的是HSFC,原理一样,但是有更多的功能。

如果将HTB的分层结构看作树,那么每个节点就被称为一个class,每个class可以设置一个qdisc,默认的是tc-pfifo。 另外HTB还可以设置一些过滤器,通过这些过滤器可以将到来的包分发到指定的class上。这里过滤器通常挂载在root节点(egress接口),但匹配只能匹配叶子节点。

HTB是属于classful的qdisc,这类classful的qdisc可以使用filter来将包指定到特定的队列。classful的qdisc的子class只能是同类型的classful qdisc,或者是classless的qdisc,即HTB的子class只能用HTB或其他的classless的qdisc,如pfifo或者


tc qdisc ... dev dev ( parent classid | root) [ handle major: ] htb [ default minor-id ]



 Qdisc的参数:  

parent major:minor 或者 root。 一个qdisc是根节点就是root,否则其他的情况指定parent。其中major:minor是class的handle id,每个class都要指定一个id用于标识。

handle major: ,这个语法有点奇怪,是可选的,如果qdisc下面还要分类(多个class),则需要指定这个hanlde。对于root,通常是"1:"。

注意:对于tc命令中的qdiscs和classes,标识handle(classid)的语法都是x:y,其中x是一个整数用来标识一个qdisc,y是一个整数,用来标识属于该qdisc的class。qdisc的handle的y值必须是0,class的handle的y值必须是非0。通常"1:0"简写为"1:",也就是上面看到的写法。

default minor-id,未分类(不能和filter匹配)的流量(默认的)会被送到这个minor所指定的类(class id为major:minor-id),默认不指定就为0,即按物理链接的速率去发送。



tc class ... dev dev parent major:[minor] [ classid major:minor ] htb rate rate [ ceil rate ] burst bytes [ cburst bytes ] [ prio priority ]

 Class的参数:

parent major:minor,指定这个类的父节点,父节点可以是Qdisc,也可以是Class,如果是Qdisc,那么就不用指定minor,这个是必须的参数。

classid major:minor,classid作为class的标识,这个是可选的。如果这个class没有子节点,就可以不指定。major是父qdisc的handle。

prio 低优先级的class会优先匹配  

rate 这个class和其所有子类的速率

ceil 如果父类有空余带宽,最高可以分配给当前class的值,默认是和rate一样。

burst 允许以ceil的速率发送的字节数,应该至少和子类的burst最大值一样。  

cburst 允许以网口的最高速率发送的字节数,应该至少和子类的cburst最大值一样。功能类似tbf中的peakrate,当这个值限制很小时,可以避免突发的流量,以避免瞬间速率超过ceil。


quantum 每轮当前的class能发送的字节数,quantum = rate / r2q.  Quantum必须大于MTU(默认1500) 小于 60000。quantum只在class的流量超过了rate但是没超过ceil时使用。quantum越小,带宽共享的效果就越好。


r2q 用来计算quantum,r2q默认是10。Quantum设置的比MTU小会导致速率统计偏小,因为这种情况下速率计算的单位是Quantum,而不是真正发生的数据量。



例子:网络拓扑如下,有两个客户A和B,给B分配60kbps的带宽,给A分配40kbps的带宽,其中有30kbps分配给WWW,剩余的带宽分配给其他应用。下面的每一个节点都对应HTB中的一个class,当某个class没有用完分配的带宽,这些剩余的带宽可以分配给其他应用。

                        Main Link
                                | 100kbps
             --------------------------
              |  30kbps    |  10kbps   | 60kbps
       A/www         A/others       B

首先第一步先添加一个root的qdisc,为接口eth0指定HTB的qdisc,并用handle 1:来标识,default 12是指如果包没有匹配到接下来任何一个class,那么就放到默认的minor id为12的class中(classid 为 1:12)。

tc qdisc add dev eth0 root handle 1: htb default 12

接下来再为root的qdisc划分多个分类:

tc class add dev eth0 parent 1: classid 1:1 htb rate 100kbps ceil 100kbps
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 30kbps ceil 100kbps
tc class add dev eth0 parent 1:1 classid 1:11 htb rate 10kbps ceil 100kbps
tc class add dev eth0 parent 1:1 classid 1:12 htb rate 60kbps ceil 100kbps

第一行创建了"root" class,父节点是"1:",root class下面的class之间是可以共享带宽的,直接把下面三个class挂载到"1:"也是可以的,但是它们之间就不会共享带宽了。

#不共享带宽

tc class add dev eth0 parent 1: classid 1:1 htb rate 30kbps ceil 100kbps
tc class add dev eth0 parent 1: classid 1:2 htb rate 10kbps ceil 100kbps
tc class add dev eth0 parent 1: classid 1:3 htb rate 60kbps ceil 100kbps

需要说明的是classid的作用域是在interface内的,即eth0或eth1都可以有同样的classid或handle id。

最后一步就是添加过滤规则,将特定的包放到指定的qdisc队列中,下面的flowid实际上就是classid。

tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip src 1.2.3.4 match ip dport 80 0xffff flowid 1:10
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip src 1.2.3.4 flowid 1:11


最后,可以给叶子节点的class指定qdisc,默认是pfifo,也可以用netem设置时延的丢包等。

tc qdisc add dev eth0 parent 1:10 handle 20: pfifo limit 5
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


使用tc命令时,最好是将这些命令都写入到bash文件中,例子如下:

#############################################################################
#!/bin/bash
set -v
# type your commands here


tc qdisc del dev eth0 root  --- deletes all tc configuration for eth0

# creates starting point for configuration on eth0 (and directs all unclasified trafic to class 5) optional
tc qdisc add dev eth0 root handle 2 htb default 5

# creates new class 8 which belongs to root 2
tc class add dev eth0 parent 2: classid 2:8 htb rate 135Kbit ceil 500Kbit prio 2

# attach the shaper itself to the class 8 if you will not use this fifo shaper will be used by default
tc qdisc add dev eth0 parent 2:8 sfq

# in the root place check if packet destination is 1.3 and then direct it to class 8
tc filter add dev eth0 parent 2: protocol  u32 match ip dst 192.168.1.3 classid 2:8
#############################################################################

没有评论:

发表评论