Linux內核TC工具鏈路帶寬設計--CBQ隊列規定

1.1 著名的 CBQ 隊列規定web

      除了能夠分類以外,CBQ 也是一個整形器。若是想把一個 10Mbps 的鏈接整造成 1Mbps 的速率,就應該讓鏈路 90%的時間處於閒置狀態,必要的話就強制,以保證 90% 的閒置時間。但閒置時間的測量很是困難,因此 CBQ 就採用了它一個近似值——來自硬件層的兩個傳輸請求之間的毫秒數——來代替它。這個參數能夠近似地表徵鏈路的繁忙程度。 算法

 

1.1.1 CBQ 整形的細節服務器

      CBQ 的工做機制是確認鏈路的閒置時間足夠長,以達到下降鏈路實際帶寬的目的。爲此,它要計算兩個數據包的平均發送間隔。有效閒置時間的測量使用EWMA(exponential weighted moving average, 指數加權移動均值)算法,也就是說最近處理的數據包的權值比之前的數據包按指數增長。UNIX 的平均負載也是這樣算出來的。計算出來的平均時間值減去 EWMA 測量值,得出的結果叫作「avgidle」。最佳的鏈路負載狀況下,這個值應當是 0,數據包嚴格按照計算出來的時間間隔到來。網絡

      在一個過載的鏈路上,avgidle 值應當是負的。若是這個負值太嚴重,CBQ 就會暫時禁止發包,稱爲「overlimit」(越限)。相反地,一個閒置的鏈路應該有很大的 avgidle 值,這樣閒置幾個小時後,會形成鏈路容許很是大的帶寬經過。爲了不這種局面,一般用 maxidle 來限制 avgidle 的值不能太大。 spa

      理論上講,若是發生越限,CBQ 就會禁止發包一段時間(長度就是事先計算出來的傳輸數據包之間的時間間隔),而後經過一個數據包後再次禁止發包。code

      下面是配置整形時須要指定的一些參數:blog

avpkt
隊列

      平均包大小,以字節計。計算 maxidle 時須要,maxidle 從 maxburst 得出。ip

bandwidth 路由

      網卡的物理帶寬,用來計算閒置時間。

cell 

      包間隔發送單元的大小。

maxburst 

      這個參數的值決定了計算 maxidle 所使用的數據包的個數。在 avgidle 跌落到 0 以前,這麼多的數據包能夠突發傳輸出去。這個值越高,越可以容納突發傳輸。沒法直接設置 maxidle 的值,必須經過這個參數來控制。

minburst 

      如前所述,發生越限時 CBQ 會禁止發包。實現這個的理想方案是根據事先計算出的閒置時間進行延遲以後,發一個數據包。然而,UNIX 的內核通常來講都有一個固定的調度週期(通常不大於10ms),因此最好禁止發包的時間稍長一些,而後突發性地傳輸 minburst 個數據包,而不是一個一個地傳輸。等待的時間叫作 offtime。從大的時間尺度上說,minburst 值越大,整形越精確。可是,從毫秒級的時間尺度上說,就會有越多的突發傳輸。 

minidle 

      若是 avgidle 值降到 0,也就是發生了越限,就須要等待,直到 avgidle 的值足夠大才發送數據包。爲避免因關閉鏈路過久而引發的意外突發傳輸, 在 avgidle 的值過低的時候會被強制設置爲 minidle 的值。參數 minidle 的值是以負微秒記的。10 表明 avgidle 被限制在-10us 上。 

mpu 

      最小包傳輸包大小——由於即便是 0 長度的數據包,在以太網上也要生成封裝成 64 字節的幀,而須要必定時間去傳輸。爲了精確計算閒置時間,CBQ 須要知道這個值。 

rate 

      實際分配的帶寬。

 

1.1.2 CBQ 在分類方面的行爲

      除了使用上述 idletime 近似值進行整形以外,CBQ 還能夠象 PRIO 隊列那樣,把各類類賦予不一樣的優先級,優先權數值小的類會比優先權值大的類被優先處理。每當網卡請求把數據包發送到網絡上時,都會開始一個 WRR(weighted round robin,加權輪轉)過程,從優先權值小的類開始。那些隊列中有數據的類就會被分組並被請求出隊。在一個類收到容許若干字節數據出隊的請求以後,再嘗試下一個相同優先權值的類。

      下面是控制 WRR 過程的一些參數:


allot 

      最大傳輸單元加 MAC 頭的大小。當從外部請求一個 CBQ 發包的時候,它就會按照「priority」參數指定的順序輪流嘗試其內部的每個類的隊列規定。當輪到一個類發數據時,它只能發送必定量的數據。「allot」參數就是這個量的基值。 

prio


      CBQ 能夠象 PRIO 設備那樣工做。其中「prio」值較低的類只要有數據就必須先服務,其餘類要延後處理。

