【问题标题】:Linux tc, u32 filters strange errorLinux tc, u32 过滤奇怪的错误
【发布时间】:2014-01-30 10:42:38
【问题描述】:

请在问题中告诉我。我正在基于 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,也没有发生哈希表句柄超限。还有什么可能导致代码中出现此错误?

【问题讨论】:

    标签: linux


    【解决方案1】:

    我用另外两个内核重现了这个问题;现代 Ubuntu 12.04 3.5.0-39-generic 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 个过滤器。我不确定这种行为是错误、限制还是设计造成的。

    要解决此问题,您可以手动指定过滤器项目 ID,方法是将其放在 u32 过滤器声明之前,它必须具有零哈希表和存储桶 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
    

    【讨论】:

      猜你喜欢
      • 2015-03-02
      • 2021-05-10
      • 2020-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-28
      • 1970-01-01
      相关资源
      最近更新 更多