限制頻寬簡便法

現在的環境是,幾個室友共用一條 64/512K ADSL, 平常用的時候當然是沒有什麼問題,但是一遇到有人在抓檔案, 其他用到 telnet 的人就叫苦連天了,按鍵反應比數據機還慢。

以下描述的是我目前的設定法,不是最完美解決法,還有討論的 空間。

-----+      rl0+---+rl1       +---+  /
ADSL |---------|NAT|----------|HUB|------- 192.168.2.x
-----+         +---+          +---+  \____ 
一、設定:
主要使用 Dummynet 的 pipe 來限制每台電腦的進出流量
bugs@nat /usr/src # cat /etc/ipfwrules
add 1000 fwd 127.0.0.1,3128 tcp from 192.168.2.0/24 to any 80 via rl1
pipe 911 config bw 7kby queue 3 mask src-ip 0xffffffff
pipe 912 config bw 56kby queue 25 mask dst-ip 0xffffffff
add 2100 pipe 911 ip from 192.168.0.0/16 to any via tun0 out
add 2200 pipe 912 ip from any to 192.168.0.0/16 via tun0 in
2.說明
最簡單的想法是,每台電腦對外的流量以 pipe 的 bandwidth 來 限制。因為ADSL上下傳是不對稱的,所以兩個pipe分開來設定。這 裡給每台電腦的上限是線路值的7/8, 也就是 56/448k。這樣一來如 果有某個白目使用者用flashget 抓檔案又不會設定,起碼其他人還 有8/64k可用。

在頻寬較小的線路上使用 pipe, 可能會遇到 queue 設定不對, 而使速度達不到要求,甚至狀似斷線的情形發生。主要的原因是 queue 太大。當packet 通過 pipe 的時候,dummynet 會先把封包 儲存在 queue 裡等待送出,如果queue 已經滿了,則送給 source host 一個 'source quench' 的 icmp message, 告知它現在這個線 路不能負荷太多的資料,讓它減緩送出的速度。以 Dummynet default 的 50 個 slot 為例,乘上PPPoE 的 1492 bytes MTU, 75KB 的queue 上傳資料需要近十秒才能送出,與封包的 TTL 不能 配合的話,東西就永遠送不到目的地了。所以上面將queue 設小。

這在 ipfw 的 man page 裡有提到。

而要針對每台host 給予頻寬限制,就需要用到 mask 了。 mask 的用處是,將 mask 過後相同的 ip/port 放在同一個 bucket 裡處 理。

如果不特別指定時,mask 是 all bits 0, 也就是大家全部共 用一個bucket。上面的 0xffffffff則是說我們要針對每個 host 給 予一個bucket, 分開使用 56/448k 的pipe。

因為內部只用到了 192.168.2.x 的ip, 事實上用0x000000ff 就可以達到相同的效果。

當然總量還是受到實際上的線路限制。

pipe 911,912 設定好後,把進出的資料分別導到對應的 pipe上 ,就大功告成了。

事實上是很簡單的。 rule 1000 是 transparent proxy 用的,和本文沒有什麼關係 。:P

3.效果

要看出究竟有哪些 pipe, 可以由 'ipfw pipe list' 這個指令看出

bugs@nat /usr/src # ipfw pipe list
00911: 56.000 Kbit/s 0 ms 3 sl. 4 queues (64 buckets) droptail
mask: 0x00 0xffffffff/0x0000 - 0x00000000/0x0000
BKT Prot ___Source IP/port____ ____Dest. IP/port____ Tot_pkt/bytes
Pkt/Byte Drp
34 ip 192.168.2.5/0 0.0.0.0/0 7364 314315 0 0 0
38 ip 192.168.2.7/0 0.0.0.0/0 8337 475080 0 0 43
48 ip 192.168.2.12/0 0.0.0.0/0 591673 24737034 0 0 222
56 ip 192.168.2.200/0 0.0.0.0/0 40134 1721600 0 0 39
00912: 448.000 Kbit/s 0 ms 25 sl. 4 queues (64 buckets) droptail
mask: 0x00 0x00000000/0x0000 - 0xffffffff/0x0000
BKT Prot ___Source IP/port____ ____Dest. IP/port____ Tot_pkt/bytes
Pkt/Byte Drp
21 ip 0.0.0.0/0 192.168.2.5/0 6440 986339 0 0 0
23 ip 0.0.0.0/0 192.168.2.7/0 10151 13172240 0 0 0
24 ip 0.0.0.0/0 192.168.2.200/0 64036 67146095 0 0 0
28 ip 0.0.0.0/0 192.168.2.12/0 513090 653854360 0 0 0


這裡可以看出,每個 host 進出都各有一個自己的bucket。

4.討論

或許有人會問,dummynet 不是可以設定 weight 嗎?

用這個方式應該比較能有效利用頻寬才對。不過就我個人的經驗來說,即使把其他的weight 都降到100, telnet port 設為 weight 1, 仍然會有可察覺的delay, 所以才沒有採用這個方法。或許我是哪邊又設錯了也說不定。 :P

<<版權所有:bugs.bbs@bbs.cis.nctu.edu.tw>>

<<排版:梁楓>>

本文轉載經原作者同意