流量控制工具TC詳細說明

onephone發表於2017-01-17

原理介紹

Linux作業系統中的流量控制器TC(Traffic Control)用於Linux核心的流量控制,它利用佇列規定建立處理資料包的佇列,並定義佇列中的資料包被髮送的方式, 從而實現對流量的控制。TC模組實現流量控制功能使用的佇列規定分為兩類,一類是無類佇列規定, 另一類是分類佇列規定。 無類佇列規定相對簡單,而分類佇列規定則引出了分類和過濾器等概念,使其流量控制功能增強。

  1. 無類佇列規定是對進入網路裝置(網路卡) 的資料流不加區分統一對待的佇列規定。
    • 使用無類佇列規定形成的佇列能夠 接受資料包以及重新編排、延遲或丟棄資料包。這類佇列規 定形成的佇列可以對整個網路裝置( 網路卡) 的流量進行整形, 但不能細分各種情況。
    • 常用的無類佇列規定主要有pfifo _fast (先進現出) 、TBF ( 令牌桶過濾器) 、SFQ(隨機公平佇列) 、ID (前 向隨機丟包)等等。這類佇列規定使用的流量整形手段主要 是排序、限速和丟包。
  2. 分類佇列規定是對進入網路裝置的資料包根據不同的需求以分類的方式區分對待的佇列規定。
    • 資料包進入一個分類的佇列後, 它就需要被送到某一個類中, 也就是說需要對資料包做分類處理。對資料包進行分類的工具是過濾器,過濾器會返回一個決定,佇列規定就根據這個決定把資料包送入相應的類進行排隊。
    • 每個子類都可以再次使用它們的過濾器進行進一步的分類。直到不需要進一步分類時, 資料包才進入該類包含的佇列排隊。
    • 除了能夠包含其它佇列規定之外, 絕大多數分類的佇列規定還能夠對流量進行整形。 這對於需要同時進行排程( 如使用 SFQ ) 和流量控制的場合非常有用。
  3. 基本原理圖
    image_1b6at6vf47qubm51vq69qvaod1g.png-54kB
    • 接收包從輸入介面(Input Interface)進來後,經過流量限制(Ingress Policing)丟棄不符合規定的資料包,由輸入多路分配器(Input De-Multiplexing)進行判斷選擇......
    • 如果接收包的目的是本主機,那麼將該包送給上層處理;否則需要進行轉發,將接收包交到轉發塊(Forwarding Block)處理。轉發塊同時也接收本主機上層(TCP、UDP等)產生的包。轉發塊通過檢視路由表,決定所處理包的下一跳。然後,對包進行排列以便將它們傳送到輸出介面(Output Interface)。
    • 一般我們只能限制網路卡傳送的資料包,不能限制網路卡接收的資料包,所以我們可以通過改變傳送次序來控制傳輸速率。
    • Linux流量控制主要是在輸出介面排列時進行處理和實現的。

TC規則

1. 流量控制

流量控制包括以下4種方式

  1. SHAPING(限制)
    當流量被限制,它的傳輸速率就被控制在某個值以下。限制值可以大大小於有效頻寬,這樣可以平滑突發資料流量,使網路更為穩定。shaping(限制)只適用於向外的流量。
  2. SCHEDULING(排程)
    通過排程資料包的傳輸,可以在頻寬範圍內,按照優先順序分配頻寬。SCHEDULING(排程)也只適於向外的流量。
  3. POLICING(策略)
    SHAPING用於處理向外的流量,而POLICIING(策略)用於處理接收到的資料。
  4. DROPPING(丟棄)
    如果流量超過某個設定的頻寬,就丟棄資料包,不管是向內還是向外。

2. 流量控制處理物件

流量的處理由三種物件控制,它們是:qdisc(排隊規則)、class(類別)和filter(過濾器)。

