LINUX TC中文版Word格式.docx
《LINUX TC中文版Word格式.docx》由会员分享,可在线阅读,更多相关《LINUX TC中文版Word格式.docx(18页珍藏版)》请在冰豆网上搜索。
标记的包放进0频道.
不要把这个无类的简单队列规定与分类的PRIO相混淆!
虽然它们的行为有些类
似,但对于无类的pfifo_fast而言,你不能使用tc命令向其中添加其它的队列规
定.
9.2.1.1.参数与使用
pfifo_fast队列规定作为硬性的缺省设置,你不能对它进行配置.它缺省是这样
配置的:
priomap:
内核规定,根据数据包的优先权情况,对应相应的频道.这个对应是根据
数据包的TOS字节进行的.TOS看上去是这样的:
01234567
+-----+-----+-----+-----+-----+-----+-----+-----+
||||
|优先权|TOS|MBZ|
TOS字段的4个bit是如下定义的:
二进制十进制意义
-----------------------------------------
10008最小延迟(md)
01004最大throughput(mt)
00102最大可靠性(mr)
37
7),它们不对应TOS映射,但是有其它的意图.
下表来自RFC1349,告诉你应用程序可能如何设置它们的TOS:
TELNET1000(minimizedelay)
控制1000(minimizedelay)FTP
数据0100(maximizethroughput)
TFTP1000(minimizedelay)
命令阶段1000(minimizedelay)SMTP
数据阶段0100(maximizethroughput)
UDP查询1000(minimizedelay)
TCP查询0000
DomainNameService
区域传输0100(maximizethroughput)
NNTP0001(minimizemonetarycost)
报错0000
请求0000(mostly)
ICMP
响应(mostly)
txqueuelen
38
队列的长度来自网卡的配置,你可以用ifconfig和ip命令修改.如设置队
列长度为10,执行:
ifconfigeth0txqueuelen10
你不能用tc命令设置这个!
9.2.2.令牌桶过滤器(TBF)
令牌桶过滤器(TBF)是一个简单的队列规定:
只允许以不超过事先设定的速率到
来的数据包通过,但可能允许短暂突发流量朝过设定值.
TBF很精确,对于网络和处理器的影响都很小.所以如果您想对一个网卡限速,
它应该成为您的第一选择!
TBF的实现在于一个缓冲器(桶),不断地被一些叫做"
令牌"
的虚拟数据以特定
速率填充着.(tokenrate).桶最重要的参数就是它的大小,也就是它能够存储
令牌的数量.
每个到来的令牌从数据队列中收集一个数据包,然后从桶中被删除.这个算法关
联到两个流上——令牌流和数据流,于是我们得到3种情景:
数据流以等于令牌流的速率到达TBF.这种情况下,每个到来的数据包都
能对应一个令牌,然后无延迟地通过队列.
数据流以小于令牌流的速度到达TBF.通过队列的数据包只消耗了一部分
令牌,剩下的令牌会在桶里积累下来,直到桶被装满.剩下的令牌可以在
需要以高于令牌流速率发送数据流的时候消耗掉,这种情况下会发生突发
传输.
数据流以大于令牌流的速率到达TBF.这意味着桶里的令牌很快就会被耗
尽.导致TBF中断一段时间,称为"
越限"
.如果数据包持续到来,将发
生丢包.
最后一种情景非常重要,因为它可以用来对数据通过过滤器的速率进行整形.
令牌的积累可以导致越限的数据进行短时间的突发传输而不必丢包,但是持续越
限的话会导致传输延迟直至丢包.
请注意,实际的实现是针对数据的字节数进行的,而不是针对数据包进行的.
9.2.2.1.参数与使用
即使如此,你还是可能需要进行修改,TBF提供了一些可调控的参数.第一个参
数永远可用:
limit/latency
limit确定最多有多少数据(字节数)在队列中等待可用令牌.你也可以
通过设置latency参数来指定这个参数,latency参数确定了一个包在TBF
中等待传输的最长等待时间.后者计算决定桶的大小,速率和峰值速率.
39
burst/buffer/maxburst
桶的大小,以字节计.这个参数指定了最多可以有多少个令牌能够即刻被
使用.通常,管理的带宽越大,需要的缓冲器就越大.在Intel体系上,
10兆bit/s的速率需要至少10k字节的缓冲区才能达到期望的速率.
如果你的缓冲区太小,就会导致到达的令牌没有地方放(桶满了),这会
导致潜在的丢包.
mpu
一个零长度的包并不是不耗费带宽.比如以太网,数据帧不会小于64字
节.Mpu(MinimumPacketUnit,最小分组单位)决定了令牌的最低消耗.
rate
速度操纵杆.参见上面的limits!
如果桶里存在令牌而且允许没有令牌,相当于不限制速率(缺省情况).Ifthe
bucketcontainstokensandisallowedtoempty,bydefaultitdoessoatinfinitespeed.
如果不希望这样,可以调整入下参数:
peakrate
如果有可用的令牌,数据包一旦到来就会立刻被发送出去,就象光速一样.
那可能并不是你希望的,特别是你有一个比较大的桶的时候.
峰值速率可以用来指定令牌以多块的速度被删除.用书面语言来说,就是:
释放一个数据包,但后等待足够的时间后再释放下一个.我们通过计算等
待时间来控制峰值速率
然而,由于UNIX定时器的分辨率是10毫秒,如果平均包长10kbit,我
们的峰值速率被限制在了1Mbps.
mtu/minburst
但是如果你的常规速率比较高,1Mbps的峰值速率对我们就没有什么价
值.要实现更高的峰值速率,可以在一个时钟周期内发送多个数据包.最
有效的办法就是:
再创建一个令牌桶!
这第二个令牌桶缺省情况下为一个单个的数据包,并非一个真正的桶.
要计算峰值速率,用mtu乘以100就行了.(应该说是乘以HZ数,Intel
体系上是100,Alpha体系上是1024)
9.2.2.2.配置范例
这是一个非常简单而实用的例子:
#tcqdiscadddevppp0roottbfrate220kbitlatency50msburst1540
为什么它很实用呢?
如果你有一个队列较长的网络设备,比如DSLmodem或者
cablemodem什么的,并通过一个快速设备(如以太网卡)与之相连,你会发现上
40
载数据绝对会破坏交互性.
这是因为上载数据会充满modem的队列,而这个队列为了改善上载数据的吞吐
量而设置的特别大.但这并不是你需要的,你可能为了提高交互性而需要一个不
太大的队列.也就是说你希望在发送数据的时候干点别的事情.
上面的一行命令并非直接影响了modem中的队列,而是通过控制Linux中的队
列而放慢了发送数据的速度.
把220kbit修改为你实际的上载速度再减去几个百分点.如果你的modem确实很
快,就把"
burst"
值提高一点.
9.2.3.随机公平队列(SFQ)
SFQ(StochasticFairnessQueueing,随机公平队列)是公平队列算法家族中的一个
简单实现.它的精确性不如其它的方法,但是它在实现高度公平的同时,需要的
计算量却很少.
SFQ的关键词是"
会话"
(或称作"
流"
),主要针对一个TCP会话或者UDP
流.流量被分成相当多数量的FIFO队列中,每个队列对应一个会话.数据按照
简单轮转的方式发送,每个会话都按顺序得到发送机会.
这种方式非常公平,保证了每一个会话都不会没其它会话所淹没.SFQ之所以被
称为"
随机"
是因为它并不是真的为每一个会话创建一个队列,而是使用一个
散列算法,把所有的会话映射到有限的几个队列中去.
因为使用了散列,所以可能多个会话分配在同一个队列里,从而需要共享发包的
机会,也就是共享带宽.为了不让这种效应太明显,SFQ会频繁地改变散列算法,
以便把这种效应控制在几秒钟之内.
有很重要的一点需要声明:
只有当你的出口网卡确实已经挤满了的时候,SFQ才
会起作用!
否则在你的Linux机器中根本就不会有队列,SFQ也就不会起作用.
稍后我们会描述如何把SFQ与其它的队列规定结合在一起,以保证两种情况下
都比较好的结果.
特别地,在你使用DSLmodem或者cablemodem的以太网卡上设置SFQ而不进
行任何进一步地流量整形是无谋的!
9.2.3.1.参数与使用
SFQ基本上不需要手工调整:
perturb
多少秒后重新配置一次散列算法.如果取消设置,散列算法将永远不会重
新配置(不建议这样做).10秒应该是一个合适的值.
quantum
41
一个流至少要传输多少字节后才切换到下一个队列.却省设置为一个最大
包的长度(MTU的大小).不要设置这个数值低于MTU!
9.2.3.2.配置范例
如果你有一个网卡,它的链路速度与实际可用速率一致——比如一个电话
MODEM——如下配置可以提高公平性:
#tcqdiscadddevppp0rootsfqperturb10
#tc-s-dqdiscls
qdiscsfq800c:
devppp0quantum1514blimit128pflows128/1024perturb10sec
Sent4812bytes62pkts(dropped0,overlimits0)
"
800c:
这个号码是系统自动分配的一个句柄号,"
limit"
意思是这个队列中可
以有128个数据包排队等待.一共可以有1024个散列目标可以用于速率审计,
而其中128个可以同时激活.(nomorepacketsfitinthequeue!
)每隔10秒种散列
算法更换一次.
9.3.关于什么时候用哪种队列的建议
总之,我们有几种简单的队列,分别使用排序,限速和丢包等手段来进行流量整
下列提示可以帮你决定使用哪一种队列.涉及到了第14章所描述的的一些队列
规定:
如果想单纯地降低出口速率,使用令牌桶过滤器.调整桶的配置后可用于
控制很高的带宽.
如果你的链路已经塞满了,而你想保证不会有某一个会话独占出口带宽,
使用随机公平队列.
如果你有一个很大的骨干带宽,并且了解了相关技术后,可以考虑前向随
机丢包(参见"
高级"
那一章).
如果希望对入口流量进行"
整形"
(不是转发流量),可使用入口流量策略,
注意,这不是真正的"
.
如果你正在转发数据包,在数据流出的网卡上应用TBF.除非你希望让数
据包从多个网卡流出,也就是说入口网卡起决定性作用的时候,还是使用
入口策略.
如果你并不希望进行流量整形,只是想看看你的网卡是否有比较高的负载
而需要使用队列,使用pfifo队列(不是pfifo_fast).它缺乏内部频道但是
可以统计backlog.
最后,你可以进行所谓的"
社交整形"
.你不能通过技术手段解决一切问
题.用户的经验技巧永远是不友善的.正确而友好的措辞可能帮助你的正
确地分配带宽!
42
9.4.术语
为了正确地理解更多的复杂配置,有必要先解释一些概念.由于这个主题的历史
不长和其本身的复杂性,人们经常在说同一件事的时候使用各种词汇.
以下来自draft-ietf-diffserv-model-06.txt,Diffserv路由器的建议管理模型.可以
在以下地址找到:
http:
//www.ietf.org/internet-drafts/draft-ietf-diffserv-model-06.txt.
关于这些词语的严格定义请参考这个文档.
队列规定
管理设备输入(ingress)或输出(egress)的一个算法.
无类的队列规定
一个内部不包含可配置子类的队列规定.
分类的队列规定
一个分类的队列规定内可一包含更多的类.其中每个类又进一步地包含一
个队列规定,这个队列规定可以是分类的,也可以是无类的.根据这个定
义,严格地说pfifo_fast算是分类的,因为它实际上包含3个频道(实际上
可以认为是子类).然而从用户的角度来看它是无类的,因为其内部的子
类无法用tc工具进行配置.
类
一个分类的队列规定可以拥有很多类,类内包含队列规定.
分类器
每个分类的队列规定都需要决定什么样的包使用什么类进行发送.分类器
就是做这个用的.
过滤器
分类是通过过滤器完成的.一个过滤器包含若干的匹配条件,如果符合匹
配条件,就按此过滤器分类.
调度
在分类器的帮助下,一个队列规定可以裁定某些数据包可以排在其他数据
包之前发送.这种处理叫做"
调度"
比如此前提到的pfifo_fast就是这样
的.调度也可以叫做"
重排序"
但这样容易混乱.
整形
在一个数据包发送之前进行适当的延迟,以免超过事先规定好的最大速
率,这种处理叫做"
.整形在egress处进行.习惯上,通过丢包来
降速也经常被称为整形.
43
|队列规定/__队列规定4__/|
|/-队列规定N_/|
||
+------------------------------------------------------------+
感谢JamalHadiSalim制作的ASCII字符图像.
整个大方框表示内核.最左面的箭头表示从网络上进入机器的数据包.它们进入
Ingress队列规定,并有可能被某些过滤器丢弃.即所谓策略.
这些是很早就发生的(在进入内核更深的部分之前).这样早地丢弃数据有利于
节省CPU时间.
数据包顺利通过的话,如果它是发往本地进程的,就会进入IP协议栈处理并提
交给该进程.如果它需要转发而不是进入本地进程,就会发往egress.本地进程
也可以发送数据,交给Egress分类器.
然后经过审查,并放入若干队列规定中的一个进行排队.这个过程叫做"
入队"
在不进行任何配置的情况下,只有一个egress队列规定——pfifo_fast——总是接
收数据包.
数据包进入队列后,就等待内核处理并通过某网卡发送.这个过程叫做"
出队"
44
这张图仅仅表示了机器上只有一块网卡的情况,图中的箭头不能代表所有情况.
每块网卡都有它自己的ingress和egress.
9.5.分类的队列规定
如果你有多种数据流需要进行区别对待,分类的队列规定就非常有用了.众多分
类的队列规定中的一种——CBQ(ClassBasedQueueing,基于类的队列)——经常
被提起,以至于造成大家认为CBQ就是鉴别队列是否分类的标准,这是不对的.
CBQ不过是家族中最大的孩子而已,同时也是最复杂的.它并不能为你做所有
的事情.对于某些人而言这有些不可思议,因为他们受"
sendmail效应"
影响较
深,总是认为只要是复杂的并且没有文档的技术肯定是最好的.
9.5.1.分类的队列规定及其类中的数据流向
一旦数据包进入一个分类的队列规定,它就得被送到某一个类中——也就是需要
分类.对数据包进行分类的工具是过滤器.一定要记住:
分类器"
是从队列规
定内部调用的,而不是从别处.
过滤器会返回一个决定,队列规定就根据这个决定把数据包送入相应的类进行排
队.每个子类都可以再次使用它们的过滤器进行进一步的分类.直到不需要进一
步分类时,数据包才进入该类包含的队列规定排队.
除了能够包含其它队列规定之外,绝大多数分类的队列规定黑能够流量整形.这
对于需要同时进行调度(如使用SFQ)和流量控制的场合非常有用.如果你用一个
高速网卡(比如以太网卡)连接一个低速设备(比如cablemodem或者ADSLmodem)
时,也可以应用.
如果你仅仅使用SFQ,那什么用也没有.因为数据包进,出路由器时没有任何延
迟.虽然你的输出网卡远远快于实际连接速率,但路由器中却没有队列可以调度.
9.5.2.队列规定家族:
根,句柄,兄弟和父辈
每块网卡都有一个出口"
根队列规定"
缺省情况下是前面提到的pfifo_fast队列
规定.每个队列规定都指定一个句柄,以便以后的配置语句能够引用这个队列规
定.除了出口队列规定之外,每块网卡还有一个入口,以便policies进入的数据流.
队列规定的句柄有两个部分:
一个主号码和一个次号码.习惯上把根队列规定称
为"
1:
等价于"
0"
.队列规定的次号码永远是0.
类的主号码必须与它们父辈的主号码一致.
9.5.2.1.如何用过滤器进行分类
下图给出一个典型的分层关系:
45
12:
2
也就是说,根所附带的一个过滤器要求把数据包直接交给12:
2.
9.5.2.2.数据包如何出队并交给硬件
当内核决定把一个数据包发给网卡的时候,根队列规定1:
会得到一个出队请求,
然后把它传给1:
1,然后依次传给10:
11:
和12:
whicheachquerytheirsiblings,
然后试图从它们中进行dequeue()操作.也就是说,内和需要遍历整颗树,因为
只有12:
2中才有这个数据包.
换句话说,类及其兄弟仅仅与其"
父队列规定"
进行交谈,而不会与网卡进行交
谈.只有根队列规定才能由内核进行出队操作!
更进一步,任何类的出队操作都不会比它们的父类更快.这恰恰是你所需要的:
我们可以把SFQ作为一个子类,放到一个可以进行流量整形的父类中,从而能
够同时得到SFQ的调度功能和其父类的流量整形功能.
9.5.3.PRIO队列规定
PRIO队列规定并不进行整形,它仅仅根据你配置的过滤器把流量进一步细分.
你可以认为PRIO队列规定是pfifo_fast的一种衍生物,区别在每个频道都是一
个单独的类,而非简单的FIFO.
当数据包进入PRIO队列规定后,将根据你给定的过滤器设置选择一个类.缺省
情况下有三个类,这些类仅包含纯FIFO队列规定而没有更多的内部结构.你可
以把它们替换成你需要的任何队列规定.
每当有一个数据包需要出队时,首先处理:
1类.只有当标号更小的类中没有需要
处理的包时,才会标号大的类.
46
当你希望不仅仅依靠包的TOS,而是想使用tc所提供的更强大的功能来进行数
据包的优先权划分时,可以使用这个队列规定.它也可以包含更多的队列规定,
而pfifo_fast却只能包含简单的fifo队列规定.
因为它不进行整形,所以使用时与SFQ有相同的考虑:
要么确保这个网卡的带
宽确实已经占满,要么把它包含在一个能够整形的分类的队列规定的内部.后者
几乎涵盖了所有cablemodems和DSL设备.
严格地说,PRIO队列规定是一种Work-Conserving调度.
9.5.3.1.PRIO的参数与使用
tc识别下列参数:
bands
创建频道的数目.每个频道实际上就是一个类.如果你修改了这个数值,
你必须同时修改:
priomap
如果你不给tc提供任何过滤器,PRIO队列规定将参考TC_PRIO的优先
级来决定如何给数据包入队.
它的行为就像前面提到过的pfifo_fast队列规定,关于细节参考前面章节.
频道是类,缺省情况下命名为主标号:
1到主标号:
3.如果你的PRIO队列规定是
把数据包过滤到12:
1将得到最高优先级.
注意:
0频道的次标号是1!
1频道的次标号是2,以此类推.
9.5.3.2.配置范例
我们想创建这个树:
root1:
prio
/|/
11:
21:
3
|||
10:
20:
30:
sfqtbfsfq
band012
大批量数据使用30:
交互数据使用20:
或10:
命令如下:
#tcqdiscadddeveth0roothandle1:
##这个命令立即创建了类:
1:
1,1:
2,1:
#tcqdiscadddeveth0parent1:
1handle10:
sfq
2handle20:
tbfrate20kbitbuffer1600limit3000
3handle30:
现在,我们看看结果如何:
47
#tc-sqdisclsdeveth0
qdiscsfq30:
quantum1514b
Sent0bytes0pkts(dropped0,ov