帶寬管理:
TC中規定描述帶寬:
mbps = 1024 kbps = 1024 * 1024 bps => byte/s
mbit = 1024 kbit => kilo bit/s
mb = 1024 kb = 1024 * 1024 b =>byte
mbit = 1024kbit => kilo bit.
默認: 數字使用bps和 b方式存儲.
無類隊列規則: 它能夠接受數據和重新編排、延時或丟棄數據包,默認使用pfifo_fast隊列規則.
pfifo_fast:
特點: 對任何數據包都使用FIFO(先進先出)隊列,來存放入隊。但它有3個所謂的"頻道",對
每一個頻道都使用FIFO規則,內核會優先將TCP的TOS標志位(“最小延遲”)置位的數據包
放入0頻道,其它的放入1和2頻道中,當然這是默認行為. 三個頻道按照0,1,2的順序,依次
等待處理,即0頻道有數據包等待發送,1頻道的包就不會發送,若1頻道有包等待發送,則
2頻道的包將不會被發送。
txqueuelen
#關於網卡設備的緩沖隊列長度,可通過ip 或 ifconfig來修改.
ifconfig eth0 txqueuelen 10
priomap:
內核對會根據數據包的優先權將其對應到不同的頻道.
TCP報文中TOS字段如下:
TOS值的含義 和 其對應的頻道:
對於以下服務推薦TOS設置:
TBF(令牌桶過濾器):
TBF是一個簡單隊列,它只允許數據包按照事先設定的速率通過,支持設置峰值流量,它很精確,
且對網絡和處理器的影響較小,因此比較常用.
TBF的原理:
它實現了一個緩沖器(即令牌桶),在這個桶里面會不斷以特定速率往里面填充“令牌",token rate
(令牌速率)是令牌桶比較重要的參數,它是桶的大小,也就是能存儲令牌的數量.
如:
rate 200kbps: 它指 令牌桶最多存儲200kbit個令牌,一個令牌1bit, 因為要通過1bit的數據,
就需要一個令牌,因此發送速率若為200k bit每秒,則桶里面始終會有令牌,若超過
則沒有可用令牌,就會產生丟包,這也就是TBF對流量整型的過程; 若低於此速率
則令牌桶可能會被裝滿,多余的令牌將丟失。
另外它也隱含說明了,緩存隊列的長度,即它最多能緩存多少bit的數據.
理解: 因為令牌的產生是按照系統的時間解析度來產生的,系統時間解析度指
多久為1個時間單位 或 多少HZ(赫茲)一個時間單位, 假如10ms為一個時間單位,
那就是每隔10毫秒系統會生產一個令牌放到令牌桶中。
假如在初始時 桶中當前只有1個令牌,按照200kbit/s的速率, 第一個bit進入,桶中
有令牌取走,該bit通過,接下來的bit,就要等10ms(一個時間單位)后,才能得到下一個
令牌,而第二個bit在等待時,第三個bit已經到了,依次類推,緩存隊列最多能存200kbit
數據,若超過了,后續的數據就丟失了,若不超過設定速率,這個隊列始終不會被填滿.
TBF可用參數:
limit 和 latency:
limit: 允許最多有多少數據(字節數)在隊列中等待可用令牌。
latency: 設定一個數據包在緩存隊列中等待發送的最長等待時間,若設置它,就相當於
決定了桶的大小、速率和峰值速率,因為數據包大小范圍:64~MTU kbit 。
burst/buffer/maxburst:
設置最多一次允許多少個令牌能被立即使用,即峰值速率。
buffer: 設置令牌桶的大小,通常是管理的帶寬越大,buffer就需要的越大.
mpu: Minimum Packet Unit:最小分組單位, 它決定了令牌的最低消耗。
rate:設置速率(缺省不限速)
peakrate:設置峰值速率,即: 一個包通過后,下一個包要等多久才允許通過.
如: Unix的時間解析度是10ms(2004年左右的參考值), 若平均包長為10kbit,
則峰值速率最大為1Mbps,即 1秒=1000ms, 按10ms的解析度, 即100個
時間單位,每個時間單位發送10kbit,就是100 X 10kbit = 1Mbps.
mtu/minburst:
mtu: 峰值速率 = mtu X 時間解析度.
例:
tc qdisc add dev ppp0 root tbf rate 220kbit latency 50ms burst 1540
SFQ(Stochastic Fairness Queueing:隨機公平隊列):
SFQ的精確度不如上面的算法,但它確能以很小的計算量,實現較高的公平數據發送。
SFQ實現的公平是隨機的, 因為它是針對一個TCP會話或UDP流,將它們通過散列的
方式平均分配到有限的幾個FIFO隊列中,所以它們實際上是共享發包機會的,但為了
讓盡量公平,SFQ會每隔指定時間改變一次散列算法,以便讓這種機制能讓所有包都
在幾秒內發送出去。
注:
SFQ僅在網卡確實已經被擠滿時,才會生效, 來創建隊列並散列TCP或UDP數據包到不同
隊列中,進行公平調度。
SFQ可用參數:
perturb: 每隔多久改變一次散列算法,10秒是比較合適的值.
quantum: 設置一個流至少傳輸多少字節后,切換到下一個隊列中發送其中的數據包。
建議使用默認值,即最大包長度(MTU). 此值不能設置數值小於MTU!!
例:
# tc qdisc add dev ppp0 root sfq perturb 10
# tc -s -d qdisc ls
qdisc sfq 800c: dev ppp0 quantum 1514b limit 128p flows 128/1024 perturb 10sec
Sent 4812 bytes 62 pkts (dropped 0, overlimits 0)
注:
“ 800c:”這個號碼是系統自動分配的句柄號
“ limit”: 是這個隊列中可以有 128 個數據包排隊等待。
“flows 128/1024”: 一共可以有 1024 個散列目標可以用於速率審計,
而其中 128 個可以同時激活。
perturb 10: 每隔 10 秒散列算法更換一次。
以上隊列何時使用最合適:
1. 僅想限速,使用令牌桶過濾器(TBF):調整桶的配置后可用於控制很高的帶寬。
2. 若鏈路已被塞滿, 使用SFQ,可避免某一會話獨占出口帶寬.
3. 若你僅想看看網卡是否有較高的負載,可使用pfifo,而非pfifo_fast,因為pfifo內部
頻道可進行backlog統計。
4.最后記住: 技術不能解決一切問題,社交還是需要的!
TC的實現流量控制的大致框架流程如下:
注:
圖中Ingress處就根據策略避免超過規定的數據包進入內核,這樣可以
減少CPU處理時間。 若數據包順利進入內核,若它是進入本地進程的,
就轉給IP協議棧, 否則就交給egress分類器. 經過審查后,最終被放入
若干隊列規定中進行排隊,此過程叫入隊。如不進行任何配置,默認
只有一個egress隊列規定,即pfifo_fast. 當數據包入隊后,等待內核處理
並通過某網卡發出,這過程叫出隊。
隊列規定: 即管理設備輸入(ingress)或輸出(egress)的算法.根據否能包含子類,
它被分為無類和分類兩種:
無類隊列規定: 一個內部不包含可配置子類的隊列規定.
分類隊列規定: 一個分類的隊列規定內可包含更多class(類),其中每個子類又
進一步地包含一個分類 或 無類的隊列規定。
整形(策略):在數據包被發送前,跟據設定進行適當延遲,避免超過設定的最大速率.
通常采用丟包來實現, 因為TCP的滑動窗口機制可以根據丟包來自動調整
其發送數據包的速率,而UDP只能通過丟包來限制其速率。
Work-Conserving: 對於work-conserving隊列規定,若得到一個數據包,就立刻
發送。即:只要網卡(egress隊列規定)允許,它就不會延遲數據包發送.
non-Work-Conserving: 有些隊列,如TBF(令牌桶過濾器),可能需要暫時停止發包,
以實現限制帶寬,也就是說它們有時即時有數據包需要處理,也可能拒絕發送.
過濾器: 對流量進行分類,如:網頁流量,視頻流量,游戲流量等進行過濾條件匹配,
匹配出來后,交給分類器處理。
分類器: 分類器可將不同的流量分發給 分類隊列規定 中不同的子類來處理。
TC的隊列規定家族:
root, 句柄(handle), 兄弟節點 和 父節點
注:
句柄(handle): 節點引用標識,它的格式: MajorNumber:MinorNumber,其中父節點的次號碼始終為0.
root節點的handle為1:0(可簡寫為:"1:"), 它有一個子節點 1:1
1:1這個子隊列規定有兩個父級的子隊列規定分別是 10: 和 11:
內核 僅和root qdisc 進行通信, 與物理網卡的通信也是有root qdisc來完成的,它們對應整體
的隊列規定家族是透明的,所有對外的接口只有root qdisc一個。
在隊列規定內部(我的理解如下):
當內核發來入隊請求時, root qdisc 會先調用過濾器來匹配數據包,若沒有匹配就直接由分類器
將其下發至子隊列規定,它也是先過濾器匹配,然后分類器分發,假如過濾器發現數據包為游戲流量
就將其送入11: 這個父級的子隊列規定,接着11: 過濾器繼續判斷,發現是boos的游戲流量,就將其
分發到11:1,在繼續到11:1的過濾器,然后是分類器,完后入隊等待發送。
當內核發來出隊請求時,root qdisc會向1:1發查詢,1:1會分別向10: 和 11:發查詢,接着10:會向
其下的10:1 和 10:2發查詢,直到11:1發現了要出隊的數據包,它將數據包出隊發給root qdisc,接着
在內核的指引下,root qdisc將數據包發給網卡。【注: 出隊要遍歷全隊列,所以隊列不要太多哦~】
隊列規定:
PRIO:它不對流量進行整形,它僅根據配置的過濾器將流量細分到不同的類中,若需要對流量進行整形處理,
可以在這些子類中包含相應的隊列,由它們來做整形。默認PRIO隊列規定包含3個類,每個類下面包含
一個FIFO隊列。
PRIO可以參數:
bands : 指定創建的頻道個數,一個頻道就是一個類, 默認是3個頻道.
priomap: 為PRIO隊列規定綁定一個過濾器,默認:根據TOS字段來匹配分類規則與pfifo_fast根據TOS
字段分類一樣。
例:
創建如下樹:
命令:
#這個命令創建了三個類,1:1, 1:2, 1:3,因為默認bands為3.
tc qdisc add dev eth0 root handle 1: prio
#為第一個子類1:1創建了一個父級子類10:, 並制定內部隊列為SFQ(隨機公平隊列)
tc qdisc add dev eth0 parent 1:1 handle 10: sfq
tc qdisc add dev eth0 parent 1:2 handle 20: tbf rate 20kbit buffer 1600 limit 3000
tc qdisc add dev eth0 parent 1:3 handle 30: sfq
tc -s qdisc ls dev eth0
qdisc sfq 30: quantum 1514b
Sent 0 bytes 0 pkts (dropped 0, overlimits 0)
qdisc tbf 20: rate 20Kbit burst 1599b lat 667.6ms
Sent 0 bytes 0 pkts (dropped 0, overlimits 0)
qdisc sfq 10: quantum 1514b
Sent 132 bytes 2 pkts (dropped 0, overlimits 0)
qdisc prio 1: bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
Sent 174 bytes 3 pkts (dropped 0, overlimits 0)
測試:
1. 嘗試使用scp 復制文件到其它主機. 然后查看 隊列統計信息。
2. 書中說 10: 它的優先權最高,交互流量會優先選它, 30:的優先權最低,大量數據流量會優先走它.
需要測試參考 TOS 標志位含義。
CBQ(Class Based Queueing:基於類的隊列):
CBQ是根據鏈路平均空閑時間,來判斷鏈路負載是否需要進行管制(即:整形),它有三種情況:
avgidle = 0 : 則說明當前連路負載最佳,數據包能夠精確按照預計時間間隔到達.
avgidle < 0 : 則說明當前鏈路過載了, 若負值逐漸增大,則說明負載超限(Overlimit),
CBQ將啟動整形,開始丟包以禁止發包,禁止發包時長為 超限前計算
出來的數據包平均發送間隔。
avgidle > 0 : 則說明當前鏈路太空閑了, 若空閑超過幾個小時,若此時有流量過來,CBQ
將允許無限制的流量轉發, 但這通常不是我期望的,因此需要設置maxidle,
來限制avgidle的值不能太大.
avgidle = 兩個數據包平均發送間隔時長 減去 EWMA
EWMA:Exponential Weighted Moving Average:指數加權移動均值,此算法是根據最近
處理的數據包的權值比以前的數據包按指數增加。 【算法具體含義不清楚】
簡單理解: 最近數據包權值 = 前一個數據包權值^n+1
另注: UNIX 的平均負載也是這樣算出來的
CBQ整形的參數:
avpkt: 平均數據包大小,單位:字節. 它是計算maxidle的參數, maxidle從maxburst得出.
bandwidth: 物理網卡的帶寬, 用於計算鏈路空閑時間.
cell: 它用於設置時間解析度(即:時間精度), 通常設為8,它必須是2的整數次冪。
maxburst: 最大突發數據包的個數(原文: 在avgidle=0前,可允許有maxburst個數據包突發傳輸出去。)
此值決定了maxidle計算使用的數據包個數【不是很理解】.
minburst: 它是設置超限后CBQ進入禁止發包延時狀態后,根據之前計算的空閑時間延遲值,
結合系統調度處理程序離開CPU到下次調度它到CPU上執行的間隔,來適當設置禁止發包的
時長,當處理程序調度到CPU上執行時,一次突發傳輸 minburst 個數據包.
注: 大尺度時間上, minburst值越大,整形越精確;
從毫秒級時間尺度上,就會有更多突發傳輸.
禁止發包的等待時間叫: offtime
minidle: 當avgidle < 0,發送越限后,CBQ進入禁止發包的等待狀態,但為了避免解禁后,再次
出現突發傳輸,導致avgidle超限更多,負值越大,導致更長的禁止狀態,所以需要設置
一個 minidle 來限制負值無限增大.
注: minidle 10 : 表示avgidle被限制其越限最大值為 -10us (負10微秒)
mpu: 數據包的最小大小.用於CBQ精確計算鏈路空閑時間
rate: 預期想限制的最大傳輸速率.
CBQ在數據包分類方面的參數:
注: 這些參數是控制那些隊列要參與計算,如:已知該隊列中無數據包,就不讓其參與調度計算,
及那些隊列要被懲罰性的降低優先級等。
CBQ使用prio參數來設定每個類的優先級,值越小越優先; 數據包出隊是按照WRR(Weighted
Round Robin:加權輪詢) 對root qdisc下每個子類進行輪詢,優先級高的子類先被調度,從
該子類中的隊列中取數據,接着是次高的,直到全部子類遍歷一遍,當然對於沒有數據的
子類將自動跳過. 每次從子類中取多少數據是根據 allot * weight 來決定的。
WRR的相關參數:
prio: 設置類的優先級,值越小越優先.
allot: 設置一次發送多少數據量.
weight: 允許多發多少數據的權重數(注: 建議weight=rate/10);假如有如下圖:
注:
對於這個圖, 1:0這個根類下有兩個子類1:1和1:2, 1:1的prio值更小,因此它
更優先被WRR調度;
一級子類1:1它的發送數據的權重=0.2+0.5
一級子類1:2它的發送數據的權重=0.3
而對於1:1的子類來說:
二級1:1發送數據的權重=0.2
二級1:2發送數據的權重=0.5
而2:1與此一樣.
CBQ兄弟類之間是否可以互相借用帶寬:
isolated / sharing:
isolated: 不會和兄弟類出借暫時多余的帶寬。
sharing: 允許借用暫時多余的帶寬.
bounded / borrow:
bounded: 不允許借
borrow: 允許借
例:
這個配置把 WEB 服務器的流量控制為 5Mbps、 SMTP 流量控制在 3Mbps , 而且
二者一共不得超過 6Mbps,互相之間允許借用帶寬。我們的網卡是 100Mbps的。
# tc qdisc add dev eth0 root handle 1:0 cbq bandwidth 100Mbit avpkt 1000 cell 8
# tc class add dev eth0 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:1物理網卡的最大帶寬為100Mbit,設置最大速率為6Mbit,允許發送數據量的權重為0.6Mbit.
一次發送數據量為1514(單位:不清楚),允許的最大突發20個數據包,平均包大小為1000字節,時間解析度為8,
不借出帶寬給兄弟節點,本例子類1:1沒有同級兄弟節點,因此設置或不設置一樣.
# tc class add dev eth0 parent 1:1 classid 1:3 cbq bandwidth 100Mbit \
rate 5Mbit weight 0.5Mbit prio 5 allot 1514 cell 8 maxburst 20 avpkt 1000
# tc class add dev eth0 parent 1:1 classid 1:4 cbq bandwidth 100Mbit \
rate 3Mbit weight 0.3Mbit prio 5 allot 1514 cell 8 maxburst 20 avpkt 1000
注:
在子類1:1下有兩個子類,它們是可以互相借用空閑帶寬的,但他倆最大能使用的總帶寬是6Mbit.
Web能占用的帶寬 = 6 X (0.5/(0.5+0.3)) Mbps
SMTP能占用的帶寬 = 6 X (0.3/(0.5+0.3)) Mbps
# tc qdisc add dev eth0 parent 1:3 handle 30: sfq
# tc qdisc add dev eth0 parent 1:4 handle 40: sfq
# tc filter add dev eth0 parent 1:0 protocol ip prio 1 u32 match ip sport 80 0xffff flowid 1:3
# tc filter add dev eth0 parent 1:0 protocol ip prio 1 u32 match ip sport 25 0xffff flowid 1:4
注:
這是添加了兩個過濾器,用於匹配Web和SMTP的流量,並將它們分別送入1:3和1:4中.
對於沒有匹配到的流量,1:0 即root隊列規定將直接處理,它采用FIFO隊列,不限制直接轉發.
注: 以上命令創建的結構如下圖:
CBQ的過濾器選項:
split節點: 當你需要使用CBQ自帶的過濾器 defmap時,定義defmap的類的父類就稱為split節點.
defmap: 它是通過與TCP的TOS(服務類型標志位) 做或運算來匹配特定TOS置位的數據包,並將
這些數據包接入到匹配類中. 0:表示不匹配.
例:
# 1:1就是split節點
# tc qdisc add dev eth1 root handle 1: cbq bandwidth 10Mbit allot 1514 cell 8 avpkt 1000 mpu 64
# tc class add dev eth1 parent 1:0 classid 1:1 cbq bandwidth 10Mbit \
rate 10Mbit allot 1514 cell 8 weight 1Mbit prio 8 maxburst 20 avpkt 1000
# c0: 1100 0000, 它是匹配TOS的第7和6位,即交互和控制位 置位的數據包.
# tc class add dev eth1 parent 1:1 classid 1:2 cbq bandwidth 10Mbit \
rate 1Mbit allot 1514 cell 8 weight 100Kbit prio 3 maxburst 20 avpkt 1000 split 1:0 defmap c0
# 3f:0011 1111, 它是匹配TOS的1~5位,也就是將剩余的所有數據包都匹配到本子類中.
# tc class add dev eth1 parent 1:1 classid 1:3 cbq bandwidth 10Mbit \
rate 8Mbit allot 1514 cell 8 weight 800Kbit prio 7 maxburst 20 avpkt 1000 split 1:0 defmap 3f
root節點1:0接收到的數據包將被分配到1:3 和 1:2子類中的情況為:
補充:
# tc class change dev eth1 classid 1:2 cbq defmap 01/01
# 這個change 可以給defmap提供一個mask(掩碼),但是暫時不理解它是什么意思.
# 這是原作者提供的 經過掩碼計算后, 優先權值的變化:
HTB(Hierarchical Token Bucket : 分層令牌桶)
有一個固定速率的鏈路,希望分割給多種不同的用途使用,為每種用途做出帶寬承諾並實現定量的帶寬借用,
這時你就需要使用HTB隊列規則了,它配置相比於CBQ簡單.
HTB參數解釋:
rate: 設定期望的最大限制速率.
burst: 設置突發流量在現有基礎上,可以增大多少.
ceil: 設置速率最高可達到多少. 此參數表明該子類可借用其兄弟類的空閑帶寬。
# tc qdisc add dev eth0 root handle 1: htb default 30
注:
default 30: 表明若過濾器沒有匹配到的流量都將被分配到root qdisc的1:30這個子類中.
# tc class add dev eth0 parent 1: classid 1:1 htb rate 6mbit burst 15k
# tc class add dev eth0 parent 1:1 classid 1:10 htb rate 5mbit burst 15k
注:
1:10這個子類,它的最大速率為5Mbps,它不可用借用其兄弟類的帶寬.
但下面兩個設置ceil ,表明它們可借用兄弟類空閑帶寬,最大速率可達到6Mbps.
# tc class add dev eth0 parent 1:1 classid 1:20 htb rate 3mbit ceil 6mbit burst 15k
# tc class add dev eth0 parent 1:1 classid 1:30 htb rate 1kbit ceil 6mbit burst 15k
# tc qdisc add dev eth0 parent 1:10 handle 10: sfq perturb 10
# tc qdisc add dev eth0 parent 1:20 handle 20: sfq perturb 10
# tc qdisc add dev eth0 parent 1:30 handle 30: sfq perturb 10
注:
perturb: 設定SFQ(隨機公平隊列)每隔10秒更新一次隨機散列算法,以便入隊數據包有機會被排在前面,
最終達到它們都能在可接受的時間內被發送.
添加過濾器,直接把流量導向相應的類:
# U32="tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32"
# $U32 match ip dport 80 0xffff flowid 1:10
# $U32 match ip sport 25 0xffff flowid 1:20
以上命令創建的TC結構圖:
TC過濾器創建:
# tc filter add dev 網卡名 parent 父類句柄 protocol ip prio 優先級值 u32 \
[match [ip [[src |dst [IPAddr/CIDR Mask]] [sport |dport 端口號 Mask] | protocol 協議號 Mask]] | \
handle FirewallMark fw] \
flowid 前面父類的子類句柄
注:
protocol: 支持/etc/protocols中定義的協議號.
創建基於端口的過濾器:
# tc filter add dev eth0 protocol ip parent 10: prio 1 u32 match ip dport 22 0xffff flowid 10:1
# tc filter add dev eth0 protocol ip parent 10: prio 1 u32 match ip sport 80 0xffff flowid 10:1
注:
上面兩個是精確匹配80, 即: 80和0xffff或運算的值 必須與 目標端口 匹配.
u32: 是一種根據協議內容做數據提取,與指定參數做匹配的參數.
# tc filter add dev eth0 protocol ip parent 10: prio 2 flowid 10:2 #默認所有流量都匹配.
創建基於地址的過濾器:
# tc filter add dev eth0 parent 10:0 protocol ip prio 1 u32 match ip dst 4.3.2.1/32 flowid 10:1
# tc filter add dev eth0 parent 10:0 protocol ip prio 1 u32 match ip src 1.2.3.4/32 flowid 10:1
注:
IP/32: 這是精確匹配主機IP. 若需要匹配網絡地址,可使用指定CIDR值,如:192.168.0.0/24
# tc filter add dev eth0 protocol ip parent 10: prio 2 flowid 10:2
基於源地址 和 源端口的過濾器:
# tc filter add dev eth0 parent 10:0 protocol ip prio 1 u32 match ip src 4.3.2.1/32 match ip sport 80 0xffff flowid 10:1
基於協議號的過濾器:
# tc filter add dev eth0 parent 10:0 protocol ip prio 1 u32 match ip protocol 1 0xff flowid 10:1
基於防火牆標記的過濾器:
# tc filter add dev eth1 protocol ip parent 1:0 prio 1 handle 6 fw flowid 1:1
# iptables -A PREROUTING -t mangle -i eth0 -j MARK --set-mark 6
基於TOS字段的過濾器:
# tc filter add dev ppp0 parent 1:0 protocol ip prio 10 u32 match ip tos 0x10 0xff flowid 1:4
高級過濾器:
基於路由的過濾器:
目的地址匹配:
# ip route add 192.168.10.0/24 via 192.168.10.1 dev eth1 realm 10
注:
realm :用於定義一個realm號碼,用於表示網絡或主機路由.
# tc filter add dev eth1 parent 1:0 protocol ip prio 100 route to 10 classid 1:10
注:
此命令定義節點 1:0 里添加了一個優先級是 100 的路由過濾器(或加分類器),
當來自192.168.10.0/24網絡的數據包到達這個節點時,就會查詢路由表,
若它要從eth1接口被路由出去,則匹配此路由,進而被發送到類1:10,並賦予優先級值為 100。
源地址匹配:
# ip route add 192.168.2.0/24 dev eth2 realm 2
# tc filter add dev eth1 parent 1:0 protocol ip prio 100 route from 2 classid 1:2
注:
若匹配到從192.168.2.0/24網絡過來的數據包,則將其送到1:2節點,並賦予優先級值為100.
管理大量過濾器:
注: 不建議使用,若真的有這類需求,可嘗試使用ipset 和 mark結合
當你需要管理大量過濾器時,為了避免大量過濾器對每一個數據包都做匹配,帶來嚴重的系統性能問題,
這里提供一種通過散列表來構建 多個鏈表,每個鏈表中僅有幾條規則過濾器,以便高效匹配過濾器.
下面的例子是對IP做散列表的示例:
假如說你有 1024 個用戶使用一個 Cable MODEM,IP 地址范圍是 1.2.0.0 到 1.2.3.255,
每個 IP 都需要不同過濾器來對待,最佳的做法如下:
1. 首先創建一個root過濾器
# tc filter add dev eth1 parent 1:0 prio 5 protocol ip u32
2. 然后構建出一個256項的散列表
# tc filter add dev eth1 parent 1:0 prio 5 handle 2: protocol ip u32 divisor 256
3.然后我們向表項中添加一些規則:利用IP地址的后半段做為
# tc filter add dev eth1 protocol ip parent 1:0 prio 5 u32 ht 2:7b: match ip src 1.2.0.123 flowid 1:1
# tc filter add dev eth1 protocol ip parent 1:0 prio 5 u32 ht 2:7b: match ip src 1.2.1.123 flowid 1:2
# tc filter add dev eth1 protocol ip parent 1:0 prio 5 u32 ht 2:7b: match ip src 1.2.3.123 flowid 1:3
# tc filter add dev eth1 protocol ip parent 1:0 prio 5 u32 ht 2:7b: match ip src 1.2.4.123 flowid 1:2
注:
這是第 123 項,包含了為 1.2.0.123、1.2.1.123、1.2.2.123 和 1.2.3.123 准備的匹配
規則,分別把它們發給 1:1、1:2、1:3 和 1:2。注意,我們必須用 16 進制來表示
散列表項,0x7b 就是 123
4.然后創建一個“散列過濾器”,直接把數據包發給散列表中的合適表項:
# tc filter add dev eth1 protocol ip parent 1:0 prio 5 u32 ht 800:: \
match ip src 1.2.0.0/16 \
hashkey mask 0x000000ff at 12 \
link 2:
注:
“800::” 這表示創建一個散列表,所有的過濾都將從這里開始.
at 12: 表示從IP頭的第12位開始匹配 mask的長度, IP頭的第12~15字節為源IP地址位.
”link 2:“ 表示匹配后,發送數據包發送到前面創建的第2個散列表項,即: 2:
IMQ(Intermediate queueing device: 中介隊列設備)
若需要使用IMQ,需要對內核,netfilter,iptables打補丁后才能使用:
https://blog.csdn.net/dayancn/article/details/45871523
這篇文章詳細講解了如何給Linux-kernel2.6.18的內核打上IMQ補丁的詳細步驟.
在Linux中由於隊列規定只能附加到網卡上,因此有兩個局限:
1. 雖可在入口做隊列規定,但在上面實現分類隊列規定可能性很小,所以相當於只支持出口整形.
2. 一個隊列規定只能處理一個網卡流量,無法全局限速.
IMQ就是為解決這兩個問題而誕生的,簡單說: 你可往一個隊列規定中放任何方向的流量, 我們可通過
iptables將打了特定標記的數據包在netfilter的NF_IP_PRE_ROUTING和NF_IP_POST_ROUTING兩個
鈎子函數處被攔截,並被送到附加在IMQ虛擬網卡上的隊列規定中, 這樣你就可對進入剛進入網卡的
數據包打上標記做入口整形,或把所有網卡當成一個個類來對待,做全局整形控制。