TC(Traffic Control)学习

qdisc是最终的用来选择哪个包的算法(代码),class只是一个可以挂载qdisc或class的东西。对于classful qdisc来说,leaf class必然要有一个qdisc在上面,如果没有指定应该就是用的默认的。

之所以有class,小秦个人觉得是为了让管理员通过命令的方式动态的实现if-else这样的选择逻辑(当然前提是这个qdisc算法支持这样的功能,比如FIFO的qdisc就没有这么复杂,所以其只是一个classless的qdisc),让packet走特定的qdisc出去。所以class就是我们做if-else判断的逻辑节点,if-else的条件就是filter,其parent就是上一层节点。

root qdisc和ingress qdisc不是qdisc…可以想象成他们是if-else的入口,其余的if-else可以挂载在上面。或者也可以直接挂一个classless的qdisc在上面,默认就是这种情况。因为这两个不是qdisc也不是class,所以他们是没有handle的,虽然在建立qdisc的时候可以指定他们为parent,但实际上这个parent和之后的子class指定的parent还是有区别的。

qdisc的minior number一定是0。class则不一定。再次强调下,class只是用于绑定filter的用于执行if-else选择packet走向的一个逻辑节点,真正处理packet的一定是qdisc。leaf class上一定会有qdisc,可以手工add,否则默认。

另外对于filter,其handle和qdisc、class的handle应该不是一个东西。filter的replace命令如果不指定filter的handle,那么会变成add。

简单的说,如果我要做流控,那么:
1.在root这个location的handle下面add一个qdisc(这个root按照上面讲的只是个location,可以做parent的参数),可以是classful的,也可以是classless的。命令为tc qdisc add XXX
2.如果上面加的是classless的,那么就结束了
3.如果上面加的是classful的,那么可以以它为parent添加class(有些classful disc会默认建立几个class,比如PRIO,这个在最下面有个例子,在那个例子里可以看到我们没有建立class,但是却可以直接add qdisc到class上),命令为tc class add XXX。class刚建立好默认应该也是有个classless qdisc在上面的,你可以自己手动用别的qdisc去替代,方法也是tc qdisc add XXX。
4.如果上面在class上面add了个classful的qdisc,那么可以重复第3步的逻辑继续加class或者qdisc
5.对于classful的qdisc,需要添加filter来决定某个packet要走哪个class出去。一般对于这种classful qdisc,在建立的时候会有参数说明对于一个packet如果没有filter匹配那么这个packet会怎么走。

名词说明:
token:一个packet需要一个token才能发送,所以token的生产速度控制了packet的发送速度
bucket:允许多少个token同时存在,如果bocket中有较多token的话,一下子来很多的packet就可以burst了

