CBQ 筆記在下拜讀了如下,關於CBQ的相關文章.
http://netcity3.web.hinet.net/UserData/vegalou/qos-4.htmlhttp://www.study-area.org/tips/adv-route/Adv-Routing-HOWTO-8.htmlhttp://www.study-area.org/tips/cbq_init/cbq_init.htmhttp://www.study-area.org/tips/cbq.htmhttp://phorum.study-area.org/viewtopic.php?t=10356&highlight=cbq.init而下面的內容是自己的實作筆記!
下面是我用tc(traffic control)指令,做的一些簡單練習,沒什麼,只是自己做個紀錄,若要有較深入的了解,請看Advanced Routing HOWTO中的說明,重點會放在cbq.init上.
1.宣告頂層戒律
2.宣告頂層類別
3.宣告自訂類別
4.宣告管理佇列
5.定義什麼封包屬於什麼類別
1.宣告頂層戒律
tc qdisc add dev eth1 root handle 10: cbq bandwidth 10Mbit avpkt 1000
宣告root discipline(頂層戒律):總支配頻寬為10Mbit,handle為10(handle 10的"10"像是代表頂層戒律的名字)
2.宣告頂層類別
tc class add dev eth1 parent 10:0 classid 10:1 cbq bandwidth 10Mbit rate 10Mbit allot 1514 weight 1Mbit prio 8 maxburst 20 avpkt 1000
宣告頂層類別:parent 10:0(表示源自handle 10),classid 10:1(10:1代表該頂層類別的名字)
3.宣告自訂類別
tc class add dev eth1 parent 10:1 classid 10:100 cbq bandwidth 10Mbit rate 1Mbit allot 1514 weight 800Kbit prio 5 maxburst 20 avpkt 1000 bounded
宣告此類別名稱為10:100,parent 10:1(表示源自handle 10),rate 1Mbit(表示撥出1Mbit),bounded(表示不能超過rate的限制)
4.宣告管理佇列
tc qdisc add dev eth1 parent 10:100 sfq quantum 1514b perturb 15
宣告queue的工具為sfq
5.定義什麼封包屬於什麼類別
tc filter add dev eth1 parent 10:0 protocol ip prio 25 u32 match ip dst 216.59.185.249 flowid 10:100
宣告filter的工具為u32,過濾由eth1出去目的為216.59.185.249的封包.
刪除
tc filter del dev eth1 parent 10:0 protocol ip prio 25 u32 match ip dst 216.59.185.249 flowid 10:100
tc qdisc del dev eth1 parent 10:100 sfq quantum 1514b perturb 15
tc class del dev eth1 parent 10:1 classid 10:100 cbq bandwidth 10Mbit rate 1Mbit allot 1514 weight 800Kbit prio 5 maxburst 20 avpkt 1000 bounded
tc class del dev eth1 parent 10:0 classid 10:1 cbq bandwidth 10Mbit rate 10Mbit allot 1514 weight 1Mbit prio 8 maxburst 20 avpkt 1000
tc qdisc del dev eth1 root handle 10: cbq bandwidth 10Mbit avpkt 1000
自eth1流出目的為216.59.185.249的流量限制在5KB
tc qdisc add dev eth1 root handle 10: cbq bandwidth 10Mbit avpkt 1000
tc class add dev eth1 parent 10:0 classid 10:1 cbq bandwidth 10Mbit rate 10Mbit allot 1514 weight 1Mbit prio 8 maxburst 20 avpkt 1000
tc class add dev eth1 parent 10:1 classid 10:100 cbq bandwidth 10Mbit rate 50Kbit allot 1514 weight 800Kbit prio 5 maxburst 20 avpkt 1000 bounded
tc qdisc add dev eth1 parent 10:100 sfq quantum 1514b perturb 15
tc filter add dev eth1 parent 10:0 protocol ip prio 25 u32 match ip dst 216.59.185.249 flowid 10:100
刪除
tc filter del dev eth1 parent 10:0 protocol ip prio 25 u32 match ip dst 216.59.185.249 flowid 10:100
tc qdisc del dev eth1 parent 10:100 sfq quantum 1514b perturb 15
tc class del dev eth1 parent 10:1 classid 10:100 cbq bandwidth 10Mbit rate 50Kbit allot 1514 weight 800Kbit prio 5 maxburst 20 avpkt 1000 bounded
tc class del dev eth1 parent 10:0 classid 10:1 cbq bandwidth 10Mbit rate 10Mbit allot 1514 weight 1Mbit prio 8 maxburst 20 avpkt 1000
tc qdisc del dev eth1 root handle 10: cbq bandwidth 10Mbit avpkt 1000
自eth0流出來自216.59.185.249的流量限制在3KB
tc qdisc add dev eth0 root handle 10: cbq bandwidth 10Mbit avpkt 1000
tc class add dev eth0 parent 10:0 classid 10:1 cbq bandwidth 10Mbit rate 10Mbit allot 1514 weight 1Mbit prio 8 maxburst 20 avpkt 1000
tc class add dev eth0 parent 10:1 classid 10:100 cbq bandwidth 10Mbit rate 30Kbit allot 1514 weight 800Kbit prio 5 maxburst 20 avpkt 1000 bounded
tc qdisc add dev eth0 parent 10:100 sfq quantum 1514b perturb 15
tc filter add dev eth0 parent 10:0 protocol ip prio 25 u32 match ip src 216.59.185.249 flowid 10:100
刪除
tc filter del dev eth0 parent 10:0 protocol ip prio 25 u32 match ip src 216.59.185.249 flowid 10:100
tc qdisc del dev eth0 parent 10:100 sfq quantum 1514b perturb 15
tc class del dev eth0 parent 10:1 classid 10:100 cbq bandwidth 10Mbit rate 30Kbit allot 1514 weight 800Kbit prio 5 maxburst 20 avpkt 1000 bounded
tc class del dev eth0 parent 10:0 classid 10:1 cbq bandwidth 10Mbit rate 10Mbit allot 1514 weight 1Mbit prio 8 maxburst 20 avpkt 1000
tc qdisc del dev eth0 root handle 10: cbq bandwidth 10Mbit avpkt 1000
自eth0及eth1流出,來源及目的為216.59.185.249的流量限制為1KB
tc qdisc add dev eth0 root handle 10: cbq bandwidth 10Mbit avpkt 1000
tc class add dev eth0 parent 10:0 classid 10:1 cbq bandwidth 10Mbit rate 10Mbit allot 1514 weight 1Mbit prio 8 maxburst 20 avpkt 1000
tc class add dev eth0 parent 10:1 classid 10:100 cbq bandwidth 10Mbit rate 10Kbit allot 1514 weight 800Kbit prio 5 maxburst 20 avpkt 1000 bounded
tc qdisc add dev eth0 parent 10:100 sfq quantum 1514b perturb 15
tc filter add dev eth0 parent 10:0 protocol ip prio 25 u32 match ip src 216.59.185.249 flowid 10:100
tc filter add dev eth1 parent 10:0 protocol ip prio 25 u32 match ip dst 216.59.185.249 flowid 10:100
刪除
tc filter del dev eth1 parent 10:0 protocol ip prio 25 u32 match ip dst 216.59.185.249 flowid 10:100
tc filter del dev eth0 parent 10:0 protocol ip prio 25 u32 match ip src 216.59.185.249 flowid 10:100
tc qdisc del dev eth0 parent 10:100 sfq quantum 1514b perturb 15
tc class del dev eth0 parent 10:1 classid 10:100 cbq bandwidth 10Mbit rate 10Kbit allot 1514 weight 800Kbit prio 5 maxburst 20 avpkt 1000 bounded
tc class del dev eth0 parent 10:0 classid 10:1 cbq bandwidth 10Mbit rate 10Mbit allot 1514 weight 1Mbit prio 8 maxburst 20 avpkt 1000
tc qdisc del dev eth0 root handle 10: cbq bandwidth 10Mbit avpkt 1000
cbq.init一開始了解CBQ(Class Based Queueing)時是使用tc指令一行一行下宣告相關的設定,但tc指令實在不好下,參數很多不好了解也不好維護,而來用了cbq.init,發現好用多,真是個不錯的功具.
cbq.init是一個shell script,能較簡單的設定CBQ是它存在的目的,用法也很容易.
其實就是給cbq.init一些必要的條件,來產生出相同目的的tc指令.
1.下載cbq.init於/sbin
2.建立cbq目錄及建立須要檔案.
3.執行
1.下載cbq.init於/sbin
http://freshmeat.net/projects/cbq.init到這下載cbq.init目前版本為v0.7.2.
複製cbq.init-v0.7.2到/sbin為cbq.init
更改權限為700
2.建立cbq目錄及建立須要檔案.
建立/etc/sysconfig/cbq目錄(若不存在請自行建立).
目錄中建立的檔案,請參考
http://netcity3.web.hinet.net/UserData/vegalou/qos-4a.html特別注意:文中提到0002到ffff的範圍,若有錯在執行cbq.init start時不會有錯誤訊息,但下cbq.init compile去看,
會得到類似如下的錯誤.
**CBQ: class ID of cbq-0001.scribe must be in range <0002-FFFF>!
文中關於檔案中的內容有{}的那行不用寫到檔案中.3.執行
最後的執行時,可以先cbq.init compile看看,輸出的tc 指令為何,沒問題的話就cbq.init start啟動,停止就用cbq.init stop
可以下cbq.init 看說明.
以下面的條件及目的來建立,cbq目錄中的檔案,
1.gateway連internet的頻寬為512Kb
2.要管理的服務有4個,分別為http(80 port),smtp(25 port),php3(110 port),ftp data(passive mode port 20),這裡指的都是internet上server的port,
但client連到這些server 的port都是挑1024以上的port,這是要了解的地方.
3.假設local都是public ip (無nat)
4.頻寬分配:
110port 分配 192Kb
25port 分配 128Kb
80port 分配 128Kb
20port 分配 64Kb
5.gateway eth1與internet 介接,eth0與local public 介接.
建立檔案:
vi cbq-0002.eth0-110
DEVICE=eth0,100Mbit,512Kbit
RATE=192Kbit
WEIGHT=7Kbit
PRIO=5
RULE=:110,
BOUNDED=yes
ISOLATED=yes
vi cbq-0003.eth0-80
DEVICE=eth0
RATE=128Kbit
WEIGHT=5Kbit
PRIO=7
RULE=:80,
BOUNDED=yes
ISOLATED=yes
PARENT=0002
# vi cbq-0004.eth0-20
DEVICE=eth0
RATE=64Kbit
WEIGHT=3Kbit
PRIO=8
RULE=:20,
BOUNDED=yes
ISOLATED=yes
PARENT=0002
# vi cbq-0102.eth1-25
DEVICE=eth1,100Mbit,512Kbit
RATE=128Kbit
WEIGHT=5Kbit
PRIO=6
RULE=:25
BOUNDED=yes
ISOLATED=yes
# vi cbq-0103.eth1-20
DEVICE=eth1
RATE=64Kbit
WEIGHT=3Kbit
PRIO=8
RULE=:20
BOUNDED=yes
ISOLATED=yes
PARENT=0102
檔案中的各項參數請參考上面提到的文章,值得一提的是,欲管理的服務中pop3及web服務多為下載流量,smtp多為上傳流量,而ftp則上下傳流量不一定.
所以分別依其流向特性設定:
由eth0流出來源port為110,80,20的要管制,也就是cbq-0002.eth0-110,cbq-0003.eth0-80,cbq-0004.eth0-20
由eth1流出目的port為25,20的要管制,也就是cbq-0102.eth1-25,cbq-0103.eth1-20
這裡有個問題是關於ftp的,現在的設定是在使用active mode下server data的通道固定是20所以很好解決,但若換成passive mode後client及server的data通道是隨機的,這是比較麻煩的.
用u32分類器,我不知道能不能做到,但若搭配iptables並不難!
iptables加上下面二行.
iptables -A POSTROUTING -o eth1 -t mangle -p tcp --
dport 1024:65535 -j MARK --set-mark 30
iptables -A POSTROUTING -o eth0 -t mangle -p tcp --
sport 1024:65535 -j MARK --set-mark 20
而cbq-0103.eth1-20 、 cbq-0004.eth0-20 這二個檔改成下面那樣!
DEVICE=eth1
RATE=64Kbit
WEIGHT=3Kbit
PRIO=8
RULE=:20
MARK=30
BOUNDED=yes
ISOLATED=yes
PARENT=0102
DEVICE=eth0
RATE=64Kbit
WEIGHT=3Kbit
PRIO=8
RULE=:20,
MARK=20
BOUNDED=yes
ISOLATED=yes
PARENT=0002
cbq.init restart
這樣passiv mode 就限制住囉!但也代表上下傳所有的port在1024以上都受限制,不一定是ftp passive mode.
CBQ+SNAT的情形先敘述一下環境與設定.
eth0:對內
eth1:對外
iptables rule(policy all accept):iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
cbq config:DEVICE=eth0,100Mbit,512Kbit
RATE=64Kbit
WEIGHT=3Kbit
PRIO=5
RULE=192.168.1.1
BOUNDED=yes
ISOLATED=yes
DEVICE=eth1,100Mbit,512Kbit
RATE=64Kbit
WEIGHT=3Kbit
PRIO=6
RULE=192.168.1.1,
BOUNDED=yes
ISOLATED=yes
cbq.init compile:tc qdisc del dev eth0 root
tc qdisc add dev eth0 root handle 1 cbq bandwidth 100Mbit avpkt 1000 cell 8
tc class change dev eth0 root cbq weight 512Kbit allot 1514
tc qdisc del dev eth1 root
tc qdisc add dev eth1 root handle 1 cbq bandwidth 100Mbit avpkt 1000 cell 8
tc class change dev eth1 root cbq weight 512Kbit allot 1514
tc class add dev eth0 parent 1: classid 1:2 cbq bandwidth 100Mbit rate 64Kbit weight 3Kbit prio 5 allot 1514 cell 8 maxburst 20 avpkt 1000 bounded isolated
tc qdisc add dev eth0 parent 1:2 handle 2 tbf rate 64Kbit buffer 10Kb/8 limit 15Kb mtu 1500
tc filter add dev eth0 parent 1:0 protocol ip prio 100 u32 match ip dst 192.168.1.1 classid 1:2
tc class add dev eth1 parent 1: classid 1:102 cbq bandwidth 100Mbit rate 64Kbit weight 3Kbit prio 6 allot 1514 cell 8 maxburst 20 avpkt 1000 bounded isolated
tc qdisc add dev eth1 parent 1:102 handle 102 tbf rate 64Kbit buffer 10Kb/8 limit 15Kb mtu 1500
tc filter add dev eth1 parent 1:0 protocol ip prio 100 u32 match ip src 192.168.1.1 classid 1:102
用以上的環境及設定,我在192.168.1.1上做ftp傳輸的時候,下載是有受控管的,但上傳是不受控管的(也就是cbq沒做用),原因是為封包先進POSTROUTING chain(改寫source address)才進QOS EGRESS
,所以這時的source address己經不是192.168.1.1了,那當然cbq的filter就對它產生不了作用了,可以參考下面這個link的圖,了解封包通過的流程!
http://www.docum.org/stef.coene/qos/kptd/可以試試把eth1的設定改成如下:
DEVICE=eth1,100Mbit,512Kbit
RATE=64Kbit
WEIGHT=3Kbit
PRIO=6
RULE=[eth1 ip],
BOUNDED=yes
ISOLATED=yes
設成eth1上綁的ip再試試,您會發現上傳受控管了,也就是生效了.但這是無意義的,因為local所以出去的封包都會snat成外部封包,那便所有的控管對local ip都一視同仁,造成無法管理.
了解到上面的原因後,可以用iptables把封包mark起來,讓這些封包進QOS EGRESS,實作如下:
iptables rule(policy all accept):iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
iptables -A PREROUTING -i eth0 -t mangle -s 192.168.1.1 -j MARK --set-mark 40
cbq config:DEVICE=eth0,100Mbit,512Kbit
RATE=64Kbit
WEIGHT=3Kbit
PRIO=5
RULE=192.168.1.1
BOUNDED=yes
ISOLATED=yes
DEVICE=eth1,100Mbit,512Kbit
RATE=64Kbit
WEIGHT=3Kbit
MARK=40
PRIO=6
BOUNDED=yes
ISOLATED=yes
cbq.init compile:tc qdisc del dev eth0 root
tc qdisc add dev eth0 root handle 1 cbq bandwidth 100Mbit avpkt 1000 cell 8
tc class change dev eth0 root cbq weight 512Kbit allot 1514
tc qdisc del dev eth1 root
tc qdisc add dev eth1 root handle 1 cbq bandwidth 100Mbit avpkt 1000 cell 8
tc class change dev eth1 root cbq weight 512Kbit allot 1514
tc class add dev eth0 parent 1: classid 1:2 cbq bandwidth 100Mbit rate 64Kbit weight 3Kbit prio 5 allot 1514 cell 8 maxburst 20 avpkt 1000 bounded isolated
tc qdisc add dev eth0 parent 1:2 handle 2 tbf rate 64Kbit buffer 10Kb/8 limit 15Kb mtu 1500
tc filter add dev eth0 parent 1:0 protocol ip prio 100 u32 match ip dst 192.168.1.1 classid 1:2
tc class add dev eth1 parent 1: classid 1:102 cbq bandwidth 100Mbit rate 64Kbit weight 3Kbit prio 6 allot 1514 cell 8 maxburst 20 avpkt 1000 bounded isolated
tc qdisc add dev eth1 parent 1:102 handle 102 tbf rate 64Kbit buffer 10Kb/8 limit 15Kb mtu 1500
tc filter add dev eth1 parent 1:0 protocol ip prio 200 handle 40 fw classid 1:102
如此,在去試就生效了,而至於是在PREROUTING及POSTROUTING做mangle在下測試的結果是都可以,應該是反正只是mark而己麻,而POSTROUTING的mangle又在nat之前,所以沒差啦!!
但cbq 針對mark的話定,卻不能在eth0上,這是要注意的地方,而這是以snat做測試的,信相改成dnat也只是反過來而己!
整個測試的結論,其實不用太在意有沒有nat,一個關鍵是,只要能符合tc filter的條件,就能發生作用了!