Linux下使用TC模擬網絡延遲/帶寬

TC

Traffic Control.
tc被用來在linux內核中進行流量控制。
tc使用三類對象對流量進行過濾、分組、排隊,分別是filterclassqdisc.

TC的語法較爲複雜,已有的教程大多僅限於netem這個classless qdisc,無法更深入的對流量進行控制。我看了很多文檔才大概明白怎麼使用,下面簡單介紹一些基礎知識和我用到的一些操作,詳細內容見參考部分的鏈接。

handle

qdisc和filter用handle選項命名,class用classid選項命名。

major:minor

  1. 一般major從1開始,和qdisc有關;而minor只與class有關,只要唯一可以任意命名。(ffff:0保留給ingress qdisc
  2. class的minor必須大於0,qdisc的minor必須爲0(qdisc也可以省略minor,默認爲0)。
  3. 同屬一個qdisc的class擁有相同的major。

tc通過這種命名方式形成一棵的結構。

qdisc

root/egress qdisc: 功能強大,主要使用這個。
ingress qdisc: 功能有限,只有policer。

每個interface都有一個默認的qdisc,pfifo_fast,可以替換。

qdisc可以分爲兩類,分別是classless qdiscclassful qdisc

classless qdisc

不能包含class。比如netem

可以參考這裏:http://tldp.org/HOWTO/Traffic-Control-HOWTO/classless-qdiscs.html

FIFO, First-In First-Out (pfifo and bfifo)

簡單的先進先出隊列,不做其他任何操作。
需要指定隊列的size,pfifobfifo分別以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對流量進行細分。比如HTBCBQ

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。
第三行是匹配的語法,分別是字節的長度valuebitmaskoffset,上面的意思就是:從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:
IP header

ToS是在RFC791中提出的,但好像並沒有使用這些bit。
RFC791-ToS

之後在RFC1349中對這個字段進行了修改:
RFC1349-ToS
再之後又在RFC2474中進行了大的修改:
RFC2474-DSCP | ECN

交互式應用的設置爲:0x10,也就是bit4bit_4設置爲1.

參考這裏:https://lartc.org/howto/lartc.qdisc.classless.html

tcng

好像是對tc複雜命令的簡化。

TODO: http://tldp.org/HOWTO/Traffic-Control-tcng-HTB-HOWTO/

參考

  1. http://man7.org/linux/man-pages/man8/tc.8.html
  2. http://man7.org/linux/man-pages/man8/tc-u32.8.html
  3. http://linux-tc-notes.sourceforge.net/tc/doc/cls_u32.txt
  4. http://tldp.org/HOWTO/Traffic-Control-HOWTO/index.html
  5. https://lartc.org/howto/lartc.qdisc.classless.html
  6. https://github.com/magnific0/wondershaper
  7. https://en.wikipedia.org/wiki/IPv4#Header
  8. https://en.wikipedia.org/wiki/Type_of_service
  9. https://unix.stackexchange.com/questions/212503/how-to-discriminate-between-ssh-and-scp-for-qos-in-openwrt-and-other-systems
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章