tc(traffic controll)用于在Linux内核中配置流量控制,流量控制包括以下内容:SHAPING/整形:当流量被整形时,其传输速率受到控制。整形可能不仅仅是降低可用带宽,它还用于平滑流量中的突发,以获得更好的网络行为。整形发生在出口处。SCHEDULING/调度:通过调度数据包的传输,可以提高需要它的流量的交互性,同时仍然保证批量传输的带宽。重新排序也称为优先级排序,仅在出口时发生。POLICING/策略:整形涉及流量的传输,而策略涉及流量的到达。因此,进入时会进行策略。DROPPING/丢弃:超过设定带宽的流量也可能在入口和出口立即丢弃。tc [ OPTIONS ] qdisc [ add | change | replace | link | delete ] dev DEV [ parent qdisc-id | root ] [ handle qdisc-id ] [ ingress_block BLOCK_INDEX ] [ egress_block BLOCK_INDEX ] qdisc [ qdisc specific parameters ]
tc [ OPTIONS ] class [ add | change | replace | delete ] dev DEV parent qdisc-id [ classid class-id ] qdisc [ qdisc specific parameters ]
tc [ OPTIONS ] filter [ add | change | replace | delete | get ] dev DEV [ parent qdisc-id | root ] [ handle filter-id ] protocol protocol prio priority filtertype [ filtertype specific parameters ] flowid flow-id
tc [ OPTIONS ] filter [ add | change | replace | delete | get ] block BLOCK_INDEX [ handle filter-id ] protocol protocol prio priority filtertype [ filtertype specific parameters ] flowid flow-id
tc [ OPTIONS ] chain [ add | delete | get ] dev DEV [ parent qdisc-id | root ] filtertype [ filtertype specific parameters ]
tc [ OPTIONS ] chain [ add | delete | get ] block BLOCK_INDEX filtertype [ filtertype specific parameters ]
tc [ OPTIONS ] [ FORMAT ] qdisc { show | list } [ dev DEV ] [ root | ingress | handle QHANDLE | parent CLASSID ] [ invisible ]
tc [ OPTIONS ] [ FORMAT ] class show dev DEV
tc [ OPTIONS ] filter show dev DEV
tc [ OPTIONS ] filter show block BLOCK_INDEX
tc [ OPTIONS ] chain show dev DEV
tc [ OPTIONS ] chain show block BLOCK_INDEX
tc [ OPTIONS ] monitor [ file FILENAME ]
OPTIONS := { [ -force ] -b[atch] [ filename ] | [ -n[etns] name ] | [ -N[umeric] ] | [ -nm | -nam[es] ] | [ { -cf | -c[onf] } [ filename ] ] [ -t[imestamp] ] | [ -t[short] | [ -o[neline] ] }
FORMAT := { -s[tatistics] | -d[etails] | -r[aw] | -i[ec] | -g[raph] | -j[json] | -p[retty] | -col[or] }
流量的处理由三种对象控制:qdiscs、classes和filters。 1、QDISCS
qdisc是“queueing discipline(队列规则)”的缩写,是理解流量控制的基础。每当内核需要向接口发送数据包时,它都会被队列到为该接口配置的qdisc。之后,内核会立即尝试从qdisc获取尽可能多的数据包,以便将其提供给网络适配器驱动程序。一个简单的QDISC是“pfifo”,它根本不进行任何处理,是一个纯粹的先进先出队列。然而,当网络接口暂时无法处理流量时,它确实会存储流量。2、CLASSES
一些qdisc可以包含“classes/类”,这些类包含更多的qdisc;然后,流量可以在类内的任何内部qdisc中队列。当内核试图从这样一个有类的qdisc中取出数据包时,它可以来自任何类。例如,qdisc可能会通过尝试从某些类中排到其他类之前来优先处理某些类型的流量。3、FILTERS
有类qdisc使用“filter/筛选器”来确定数据包将在哪个类中队列。每当流量到达具有子类的类时,都需要对其进行分类。可以采用各种方法来实现这一点,其中之一就是筛选器。所有附加到类的筛选器都会被调用,直到其中一个筛选器返回判决。如果没有做出裁决,可能还有其他标准,这因qdisc而异。重要的是要注意,筛选器驻留在qdisc中——它们不是发生什么的关键。 basic:基于ematch表达式筛选数据包。详见tc-ematch(8)。bpf:使用(e)BPF筛选数据包,详见tc-bpf(8)。cgroup:根据进程的控制组筛选数据包。详见tc-cgroup(8)。flow, flower:基于流的分类器,根据数据包的流(由可选键标识)筛选数据包。详见tc-flow(8)和tc-flower(8)。fw:基于fwmark的筛选器。直接将fwmark值映射到流量类别。见tc-fw(8)。route:根据路由表筛选数据包。详见tc-route(8)。rsvp:匹配资源预留协议(Resource Reservation Protocol,RSVP)的数据包。tcindex:根据流量控制索引筛选数据包。详见tc-tcindex(8)。u32:对任意数据包进行通用筛选,借助语法抽象常见操作。详见tc-u32(8)。matchall:匹配每个数据包的流量控制筛选器。详见tc-matchall(8)。4、QEVENTS
当qdisc中发生某些有趣的事件时,Qdiscs可能会调用用户配置的操作。每个qevent可以是未使用的,也可以附加一个块。然后使用“tc block BLOCK_IDX”语法将筛选器附加到该块上。当与连接点关联的qevent发生时,该块将被执行。例如,根据所讨论的qdisc和qevent,数据包可能会被丢弃或延迟等。 tc qdisc add dev eth0 root handle 1: red limit 500K avpkt 1K qevent early_drop block 10
tc filter add block 10 matchall action mirred egress mirror dev eth1
5、无类QDISCS
choke:CHOKe(CHOose(选择)并Keep(保持)用于响应流,CHOose(选择)并Kill(丢弃)用于无响应流)是一个无类qdisc,旨在识别和惩罚垄断队列的流。CHOKe是RED的变体,其配置与RED相似。codel:CoDel(发音为“coddle”)是一种自适应的“no-knobs/无旋钮”主动队列管理(Active Queue Management,AQM)算法方案,旨在解决RED及其变体的缺点。[p|b]fifo:最简单可用的qdisc,纯先进先出行为。输入的数据包或字节数有限。fq:公平队列(Fair Queue)调度器实现TCP定步,并可扩展到每个qdisc数百万个并发流。fq_codel:公平队列控制延迟是将公平队列与CoDel AQM方案相结合的队列规则。FQ_Codel使用随机模型将传入数据包分类为不同的流,并用于为使用队列的所有流提供公平的带宽份额。每个这样的流都由CoDel队列规则管理。由于CoDel内部使用FIFO队列,因此避免了流内的重新排序。 fq_pie:FQ-PIE(Flow Queuing with Proportional Integral controller Enhanced,增强比例积分控制器的流队列)是一种将流队列与PIE AQM方案相结合的队列规则。FQ-PIE使用Jenkins哈希函数将传入的数据包分类为不同的流,并使用qdisc为所有流提供公平的带宽份额。每个这样的流都由PIE算法管理。gred:广义随机早期检测(Generalized Random Early Detection)结合了多个RED队列,以实现多个丢弃优先级。这是实现保证转发(RFC 2597)所必需的。hhf:大流量筛选器(Heavy-Hitter Filter)区分小流量和相反的重打击。目标是抓住大流量,并将其转移到优先级较低的单独队列中,这样批量流量就不会影响关键流量的延迟。ingress:这是一个特殊的qdisc,因为它适用于接口上的传入流量,允许对其进行筛选和监管。multiq:Multiqueue是一个针对具有多个Tx队列的设备进行优化的qdisc。它是为希望避免线路头部堵塞的硬件添加的。它将循环遍历频带,并验证与频带相关的硬件队列在数据包去量化之前没有停止。mqprio:多队列优先级(Multiqueue Priority)Qdisc是一种简单的队列规则,允许使用优先级和可配置的优先级到流量类映射将流量映射到硬件队列范围。在此上下文中,流量类是一组连续的qdisc类,它们以1:1的比例映射到一组硬件公开的队列。 netem:网络模拟器(Network Emulator)是Linux流量控制设施的增强版,允许为从选定网络接口传出的数据包添加延迟、数据包丢失、重复和更多其他特性。pfifo_fast:启用“高级路由器”的内核的标准qdisc。由一个三带队列组成,该队列尊重服务类型标志以及可能分配给数据包的优先级。pie:比例积分控制器增强型(Proportional Integral controller-Enhanced,PIE)是一种基于控制理论的主动队列管理方案。它基于比例积分控制器,但旨在控制延迟。red:随机早期检测(Random Early Detection)通过在接近配置的带宽分配时随机丢弃数据包来模拟物理拥塞。非常适合带宽非常大的应用。rr:循环(Round-Robin)qdisc,支持多队列网络设备。从Linux内核版本2.6.27开始删除。sfb:随机公平蓝(Stochastic Fair Blue)是一种无类qdisc,用于根据丢包和链路利用率历史来管理拥塞,同时试图防止非响应流(即对拥塞标记或丢包没有反应的流)影响响应流的性能。与必须配置标记概率的RED不同,BLUE试图自动确定理想的标记概率。sfq:随机公平队列(Stochastic Fairness Queueing)重新排序队列的流量,因此每个“会话”都可以依次发送一个数据包。tbf:令牌桶筛选器(Token Bucket Filter)适用于将流量减缓到精确配置的速率。可很好地扩展到大带宽。 6、配置无类QDISCS
在没有有类qdisc的情况下,无类qdiscs只能连接到设备的根目录。完整语法:tc qdisc add dev DEV root QDISC QDISC-PARAMETERS
tc qdisc del dev DEV root
如果没有配置的qdisc,pfifo_fast qdisc是自动默认值。7、有类QDISCS
CBQ:基于类的队列(Class Based Queueing)实现了丰富的类链接共享层次结构。它包含塑造要素以及优先考虑能力。整形是使用基于平均数据包大小和底层链路带宽的链路空闲时间计算来执行的。对于某些接口,后者可能定义不清。DRR:差额调度(Deficit Round Robin)程序是随机公平队列的更灵活的替代品。与SFQ不同,它没有内置队列:您需要添加类,然后设置筛选器来相应地对数据包进行分类。这可能很有用,例如,对于特定流量使用具有不同设置的RED qdisc。它没有默认类:如果一个数据包无法分类,它将被丢弃。 DSMARK:根据TOS字段对数据包进行分类,根据分类更改数据包的TOS字段。PRIO:PRIO qdisc是一个非整形容器,用于按顺序出列的可配置数量的类。这允许对流量进行简单的优先级排序,其中较低的类别只有在较高的类别没有可用数据包的情况下才能发送。为了便于配置,默认情况下会尊重服务类型位。ETS:ETS qdisc是一种队列规则,它将PRIO和DRR qdisc的功能合并到一个调度器中。ETS使得配置一组严格的带宽共享频带以实现802.1Qaz中描述的传输选择变得容易。HTB:层次结构令牌桶(Hierarchy Token Bucket)实现了丰富的类链接共享层次结构,重点是符合现有实践。HTB有助于保证类的带宽,同时也允许指定类间共享的上限。它包含基于TBF的整形元素,可以对类进行优先级排序。HFSC:分层公平服务曲线(Hierarchical Fair Service Curve)保证了叶子类的精确带宽和延迟分配,并公平地分配了多余的带宽。与HTB不同,它利用丢包来实现交互会话受益的低延迟。QFQ:快速公平队列(Quick Fair Queueing)是一种O(1)调度器,它提供近乎最优的保证,并且是第一个在组数和数据包长度方面以恒定成本实现这一目标的调度器。QFQ算法没有循环,使用非常简单的指令和数据结构,非常适合硬件实现。 8、操作理论
类形成一棵树,每个类都有一个父类。一个类可能有多个子类。一些qdisc允许在运行时添加类(CBQ、HTB),而另一些(PRIO)则使用静态数量的子类创建。允许动态添加类的Qdisc可以有零个或多个子类,流量可以排队。此外,每个类都包含一个叶子qdisc,默认情况下具有pfifo行为,尽管可以在适当的位置附加另一个qdisc。此qdisc可能再次包含类,但每个类只能有一个叶子qdisc。当数据包进入一个有类qdisc时,它可以被分类到其中的一个类中。有三个标准可供选择,但并非所有qdisc都会使用这三个标准:A:tc filters,如果tc筛选器连接到某个类,则首先会查阅相关说明。筛选器可以在数据包报头的所有字段上匹配,也可以在iptables应用的防火墙标记上匹配。B:Type of Service,一些qdisc内置了基于TOS字段对数据包进行分类的规则。C:skb->priority,用户空间程序可以使用SO_PRIORITY选项在“skb->priority”字段中编码类id。树中的每个节点都可以有自己的筛选器,但更高级别的筛选器也可以直接指向较低级别的类。如果分类不成功,数据包将被队列到附加到该类的叶子qdisc。但是,请查看qdisc特定的手册页以了解详细信息。 9、NAMING
所有qdisc、classes和filters都有ID,可以指定或自动分配。ID由一个主要数字和一个次要数字组成,用冒号分隔:“major:minor”。main和minor都是十六进制数字,并且限制为16位。有两个特殊值:根由全1的主和次表示,未指定的全为零。QDISCS:一个可能有子类的qdisc,被分配了一个称为“句柄”的主要数字,将次要数字命名空间留给类。句柄表示为“10:”。通常会为预期有子类的qdisc明确分配一个句柄。CLASSES:位于一个qdisc下的类共享其qdisc主编号,但每个类都有一个单独的次编号,称为“classid”,与其父类无关,只与其父qdisc有关。与qdiscs相同的命名自定义适用。FILTERS:筛选器有一个由三部分组成的ID,只有在使用哈希筛选器层次结构时才需要它。10、PARAMETERS参数
以下参数在TC中广泛使用。有关其他参数,请参阅单个qdisc的手册页。10.1、RATES/速率
Bandwidths/带宽或rates/速率。这些参数接受一个浮点数,后面可能跟一个单位(支持SI和IEC单位),或者一个浮点后面跟一个“%”字符,以指定速率占设备速度的百分比(例如5%、99.5%)。警告:将速率指定为百分比表示当前速度的一小部分;如果速度改变,则不会重新计算该值。 bit或者只有一个数字:每秒的比特数。
kbit:每秒的K千比特数。
mbit:每秒的M兆比特数。
gbit:每秒的G吉比特数。
tbit:每秒的T太比特数。
bps:每秒的字节数。
kbps:每秒的K千字节数。
mbps:每秒的M兆字节数。
gbps:每秒的G吉字节数。
tbps:每秒的T太字节数。
要使用IEC单位来指定(某个量),分别用IEC前缀(ki-、mi-、gi-和ti-)替换SI前缀(k-、m-、g-、t-)。TC在内部将速率存储为一个32位无符号整数(以每秒比特数bps为单位),所以我们可以指定的最大速率为 4294967295 bps。10.2、TIMES/时间
s、sec或者secs:整秒。
ms、msec或者msecs:毫秒。
us、usec、usecs或者只有一个数字:微秒。
TC定义了自己的时间单位(等于微秒),并将时间值存储为32位无符号整数,因此我们可以指定最大时间值4294967295微秒。 10.3、SIZES/规格
b或者只有一个数字:Bytes字节。
kbit:K千位。
kb或k:K千字节。
mbit:M兆位。
mb或m:M兆字节。
gbit:G吉位。
gb或g:G吉字节。
TC在内部将大小存储为以字节为单位的32位无符号整数,因此我们可以指定最大大小为4294967295字节。10.4、VALUES/值
其他没有单位的值。默认情况下,这些参数被解释为十进制,但您可以通过分别添加“0”或“0x”前缀来指示TC将它们解释为八进制和十六进制。11、TC COMMANDS
add:向节点添加qdisc、类或筛选器。对于所有实体,必须传递父实体,要么传递其ID,要么直接附加到设备的根。创建qdisc或筛选器时,可以使用handle参数命名。类用classid参数命名。 delete:可以通过指定其句柄来删除qdisc,该句柄也可以是“root”。所有子类及其叶子qdisc以及附加到它们的任何筛选器都会自动删除。change:某些实体可以“就地”修改。共享“add”的语法,但句柄和父级都不能更改。换句话说,更改不能移动节点。replace:对现有节点id执行近乎原子的删除/添加。如果节点尚不存在,则创建它。get:显示给定接口DEV、qdisc id、优先级、协议和筛选器id的单个筛选器。show:显示连接到给定界面的所有筛选器。必须传递有效的父ID。link:仅适用于qdiscs,并在节点必须已存在的情况下执行替换。12、MONITOR
tc实用程序可以监视内核生成的事件,例如添加/删除qdisc、筛选器或操作,或修改现有的事件。file:如果给出了file选项,则tc不会监听内核事件,而是打开给定的文件并转储其内容。该文件必须为二进制格式,并包含netlink消息。13、OPTIONS
-b, -b filename, -batch, -batch filename:从提供的文件或标准输入中读取命令并调用它们。首次失败将导致tc终止。 -force:不要在批处理模式下因错误而终止tc。如果在执行命令期间出现任何错误,应用程序返回代码将不为零。-o, -oneline:将每条记录输出到一行,用“\”字符替换换行符。当您想使用wc(1)计数记录或grep(1)输出时,这很方便。-n, -net, -netns:将tc切换到指定的网络命名空间NETNS。实际上,它只是简化了以下操作的执行:ip netns exec NETNS tc [ OPTIONS ] OBJECT { COMMAND | help }
tc -n[etns] NETNS [ OPTIONS ] OBJECT { COMMAND | help }
-N, -Numeric:直接打印协议、作用域、dsfield等的编号,而不是将其转换为人类可读的名称。-cf, -conf:指定配置文件的路径。此选项与其他选项(例如-nm)结合使用。-t, -timestamp:当tc监视器运行时,以以下格式打印事件消息前的时间戳:Timestamp: <Day> <Month> <DD> <hh:mm:ss> <YYYY> <usecs> usec
-ts, -tshort:当tc监视器运行时,以以下格式在事件消息前打印短时间戳:[<YYYY>-<MM>-<DD>T<hh:mm:ss>.<ms>]
14、FORMAT
show命令具有其他格式选项:
输出更多关于数据包使用情况的统计数据。
输出有关速率和数据包大小的更详细信息。
输出句柄的原始十六进制值。
对于u32筛选器,将偏移和掩码值解码为基于TCP/IP的等效筛选器命令。在JSON输出中,添加空格以提高可读性。
-iec,以IEC单位表示的输出速率(即1K=1024)。
将类显示为ASCII图。如果指定了-s选项,则打印每个类下的通用统计信息。类只能通过dev选项进行筛选。
-c[color][={always|auto|never}
配置颜色输出。若参数被省略或始终存在,则无论stdout状态如何,颜色输出都将启用。若参数为auto,则在启用颜色输出之前,检查stdout是否为终端。若参数从不,则禁用颜色输出。如果多次指定,则最后一次优先。如果同时给出-json,则忽略此标志。
以JSON格式显示结果。
从/etc/iproute2/tc_cls文件或-cf选项指定的文件中解析类名。这个文件只是class到类名的映射:
1:40 voip # Here is another comment
1:50 web
1:60 ftp
1:2 home
如果指定了-nm而没有-cf选项,但/etc/iproute2/tc_cls文件不存在,则tc不会失败,这使得可以通过-nm选项创建tc别名。-br, -brief:仅打印识别筛选器和操作(句柄、cookie等)以及统计数据所需的基本数据。此选项目前仅受tc filter show和tc actions ls命令支持。15、EXAMPLES
tc -g class show dev eth0
将类显示为ASCII图,每个类下都有统计信息。
tc -g -s class show dev eth0
参考命令:tc-basic(8), tc-bfifo(8), tc-bpf(8), tc-cake(8), tc-cbq(8), tc-cgroup(8), tc-choke(8), tc-codel(8), tc-drr(8), tc-ematch(8), tc-ets(8), tc-flow(8), tc-flower(8), tc-fq(8), tc-fq_codel(8), tc-fq_pie(8), tc-fw(8), tc-hfsc(7), tc-hfsc(8), tc-htb(8), tc-mqprio(8), tc-pfifo(8), tc-pfifo_fast(8), tc-pie(8), tc-red(8), tc-route(8), tc-sfb(8), tc-sfq(8), tc-stab(8), tc-tbf(8), tc-tcin‐dex(8), tc-u32(8)。