PLease在问题上告诉我。我正在使用基于CentOS x86_64,Linux版本2.6.32-431.3.1.el6.x86_64的构建流量整形器。因此,它有大约10个u32哈希表,全部有256个除数。在默认表800中,我对第3个八位字节进行散列并将数据包指向其中一个表,然后在散列第4个八位字节和点数据包到描述每个用户的带宽限制的类中。因此,对于每个IP地址,都有一个相应的tc类。我们很容易塑造3000个ip地址。当我的脚本将此IP添加到哈希表中时,我收到一个错误:RTNETLINK答案:文件存在。这里有更多代码:
tc qdisc add dev $inet root handle 2: htb default 8000
tc class add dev $inet parent 2: classid 2:6000 htb rate 100mbit
#this hash-tables are for subnets
for i in {901..912}; do
tc filter add dev $inet parent 2: handle $i: protocol ip u32 divisor 256
done
#adding filters for packet classifying
tc filter add dev $inet protocol ip parent 2: u32 ht 800:: match ip src 172.16.16.0/20 hashkey mask 0x0000ff00 at 12 link 901:
tc filter add dev $inet protocol ip parent 2: u32 ht 901:11: match ip src 172.16.17.0/24 hashkey mask 0x000000ff at 12 link 902:
tc filter add dev $inet protocol ip parent 2: u32 ht 901:12: match ip src 172.16.18.0/24 hashkey mask 0x000000ff at 12 link 903:
#...
#and so on under "link 912:"
#creating classes for every host, place it under root class 2: (100mb for all)
for i in {1..2815}; do tc class add dev $inet parent 2:6000 classid 2:$i htb rate 1mbit ceil 6mbit; done
#place each host in corresponding u32 table
for i in {1..255}; do printf -v hi "%x" "$i";
tc filter add dev $inet protocol ip parent 2: u32 ht 902:$hi: match ip src 172.16.17.$i flowid 2:$i
done
for i in {256..511}; do let j="i-256"; printf -v hi "%x" "$j";
tc filter add dev $inet protocol ip parent 2: u32 ht 903:$hi: match ip src 172.16.18.$j flowid 2:$i
done
#....
#and so on under 2815 hosts
在命令结束后的某个地方
tc filter add dev eth0 protocol ip parent 2: u32 ht 909:dc: match ip src 172.16.24.220 flowid 2:2012
RTNETLINK answers: File exists
We have an error talking to the kernel
我无法解决这个问题,我认为Linux内核中有一个过滤器编号限制,但是有些人说我这不是真的,没有任何限制。没有重复使用的flowid,并且没有哈希表处理超限发生。还有什么可以在代码中引起这个错误?
答案 0 :(得分:0)
我用另外两个内核重新创建了这个问题;现代的Ubuntu 12.04 3.5.0-39通用x86_64内核和较旧的Fedora 2.6.33.3-85 i686内核。它出现在两者上。
这里有一些u32过滤器文档:http://ace-host.stuart.id.au/russell/files/tc/doc/cls_u32.txt建议过滤器句柄的最后一部分,过滤器项,应该达到十六进制0xFFF,即4096(例如901:0:0到901:0: FFF)。手动添加过滤器时也是如此。但是,使用散列添加过滤器时,可以指定散列表和存储桶,但会自动创建过滤器ID。
问题是过滤器项目在自动创建时从800开始,这意味着您实际上只能使用0x800到0xFFE过滤器(总共2048个)。
你会认为你可以为你添加的每个2048个过滤器切换哈希表,正如你在你的例子中所做的那样,但事实并非如此 - 它仍然只允许你在散列时总共添加2048个过滤器。我不确定这种行为是一个错误,一个限制,还是放在那里设计。
要解决此问题,您可以通过将其置于u32过滤器声明之前手动指定过滤器项ID,它必须具有零散列表和存储区ID。这将允许您添加完整的4096过滤器,其中包含您的子网声明。它似乎也允许每个哈希表添加4096个过滤器,因此您可以通过链接到另一个哈希表来添加更多过滤器。你的脚本的最后一部分需要是这样的:
#place each host in corresponding u32 table
for i in {1..255}; do
printf -v hi "%x" "$i";
tc filter add dev $inet protocol ip parent 2: handle ::$hi u32 ht 902:$hi: match ip src 172.16.17.$i flowid 2:$i
done
for i in {256..511}; do
let j="i-256";
printf -v hi "%x" "$i";
printf -v hj "%x" "$j";
tc filter add dev $inet protocol ip parent 2: handle ::$hi u32 ht 903:$hj: match ip src 172.16.18.$j flowid 2:$i
done
#....
#and so on under 2815 hosts
这是我测试过的代码,它与你的代码相同,但我重组它只使用一个哈希表。它应该具有相同的效率。它只散列到最后一个八位字节所需的存储桶,然后按顺序匹配存储桶内的过滤器,而不是顺序匹配和链接到子网,然后散列到存储桶。
#!/bin/bash
inet='eth0'
# Delete any existing traffic shaping
tc qdisc del dev $inet root
tc qdisc add dev $inet root handle 2: htb default 8000
tc class add dev $inet parent 2: classid 2:6000 htb rate 100mbit
# Create a single hash table (901) with 256 buckets
tc filter add dev $inet parent 2: handle 901: protocol ip u32 divisor 256
# Direct traffic from 172.16.16.0 - 172.16.31.255 to link 901, hash on last octet of src ip
tc filter add dev $inet protocol ip parent 2: u32 ht 800:: match ip src 172.16.16.0/20 hashkey mask 0x000000ff at 12 link 901:
# Create classes for each host, place it under root class 2: (100mb for all)
for i in {1..2815}; do
hex_handle=$(echo "obase=16; $i" | bc)
tc class add dev $inet parent 2:6000 classid 2:$hex_handle htb rate 1mbit ceil 6mbit || exit 1;
done
# Add filters for each possible host
for y in {16..27}; do
for x in {1..255}; do
j=$(( (($y - 16) * 255) + $x ));
hex_bucket=$(echo "obase=16; $x" | bc)
hex_handle=$(echo "obase=16; $j" | bc)
tc filter add dev $inet protocol ip parent 2: handle ::$hex_handle u32 ht 901:$hex_bucket match ip src 172.16.$y.$x flowid 2:$hex_handle || exit 1;
done
done