2.1 QDisc

  • QDisc(排隊規則)是queueing discipline的簡寫,它是理解流量控制(traffic control)的基礎。
  • 無論何時,核心如果需要通過某個網路介面傳送資料包,它都需要按照為這個介面配置的qdisc(排隊規則)把資料包加入佇列。然後,核心會盡可能多地從qdisc裡面取出資料包,把它們交給網路介面卡驅動模組。
  • 最簡單的QDisc是pfifo它不對進入的資料包做任何的處理,資料包採用先入先出的方式通過佇列。不過,它會儲存網路介面一時無法處理的資料包。
  • QDISC的分為CLASSLESS QDisc和CLASSFUL QDISC類別,即不可分類QDisc可分類QDisc

2.2 CLASSLESS QDisc

  1. 無類別QDISC包括
    • [p|b]fifo
      使用最簡單的qdisc,純粹的先進先出。只有一個引數:limit,用來設定佇列的長度,pfifo是以資料包的個數為單位;bfifo是以位元組數為單位。
    • pfifo_fast
      在編譯核心時,如果開啟了高階路由器(Advanced Router)編譯選項,pfifo_fast就是系統的標準QDISC。它的佇列包括三個波段(band)。在每個波段裡面,使用先進先出規則。而三個波段(band)的優先順序也不相同,band 0的優先順序最高,band 2的最低。如果band裡面有資料包,系統就不會處理band 1裡面的資料包,band 1和band 2之間也是一樣。資料包是按照服務型別(Type of Service,TOS)被分配多三個波段(band)裡面的。
    • red
      red是Random Early Detection(隨機早期探測)的簡寫。如果使用這種QDISC,當頻寬的佔用接近於規定的頻寬時,系統會隨機地丟棄一些資料包。它非常適合高頻寬應用。
    • sfq
      sfq是Stochastic Fairness Queueing的簡寫。它按照會話(session--對應於每個TCP連線或者UDP流)為流量進行排序,然後迴圈傳送每個會話的資料包。
    • tbf
      tbf是Token Bucket Filter的簡寫,適合於把流速降低到某個值。
  2. 無類別QDisc的配置
    • 如果沒有可分類QDisc,不可分類QDisc只能附屬於裝置的根,使用命令tc qdisc add dev DEV root QDISC QDISC-PARAMETERS
    • 要刪除一個不可分類QDisc,需要使用命令tc qdisc del dev DEV root
    • 一個網路介面上如果沒有設定QDisc,pfifo_fast就作為預設的QDisc。

2.3 CLASSFUL QDISC

可分類QDISC包括:

  1. CBQ
    • CBQ是Class Based Queueing(基於類別排隊)的縮寫。
    • 它實現了一個豐富的連線共享類別結構,既有限制(shaping)頻寬的能力,也具有頻寬優先順序管理的能力。
    • 頻寬限制是通過計算連線的空閒時間完成的。
    • 空閒時間的計算標準是資料包離隊事件的頻率和下層連線(資料鏈路層)的頻寬。
  2. HTB
    • HTB是Hierarchy Token Bucket的縮寫。
    • 通過在實踐基礎上的改進,它實現了一個豐富的連線共享類別體系。使用HTB可以很容易地保證每個類別的頻寬,雖然它也允許特定的類可以突破頻寬上限,佔用別的類的頻寬。
    • HTB可以通過TBF(Token Bucket Filter)實現頻寬限制,也能夠劃分類別的優先順序。
  3. PRIO
    • PRIO QDisc不能限制頻寬,因為屬於不同類別的資料包是順序離隊的。
    • 使用PRIO QDisc可以很容易對流量進行優先順序管理,只有屬於高優先順序類別的資料包全部傳送完畢,才會傳送屬於低優先順序類別的資料包。
    • 為了方便管理,需要使用iptables或者ipchains處理資料包的服務型別(Type Of Service,ToS)。

2. 操作原理

  • 類(Class)組成一個樹,每個類都只有一個父類,而一個類可以有多個子類。某些QDisc(例如:CBQ和HTB)允許在執行時動態新增類,而其它的QDisc(例如:PRIO)不允許動態建立類。允許動態新增類的QDisc可以有零個或者多個子類,由它們為資料包排隊。
  • 此外,每個類都有一個葉子QDisc,預設情況下,這個葉子QDisc使用pfifo的方式排隊,我們也可以使用其它型別的QDisc代替這個預設的QDisc。而且,這個葉子葉子QDisc有可以分類,不過每個子類只能有一個葉子QDisc。當一個資料包進入一個分類QDisc,它會被歸入某個子類。
  • 如果過濾器附屬於一個類,相關的指令就會對它們進行查詢。過濾器能夠匹配資料包頭所有的域,也可以匹配由ipchains或者iptables做的標記。
  • 樹的每個節點都可以有自己的過濾器,但是高層的過濾器也可以直接用於其子類。如果資料包沒有被成功歸類,就會被排到這個類的葉子QDisc的隊中。相關細節在各個QDisc的手冊頁中

