Linux TC(Traffic Control) 簡介(一)

衆所周知,在互聯網誕生之初都是各個高校和科研機構相互通訊,並沒有網絡流量控制方面的考慮和設計,IP協議的原則是儘可能好地爲所有數據流服務,不同的數據流之間是平等的。然而多年的實踐表明,這種原則並不是最理想的,有些數據流應該得到特別的照顧,比如,遠程登錄的交互數據流應該比數據下載有更高的優先級。

      針對不同的數據流採取不同的策略,這種可能性是存在的。並且,隨着研究的發展和深入,人們已經提出了各種不同的管理模式。IETF已經發布了幾個標準,如綜合服務(Integrated Services)、區分服務(Diferentiated Services)等。其實,Linux內核從2.2開始,就已經實現了相關的流量控制功能。本文將介紹Linux中有關流量控制的相關概念, 用於流量控制的工具TC的使用方法,並給出幾個有代表性實例。

一、相關概念

      報文分組從輸入網卡(入口)接收進來,經過路由的查找,以確定是發給本機的,還是需要轉發的。如果是發給本機的,就直接向上遞交給上層的協議,比如TCP,如果是轉發的,則會從輸出網卡(出口)發出。網絡流量的控制通常發生在輸出網卡處。雖然在路由器的入口處也可以進行流量控制,Linux也具有相關的功能,但一般說來,由於我們無法控制自己網絡之外的設備,入口處的流量控制相對較難。因此我們這裏處理的流量控制一般指出口處的流量控制。流量控制的一個基本概念是隊列(Qdisc),每個網卡都與一個隊列(Qdisc)相聯繫,每當內核需要將報文分組從網卡發送出去,都會首先將該報文分組添加到該網卡所配置的隊列中,由該隊列決定報文分組的發送順序。因此可以說,所有的流量控制都發生在隊列中,詳細流程圖見圖1。

      圖1報文在Linux內部流程圖

 

      有些隊列的功能是非常簡單的,它們對報文分組實行先來先走的策略。有些隊列則功能複雜,會將不同的報文分組進行排隊、分類,並根據不同的原則,以不同的順序發送隊列中的報文分組。爲實現這樣的功能,這些複雜的隊列需要使用不同的過濾器(Filter)來把報文分組分成不同的類別(Class)。這裏把這些複雜的隊列稱爲可分類(Classiful)的隊列。通常,要實現功能強大的流量控制,可分類的隊列是必不可少的。因此,類別(Class)和過濾器(Filter)也是流量控制的另外兩個重要的基本概念。圖2所示的是一個可分類隊列的例 子。

      圖2多類別隊列

 

      由圖2可以看出,類別(Class)和過濾器(Filter)都是隊列的內部結構,並且可分類的隊列可以包含多個類別,同時,一個類別又可以進一步包含有子隊列,或者子類別。所有進入該類別的報文分組可以依據不同的原則放入不同的子隊列 或子類別中,以此類推。而過濾器(Filter)是隊列用來對數據報文進行分類的工具,它決定一個數據報文將被分配到哪個類別中。

二、使用TC

      在Linux中,流量控制都是通過TC這個工具來完成的。通常,要對網卡進行流量控制的配置,需要進行如下的步驟:

  ◆ 爲網卡配置一個隊列;

  ◆ 在該隊列上建立分類;

  ◆ 根據需要建立子隊列和子分類;

  ◆ 爲每個分類建立過濾器。

      在Linux中,可以配置很多類型的隊列,比如CBQ、HTB等,其中CBQ 比較複雜,不容易理解。HTB(Hierarchical Token Bucket)是一個可分類的隊列, 與其他複雜的隊列類型相比,HTB具有功能強大、配置簡單及容易上手等優點。在TC中,使用"major:minor"這樣的句柄來標識隊列類別,其中major和minor都是數字。

      對於隊列來說,minor總是爲0,即"major:0"這樣的形式,也可以簡寫爲"major: "比如,隊列1:0可以簡寫爲1:。需要注意的是,major在一個網卡的所有隊列中必須是惟一的。對於類別來說,其major必須和它的父類別或父隊列的major相同,而minor在一個隊列內部則必須是惟一的(因爲類別肯定是包含在某個隊列中的)。舉個例子,如果隊列2:包含兩個類別,則這兩個類別的句柄必須是2:x這樣的形式,並且它們的x不能相同,比如2:1和2:2。

      下面,將以HTB隊列爲主,結合需求來講述TC的使用。假設eth0出口有100mbit/s的帶寬,分配給WWW、E-mail和Telnet三種數據流量,其中分配給WWW的帶寬爲40Mbit/s,分配給Email的帶寬爲40Mbit/s,分配給Telnet的帶寬爲20Mbit/S。

      需要注意的是,在TC 中使用下列的縮寫表示相應的帶寬:

      ◆ Kbps : kilobytes per second,千字節每秒 ;

      ◆ Mbps : megabytes per second,兆字節每秒 ,

      ◆ Kbit : kilobits per second,千比特每秒 ;

      ◆ Mbit : megabits per second, 兆比特每秒 。

