Sunday, July 8, 2012

TC (Traffic Control) command, 限制网络速度

几年前为宿舍的网速问题而烦恼的时候,师傅说了一句
"怎么你自己不做一个 server 来玩?"
"怎样?什么 server?"
"做自己的 gateway, firewall, dns server 啦!"
(心想。。。反正没有做过,何不一试?)
经过了几个礼拜的琢磨,终于有了一点着落,但是限制网速的办法还是没有,只好用最牛的方法 (完全 command line) 来限制网速。仅仅用一个 TC command 来搞定。
对于这个 TC command,我到现在都还没完全了解,只是上网找了一找,然后一直 try n error 将近两个月才调到到比较稳定的变量;很 efficient,不会有人拿多速度。

可是问题是这个限制一次只给一整个 IP range / subnet,也就是说当限制 300kbits 的时候,整个IP range/subnet 共享一个速度 (300 kbits)。 这可不行,我的目标是每一个 IP 都有自己的速度,当他怎么下载,下载的几快都好,都不会影响别人的速度。

在不断的尝试下,以我有限的知识,我只能想到一个 IP 一个 rule 的办法 (最多 255 个 rules)。
就写了以下的 shell script 来省时省力。

let's say 我们的目标,network interface 是 eth1,然后 interface speed 是 100 mbits,只限制 192.168.1.21 到 192.168.1.50 的 IP,再给每一个受限制 IP 都享有最高 768 kbits 的速度。

以下红色部分是可更改的 (based on 我们的目标),其余的部分当然也可更改(个人建议维持这个变量)。

oK! 新手,自己消化!有问题请 email 到 nick_khor@hotmail.com

1:  #!/bin/sh  
2:  TC=/sbin/tc  
3:  startNum=21  
4:  DEV=eth1  
5:  IP=192.168.1.  
6:  endNum=50  
7:    
8:  LINERATE=100mbit  
9:  THROTTLERATE=768kbit  
10:  sfqMTU=1500  
11:  sfqInterval=10  
12:  avpktSize=1000  
13:  classPrio=5  
14:  filterPrio=16  
15:  allotByte=1500  
16:  weightSize=1000kbit  
17:    
18:  $TC qdisc del dev $DEV root >/dev/null  
19:  $TC qdisc add dev $DEV root handle 1: cbq avpkt $avpktSize bandwidth $LINERATE   
20:    
21:  while [ $startNum != $endNum ]; do  
22:       $TC class add dev $DEV parent 1: classid 1:$startNum cbq rate $THROTTLERATE avpkt $avpktSize cell 8 weight $weightSize allot $allotByte prio $classPrio bounded isolated  
23:       $TC filter add dev $DEV parent 1: protocol ip prio $filterPrio u32 match ip dst $IP$startNum flowid 1:$startNum  
24:       $TC qdisc add dev $DEV parent 1:$startNum sfq quantum $sfqMTU perturb $sfqInterval  
25:       echo "$IP$startNum is added"  
26:        startNum=$(($startNum+1))  
27:  done