基本操作
- 清除現有的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
上的對象取為1y
為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