weight 

      「weight」參數控制 WRR 過程。每一個類都輪流取得發包的機會。若是其中一個類要求的帶寬顯著地高於其餘的類,就應該讓它每次比其餘的類發送更多的數據。CBQ 會把一個類下面全部的 weight 值加起來後歸一化,因此數值能夠任意定,只要保持比例合適就能夠。一般把「速率/10」做爲參數的值來使用。歸一化值後的值乘以「allot」參數後,決定了每次傳輸多少數據。 

      須要注意的是,在一個 CBQ 內部全部的類都必須使用一致的主號碼。

 

1.1.3 決定鏈路的共享和借用的 CBQ 參數 

      除了純粹地對某種數據流進行限速以外,CBQ 還能夠指定哪些類能夠向其它哪些類借用或者出借一部分帶寬。

isolated/sharing 

      凡是使用「isolated」選項配置的類,就不會向其兄弟類出借帶寬。選項「sharing」是「isolated」的反義選項。 

bounded/borrow 

      一個類也能夠用「bounded」選項配置,意味着它不會向其兄弟類借用帶寬。選項「borrow」是「bounded」的反義選項。 

      一個典型的狀況就是一個鏈路上有多個客戶都設置成了「isolated」和「bounded」,那就是說他們都被限制在其要求的速率之下,且互相之間不會借用帶寬。在這樣的一個類的內部的子類之間是能夠互相借用帶寬的。

 

1.1.4 配置範例

      這個配置把 WEB 服務器的流量控制爲 5Mbps、SMTP 流量控制在 3Mbps。並且兩者一共不得超過 6Mbps,互相之間容許借用帶寬。網卡帶寬爲 100Mbps。

# sudo tc qdisc add dev enp0s5 root handle 1: cbq bandwidth 100Mbit avpkt 1000 cell 8
# sudo tc class add dev enp0s5 parent 1:0 classid 1:1 cbq bandwidth 100Mbit rate 6Mbit weight 0.6Mbit prio 8 allot 1514 cell 8 maxburst 20 avpkt 1000 bounded

      這裏設置了根爲 1:0,而且綁定了類 1:1。也就是說整個帶寬不能超過 6Mbps。

# sudo tc class add dev enp0s5 parent 1:1 classid 1:3 cbq bandwidth 100Mbit rate 5Mbit weight 0.5Mbit prio 5 allot 1514 cell 8 maxburst 20 avpkt 1000
# sudo tc class add dev enp0s5 parent 1:1 classid 1:4 cbq bandwidth 100Mbit rate 3Mbit weight 0.3Mbit prio 5 allot 1514 cell 8 maxburst 20 avpkt 1000

      這裏創建了 2 個類。兩個類都沒有配置成「bounded」,但它們都鏈接到了類 1:1 上,而 1:1 設置了「bounded」。 因此兩個類的總帶寬不會超過 6Mbps。須要注意的是,同一個 CBQ 下面的子類的主號碼都必須與 CBQ 本身的主號碼相一致。

# sudo tc qdisc add dev enp0s5 parent 1:3 handle 30: sfq 
# sudo tc qdisc add dev enp0s5 parent 1:4 handle 40: sfq 

      缺省狀況下,兩個類都有一個 FIFO 隊列規定。這裏把它換成 SFQ 隊列,以保證每一個數據流都公平對待。

# sudo tc filter add dev enp0s5 parent 1:0 protocol ip prio 1 u32 match ip sport 80 0xffff flowid 1:3
# sudo tc filter add dev enp0s5 parent 1:0 protocol ip prio 1 u32 match ip sport 25 0xffff flowid 1:4

      這裏規定了根上的過濾器,保證數據流被送到正確的隊列規定中去。注意:上面命令先使用了「tc class add」在一個隊列規定中建立了類,而後使用「tc 
qdisc add」在類中建立隊列規定。那些沒有被那兩條規則分類的數據流被 1:0 直接處理,沒有限制。若是 SMTP+web 的總帶寬需求大於 6Mbps,那麼這 6Mbps 帶寬將按照兩個類的 weight 參數的比例狀況進行分割:WEB 服務器獲得 5/8 的帶寬,SMTP 獲得 3/8 的帶寬。從這個例子來講,能夠這麼認爲:WEB 數據流老是會獲得 5/8*6Mbps=3.75Mbps 的帶寬。 

 

1.2 一個完整的 CBQ 隊列規定實例

流量需求:                                                                                                                               

      流量控制器上的以太網卡(enp0s5)的IP地址爲 10.211.55.17, 在其上創建一個 CBQ 隊列。假設包的平均大小爲 1000 字節,包間隔發送單元的大小爲 8 字節,可接收衝突的發送最長包的數目爲 20 字節。                                                                                              

      加入有三種類型的流量須要控制:                                                                                                          

            (1)是發往主機 1 的,其 IP 地址爲1 0.211.55.20。其流量帶寬控制在 8Mbit,優先級爲 2;              

            (2)是發往主機 2 的,其 IP 地址爲 10.211.55.21。其流量帶寬控制在 1Mbit,優先級爲 1;                                                          

            (3)是發往子網 1 的,其子網號爲 10.211.55.0。 子網掩碼爲 255.255.255.0。流量帶寬控制在 1Mbit,優先級爲 6。

