我目前正在使用一个流量整形 Linux 节点。规则集已增长到大约 2500 个主机,所有主机都通过 MAC 地址明确标识。过滤器配置是“基本”的,这意味着平均而言,在将数据包过滤到正确的类别之前,必须测试 1250 条规则。在我们目前看到的线路速率下,这会导致主机上的 CPU 过多,从而导致数据包被丢弃。
我想从线性链表规则集转移到 6 级哈希表查找(每个 MAC 地址字节一个)
我目前完全不确定如何实现这一点。关于此功能的大部分文档对我来说相当混乱,而且据我所知,它们全都基于 IP 地址哈希。
我目前正在使用过滤器根据 L2 标头值匹配数据包,例如(针对出口/上传):
苹果:52:54:00:12:34:56
tc filter add dev <dev> protocol ip parent 1:0 prio 1 u32 match u16 0x0800 at -2 match u16 0x3456 0xffff at -4 match u32 0x52540012 0xffffffff at -8 flowid 1:50
是否有任何资源可以供我参考,以便更好地解释哈希表设置?
答案1
假设 52:54:00:12:34:56 转到 1:50 和 52:54:00:12:37:56 变为 1:51。
对于 256 项规则拆分,首先从一哈希表,我们称之为2:
:
# tc filter add dev eth1 parent 1:0 prio 1 handle 2: protocol ip u32 divisor 256
要选择单个字节,我们选择特定偏移处的 4 个字节,并使用位掩码来选择哪一个。偏移量 0 将是有效负载的开始,负寻址将我们带回到第 2 层帧头。首先,返回 2 个字节以检查 ethertype (0x800),再返回 6 个字节将我们带到 (48 位) 源 mac 地址的开头。添加回 2 意味着以下内容(从减 6)4个字节是降低源 mac 地址的 32 位。从这里,我们可以将掩码中的 ff 替换为我们想要的 mac 地址中的字节。
# tc filter add dev <dev> protocol ip parent 1:0 prio 1 u32 ht 800:: \
match u16 0x0800 at -2 \
hashkey mask 0x000000ff at -6 \
link 2:
请注意,我的示例立即匹配 IPv4 过滤器,并且稍后不会重复,我认为这并不重要 - 无论如何,我们只需要它一次。
然后插入规则,将(十六进制)字节放入 ht 句柄。上面的对齐意味着哈希对于 8 位值来说inhashtable
是无操作,这意味着以:56
十六进制结尾的地址以十六进制显示ht 2:56
:
# tc filter add dev <dev> protocol ip parent 1:0 prio 1 u32 \
ht 2:56: \
match u16 0x3456 0xffff at -4 match u32 0x52540012 0xffffffff at -8 \
flowid 1:50
# tc filter add dev <dev> protocol ip parent 1:0 prio 1 u32 \
ht 2:56: \
match u16 0x3756 0xffff at -4 match u32 0x52540012 0xffffffff at -8 \
flowid 1:51
... any many more mac addr rules
流程图:
1:0 =hash 1st byte=> ht 2:56 =sequential mac filter=> flowid 1:50
当然,现在hashtable
为第二个(或更多)字节添加另一层是可能的,并且可能进一步减少遍历的规则数量,但你可能只有少数几个 mac 地址与最后一个字节匹配,所以为什么要费心去做6 级?