使用TC的htb队列控制网络流量 - 布衣(Dream2008)

时间:2024-04-17 20:18:28

使用TC的htb队列控制网络流量

起因,放在公司内的部分服务器对外提供服务,而且是很重要的服务,但由于公司员工上网也要占据很大的流量,往往导致服务器抢不到带宽,严重影响服务器的对外服务,于是考虑限制公司员工上网的带宽,确保服务器对外提供服务的带宽。
网络设备及网络结构:
一根外接光缆专线,isp提供的带宽为4M(实际为不到5M,大概在4.8左右,也可能是换算方式不同导致的),对端(ISP方面)一个网关 1.1.1.1,下接一光猫,光猫接在一台linux双网卡PC上(配置只有赛扬2.1,512内存,用作iptables桥式防火墙,桥式防火怎么做我 以前说过,有点就是本身没有IP地址,一般来说无法从网上对其直接发起攻击,而且一旦出现故障,把网线拔了直接接在交换机上就可以让网络恢复正常工 作),pc下接一个交换机,分别连接了多台服务器,包括对外提供服务的视频服务器1.1.1.60,为员工提供上网服务的nat服务器1.1.1.56, 公司的邮件服务器1.1.1.57,测试监控服务器1.1.1.58等。
TC简介(traffic control):
tc自linux2.2内核以后逐渐被加在了内核里,成为linux服务器本身就能提供的一种服务,主要用作流量整形Shaping(就是控制带宽啦)和 流量调度Scheduling(防止个别人抢占带宽,保障大家都能获得相同上网机会的一种方法),它的工作方式是通过控制网卡的发包来控制流量(注意是网 卡,和具体跑什么协议就没有太多关系了,所以无论我的机器有没有IP地址都可以用它)。具体的可以通过我以前贴的linux高级路由和流量控制手册来了 解。
在最近版本的linux下,输入命令
ip link show
可以看到大概如下的信息:
1: lo: <LOOPBACK,UP,10000> mtu 16436 qdisc noqueue
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,10000> mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether 00:ab:cd:ef:50:51 brd ff:ff:ff:ff:ff:ff
3: eth1: <BROADCAST,MULTICAST,UP,10000> mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether 00:ab:cd:ef:50:52 brd ff:ff:ff:ff:ff:ff
这个命令主要是来看网络设备信息的,我们可以看到默认的qdisc规则是pfifo_fast,这就是无类的队列,完全由机器(系统)操作,我们不能人为地控制它。基本工作方式就是先进先出,或者说几乎不进行任何处理,只要能发的过来就都发出去。
htb队列是tc可分类队列的一种(对应无类的队列),最著名的其实是CBQ队列,但是CBQ好复杂啊,而且也很难做到精确,我看了头大,然后看到书里 说:“你有一个固定速率的链路,希望分割给多种不同的用途使用。为每种用途做出带宽承诺并实现定量的带宽借用。”哇,这正是我想要的,于是选择了htb。
我发现光讲概念很难说清楚——很难说得比手册里面说的更好了。干脆把脚本直接贴出来,然后进行详细解释,不懂的地方查手册好了。
先给大家看我的TCstart.sh
#!/bin/sh
#eth0 is pci card,eth1 is intergarte card!Note that!!
#configure for eth0
tc qdisc add dev eth0 root handle 1: htb default 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 2mbit ceil 3mbit burst 15k
tc class add dev eth0 parent 1:1 classid 1:20 htb rate 1mbit ceil 2mbit burst 15k
tc class add dev eth0 parent 1:1 classid 1:30 htb rate 0.5mbit ceil 1mbit 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
tc filter add dev eth0 protocol ip parent 1: prio 10 u32 match ip src 1.1.1.60/32 flowid 1:10
tc filter add dev eth0 protocol ip parent 1: prio 20 u32 match ip src 1.1.1.56/32 flowid 1:20
tc filter add dev eth0 protocol ip parent 1: prio 30 u32 match ip src 1.1.1.0/26 flowid 1:30
#configure for eth1
tc qdisc add dev eth1 root handle 1: htb default 30
tc class add dev eth1 parent 1: classid 1:1 htb rate 6mbit burst 15k
tc class add dev eth1 parent 1:1 classid 1:10 htb rate 2mbit ceil 3mbit burst 15k
tc class add dev eth1 parent 1:1 classid 1:20 htb rate 1mbit ceil 2mbit burst 15k
tc class add dev eth1 parent 1:1 classid 1:30 htb rate 0.5mbit ceil 1mbit burst 15k
tc qdisc add dev eth1 parent 1:10 handle 10: sfq perturb 10
tc qdisc add dev eth1 parent 1:20 handle 20: sfq perturb 10
tc qdisc add dev eth1 parent 1:30 handle 30: sfq perturb 10
tc filter add dev eth1 protocol ip parent 1: prio 10 u32 match ip dst 1.1.1.60/32 flowid 1:10
tc filter add dev eth1 protocol ip parent 1: prio 20 u32 match ip dst 1.1.1.56/32 flowid 1:20
tc filter add dev eth1 protocol ip parent 1: prio 30 u32 match ip dst 1.1.1.0/26 flowid 1:30

