2010年8月24日 星期二

實作QOS頻寬管制(上下載)

為什麼要頻寬管制,因為有人佔住了頻寬,所以我們要加以管制
(切記,以下是在ubuntu 7.10底下實作,等我有時間會在CentOS4,5下試試是否可行)

1.首先請先確定你的linux系統核心(kernel}有無支源HTB
grep "HTB" /boot/config-`uname -r`
有秀出config_net_sch_htb=m 就ok

2..確認有無裝iproute 套件 因為套件裡需要用到tc指令
apt-cache search iproute 確認看看 基本上ubunut7.10上已經有內建在核心了
apt-cache show iproute 顯示套件資訊(題外話,供參考)
apt-cache showsrc iproute顯示原始碼相關資料(題外話,供參考)
apt-cache depends iproute 秀出相依性(題外話,供參考)

開始實作,但實作前請先到
這邊看一下基本語法
然而這邊已假設您已經看過上述網頁 這邊引用文章裡的重要語法來說明
有礙於篇幅,只能針對重點來說明:
Linux QoS 的佇列規則有兩種:CBQ,HTB
CBQ (Class Based Queueing) 的設定比較複雜,但可設定的東西較多,彈性較大
HTB (Hierarchy Token Bucket) 是 CBQ 的改良版 ,設定較精簡,效能也比 CBQ 來的好
所以以下步驟是以 HTB 為主。
Linux QoS 過濾器有兩種:u32,fw
u32: 設定比較複雜,需懂封包結構,才有辦法設定
fw:fw 是靠 iptables 給封包貼標籤,設定比較簡單
所以以下步驟是 fw 為主。
另外您要對iptables 也要稍為有一些概念
iptables 指令:
Linux 負責防火牆功能的,是一個叫 NetFilter 的模組,而 iptables 就是用來設定 NetFilter 模組的指令。
tc 指令:
Linux 負責QoS (頻寬管制) 功能的,是一個叫 Traffic Control 的模組,而 tc 就是用來設定 Traffic Control 模組的指令。
以下所有的編輯內容將會透過shell script來完成
這樣除錯也方便,不是嗎! ^^
(底下盡可能將在實作上遇到的一些轉換即路由封包的來源原理透過比較白話的方式表達)
實作開始:
筆者家中網路環境是:中華電信 8M / 640K
先了解一下單位數
ADSL 的頻寬單位,是 bps (bits per second)
所以-->8M等於1024*8=8192k bps
但因為HTB 佇列規則用的是 KByte/s
故8 bps = 1 Byte/s
所以8192/8=1024 kb/s
下載總頻寬 8Mbps= 1024 KB/s
上傳總頻寬 640kbps=80 KB/s
接下來至
hinet測速度網站得知大約值
[ 5614 K bps ] (相當於 688 K bytes/sec )<--這是筆者這邊測的數據不代表你也是這個= =
也就是說每秒最高可達688 kb(下載)當然因受距離與環境限制所以這個值還算可以接受
我將這個平均值除以2取整數為300kb/s來當做我要Qos的總頻寬
上載部份80/2=40kb/s
實際規劃瓜分數據
下載總頻寬=300kb/s
上傳總頻寬=40kb/s
將現有頻寬分為三塊
1.高優先且頻寬給最多 (10:10)
2.普通使用者(10:20)
3.常透過Foxy將頻寬佔住的 畫分少量頻寬(10:30)
(前者(160)為保證頻寬,後者(200)為最大頻寬)
1.(10:10) 160~200 101
2.(10:20) 90~150 102
3.(10:30) 50~100 103
原始碼/usr/local/bin/qos
以下內容是根據上面的原則來規範
(您必需知道的是在linux核心限制,CBQ與HTB最多能定義8層,但因包
含最上層佇列規則,所以實施使用只能定義7層)
#!/bin/bash
#一開始就清除所有的佇列規則並且忽略錯誤訊息(2>/dev/null)
tc qdisc del dev eth1 root 2>/dev/null
#定義最頂層(根)佇列規則,並指定 default 類別編號
tc qdisc add dev eth1 root handle 10: htb default 20
# 定義第一層的 10:1 類別 (總頻寬)
tc class add dev eth1 parent 10: classid 10:1 htb rate 300kbps ceil 300kbps
# 定義第二層葉類別(rate 保證頻寬,ceil 最大頻寬,prio 優先權)
tc class add dev eth1 parent 10:1 classid 10:10 htb rate 160kbps ceil 200kbps prio 0
tc class add dev eth1 parent 10:1 classid 10:20 htb rate 90kbps ceil 150kbps prio 1
tc class add dev eth1 parent 10:1 classid 10:30 htb rate 50kbps ceil 100kbps prio 2
#------定義各葉類別的佇列規則---------------
#parent 類別編號,handle 葉類別佇列規則編號
#因上面已經用htb來頻寬管理了故後面用簡單無qos的佇列規則piffo即可
tc qdisc add dev eth1 parent 10:10 handle 101: pfifo
tc qdisc add dev eth1 parent 10:20 handle 102: pfifo
tc qdisc add dev eth1 parent 10:30 handle 103: pfifo
#---------------set filter--------------------------
#FW可以依標籤將封包分類
#指定貼有 10 標籤 (handle) 的封包,歸類到 10:10 類別,以此類推
tc filter add dev eth1 parent 10: protocol ip prio 100 handle 10 fw classid 10:10
tc filter add dev eth1 parent 10: protocol ip prio 100 handle 30 fw classid 10:30
#---------------set iptables mangle-----------------
#利用防火牆將封包貼上標籤
iptables -F -t mangle
iptables -t mangle -A POSTROUTING -d 192.168.1.99 -j MARK --set-mark 30