三、創建HTB隊列

      有關隊列的TC命令的一般形式爲:

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

      首先,需要爲網卡eth0配置一個HTB隊列,使用下列命令:

      #tc qdisc add dev eth0 root handle 1:htb default 11

      這裏,命令中的”add”表示要添加,”dev eth0”表示要操作的網卡爲eth0。”root”表示爲網卡eth0添加的是一個根隊列。”handle 1:”表示隊列的句柄爲1: 。”htb”表示要添加的隊列爲HTB隊列。命令最後的”default 11”是htb特有的隊列參數,意思是所有未分類的流量都將分配給類別1:11。

四、爲根隊列創建相應的類別

      有關類別的TC 命令的一般形式爲:

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

      可以利用下面這三個命令爲根隊列1創建三個類別,分別是1:1 1、1:12和1:13,它們分別佔用40、40和20mb[t的帶寬。

      #tc class add dev eth0 parent 1: classid 1:1 htb rate 40mbit ceil 40mbit

      #tc class add dev eth0 parent 1: classid 1:12 htb rate 40mbit ceil 40mbit

      #tc class add dev eth0 parent 1: cllassid 1:13 htb rate 20mbit ceil 20mbit

      命令中,”parent 1:”表示類別的父親爲根隊列1: 。”classid1:11”表示創建一個標識爲1:11的類別,”rate 40mbit”表示系統將爲該類別確保帶寬40mbit,”ceil 40mbit”,表示該類別的最高可佔用帶寬爲40mbit。

五、爲各個類別設置過濾器

      有關過濾器的TC 命令的一般形式爲:

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

      由於需要將WWW、E-mail、Telnet三種流量分配到三個類別,即上述1:11、1:12和1:13,因此,需要創建三個過濾器,如下面的三個命令:

      #tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dport 80 0xffff flowid 1:11

      #tc filter add dev eth0 prtocol ip parent 1:0 prio 1 u32 match ip dport 25 0xffff flowid 1:12

      #tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dport 23 oxffff flowid 1:13

      這裏,”protocol ip”表示該過濾器應該檢查報文分組的協議字段。”prio 1” 表示它們對報文處理的優先級是相同的,對於不同優先級的過濾器,系統將按照從小到大的優先級順序來執行過濾器,對於相同的優先級,系統將按照命令的先後順序執行。這幾個過濾器還用到了u32選擇器(命令中u32後面的部分)來匹配不同的數據流。以第一個命令爲例,判斷的是dport字段,如果該字段與Oxffff進行與操作的結果是8O,則”flowid 1:11”表示將把該數據流分配給類別1:1 1。更加詳細的有關TC的用法可以參考TC的手冊頁。

六、複雜的實例

      在上面的例子中, 三種數據流(www、Email、Telnet)之間是互相排斥的。當某個數據流的流量沒有達到配額時,其剩餘的帶寬並不能被其他兩個數據流所借用。在這裏將涉及如何使不同的數據流可以共享一定的帶寬。

      首先需要用到HTB的一個特性, 即對於一個類別中的所有子類別,它們將共享該父類別所擁有的帶寬,同時,又可以使得各個子類別申請的各自帶寬得到保證。這也就是說,當某個數據流的實際使用帶寬沒有達到其配額時,其剩餘的帶寬可以借給其他的數據流。而在借出的過程中,如果本數據流的數據量增大,則借出的帶寬部分將收回,以保證本數據流的帶寬配額。

      下面考慮這樣的需求,同樣是三個數據流WWW、E-mail和Telnet, 其中的Telnet獨立分配20Mbit/s的帶寬。另一方面,WWW 和SMTP各自分配40Mbit/s的帶寬。同時,它們又是共享的關係,即它們可以互相借用帶寬。如圖3所示。

 

      需要的TC命令如下:

      #tc qdisc add dev eth0 root handle 1: htb default 21

      #tc class add dev eth0 partent 1: classid 1:1 htb rate 20mbit ceil 20mbit

      #tc class add dev eth0 parent 1: classid 1:2 htb rate 80mbit ceil 80mbit

      #tc class add dev eth0 parent 1: classid 1:21 htb rate 40mbit ceil 20mbit

      #tc class add dev eth0 parent 1:2 classid 1:22 htb rate 40mbit ceil 80mbit

      #tc filter add dev eth0 protocol parent 10 prio 1 u32 match ip dport 80 0xffff flowid 1:21

      #tc filter add dev eth0 protocol parent 1:0 prio 1 u32 match ip dport 25 0xffff flowid 1:22

      #tc filter add dev eth0 protocol parent 1:0 prio 1 u32 match ip dport 23 0xffff flowid 1:1

      這裏爲根隊列1創建兩個根類別,即1:1和1:2,其中1:1對應Telnet數據流,1:2對應80Mbit的數據流。然後,在1:2中,創建兩個子類別1:21和1:22,分別對應WWW和E-mail數據流。由於類別1:21和1:22是類別1:2的子類別,因此他們可以共享分配的80Mbit帶寬。同時,又確保當需要時,自己的帶寬至少有40Mbit。

      從這個例子可以看出,利用HTB中類別和子類別的包含關係,可以構建更加複雜的多層次類別樹,從而實現的更加靈活的帶寬共享和獨佔模式,達到企業級的帶寬管理目的。


原文鏈接:
http://m.blog.csdn.net/blog/zhaobryant/38797655
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章