3. 命令規則

所有的QDisc、類和過濾器都有ID。ID可以手工設定,也可以有核心自動分配。ID由一個主序列號和一個從序列號組成,兩個數字用一個冒號分開。

  • QDISC,一個QDisc會被分配一個主序列號,叫做控制程式碼(handle),然後把從序列號作為類的名稱空間。控制程式碼採用象10:一樣的表達方式。習慣上,需要為有子類的QDisc顯式地分配一個控制程式碼。
  • 類(CLASS),在同一個QDisc裡面的類分享這個QDisc的主序列號,但是每個類都有自己的從序列號,叫做類識別符(classid)。類識別符只與父QDisc有關,和父類無關。類的命名習慣和QDisc的相同。
  • 過濾器(FILTER),過濾器的ID有三部分,只有在對過濾器進行雜湊組織才會用到。詳情請參考tc-filters手冊頁。

TC命令

tc可以使用以下命令對QDisc、類和過濾器進行操作:

  1. add,在一個節點裡加入一個QDisc、類或者過濾器。新增時,需要傳遞一個祖先作為引數,傳遞引數時既可以使用ID也可以直接傳遞裝置的根。如果要建立一個QDisc或者過濾器,可以使用控制程式碼(handle)來命名;如果要建立一個類,可以使用類識別符(classid)來命名。
  2. remove,刪除有某個控制程式碼(handle)指定的QDisc,根QDisc(root)也可以刪除。被刪除QDisc上的所有子類以及附屬於各個類的過濾器都會被自動刪除。
  3. change,以替代的方式修改某些條目。除了控制程式碼(handle)和祖先不能修改以外,change命令的語法和add命令相同。換句話說,change命令不能一定節點的位置。
  4. replace,對一個現有節點進行近於原子操作的刪除/新增。如果節點不存在,這個命令就會建立節點。
  5. link,只適用於DQisc,替代一個現有的節點。

```
tc qdisc [ add | change | replace | link ] dev DEV [ parent qdisc-id | root ] [ handle qdisc-id ] qdisc [ qdisc specific parameters ]

tc class [ add | change | replace ] dev DEV parent qdisc-id [ classid class-id ] qdisc [ qdisc specific parameters ]

tc filter [ add | change | replace ] dev DEV [ parent qdisc-id | root ] protocol protocol prio priority filtertype [ filtertype specific parameters ] flowid flow-id

tc [-s | -d ] qdisc show [ dev DEV ]

tc [-s | -d ] class show dev DEV tc filter show dev DEV
```

具體操作

Linux流量控制主要分為建立佇列、建立分類和建立過濾器三個方面。

1. 基本步驟

  1. 針對網路物理裝置(如乙太網卡eth0)繫結一個佇列QDisc;
  2. 在該佇列上建立分類class;
  3. 為每一分類建立一個基於路由的過濾器filter;
  4. 最後與過濾器相配合,建立特定的路由表。

2. 模擬例項

流量控制器上的乙太網卡(eth0) 的IP地址為192.168.1.66,在其上建立一個CBQ佇列。假設包的平均大小為1000位元組,包間隔傳送單元的大小為8位元組,可接收衝突的傳送最長包數目為20位元組。
假如有三種型別的流量需要控制:

  • 是發往主機1的,其IP地址為192.168.1.24。其流量頻寬控制在8Mbit,優先順序為2;
  • 是發往主機2的,其IP地址為192.168.1.30。其流量頻寬控制在1Mbit,優先順序為1;
  • 是發往子網1的,其子網號為192.168.1.0,子網掩碼為255.255.255.0。流量頻寬控制在1Mbit,優先順序為6。