开始解说:因为只能控制发送包,所以想要限速必须在两块网卡上都限制,只是方向不同,你可以仔细看我加在eth0和eth1上的规则有什么不同。先说这5句:
tc qdisc add dev eth0 root handle 1: htb default 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 2mbit ceil 3mbit burst 15k
tc class add dev eth0 parent 1:1 classid 1:20 htb rate 1mbit ceil 2mbit burst 15k
tc class add dev eth0 parent 1:1 classid 1:30 htb rate 0.5mbit ceil 1mbit burst 15k
1首先在网卡eth0上建立根句柄1:,采用htb这种可分类的队列规定,默认数据包传输会被送到1:30这个下一级的分类队列中。2然后给根1:(你也 可以写成1:0)分配带宽,速率为6m,最大允许超出量为15k。3创建一个子类(或者叫子队列)1:10,速率为2兆,最大不能超过3m(意味着在总带 宽有剩余可用的状态下可以借用1m)。4创建子类1:20,速率1m,最大2m,最大允许超出量15k。5和前面差不多,应该能看懂吧?而且5就是默认的 发送方法。

再说这一段
tc qdisc add dev eth1 parent 1:10 handle 10: sfq perturb 10
tc qdisc add dev eth1 parent 1:20 handle 20: sfq perturb 10
tc qdisc add dev eth1 parent 1:30 handle 30: sfq perturb 10
目的是调度,或者说确保不至于让某种传输占用过多的带宽,针对每个分类1:10,1:20和1:30设置每10秒钟变换一次算法——保障不会出现某种网络连接因为某种算法优势一直传输的比其他连接快。

最后一段,添加过滤器,也就是说让计算机知道哪种数据包会被分到哪个队列中排队。
tc filter add dev eth1 protocol ip parent 1: prio 10 u32 match ip dst 1.1.1.60/32 flowid 1:10
tc filter add dev eth1 protocol ip parent 1: prio 20 u32 match ip dst 1.1.1.56/32 flowid 1:20
tc filter add dev eth1 protocol ip parent 1: prio 30 u32 match ip dst 1.1.1.0/26 flowid 1:30
第一条是给eth1添加过滤器filter,针对的协议是ip协议,放置的位置在根节点1:上,优先级为10,使用u32匹配的方式,匹配 (match)ip的目的地址为1.1.1.60/32(一台主机),一旦数据包满足条件,就放到队列1:10中去,也就是传输速率保障在2兆,但可以从 富裕带宽中借用1兆的那个队列。

TC实在是有点复杂,我没法表达的很清楚(自己还有很多地方没闹明白呢),有具体问题再交流吧。