shaping:当一个packet从queue重出来的时候,shaping就是用来决定出来速度的机制(比如基于token、bucket)。sharping针对的是egress,policing针对的是ingress。
scheduling:当一个queue中有很多packet的时候,scheduling就是决定哪个packet可以出来,比如FIFO就是一种scheduling的机制
SFQ:Stochastic Fair Queuing。通过一个hash算法将packet随机分配到某个FIFO的queue中,然后对于每个FIFO通过Round Robin进行packet的发送。perturb用于设置hash函数的改变,也就是说hash函数是会不停的变的。如果不想某个session用去了全部的贷款可以使用这个。
GRED:Generic Random Early Drop。基于RED算法。
ESFQ:Extended Stochastic Fair Queuing。相比较SFQ其提供了更多的可配置参数。
chassifying:当一个packet准备出去的时候,classifying可以决定这个packet去哪个queue
policing:当queue中的packet太多超过了速率的时候,policing决定对packet采取何种操作。比如drop、reclassified等。policing针对的是ingress,sharping针对的是egress。
droping:丢弃
marking:给packet打上标记,iptables可以做到这一点
class:只存在于classful qdisc中。类似于树的子节点、叶子节点。class可以是classlesss qdisc,也可以是另一个classful qdisc。中间节点没有qdisc在上面。叶子节点必须有qdisc,默认是FIFO。
qdisc:scheduler的一种。每个output queue都需要scheduler决定哪个packet要被发送出去,默认是FIFO。qdisc可以看成是用于管理queue的一个算法。
classful qdisc:通过class来进行scheduler的qdisc
HFSC:Hierarchical Fair Service Curve。
PRIO:priority scheduler。classful qdisc。当可以发送packet的时候,第一个class会的被用来发送,之后第二个、第三个……然后再回过来重复这个过程。
FIFO:先进先出。
queuing discipline:qdisc的全称
reclassified:重新走filter
HTB:Hierarchical Token Bucket。基于token和bucket,通过filter实现复杂的流量控制。HTB有一个borrow mechanism。当一个clild class到达ceil的适合,其就会向parent借token,当其速率达到限制的rate后,会停止borrow。
CBQ:Class Based Queuing。
TBF:Token Bucket Filter。基于token和bucket。可以用于sharping。
handle:用于标示class和classful qdisc的一个ID,由major number和minor number组成。major对于那些拥有共同parent的traffic struct的object需要一致。minor对于qdisc必须是0,其余的数字表明其是一个class。ffff:0代表ingress qdisc。minor小的class总是会的比minor大的先被尝试。
root qdisc:用于egress挂载traffic control相关组件的一个location。其直接挂在在device上。
egress qdisc:就是root qdisc
ingress qdisc:用于ingree挂载traffic control相关组件的一个location
pfifo_qdisc:Linux默认的disc。在FIFO的基础上增加了priorization。其提供了三个bands(也就是三个queue),每个的优先级不一样,高优先级的总是会的先被处理,同一个band下的走FIFO。
Classless Queuing Disciplines:可以被用于作为interface上的primary qdisc。或者也可以成为classful qdisc下的leaf class。其没有啥internal的组件、配置。可以直接用。
Classful Queuing Disciplines:Classless Queuing Disciplines是基础,Classful Queuing Disciplines可以用树形结构包括多个Classless Queuing Disciplines,并且可以通过filter决定一个packet去往哪个leaf class(也就是Classful Queuing Disciplines)。说的简单点起就是一个classless qdisc的集合。不过要注意,虽然是树形结构,但是一个qdisc可以在filter的作用下直接将packet从root传到任意一个class上。
terminal class:leaf class
root classes:attach在root qdisc上的class
Classifier:用于确定一个packet在classful qdisc中去到哪个叶子class。
work-conserving qdisc:一有packet就立马传输的qdisc
non-work-conserving qdisc:比如TBF,packet有了也不一定能传输,需要等token的这种qdisc。

常见命令:
#查看某个设备上的qdisc信息
tc qdisc show dev eth0

#查看某个设备上的qdisc统计信息
tc -s qdisc ls dev eth0

#查看某个设备上class信息
tc class show dev eth0

#查看某个设备上的filter信息
tc filter show dev eth0

#建立一个root为pfifo且每个bond接着qdisc的例子(这里没有filter,packet从root往哪里流是根据如IP的TOS来决定的)
## This *instantly* creates classes 1:1, 1:2, 1:3
tc qdisc add dev eth0 root handle 1: prio
tc qdisc add dev eth0 parent 1:1 handle 10: sfq
tc qdisc add dev eth0 parent 1:2 handle 20: tbf rate 20kbit buffer 1600 limit 3000
tc qdisc add dev eth0 parent 1:3 handle 30: sfq

#设置filter,匹配的packet会去往flowid(handle)的class
tc filter add dev eth0 protocol ip parent 10: prio 1 u32 match ip dport 22 0xffff flowid 10:1
tc filter add dev eth0 parent 10:0 protocol ip prio 1 u32 match ip src 4.3.2.1/32 match ip sport 80 0xffff flowid 10:1

#根据iptables设置mark,然后通过filter具体的mark送往不同的class
iptables -A PREROUTING -t mangle -i eth0 -j MARK –set-mark 6
tc filter add dev eth1 protocol ip parent 1:0 prio 1 handle 6 fw flowid 1:1

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*