linux tc流量控制(二):classful qdisc

classful qdisc是指可以作为class对象的父节点的qdisc,顾名思义,class是类别,用于进行数据包的分类。实际上,我们在设置class对象的时候,也会为其设置为一个classful qdisc值与其绑定,父classful qdisc的包会根据规则进入这些class中的其中一个,决定进入哪个class是由filter对象判断的(除了filter外,有些qdisc也会看TOS或者skb中的priority段)。class定义时指定的classful qdisc类型也会生效。我们可以进一步为class指定qdisc类型的子节点(既可以为classless也可以为classful)

qdisc和class的父子关系通过ID来指定,使用parent参数指定父节点的ID:

  • qdisc的ID格式为major:通过handle指定自己的ID。如果不手动指定,会被自动分配一个
  • class的ID格式为major:minor,通过classid指定自己的ID,这里major需要对应其父qdisc的major
  • 为class指定qdisc的子节点时,同样使用handle自己的ID,parent id为class的ID,此时qdisc的id与class的id无关,且不能和class的major冲突,比较已经有qdisc使用了这个ID了

例如

root@ubuntu:~# tc qdisc add dev lo root handle 1: htb default 1
root@ubuntu:~# tc class add dev lo parent 1:0 classid 1:1 htb rate 10Mbit burst 15k
root@ubuntu:~# tc class add dev lo parent 1:1 classid 1:10 htb rate 10Mbit ceil 10Mbit burst 15k
root@ubuntu:~# tc qdisc add dev lo parent 1:10 handle 10: sfq perturb 10

以下三条命令的结果是一样的

# tc qdisc add dev lo root handle 1 htb default 1
# tc qdisc add dev lo root handle 1: htb default 1
# tc qdisc add dev lo root handle 1:75 htb default 1
​
# tc qdisc ls dev lo
qdisc htb 1: root refcnt 2 r2q 10 default 0x1 direct_packets_stat 8 direct_qlen 1000

设置class不能使用classless qdisc

root@ubuntu:~# tc class add dev lo parent 1: classid 1:8 tbf
Error: Qdisc "tbf" is classless.

但是可以给class子节点添加classless qdisc。事实上,即使不设置,也会默认给每个class添加一个classless的qdisc

root@ubuntu:~# tc qdisc add dev lo parent 1:2 handle 10 sfq perturb 10

class也可以作为class的子节点

root@ubuntu:~# tc class add dev lo parent 1:2 classid 1:15 htb rate 10Mbit burst 15k
root@ubuntu:~# tc class ls dev lo
class htb 1:2 root rate 10Mbit ceil 10Mbit burst 15Kb cburst 1600b 
class htb 1:3 root prio 0 rate 10Mbit ceil 10Mbit burst 15Kb cburst 1600b 
class htb 1:15 parent 1:2 prio 0 rate 10Mbit ceil 10Mbit burst 15Kb cburst 1600b 
class htb 1:7 root prio 0 rate 10Mbit ceil 10Mbit burst 15Kb cburst 1600b 

filter命令,用于根据一定的规则,将包发送给某一个class,可以跨层级,下面是一个使用的例子:

root@ubuntu:~# tc qdisc add dev lo root handle 1:0 htb default 1
root@ubuntu:~# tc class add dev lo parent 1:0 classid 1:1 htb rate 10Mbit burst 15k
root@ubuntu:~# tc class add dev lo parent 1:1 classid 1:10 htb rate 10Mbit ceil 10Mbit burst 15k
root@ubuntu:~# tc qdisc add dev lo parent 1:10 handle 10: sfq perturb 10
​
root@ubuntu:~# tc filter add dev lo protocol ip parent 1: prio 1 u32 match ip dst 0.0.0.0/0 flowid 1:10
​
root@ubuntu:~# tc filter show dev lo 
filter parent 1: protocol ip pref 1 u32 chain 0 
filter parent 1: protocol ip pref 1 u32 chain 0 fh 800: ht divisor 1 
filter parent 1: protocol ip pref 1 u32 chain 0 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:10 not_in_hw 
  match 00000000/00000000 at 16
​

该命令的含义为,使用ip这个过来的协议,如果ip的目标地址匹配到了0.0.0.0/0,那么就会发送到1:10的class进行进一步处理,且匹配的优先级为1。有意思的是,我们可以不为filter指定parent,filter会自动选择上面的和虚拟设备绑定的qdisc作为parent,

  • tc支持以下的classful qdisc
    • ATM
    • CBQ
    • DRR
    • DSMARK
    • HFSC
    • HTB
    • PRIO
    • QFQ

  • 支持以下的filter
    • basic
    • bpf
    • cgroup
    • flow
    • fw
    • route
    • rsvp
    • tcindex
    • u32
    • matchall

这里介绍一下HTB这个classful qdisc。HTB全称为hierarchical token bucket,可以用来控制出口流量的带宽,同样基于之前文章中提到的令牌桶的算法。使用HTB可以将总带宽分成不同的部分,为每个部分分配带宽,也可以从其他部分借用带宽,即共享带宽,每个部分用于不同的目标。

举一个使用场景的使用例子,例如某网络上面有两台机器1.2.3.4和1.2.3.5,1.2.3.4向外部访问www及smtp服务,我们想限制1.2.3.4机器的整体出口带宽为40Mbps,其中www使用30Mbps,smtp使用10Mbps,1.2.3.5带宽为60Mbps,整体的带宽为100Mbps那么我们可以在网关的网络设备上这样配置。

tc qdisc add dev eth0 root handle 1: htb default 12
tc class add dev eth0 parent 1: classid 1:1 htb rate 100Mbps ceil 100Mbps 
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 30Mbps ceil 100Mbps
tc class add dev eth0 parent 1:1 classid 1:11 htb rate 10Mbps ceil 100Mbps
tc class add dev eth0 parent 1:1 classid 1:12 htb rate 60Mbps ceil 100Mbps
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

这里使用了u32过滤器对ip进行了匹配。

猜你喜欢

转载自blog.csdn.net/buhuidage/article/details/128331663
今日推荐