2.1 建立佇列

一般情況下,針對一個網路卡只需建立一個佇列。
將一個cbq佇列繫結到網路物理裝置eth0上,其編號為1:0;網路物理裝置eth0的實際頻寬為10 Mbit,包的平均大小為1000位元組;包間隔傳送單元的大小為8位元組,最小傳輸包大小為64位元組。
tc qdisc add dev eth0 root handle 1: cbq bandwidth 10Mbit avpkt 1000 cell 8 mpu 64

2.2 建立分類

分類建立在佇列之上。
一般情況下,針對一個佇列需建立一個根分類,然後再在其上建立子分類。對於分類,按其分類的編號順序起作用,編號小的優先;一旦符合某個分類匹配規則,通過該分類傳送資料包,則其後的分類不再起作用。

  1. 建立根分類1:1;分配頻寬為10Mbit,優先順序別為8。
    • tc class add dev eth0 parent 1:0 classid 1:1 cbq bandwidth 10Mbit rate 10Mbit maxburst 20 allot 1514 prio 8 avpkt 1000 cell 8 weight 1Mbit
    • 該佇列的最大可用頻寬為10Mbit,實際分配的頻寬為10Mbit,可接收衝突的傳送最長包數目為20位元組;最大傳輸單元加MAC頭的大小為1514位元組,優先順序別為8,包的平均大小為1000位元組,包間隔傳送單元的大小為8位元組,相應於實際頻寬的加權速率為1Mbit。
  2. 建立分類1:2,其父分類為1:1,分配頻寬為8Mbit,優先順序別為2。
    • tc class add dev eth0 parent 1:0 classid 1:1 cbq bandwidth 10Mbit rate 10Mbit maxburst 20 allot 1514 prio 8 avpkt 1000 cell 8 weight 1Mbit
    • 該佇列的最大可用頻寬為10Mbit,實際分配的頻寬為 8Mbit,可接收衝突的傳送最長包數目為20位元組;最大傳輸單元加MAC頭的大小為1514位元組,優先順序別為1,包的平均大小為1000位元組,包間隔傳送單元的大小為8位元組,相應於實際頻寬的加權速率為800Kbit,分類的分離點為1:0,且不可借用未使用頻寬。
  3. 建立分類1:3,其父分類為1:1,分配頻寬為1Mbit,優先順序別為1。
    • tc class add dev eth0 parent 1:1 classid 1:3 cbq bandwidth 10Mbit rate 1Mbit maxburst 20 allot 1514 prio 1 avpkt 1000 cell 8 weight 100Kbit split 1:0
    • 該佇列的最大可用頻寬為10Mbit,實際分配的頻寬為 1Mbit,可接收衝突的傳送最長包數目為20位元組;最大傳輸單元加MAC頭的大小為1514位元組,優先順序別為2,包的平均大小為1000位元組,包間隔傳送單元的大小為8位元組,相應於實際頻寬的加權速率為100Kbit,分類的分離點為1:0。
  4. 建立分類1:4,其父分類為1:1,分配頻寬為1Mbit,優先順序別為6。
    • tc class add dev eth0 parent 1:1 classid 1:4 cbq bandwidth 10Mbit rate 1Mbit maxburst 20 allot 1514 prio 6 avpkt 1000 cell 8 weight 100Kbit split 1:0
    • 該佇列的最大可用頻寬為10Mbit,實際分配的頻寬為1Mbit,可接收衝突的傳送最長包數目為20位元組;最大傳輸單元加MAC頭的大小為1514位元組,優先順序別為6,包的平均大小為1000位元組,包間隔傳送單元的大小為8位元組,相應於實際頻寬的加權速率為100Kbit,分類的分離點為1:0。

2.3. 建立過濾器

過濾器主要服務於分類。
一般只需針對根分類提供一個過濾器,然後為每個子分類提供路由對映。

  1. 應用路由分類器到cbq佇列的根,父分類編號為1:0;過濾協議為ip,優先順序別為100,過濾器為基於路由表。
    • tc filter add dev eth0 parent 1:0 protocol ip prio 100 route
  2. 建立路由對映分類1:2, 1:3, 1:4
    • tc filter add dev eth0 parent 1:0 protocol ip prio 100 route to 2 flowid 1:2
    • tc filter add dev eth0 parent 1:0 protocol ip prio 100 route to 3 flowid 1:3
    • tc filter add dev eth0 parent 1:0 protocol ip prio 100 route to 4 flowid 1:4

