- 论坛徽章:
- 0
|
原帖由 platinum 于 2006-12-20 15:56 发表
这句我没有明白
不知道你是否理解 hash 的原理,根据我的理解,只要内存足够大,hash 检索的时间几乎可以忽略不计,比如大数组下标
12.4. 当过滤器很多时如何使用散列表
如果你需要使用上千个规则——比如你有很多需要不同QoS的客户机——你可
能会发现内核花了很多时间用于匹配那些规则.
缺省情况下,所有的过滤器都是靠一个链表来组织的,链表按priority的降序排
列.如果你有1000个规则,那么就有可能需要1000次匹配来决定一个包如何处
理.
而如果你有256个链表,每个链表4条规则的话,这个过程可以更快.也就是说
如果你能把数据包放到合适的链表上,可能只需要匹配4次就可以了.
利用散列表可以实现.比如说你有1024个用户使用一个Cable MODEM,IP地
址范围是1.2.0.0到1.2.3.255,每个IP都需要不同容器来对待,比如"轻量级",
"中量级"和"重量级".你可能要写1024个规则,象这样:
# tc filter add dev eth1 parent 1:0 protocol ip prio 100 match ip src \
1.2.0.0 classid 1:1
# tc filter add dev eth1 parent 1:0 protocol ip prio 100 match ip src \
1.2.0.1 classid 1:1
...
# tc filter add dev eth1 parent 1:0 protocol ip prio 100 match ip src \
1.2.3.254 classid 1:3
# tc filter add dev eth1 parent 1:0 protocol ip prio 100 match ip src \
1.2.3.255 classid 1:2
为了提高效率,我们应该利用IP地址的后半部分作为散列因子,建立256个散
列表项.第一个表项里的规则应该是这样:
# tc filter add dev eth1 parent 1:0 protocol ip prio 100 match ip src \
1.2.0.0 classid 1:1
# tc filter add dev eth1 parent 1:0 protocol ip prio 100 match ip src \
1.2.1.0 classid 1:1
# tc filter add dev eth1 parent 1:0 protocol ip prio 100 match ip src \
1.2.2.0 classid 1:3
# tc filter add dev eth1 parent 1:0 protocol ip prio 100 match ip src \
1.2.3.0 classid 1:2
下一个表项应该这么开始:
# tc filter add dev eth1 parent 1:0 protocol ip prio 100 match ip src \
1.2.0.1 classid 1:1
...
这样的话,最坏情况下也只需要4次匹配,平均2次.
70
具体配置有些复杂,但是如果你真有很多规则的话,还是值得的.
我们首先生成root过滤器,然后创建一个256项的散列表:
# tc filter add dev eth1 parent 1:0 prio 5 protocol ip u32
# tc filter add dev eth1 parent 1:0 prio 5 handle 2: protocol ip u32 divisor 256
然后我们向表项中添加一些规则:
# tc filter add dev eth1 protocol ip parent 1:0 prio 5 u32 ht 2:7b: \
match ip src 1.2.0.123 flowid 1:1
# tc filter add dev eth1 protocol ip parent 1:0 prio 5 u32 ht 2:7b: \
match ip src 1.2.1.123 flowid 1:2
# tc filter add dev eth1 protocol ip parent 1:0 prio 5 u32 ht 2:7b: \
match ip src 1.2.3.123 flowid 1:3
# tc filter add dev eth1 protocol ip parent 1:0 prio 5 u32 ht 2:7b: \
match ip src 1.2.4.123 flowid 1:2
这是第123项,包含了为1.2.0.123,1.2.1.123,1.2.2.123和1.2.3.123准备的匹配
规则,分别把它们发给1:1,1:2,1:3和1:2.注意,我们必须用16进制来表示
散列表项,0x7b就是123.
然后创建一个"散列过滤器",直接把数据包发给散列表中的合适表项:
# tc filter add dev eth1 protocol ip parent 1:0 prio 5 u32 ht 800:: \
match ip src 1.2.0.0/16 \
hashkey mask 0x000000ff at 12 \
link 2:
好了,有些数字需要解释.我们定义散列表叫做"800:",所有的过滤都从这里
开始.然后我们选择源地址(它们位于IP头的第12,13,14,15字节),并声明
我们只对它的最后一部分感兴趣.这个例子中,我们发送到了前面创建的第2个
散列表项.
这比较复杂,然而实际上确实有效而且性能令人惊讶.注意,这个例子我们也可
以处理成理想情况——每个表项中只有一个过滤器!
======================================
以上是转自高级路由流量控制的, 如果要所有ip都使用一个规则:比如所有ip出口都控制在50k (不要惊讶,对于lz的网络同时在线的,如果想平均分配,也就这么点带宽了),那么的确简单 hashkey那里的 mask修改地大一些,全部匹配进去就ok了,这就是你所谓的快速;但是,真正实施的时候,经常是针对着不同的区域乃至不同的用户来进行流量控制的(我们这里按照lz的想法,不在下面的switch上做qos,所有的qos都在nat位置做),那么势必就需要增多规则,并将不同的ip划分到不同的规则里,需要不同的hashkey mask了,确认否?然后再仔细一点,教工区的行政/教师办公/乃至给敬爱的校长大人们是否又需要特别地设置不同地带宽(要真够胆子让校长家/办公室只有那么点平均带宽,怕是年终考评不想及格了!?)? 这样仔细地分下去,那么到最后很可能需要的就是一段ip乃至一个ip就需要一个特别的hashkey mask,也就是说针对每个ip需要独立而且不同的流量控制了~~~ 这时候散列表的需求就出来了。 说得明白否? |
|