原理:
CBQ会统计链路的idle时间(moving_avg),并将这个同理论计算的idle时间比较,idle_moving_avg - idle_target = avgidle,理想情况下avgidle是0,如果链路过载,那么avgidle就是负值,CBQ会限制发送一段时间,如果长时间不发生数据,那么avgidle就会变大,这种情况下就会有一些burst,为了限制burst,就需要设置maxidle.
idle时间的衡量在实现中是用的设备驱动的数据请求之间的jiffies.
参数:
avgpkt - 包的平均大小,字节数。这个用来计算maxidle。
bandwidth - 链路的capacity,用来计算理论idle时间
cell - 计算包的传输时延时用到,cell作为包大小的基本单位,默认为8。例如:800byte和806byte的包的传输时延都一样。
maxburst - 突发流量的设置,这里是设置包的个数,maxidle不能直接设置,只能通过这个参数设置。
minburst - CBQ在流量过载时,理想情况下是在计算的每个idle时间点只发送一个包,但内核的时间精度有限制,所以只能选择在相对长一点的时间内多一次性的多发送一些数据包。minburst设置的越大,那么在长时间内的流控就越准,但会带来瞬间的突发流量。
minidle - CBQ在流量过载时,avgidle小于0,再次发生数据要等到avgidle恢复到某个比较大的值,如果之前的流量有很大的突发,这段时间可能会很长。如果指定minidle,就可以防止avgidle出现过小的情况。Minidle的单位是us(microseconds), 设置为10表示-10us。
mpu - 最小包单元的字节数,因为即便payload是0, ethernet的包长度必须填充为64字节,也是需要时间来传输的,这个用来精确的计算idle时间。
rate - 要限制的带宽。
CBQ的class特性:
CBQ也可以组织成树形结构,每个class是一个节点,可以设置优先级,优先级小的优先调度,调度采用WWR(weighted round robin)方式,下面是相关的一些参数:
allot - 每次调度可以发送的字节数(最小单元)。一个class一轮可以调度多次,根据weight来。
prio - 优先级
weight - 权值,最终会做归一化处理,一般采用10分制。renormalized weight和alloc的乘积就是每轮调度该class能发生的字节数。
CBQ的带宽共享:
isolated - 不借给子节点class带宽
sharing - 可以借给字节的class带宽,默认值。
bounded - 不去借用父节点class带宽
borrow - 可以借用父节点class带宽,默认值。
例子:
1: root qdisc | 1:1 child class / \ / \ 1:3 1:4 leaf classes | | 30: 40: qdiscs (sfq) (sfq)
在这个例子中,给http 5mbit,给smtp 3mbit,他们加起来不超过6 mbit/s, 并且他们直接可以共享带宽。
链路的capacity是100mbit。
1)设置root节点,设置为bounded那么带宽就不会超出6 mbit.
# tc qdisc add dev eth0 root handle 1:0 cbq bandwidth 100Mbit \ avpkt 1000 cell 8
# tc class add dev eth0 parent 1:0 classid 1:1 cbq bandwidth 100Mbit \ rate 6Mbit weight 0.6Mbit prio 8 allot 1514 cell 8 maxburst 20 \ avpkt 1000 bounded
2) 设置两个叶子节点:
# tc class add dev eth0 parent 1:1 classid 1:3 cbq bandwidth 100Mbit \ rate 5Mbit weight 0.5Mbit prio 5 allot 1514 cell 8 maxburst 20 \ avpkt 1000 # tc class add dev eth0 parent 1:1 classid 1:4 cbq bandwidth 100Mbit \ rate 3Mbit weight 0.3Mbit prio 5 allot 1514 cell 8 maxburst 20 \ avpkt 1000
4)采用SFQ替换FIFO,达到流间调度的公平性。
# tc qdisc add dev eth0 parent 1:3 handle 30: sfq # tc qdisc add dev eth0 parent 1:4 handle 40: sfq
5)加入过滤,针对特定的协议端口:
# tc filter add dev eth0 parent 1:0 protocol ip prio 1 u32 match ip \ sport 80 0xffff flowid 1:3 # tc filter add dev eth0 parent 1:0 protocol ip prio 1 u32 match ip \ sport 25 0xffff flowid 1:4
工具:
CentOS/Redhat默认已经带了一个cbq的工具,相关的配置在/etc/sysconf/cbq,shell脚本在sbin/cbq下.
没有评论:
发表评论