我是靠谱客的博主 无情世界,最近开发中收集的这篇文章主要介绍tc流量控制原理和实现,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

备注:部分内容和图片来源于网络,侵删~

一、概念

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流量控制原理和实现所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部