建立 CBQ 隊列主要分爲四個步驟:創建隊列、創建分類、建立過濾器、創建路由。在創建隊列以前,須要對網卡的隊列規則進行清除,具體操做以下:

清除網卡全部隊列規則

# sudo tc qdisc del dev enp0s5 root 2> /dev/null > /dev/null

創建隊列

# sudo tc qdisc add dev enp0s5 root handle 1: cbq bandwidth 10Mbit avpkt 1000 cell 8 mpu 64

      將一個 cbq 隊列綁定到物理網絡設備 enp0s5 上,其編號爲 1:0;物理網絡設備 enp0s5 的實際帶寬爲 10Mbit,包的平均大小爲 1000 字節;包間隔發送單元的大小爲 8 字節,最小傳輸包大小爲 64 字節。

 

創建分類

      建立根分類 1:1,分配帶寬爲 10Mbit,優先級別爲 8:

#  sudo tc class add dev enp0s5 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。

      建立分類 1:2,其父類爲 1:1,分配帶寬爲 8Mbit,優先級別爲 2:

#   sudo tc class add dev enp0s5 parent 1:1 classid 1:2 cbq bandwidth 10Mbit rate 8Mbit maxburst 20 allot 1514 prio 2 avpkt 1000 cell 8 weight 800Kbit split 1:0 bounded

      該隊列的最大可用帶寬爲 10Mbit,實際分配的帶寬爲 8Mbit,可接收衝突的發送最長包數目爲 20 字節;最大傳輸單元加 MAC 頭的大小爲 1514 字節,優先級別爲 2,包的平均大小爲 1000 字節,包間隔發送單元的大小爲 8 字節,至關於實際帶寬的加權速率爲 800Kbit,分類的分離點爲 1:0,且不可借用未使用帶寬。

      建立分類 1:3,其父分類爲 1:1,分配帶寬爲 1Mbit,優先級別爲 1:

#   sudo tc class add dev enp0s5 parent 1:1 classid 1:3 cbq bandwidth 10Mbit rate 1Mbit maxburst 20 allot 1514 prio 2 avpkt 1000 cell 8 weight 100Kbit split 1:0

      該隊列的最大可用帶寬是 10Mbit,實際分配的帶寬爲 1Mbit,可接收衝突的發送最長包數目爲 20 字節;最大傳輸單元加 MAC 頭的大小爲 1514 字節,優先級別爲 1,包的平均大小爲 1000 字節,包間隔發送單元的大小爲 8 字節,至關於實際帶寬的加權速率爲 100Kbit,分類的分離點爲 1:0。

      建立分類 1:4,其父分類爲 1:1,分配帶寬爲 1Mbit,優先級別爲 6:

#   sudo tc class add dev enp0s5 parent 1:1 classid 1:3 cbq bandwidth 10Mbit rate 1Mbit maxburst 20 allot 1514 prio 2 avpkt 1000 cell 8 weight 100Kbit split 1:0

      該隊列的最大可用帶寬爲 10Mbit,實際分配的帶寬爲 1Mbit,可接收衝突的發送最長包數目爲 20 字節;最大傳輸單元加 MAC 頭的大小爲 1514 字節,優先級別爲 6,包的平均大小爲 1000 字節,包間隔發送單元的大小爲 8 字節,至關於實際帶寬的加權速率爲 100Kbit,分類的分離點爲 1:0。

 

建立過濾器

      (1)應用路由分類器到 cbq 隊列的根,父分類編號爲 1:0;過濾協議爲 ip,優先級別爲 100,過濾器爲基於路由表:

# sudo tc filter add dev enp0s5 parent 1:0 protocol ip prio 100 route

      (2)創建路由映射分類 1:2 , 1:3 , 1:4

# sudo tc filter add dev enp0s5 parent 1:0 protocol ip prio 100 route to 2 flowid 1:2

# sudo tc filter add dev enp0s5 parent 1:0 protocol ip prio 100 route to 3 flowid 1:3

# sudo tc filter add dev enp0s5 parent 1:0 protocol ip prio 100 route to 4 flowid 1:4

 

創建路由

      (1)發往主機 10.211.55.20 的數據包經過分類 2 轉發(分類 2 的速率 8Mbit)

# sudo ip route add 10.211.55.20 dev enp0s5 via 10.211.55.17 realm 2

      (2)發往主機 10.211.55.21 的數據包經過分類 3 轉發(分類 3 的速率 1Mbit)

# sudo ip route add 10.211.55.21 dev enp0s5 via 10.211.55.17 realm 3

      (3)發往子網 10.211.55.0/24 的數據包經過分類 4 轉發(分類 4 的速率 1Mbit)

# sudo ip route add 10.211.55.0/24 dev enp0s5 via 10.211.55.17 realm 4
相關文章
相關標籤/搜索