一:综述:

linux系统中的流量控制器(TC)主要是在输出端口处建立一个队列进行流量控制。

TC是一个可以根据数据包的任何一个部分的特征对其进行分类的工具,并且可以为各类数据提供不同带宽,从而控制他们的传输速度。TC是iproute2的一部分,集成在2.2.及以上版本的内核中,还可以与linux内核里的各种架构(如Netfilter netem)协同工作。


二:TC的组件

TC主要由队列规定(qdisc),类(class)和过滤器(filter)这3个组件组成,绘图中一般用圆形表示队列规定,用矩形表示类:

Linux 下TC 以及netem队列的使用_netem队列


1:qdisc:TC的核心组件,也被称为队列,是管理网卡输入,输出数据的一个算法,用于确定数据包的发送方式。

队列规定可分为两类:

(1) 不分类的qdisc:内部不包含可配置的子类,对进入队列的数据包不进行区分对待,而只是对数据包进行重新编排,延迟发送或者丢弃,主要有:pfifo-fast.TBF.SFQ等

(2) 分类队列规定:内部可包含一个或多个子类,使用过滤器对数据包进行分类,然后交给相应的子类处理,分类队列规定有CBQ,HTB等


2:类:

就是数据的类别,各种数据通过过滤器进行分类,最后被放入类的队列规定里面进行排队。

如果一个类没有子类,那么这个类被称为叶子类,否则就被成为内部类。1:1和1:12是内部类,其他均为叶子类,叶子类有一个负责为这个类发送数据的队列规定,而且这个qdisc可以是分类的,如1:10有一个分类的队列规定。TC中通常把类的队列规定称为叶子qdisc(只有叶子类才有队列规定)


3:过滤器

就是一些规则,根据这些规则对数据包进行分类,过滤器可以属于队列规定,也可以属于内部类,若需要在叶子类上再实现分类,那就必须将过滤器与叶子类的分类队列规定关联起来,而不能与叶子类相关联。

最常用的是U32过滤器,由一个过滤器和一个动作组成,选择器用来对数据包进行匹配,一旦匹配成功就执行该动作。


三:TC的结构

都是以一个根qdisc开始的,若根qdisc是不分类的队列规定,那它就没有子类,因此不可能包含其他的子对象,也不会有过滤器与之关联,发送数据时,数据包进入这个队列里面排队,然后根据该队列规定的处理方式将数据包发送出去。

分类的qdisc内部包含一个或多个类,而每个类可以包含一个队列规定或者包含若干个子类,这些子类友可以包含分类或者不分类的队列规定,如此递归,形成了一个树。


句柄号:qdisc和类都使用一个句柄进行标识,且在一棵树中必须是唯一的,每个句柄由主号码和次号码组成qdisc的次号码必须为0(0通常可以省略不写)

根qdisc的句柄为1:,也就是1:0。类的句柄的主号码与它的父辈相同(父类或者父qdisc),如类1:1的主号码与包含他的队列规定1:的主号码相同,1:10和1:11与他们的父类1:1的主号码相同,也为1。

新建一个类时,默认带有一个pfifo_fast类型的不分类队列规定,当添加一个子类时,这个类型的qdisc就会被删除,所以,非叶子类是没有队列规定的,数据包最后只能到叶子类的队列规定里面排队。

若一个类有子类,那么允许这些子类竞争父类的带宽,但是,以队列规定为父辈的类之间是不允许相互竞争带宽的。


四:TC的工作原理:

对互联网而言,一切都是数据包,操控网络实际上是在操控数据包,操控它如何产生,路由,传输,分片等等。TC在数据包离开系统的时候进行控制,在IP层与网卡之间做手脚,实际上,负责将数据包传递到物理层的正是TC模块,这意味着在系统内核中,TC作为数据包的调度者是一直运作的,甚至在你不想用他的时候,一般情况下,TC维持 一个先进先出的数据队列。

数据包入队的时候首先调用根队列规定的过滤器,根据过滤器定义的规则将数据包交给某个类,如果该类不是叶子类,将会调用该类定义的过滤器进一步分类,若该类没有定义过滤器,就会交给包含他的队列规定的默认类来处理,若接收到数据包的类是叶子类,数据包将进入到叶子类的队列规定里面排队,需要注意的是:过滤器只能将数据包交给某个类,类再将数据包放入自己的队列规定进行排队,而不能直接交给某个队列规定。

接受包从数据接口进来后,经过流量限制,丢弃不合规定的数据包,然后输入多路分配器判断:若接受包的目的地是本主机,那么将该包送给上册处理,否则需转发,将接受包交到转发块处理。转发块同时也接收本主机上层产生的包。转发块通过查看路由表,决定所处理包的下一跳,然后对包排序以便将他们传送到输出接口。

Linux的TC主要是在输出接口排列时进行处理和实现的。