2.4 建立路由

該路由是與前面所建立的路由對映一一對應。

  1. 發往主機192.168.1.24的資料包通過分類2轉發(分類2的速率8Mbit)
    • ip route add 192.168.1.24 dev eth0 via 192.168.1.66 realm 2
  2. 發往主機192.168.1.30的資料包通過分類3轉發(分類3的速率1Mbit)
    • ip route add 192.168.1.24 dev eth0 via 192.168.1.66 realm 2
  3. 發往子網192.168.1.0/24的資料包通過分類4轉發(分類4的速率1Mbit)
    • ip route add 192.168.1.0/24 dev eth0 via 192.168.1.66 realm 4

注:一般對於流量控制器所直接連線的網段建議使用IP主機地址流量控制限制,不要使用子網流量控制限制。如一定需要對直連子網使用子網流量控制限制,則在建立該子網的路由對映前,需將原先由系統建立的路由刪除,才可完成相應步驟。

2.5 監視

主要包括對現有佇列、分類、過濾器和路由的狀況進行監視。

  1. 顯示佇列的狀況
    • 簡單顯示指定裝置(這裡為eth0)的佇列狀況
      tc qdisc ls dev eth0
    • 詳細顯示指定裝置(這裡為eth0)的佇列狀況
      tc -s qdisc ls dev eth0
  2. 顯示分類的狀況
    • 簡單顯示指定裝置(這裡為eth0)的分類狀況
      tc class ls dev eth0
    • 詳細顯示指定裝置(這裡為eth0)的分類狀況
      tc -s class ls dev eth0
  3. 顯示過濾器的狀況
    • tc -s filter ls dev eth0
  4. 顯示現有路由的狀況
    • ip route

2.6 維護

主要包括對佇列、分類、過濾器和路由的增添、修改和刪除。
增添動作一般依照"佇列->分類->過濾器->路由"的順序進行;修改動作則沒有什麼要求;刪除則依照"路由->過濾器->分類->佇列"的順序進行。

  1. 佇列的維護
    一般對於一臺流量控制器來說,出廠時針對每個乙太網卡均已配置好一個佇列了,通常情況下對佇列無需進行增添、修改和刪除動作了。
  2. 分類的維護
    • 增添,增添動作通過tc class add命令實現
    • 修改,修改動作通過tc class change命令實現
      tc class change dev eth0 parent 1:1 classid 1:2 cbq bandwidth 10Mbit rate 7Mbit maxburst 20 allot 1514 prio 2 avpkt 1000 cell 8 weight 700Kbit split 1:0 bounded
      對於bounded命令應慎用,一旦新增後就進行修改,只可通過刪除後再新增來實現。
    • 刪除,刪除動作只在該分類沒有工作前才可進行,一旦通過該分類傳送過資料,則無法刪除它了。因此,需要通過shell檔案方式來修改,通過重新啟動來完成刪除動作。
  3. 過濾器的維護

    • 增添,增添動作通過tc filter add命令實現
    • 修改,修改動作通過tc filter change命令實現
      tc filter change dev eth0 parent 1:0 protocol ip prio 100 route to 10 flowid 1:8
    • 刪除,刪除動作通過tc filter del命令實現
      tc filter change dev eth0 parent 1:0 protocol ip prio 100 route to 10 flowid 1:8
  4. 與過濾器一一對映路由的維護

    • 增添,增添動作通過ip route add命令實現,如前面所示。
    • 修改,修改動作通過ip route change命令實現
      ip route change 192.168.1.30 dev eth0 via 192.168.1.66 realm 8

    • 刪除,刪除動作通過ip route del命令實現
      ip route del 192.168.1.30 dev eth0 via 192.168.1.66 realm 8
      ip route del 192.168.1.30 dev eth0 via 192.168.1.66 realm 8

相關文章