linux使用tc進行流量控制

Linux下利用TC工具控制網絡流量(圖)



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

      

                            圖1報文在Linux內部流程圖  

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

     



                                         圖2多類別隊列  

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



  二、使用TC  

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

  ◆ 爲網卡配置一個隊列;  

  ◆ 在該隊列上建立分類;  

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

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

  在Linux中,可以配置很多類型的隊列,比如CBQ、HTB等,其中CBQ 比較複雜,不容易理解。HTB(HierarchicaIToken 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。如圖3所示。  

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

  ◆ Kbps kiIobytes 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"表示該過濾器應該檢查報文分組的協議字段。"pr[o 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的帶寬。另一方面,VWVW 和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中類別和子類別的包含關係,可以構建更加複雜的多層次類別樹,從而實現的更加靈活的帶寬共享和獨佔模式,達到企業級的帶寬管理目的。 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章