大致上是這樣子,設定完記的為qos檔加上執行權限
chmod 700 /usr/local/bin/qos
接下來,開機要執行將qos檔加入/etc/rc.local裡就可以摟!
如果要測試可以打source qos 或 . qos都可以唷 兩張方式
然後用tc qdisc 觀看結果
筆者測試方式是先用
wget ftp://ftp.adsl.hinet.net/test_100m.zip
此檔為
中華電信網站
所提供測試網站的檔案(下載速度測試,檔案大小 100 MB)
測試電腦ip為192.168.1.99

root@ubuntu # wget ftp://ftp.adsl.hinet.net/test_100m.zip
==>SYST...done.  ==> PWD...done.
.....
11%[             ]7,652,144   623.70K/s

第一次測試差不多500~650kb左右 然後. qos 載入我剛打好的指令稿
在跑一次

root@ubuntu #source qos(秉持著沒有消息就是好消息的原則)成功載入
root@ubuntu # wget ftp://ftp.adsl.hinet.net/test_100m.zip
....
9%[             ]7,652,144   94.70K/s

實際測試速度果然在控制範圍之內100kb之內
這是因為上面我們定義mark 30的保證頻寬50kbps最大頻寬為100kbps
保證一定在50以上但不會超過100,但這是因為Mark10與20都沒有人在下載東西
你要注意Mark 30的優先順序是2(越小優先權越高),如果10與20都有電腦在抓東西
那麼肯定30這台電腦絕對跑不到94.70應該就在50左右,頻寬會優先分給prio為0的電腦唷!

另外來解釋一下這一行 為什麼是下載是POsTROUTING 而不是PREROUTING
iptables -t mangle -A POSTROUTING -d 192.168.1.99 -j MARK --set-mark 30
這邊會一併解釋下載與上傳的原理
因為是透過NAT加兩張網卡,一張對內(eth1)一張對外(ppp0)
故會用到兩種串鍊(chains)
正常NAT架構是
封包進來>(PREROUTING)>(INPUT)>本機電腦
封包出去<(POSTROUTING)<(OUTPUT)< 本機電腦