五:TC命令


1:add命令:在一个节点里加入一个qdisc,类或者过滤器。添加时,需要传递一个祖先作为参数,传递参数时既可以使用ID也可以直接传递设备的根,若建一个qdisc或者filter,可以使用句柄来命名,若建一个类,使用类识别符来命名。


2:remove:删除由某个句柄指定的qdisc,根qdisc也可以被删除,被删除的qdisc上的所有子类以及附属于各个类的过滤器都会被自动删除。


3:change:以替代方式修改某些项目,句柄和祖先不能修改,change和add语法相同。


4:replace:对一个现有节点进行近于原子操作的删除/添加,如果节点不存在,这个命令就会建立节点。


5:link:只适用于qdisc,替代一个现有的节点



tc qdisc [add|change|replace|link] dev DEV [parent qdisc-id |root] [handle qdisc-id ] qdisc [qdisc specific parameters]


tc class [add|change|replace] dev DEV parent qdisc-id [classid class-id] qdisc [qdisc specific parameters]


tc filter [add|change|replace] dev DEV [parent qdisc-id|root] protocol Protocol prio Priority filtertype [filtertype specific parameters] flowid flow-id


tc [-s|-d] qdisc show [dev DEV]


tc [-s|-d] class show dev DEV


tc filter show dev DEV


六:TBF队列:(令牌桶队列)


tc qdisc add tbf limit BYTES burst BYTES rate KBPS [mtu BYTES] [peakrate KBPS] [latency TIME] [overhead BYTES] [linklayer TYPE]

rate是第一个令牌桶的填充速率

peakrate是第二个令牌桶的填充速率

peakrate>rate


burst是第一个令牌桶的大小

mtu是第二个令牌桶的大小

burst>mtu


若令牌桶中令牌不够,数据包就需要等待一定时间,这个时间由latency参数控制,如果等待时间超过latency,那么这个包就会被丢弃


limit参数是设置最多允许多少数据可以在队列中等待

latency=max((limit-burst)/rate,(limit-mtu)/peakrate);

 

burst应该大于mtu和rate


overhead表示ADSL网络对数据包的封装开销

linklayer指定了链路的类型,可以是以太网或者ATM或ADSL

ATM和ADSL报头开销均为5个字节。



七:netem模块

netem提供网络方针的功能,可以方针广域网的可变时延,丢包,数据包副本和重排序等性质。

netem被包含在内核中的iproute2中,netem模块被TC控制调用。

netem包含两部分:

(1) qdisc的内核模块:被整合到内核中

(2) 配置该模块的命令行功能:iproute2的一部分

两者通过netlink套接字练习,命令行将其请求编成一种格式,而内核进行解码。



1:模拟时延:

例:#tc qdisc add dev eth0 root netem delay 100ms

所有经过eth设备输出的数据包均延迟100ms


#tc qdisc change dev eth0 root netem delay 100ms 10ms

表示延迟具有随机性,延时范围是100+_10ms


#tc qdisc change dev eth0 root netem delay 100ms 10ms 25%

表示延时范围是:100+_10ms*25%


2:延时的分布:

在实际网络中,延时并不是均匀分布的,更像正态分布


#tc qdisc change dev eth0 root netem delay 100ms 20ms distribution normal


注意:分配(如normal,pareto,paretonormal)是iproute2编译出放在/usr/lib/tc下的,所以可以编译出自己的分布


3:丢包


可设置的最小丢包率为 232=0.000 000 0232%


#tc qdisc change dev eth0 root netem loss 0.1%

表示0.1%的随机性丢包


#tc qdisc change dev eth0 root netem loss 0.3% 25%

引起0.3%的丢包率

25%指的是相关性,相关性可以用来模拟突发造成的丢包


4:数据包副本

#tc qdisc change dev eth0 root netem duplicate 1%



5:数据包冲突错误:

实际网络中的随即噪声会导致包出错,可以用corrupt option模块模拟


#tc qdisc change dev eth0 root netem corrupt 0.1%

会引起0.1%的出错


6:数据包重排序


#tc qdisc change dev eth0 root netem gap 5 delay 10ms

只有5的倍数的数据包不被延迟,其他均延迟10ms



#tc qdisc change dev eth0 root netem delay 10ms recorder 25% 50%


25%的数据包被立即发送,其他包被延迟10ms

这里50%指的是25%的数据包具有的相关性

另外随机延迟的不同也会导致重排序



在构造丢包时,线性相关系数用来设定丢包的分布情况,若为0,表示丢包随机:从0-1,表示丢包的分布趋于集中。比如设定丢包率为10%,线性相关系数为1,则表示每100个数据包丢10个,但是这十个包非常集中(有可能20个连续包就丢了10个),需要特别说明的是,实际的丢包效果绝不是一个精确的数字,更多的是一个统计数。