文章目錄
TC
Traffic Control.
tc被用來在linux內核中進行流量控制。
tc使用三類對象對流量進行過濾、分組、排隊,分別是filter
,class
,qdisc
.
TC的語法較爲複雜,已有的教程大多僅限於
netem
這個classless qdisc
,無法更深入的對流量進行控制。我看了很多文檔才大概明白怎麼使用,下面簡單介紹一些基礎知識和我用到的一些操作,詳細內容見參考部分的鏈接。
handle
qdisc和filter用handle
選項命名,class用classid
選項命名。
major:minor
- 一般major從1開始,和qdisc有關;而minor只與class有關,只要唯一可以任意命名。(
ffff:0
保留給ingress qdisc
) - class的minor必須大於0,qdisc的minor必須爲0(qdisc也可以省略minor,默認爲0)。
- 同屬一個qdisc的class擁有相同的major。
tc通過這種命名方式形成一棵樹
的結構。
qdisc
root/egress qdisc
: 功能強大,主要使用這個。
ingress qdisc
: 功能有限,只有policer。
每個interface都有一個默認的qdisc,pfifo_fast
,可以替換。
qdisc
可以分爲兩類,分別是classless qdisc
和classful qdisc
。
classless qdisc
不能包含class。比如netem
。
可以參考這裏:http://tldp.org/HOWTO/Traffic-Control-HOWTO/classless-qdiscs.html
FIFO, First-In First-Out (pfifo and bfifo)
簡單的先進先出隊列,不做其他任何操作。
需要指定隊列的size,pfifo
和bfifo
分別以packet和byte作爲size的單位。
SFQ, Stochastic Fair Queuing
隨機公平隊列。
由多個FIFO組成,通過哈希函數將packet送入不同的FIFO。
爲了保證哈希函數的選取的公平性,通過perturb
參數週期性的改變哈希函數。
netem
網上大多都是關於netem的資料,這裏簡單介紹一下。
netem是對tc的增強,可以增加延時、丟包等。
# set latency: 100ms
sudo tc qdisc add dev eth0 root netem delay 100ms
也可以增加一些latency的波動,設置丟包率等,這裏不再介紹。
classful qdisc
可以包含class,繼而通過filter對流量進行細分。比如HTB
、CBQ
。
HTB
參考這裏:http://tldp.org/HOWTO/Traffic-Control-HOWTO/classful-qdiscs.html#qc-htb
大概就是基於令牌控制traffic rate,child可以向parent借用令牌,暫時的超出自己的rate。
下面是一些參數:
- default: 將沒有被分類的traffic放到default指定的class/qdisc。默認是0,不做任何軟件層面的限制,交給硬件處理。
- rate:期望的最小速率
- ceil:期望的最大速率(通過借用令牌)
- burst: size
- cburst:size
- prio:越小優先級越高
class
每一個class都有一個默認的qdisc,FIFO。可以替換成其它的qdisc。
class上可以掛載多個class,或者掛載一個qdisc。
leaf class掛載一個qdisc,不能再掛載class。
注意qdisc只能掛載同類的class。
filter
filter可以掛載到classful qdisc或者class。
u32是可以逐字節進行比較、過濾的一個過濾器,非常強大,需要使用者熟悉各種協議的格式。
u32
參考:http://linux-tc-notes.sourceforge.net/tc/doc/cls_u32.txt
以下面這個例子說明語法:
tc filter add dev eth0 parent 999:0 protocol ip prio 99 u32 \
classid 1:1 \
match u32 0xc0a80800 0xffffff00 at 12
第一行不再說明,所有的filter都差不多。
第二行指定如果traffic匹配該過濾器,就將traffic送入 1:1標識的class。
第三行是匹配的語法,分別是字節的長度
、value
、bitmask
、offset
,上面的意思就是:從IP packet從0偏移12個字節開始,取32個bit,將這32個bit與掩碼0xffffff00
進行異或,若果結果等於value0xc0a80800
,那麼該packet就匹配成功。
由於需要知道各個字段的偏移才能使用這個過濾器,較爲麻煩,u32提供了一些語法糖,但最終還是轉換爲上面的匹配方式進行過濾。
舉幾個例子:
tc filter add dev eth0 parent 999:0 protocol ip prio 99 u32 \
classid 1:1 \
match ip src 192.168.8.0/24
tc filter add dev eth0 parent 999:0 protocol ip prio 99 u32 \
classid 1:1 \
match ip src 192.168.8.0/24 \
match ip tos 0x10 1e
一些參考命令
# TODO
wondershaper
wondershaper是對tc的一個包裝,簡化了使用,更加方便的控制網卡的上傳下載速率,但同時也限制了其他功能。
可以去看一下源碼,學習一下如何使用tc 😃
源碼中設置了針對ssh的filter,因爲不希望交互式的應用被延遲:
# start filters
# TOS Minimum Delay (ssh, NOT scp) in 1:10:
tc filter add dev $IFACE parent 1: protocol ip prio 10 u32 \
match ip tos 0x10 0xff flowid 1:10
去查了一下IP協議的ToS字段,學到了一點別的東西。
先附上IP header:
ToS是在RFC791
中提出的,但好像並沒有使用這些bit。
之後在RFC1349
中對這個字段進行了修改:
再之後又在RFC2474
中進行了大的修改:
交互式應用的設置爲:0x10
,也就是設置爲1.
參考這裏:https://lartc.org/howto/lartc.qdisc.classless.html
tcng
好像是對tc複雜命令的簡化。
TODO: http://tldp.org/HOWTO/Traffic-Control-tcng-HTB-HOWTO/
參考
- http://man7.org/linux/man-pages/man8/tc.8.html
- http://man7.org/linux/man-pages/man8/tc-u32.8.html
- http://linux-tc-notes.sourceforge.net/tc/doc/cls_u32.txt
- http://tldp.org/HOWTO/Traffic-Control-HOWTO/index.html
- https://lartc.org/howto/lartc.qdisc.classless.html
- https://github.com/magnific0/wondershaper
- https://en.wikipedia.org/wiki/IPv4#Header
- https://en.wikipedia.org/wiki/Type_of_service
- https://unix.stackexchange.com/questions/212503/how-to-discriminate-between-ssh-and-scp-for-qos-in-openwrt-and-other-systems