概述
备注:部分内容和图片来源于网络,侵删~
一、概念
TC (traffic control), linux基于ip的流量限制
二、原理
2.1 原理图
三、规则
3.1 流量控制方式
流量控制包括以下几种方式:
- SHAPING(限制): 当流量被限制,它的传输速率就被控制在某个值以下。限制值可以大大小于有效带宽,这样可以平滑突发数据流量,使网络更为稳定。shaping(限制)只适用于向外的流量。
- SCHEDULING(调度): 通过调度数据包的传输,可以在带宽范围内,按优先级分配带宽。SCHEDULING(调度)也只适于向外的流量。
- POLICING(策略):用于处理接收到的数据包。
- DROPPING(丢弃): 如果流量超过某个设定的带宽,就丢弃数据包,不管是向内还是向外。
3.2 流量控制处理对象
流量的处理由三种对象控制,它们是:
- qdisc(排队规则)
- class(类别)
- filter(过滤器)
2.2.1 qdisc(排队规则)
QDisc(排队规则)是queueing discipline的简写,它是理解流量控制(traffic control)的基础。无论何时,内核如果需要通过某个网络接口发送数据包,它都需要按照为这个接口配置的qdisc(排队规则)把数据包加入队列。然后,内核会尽可能多地从qdisc里面取出数据包,把它们交给网络适配器驱动模块。最简单的QDisc是pfifo它不对进入的数据包做任何的处理,数据包采用先入先出的方式通过队列。不过,它会保存网络接口一时无法处理的数据包。
qdisc的类别如下:
- CLASSLESS QDisc(无类QDisc)
-
- [p|b]fifo:
- 使用最简单的qdisc,纯粹的先进先出。只有一个参数:limit,用来设置队列的长度,pfifo是以数据包的个数为单位;bfifo是以字节数为单位。
- pfifo_fast:
- 在编译内核时,如果打开了高级路由器(Advanced Router)编译选项,pfifo_fast就是系统的标准QDISC。它的队列包括三个波段(band)。在每个波段里面,使用先进先出规则。而三个波段(band)的优先级也不相同,band 0的优先级最高,band 2的最低。如果band0里面有数据包,系统就不会处理band 1里面的数据包,band 1和band 2之间也是一样。数据包是按照服务类型(Type of Service,TOS)被分配多三个波段(band)里面的。
- red:
- red是Random Early Detection(随机早期探测)的简写。如果使用这种QDISC,当带宽的占用接近于规定的带宽时,系统会随机地丢弃一些数据包。它非常适合高带宽应用。
- sfq:
- sfq是Stochastic Fairness Queueing(随即公平队列)的简写。它按照会话(session--对应于每个TCP连接或者UDP流)为流量进行排序,然后循环发送每个会话的数据包。
- tbf:
- tbf是Token Bucket Filter(令牌桶过滤器)的简写,适合于把流速降低到某个值。
- 无类qdisc配置: 如果没有可分类QDisc,不可分类QDisc只能附属于设备的根。它们的用法如下:
tc qdisc add dev DEV root QDISC QDISC-PARAMETERS
要删除一个不可分类QDisc,需要使用如下命令:
tc qdisc del dev DEV root
一个网络接口上如果没有设置QDisc,pfifo_fast就作为缺省的QDisc。
- CLASSFUL QDISC(分类QDisc):
- 可分类的qdisc包括:
- CBQ: CBQ是Class Based Queueing(基于类别排队)的缩写。它实现了一个丰富的连接共享类别结构,既有限制(shaping)带宽的能力,也具有带宽优先级管理的能力。带宽限制是通过计算连接的空闲时间完成的。空闲时间的计算标准是数据包离队事件的频率和下层连接(数据链路层)的带宽。
- HTB: HTB是Hierarchy Token Bucket(分层令牌筒)的缩写。通过在实践基础上的改进,它实现了一个丰富的连接共享类别体系。使用HTB可以很容易地保证每个类别的带宽,它也允许特定的类可以突破带宽上限,占用别的类的带宽。HTB可以通过TBF(Token Bucket Filter)实现带宽限制,也能够划分类别的优先级。
- PRIO: PRIO QDisc不能限制带宽,因为属于不同类别的数据包是顺序离队的。使用PRIO QDisc可以很容易对流量进行优先级管理,只有属于高优先级类别的数据包全部发送完毕,才会发送属于低优先级类别的数据包。为了方便管理,需要使用iptables或者ipchains处理数据包的服务类型(Type Of Service,ToS)。
2.2.2 class(类)
某些QDisc(排队规则)可以包含一些类别,不同的类别中可以包含更深入的QDisc(排队规则),通过这些细分的QDisc还可以为进入的队列的数据包排队。通过设置各种类别数据包的离队次序,QDisc可以为设置网络数据流量的优先级。
2.2.3 filter(过滤器)
Filter(过滤器)用于为数据包分类,决定它们按照何种QDisc进入队列。无论何时数据包进入一个划分子类的类别中,都需要进行分类。分类的方法可以有多种,使用fileter(过滤器)就是其中之一。使用filter(过滤器)分类时,内核会调用附属于这个类(class)的所有过滤器,直到返回一个判决。如果没有判决返回,就作进一步的处理,而处理方式和QDISC有关。需要注意的是,filter(过滤器)是在QDisc内部,它们不能作为主体。
3.3 执行过程
类(Class)组成一个树,每个类都只有一个父类,而一个类可以有多个子类。某些QDisc(例如:CBQ和HTB)允许在运行时动态添加类,而其它的QDisc(例如:PRIO)不允许动态建立类。允许动态添加类的QDisc可以有零个或者多个子类,由它们为数据包排队。此外,每个类都有一个叶子QDisc,默认情况下,这个叶子QDisc使用pfifo的方式排队,我们也可以使用其它类型的QDisc代替这个默认的QDisc。而且,这个叶子QDisc有可以分类,不过每个子类只能有一个叶子QDisc。 当一个数据包进入一个分类QDisc,它会被归入某个子类。
我们可以使用以下三种方式为数据包归类,不过不是所有的QDisc都能够使用这三种方式:
- tc过滤器(tc filter): 如果过滤器附属于一个类,相关的指令就会对它们进行查询。过滤器能够匹配数据包头所有的域,也可以匹配由ipchains或者iptables做的标记。
- 服务类型(Type of Service): 某些QDisc有基于服务类型(Type of Service,ToS)的内置的规则为数据包分类。
- skb->priority: 用户空间的应用程序可以使用SO_PRIORITY选项在skb->priority域设置一个类的ID。
- 树的每个节点都可以有自己的过滤器,但是高层的过滤器也可以直接用于其子类。
- 如果数据包没有被成功归类,就会被排到这个类的叶子QDisc的队中。相关细节在各个QDisc的手册页中。
3.4 命名规则
所有的QDisc、类和过滤器都有ID。ID可以手工设置,也可以有内核自动分配。ID由一个主序列号和一个从序列号组成,两个数字用一个冒号分开。
- QDISC:
一个QDisc会被分配一个主序列号,叫做句柄(handle),然后把从序列号作为类的命名空间。句柄采 用象10:一样的表达方式。习惯上,需要为有子类的QDisc显式地分配一个句柄。
- class:
在同一个QDisc里面的类分享这个QDisc的主序列号,但是每个类都有自己的从序列号,叫做类识别 符(classid)。类识别符只与父QDisc有关,和父类无关。类的命名习惯和QDisc的相同。
- filter:
过滤器的ID有三部分,只有在对过滤器进行散列组织才会用到。详情请参考tc-filters手册页。
3.5 单位
A、区别
1、带宽:比特/秒(bps):100M=100Mbps;
2、网速:字节/秒(B/s KB/s MB/s , 1MB/s=1024KB/s ;1KB/s=1024B/s。
3、流量:字节(Byte);
比特是信息的最小单位:1字节=8比特(1B=8bit或者1B=8b);1字节/秒=8比特/秒(1B/s=8bps)
B、如何换算
我们这里来用实例看下:比如200M宽带下载速度是多少?
首先,运营商所说的200M宽带光纤,完整单位是200Mbps,而我们电脑中所说的下载速度单位是:MB。因此200M宽带下载速度并不代表下载速度就是200Mb/s,而是需要按照如下公式进行换算:
1Mbps=1024Kbps=1024/8KBps=128KB/s
也就是说 1M 的宽带下载速度不会超过 128KB/s ,也就是理论上1秒钟,可以下载128K的内容,实际上1M宽带,下载速度100k/s就属于正常,毕竟理论值不一定能达到。
200M宽带的下载速度理论上为:128KB/s x 200 = 25600 KB/s = 25.6MB/s
正常的下载速度是:25M;当然,这是理论上的下载速度,在实际使用的过程中,可能会略低于/高于25M,一般来说上下浮动1M都属于正常的,即24-26都属于正常的。
如果你家网速测试小于25M太多的话,要么是连的假200M带宽,要么就是其它的路由器、光猫没有使用千兆的。
三、参数
tc可以使用以下命令对QDisc、类和过滤器进行操作:
- add:
- 在一个节点里加入一个QDisc、类或者过滤器。添加时,需要传递一个祖先作为参数,传递参数时既可以使用ID也可以直接传递设备的根。如果要建立一个QDisc或者过滤器,可以使用句柄(handle)来命名;如果要建立一个类,可以使用类识别符(classid)来命名。
- remove:
- 删除有某个句柄(handle)指定的QDisc,根QDisc(root)也可以删除。被删除QDisc上的所有子类以及附属于各个类的过滤器都会被自动删除。
- change:
- 以替代的方式修改某些条目。除了句柄(handle)和祖先不能修改以外,change命令的语法和add命令相同。换句话说,change命令不能移动节点的位置。
- replace:
- 对一个现有节点进行近于原子操作的删除/添加。如果节点不存在,这个命令就会建立节点。
- link:
- 只适用于DQisc,替代一个现有的节点。
四、应用
Linux流量控制主要分为建立队列、建立分类和建立过滤器三个方面。
4.1 步骤:
- 针对网络物理设备(如以太网卡eth0)绑定一个队列QDisc;
- 在该队列上建立分类class;
- 为每一分类建立一个基于路由的过滤器filter;
- 最后与过滤器相配合,建立特定的路由表。
4.2 应用:
参见网页https://cloud.tencent.com/developer/article/1409664
https://www.zhihu.com/question/21053403 【看应用部分】
常用关键字汇总:
avpkt 1000 包平均大小为1000字节
cell 8 包间隔发送单元的大小为8字节
mpu 64 最小传输包的大小为64字节
rate 10Mbit 带宽大小,所有子类的和必须小于父类
ceil 10Mbit 最大能得到的带宽值为10Mbit
[sfq] perturb 10 10s后重新配置一次散列算法
bandwitch 10Mbit 物理网口设备接口的实际带宽
maxburst 20 可接收冲突的发送最长包数目为20
allot 1514 最大传输单元加MAC头的大小为1514字节
weight 1Mbit 相应于实际带宽的加权速率为1Mbit
split 1:0 分类分离点
bounded 不可借用未使用的带宽
flowid 1:10 流向的子类
burst 15k 令牌桶大小
handle 为队列命名或指定某队列
realm 4 归为过滤器4
rate和bandwidth的区别
fw classid 10:3和flowid 10:3
default 1
r2q 1:在规则中的作用是用来分配剩余带宽的全局变量,它的默认值为10,此时最实用的规则的速度为15KBps(120kbit)。
quantum与r2q的关系为quantum=rate/r2q,quantum的值必须在1500到60000之间,值越小越好
每个规则的quantum的值就是从父类借用带宽的因子(也就是每个子类每次可以从父类借用空闲带宽的大小)也可以说是与其他子类同时从父类借带宽的比例。
TC命令参数
一个CBQ qdisc类的根有如下参数:
parent major:minor | root
这个命令的参数决定这个CBQ实例所在的位置,或者是在一个网络接口的根(root),或者位于一个现有的类里面。
handle major:
和其他的qdisc一样,CBQ qdisc也可以指定一个句柄。句柄只能包含主识别号(major number)和一个冒号。数字的选择是随意的,不过如果在这个qdisc里面会继续分类,这个数字非常有用。
allot bytes
这个参数用于分配的带宽,决定数据包传输的时间表。qdisc的allot参数和类的allot参数略有不同。数字bytes是任意的。缺省是一个根据avpkt得到的数字。
avpkt bytes
数据包的平均大小,它用于计算最大空闲时间(maxidle),也用于确认allot参数的值是安全的。
bandwidth rate
为了决定空闲时间(idle time),CBQ必须知道底层物理接口的带宽,或者父qdisc的带宽。这是一个极为重要的参数。
cell time
time的值决定进行数据包传输时间计算的时间间隔。使用缺省值是比较明智的。
mpu bytes
一个大小为0的数据包仍然会消耗时间来传输。用这个参数设置小于bytes个字节的数据包在进行传输时间的计算忽略不计,缺省值是0。
ewma log
在CBQ需要测量平均空闲使劲啊,它会使用加权指数移动平均算法来平滑测量的值,得到一个移动平均值。log决定平滑印子的大小。这个数值介于0到31之间,数字越小敏感度越大。默认值是5。
一个CBQ qdisc只需要知道底层连接的大小,实际的带宽限制由其子类完成。
CLASS的参数:
parent major:minor
确定父qidsc的位置,把这个类加入到树状结构中。如果它是直接附属于一个qdisc,而且这个qdisc没有其他的类,minor可以被忽略。
classid major:minor
和qdisc一样,类也可以命名。主识别号(major number)必须等于其父qdisc的主识别号。这个参数是可选的,只有它还需要细分才需要。
weight weight
在从队列中取出数据包通过网络接口向外发送时,CBQ会采用轮转的方式轮流从队列中取出属于不同分类的数据包。weight设置每个类的权重。权重越高,在每个循环CBQ取出的数据包也就越多。一个类中所有的权重都会被换算成与rate参数设定值的百分比。
allot bytes
这个参数设置每个循环可以有多少个字节出队。这个值最小为avpkt的2/3。这个参数是必须的。
avpkt bytes
rate rate
设置这个类可以达到的最大速率,以及所有子类速率总和可以达到的值。这个参数是必须的。
bandwidth rate
这个参数不同于建立CBQ时的bandwidth参数。只有在决定maxidle和offtime时才有用,在设置maxburst或者minburst时,CBQ会使用maxidle和offtime进行计算。如果需要设置最大突发(maxburst)或者最小突发(minburst),这个参数是必须的。
maxburst
这个参数设置的数字用于计算maxidle,以便avgidle的值等于maxidle时,在avgidle达到0之前,允许设定的数据包突发性地通过。这个数字越大,对于突发流量的适应性越好。你不能直接设置maxidle,只能通过这个参数来设置。
minburst
在限制溢出(overlimit)情况下,CBQ需要调低带宽。为了避免这种情况的出现,比较理想的解决方案是精确地空闲某个时间,然后放行一 个数据包。然而,对于UNIX内核来说,很难对时间间隔小于10ms的时间进行调度,因此只好把等待时间放长,接着突发性地放行多个数据包。等待时间叫做offtime。minburst的值越高,在一个较长时间内进行的带宽限制越准确,但是也会导致更大的突发流量。可选参数。
minidle
如果avgidle小于0,需要等待avgidle增加到一个足够大的值才能发送一个数据包。为了避免在一个长期处于关闭状态下的连接出现突发流 量,如果avgidle太低就会被复位为minidle参数设置的数值minidle的单位是负微秒,10表示avgidle不能低于-10微秒。可选参数。
bounded
这个类的带宽不外借。
isolated
这个累的带宽不愿意外借。
split major:minor & defmap bitmap[/bitmap]
如果附属于这个类的过滤器不能判断数据包所属类别,CBQ也可以根据数据包的优先级为它们分类。优先级共有8个,范围是0到7。defmap设置这个类接受具备哪些优先级的数据包,接受的优先级使用bitmap来计算,CBQ用bitmap和数据包的优先级域进行and运算。最低有效位(least significant bit)对应优先级0。split告诉CBQ需要做出决定的类,参数应该是其父类。
BUGS
底层链路的带宽可能是无法预知的。CBQ对于主要的带宽配置错误有很大的弹性,代价可能就是带宽固定(shaping)精度降低。 默认情况下,内核依靠粗糙的计时信息进行带宽固定。在一个较长的时间段内,可以维持很好的精度,但是在以秒为单位进行计量的时间段内,其结果就不准确了。
五、参考
tc命令man原理【看tc命令参数部分】
最后
以上就是无情世界为你收集整理的tc流量控制原理和实现的全部内容,希望文章能够帮你解决tc流量控制原理和实现所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复