基本操作
- 清除现有的qdisc
tc qdisc del root dev eth0
Qdisc
Classless Qdisc
-
负责流量基本管理,包括流量整形、排序、限速等
-
不能在其上新建qdisc分支(即class)
-
分类
-
fifo_fast
:没有自定义规则时的默认qdisc,直接对packet先进先出 -
tbf
: Token Bucket Filter,令牌桶过滤,以一定速率发放token,对流量进行限速。token用完时,packet等待,如果等待超时(latency)将被dropped。token堆积时将允许网络bursttc qdisc add dev ppp0 root tbf rate 220kbit latency 50ms burst 1540 // 限速220kbit,超时时间50ms,最高1540kbit
-
sqf
: Stochastic Fairness Queueing,随机公平排序,将每个conversation(连接?)算作一个队列,每次随机从中选择其中一个conversation中的packet发送。其随机本质是采用哈希,同时每隔一定时间替换(perturb)哈希算法tc qdisc add dev eth0 root sfq perturb 10
-
CoDel and Fair Queueing CoDel
-
Classful Qdisc
-
允许在其上增添qdisc分支,比如filter规则等。新建的qdisc可以为classful或classless
-
qdisc分支称作class,采用
classid
编号命名,而parent
代指该class的母亲节点。命名方式为x:y
,其中x
为root的名称一般为1:
,而子类则类似于1:10
. 注意所有x和y不一定为母子关系,因为此处x
必为root,比如下面HTB的例子中1:1
为root子节点,而1:10
、1:20
、1:30
为1:1
子节点 -
Hierarchical Token Bucket (HTB)
- 用于对根据目的对有限的带宽进行分层限流
# This line sets a HTB qdisc on the root of eth0, and it specifies that the class 1:30 is used by default. It sets the name of the root as 1:, for future references. tc qdisc add dev eth0 root handle 1: htb default 30 # This creates a class called 1:1, which is direct descendant of root (the parent is 1:), this class gets assigned also an HTB qdisc, and then it sets a max rate of 6mbits, with a burst of 15k tc class add dev eth0 parent 1: classid 1:1 htb rate 6mbit burst 15k # The previous class has this branches: # Class 1:10, which has a rate of 5mbit tc class add dev eth0 parent 1:1 classid 1:10 htb rate 5mbit burst 15k # Class 1:20, which has a rate of 3mbit tc class add dev eth0 parent 1:1 classid 1:20 htb rate 3mbit ceil 6mbit burst 15k # Class 1:30, which has a rate of 1kbit. This one is the default class. tc class add dev eth0 parent 1:1 classid 1:30 htb rate 1kbit ceil 6mbit burst 15k # Martin Devera, author of HTB, then recommends SFQ for beneath these classes: tc qdisc add dev eth0 parent 1:10 handle 10: sfq perturb 10 tc qdisc add dev eth0 parent 1:20 handle 20: sfq perturb 10 tc qdisc add dev eth0 parent 1:30 handle 30: sfq perturb 10
Filter
-
仅用于Classful Qdisc
-
可仅采用tc或tc + iptables的方式
-
tc only
# This command adds a filter to the qdisc 1: of dev eth0, set the # priority of the filter to 1, matches packets with a # destination port 22, and make the class 1:10 process the # packets that match. tc filter add dev eth0 protocol ip parent 1: prio 1 u32 match ip dport 22 0xffff flowid 1:10 # This filter is attached to the qdisc 1: of dev eth0, has a # priority of 2, and matches the ip address 4.3.2.1 exactly, and # matches packets with a source port of 80, then makes class # 1:11 process the packets that match tc filter add dev eth0 parent 1: protocol ip prio 2 u32 match ip src 4.3.2.1/32 match ip sport 80 0xffff flowid 1:11
-
tc + iptables
// 对于标记有6的包,用1:30 class处理 tc filter add dev eth0 protocol ip parent 1: prio 1 handle 6 fw flowid 1:30 // 利用iptables的fwmark方法标记packet iptables -A PREROUTING -t mangle -i eth0 -j MARK --set-mark 6
-
基本概念
-
noqueue
用于虚拟设备默认qdisc,不能用于物理设备。无法通过tc qdisc add noque
赋予,而应通过tc qdisc del
删除虚拟设备qdisc
得到。表示不要放入队列,直接发送(如果无法发送则丢弃)。 -
pfifo_fast
用于物理设备,无法用于虚拟设备。无法通过tc qdisc add
赋予,而应通过tc qdisc del
删除虚拟设备qdisc
得到。- 内部包含3个class(又称band),这3个class的qdisc规则不允许用户更改
- packet发送顺序:
class 1
先于class 2
先于class 3
,同级按先入先出处理。无限速、无延迟。 - 当高优先级流量超过设备处理能力时,低优先级流量将不被发送,可能会导致低优先级流量饥饿,特别是tcp连接
- IP Header中的TOS会对应转化成优先级,不同优先级与class 1-3有对应关系
-
prio
非常类似于pfifo_fast
,但是允许自定义class和classifier- 当采用默认值时,与pfifo_fast一样
- 参数
bands 3
指定具备的class数量(2~16),默认值为3,对应于N:1 N:2 ... N:NUMBER - 总共具有16个优先级,与bands有对应关系
-
priomap class_for_prio_0 class_for_prio_1 ... class_for_prio_15
,此处的class数字代表n+1,比如0代表class 1. - class内部规则与
pfifo_fast
一致,可能出现低优先级流量饥饿。但可以选择为class定义一个qdisc限流规则(如tbf)
- 虚拟设备与物理设备的差异
- traffic engine处理方式几乎一致,但存在下列差异
- 由于虚拟设备一般只需对packet处理后便发送到下一个device,故packet一般不需要放到队列中等待处理。故所有对队列进行简单的重排序的qdisc都将失效,比如
pfifo_fast
、cbq
、sfq
、prio
等。而其他诸如改变发送速率的qdisc将保留 - 设备默认创建时,物理设备qdisc时
pfifo_fast
,虚拟设备是noqueue
-
root(egress)
与ingress
分别针对出流量和入流量,但并非实际的qdisc规则,只是为了便于将traffic control规则关联到上面结构化而已-
root
支持所有qdisc规则,而ingress
不支持绑定子class,只能绑定filter。实际作用相当于对进入的流量限流而已
-
- handle
- 所有class及classful qdisc均需要一个唯一的ID,由两部分组成
x:y
-
x
取值任意,但具有相同parent的类需要有相同的x
。一般将直接附属在root
上的对象取为1 -
y
为0时代表qdisc,其他值代表为class。(为0时可省略,故qdisc时必须用1:0或1: )
-
- 所有class及classful qdisc均需要一个唯一的ID,由两部分组成
- class
- 仅存在于classful qdisc中,如HTB和CBQ。每个类都可以包含任意多个class或单个qdisc
- 每个class可以绑定任意多个filter
- leaf class为qdisc中的终端class,包含一个qdisc而不包含子class