先要有一個概念就是內部電腦不管下載或上傳都是外送流量到nat主機上
內部電腦(pc)下載的解釋:
pc向internet請求封包(可想成在瀏覽網頁突然要下載東西)然後nat主
機收到將封包傳給eth1(eth1在將封包外送給pc)所以下載就是eth1的
外送流量,既然是將封包送出去所以當然是用(POSTROUTING)這個鍊摟!
內部電腦(pc)上傳的解釋:
假設內部有架設web Server,路人甲上網瀏覽透過你的網站下載了一個檔
案,即是外網向PC請求封包,在封包進入對外PPP0介面時即透過PREROUTING
轉向內部在透過PPP0外送流量給外網。
所以上傳是設定在PPP0此介面,以下將會介紹如何頻寬管制(上傳篇)

頻寬管制上傳實作設定:
上傳總頻寬為40kb
這邊一樣分成三塊
佇列規則根為40: (自取名稱)
1.(40:10)101 高優先且頻寬給最多
2.(40:20)102 普通使用者
3.(40:30)103 濫用網路的使用者
這邊只基本的將要限至上傳的葉類別分成三塊

原始碼/usr/local/bin/qosppp
#!/bin/bash
#一開始就清除所有的佇列規則並且忽略錯誤訊息
tc qdisc del dev ppp0 root 2>/dev/null
#定義最頂層(根)佇列規則,並指定 default 類別編號
#default就是當沒有任何來源被指定標籤就會套用這個Default 20
tc qdisc add dev ppp0 root handle 40: htb default 20
# 定義第一層的 10:1 類別 (上傳總頻寬)
tc class add dev ppp0 parent 40: classid 40:1 htb rate 40kbps ceil 40kbps
# 定義第二層葉類別(rate 保證頻寬,ceil 最大頻寬,prio 優先權)
tc class add dev ppp0 parent 40:1 classid 40:10 htb rate 24kbps ceil 40kbps prio 1
tc class add dev ppp0 parent 40:1 classid 40:20 htb rate 10kbps ceil 20kbps prio 2
tc class add dev ppp0 parent 40:1 classid 40:30 htb rate 6kbps ceil 10kbps prio 3
#------定義各葉類別的佇列規則---------------
#parent 類別編號,handle 葉類別佇列規則編號
#因上面已經用htb來頻寬管理了故後面用簡單無qos的佇列規則piffo即可
tc qdisc add dev ppp0 parent 40:10 handle 101: pfifo
tc qdisc add dev ppp0 parent 40:20 handle 102: pfifo
tc qdisc add dev ppp0 parent 40:30 handle 103: pfifo
#FW可以依標籤將封包分類
tc filter add dev ppp0 parent 40: protocol ip prio 100 handle 10 fw classid 40:10
tc filter add dev ppp0 parent 40: protocol ip prio 100 handle 20 fw classid 40:20
tc filter add dev ppp0 parent 40: protocol ip prio 100 handle 30 fw classid 40:30
#利用防火牆將封包貼上標籤
iptables -t mangle -A PREROUTING -s 192.168.3.11 -j MARK --set-mark 10
iptables -t mangle -A PREROUTING -s 192.168.1.12 -j MARK --set-mark 30

一樣將原始碼/usr/local/bin/qosppp 加在/etc/rc.local裡讓開機載入!
實作完成後來透過內部的HTTP SERVER測試一下 以192.168.1.12 來測試
透過外網來抓取內部的檔案就等於是192.168.1.12這台http server的上傳
果然在實測部份每秒的傳輸速度都控制在6~10kb/s左右
以上規則您可以照您的需求來變更~

轉載自: http://ms2.chshs.tpc.edu.tw/blog/index.php?op=ViewA

How to use simple speedtest in RaspberryPi CLI

  pi@ChunchaiRPI2:/tmp $  wget -O speedtest-cli https://raw.githubusercontent.com/sivel/speedtest-cli/master/speedtest.py --2023-06-26 10:4...