如何为非对齐的ICMP Code字段设置DPDK ACL的数值与掩码
我之前在配置DPDK ICMP ACL规则时也踩过几乎一模一样的坑,尤其是这个Code字段的匹配问题,DPDK的文档对这个细节讲得不够清楚,很容易绕进去。结合你的代码和遇到的问题,我给你梳理下关键点和解决办法:
核心问题:DPDK BITMASK字段的32位对齐要求
你已经注意到DPDK的限制——BITMASK字段必须用32位类型,但关键是如何设置对应的数值和掩码,而不是单纯把类型改成u32就行。当你把Code字段定义为RTE_ACL_FIELD_TYPE_BITMASK且size=sizeof(uint32_t)时,DPDK会从指定的offset位置读取完整的32位数据,然后用掩码去匹配,而不是只读取单个字节的Code值。
具体解决步骤
确认字段定义的正确性
你当前的icmp_defs中Code字段的定义是没问题的:{ .type = RTE_ACL_FIELD_TYPE_BITMASK, .size = sizeof(uint32_t), .field_index = C_CODE_FIELD_ICMP, .input_index = 3, .offset = offsetof (struct icmp_acl_tuple, code), },这里的
offset正确指向了code字段的起始地址,size=4符合DPDK的要求,不用改。设置规则的数值和掩码时要精准匹配字节位置
因为DPDK读取的是32位数据,而Code只是其中的1个字节,所以你需要:- 掩码:设置为
0x000000FF,这样只会匹配32位数据中的最低字节(也就是Code字段本身),忽略后面的3字节(结构体填充或其他数据)。 - 数值:把你要匹配的Code值放在32位变量的最低字节,比如要匹配Code=0,就设为
0x00000000;匹配Code=3,就设为0x00000003。
举个构造规则的代码示例:
struct rte_acl_rule icmp_rule = {0}; // 设置Code字段的匹配规则:匹配Code=0 icmp_rule.data[C_CODE_FIELD_ICMP].value.u32 = 0x00000000; icmp_rule.data[C_CODE_FIELD_ICMP].mask.u32 = 0x000000FF; // 其他字段(src_ip、dst_ip、type)的规则设置...- 掩码:设置为
检查输入数据的提取是否正确
你提到把数据指针指向mbuf中的IP源地址字段,这里要注意:- ICMP的Code字段在IP头之后的第2个字节(IP头长度一般是20字节,所以ICMP头起始于mbuf数据偏移+20的位置,Code是该位置的第1个字节之后的字节)。
- 如果你是把mbuf中的数据直接映射到
icmp_acl_tuple结构,要注意结构体的对齐问题:你的icmp_acl_tuple中,code字段后面会有2字节的填充(因为结构体要对齐到4字节边界),但这不影响,因为我们的掩码已经忽略了这些填充字节。
验证field_index的唯一性
确保C_CODE_FIELD_ICMP这个宏的数值和其他字段的field_index(比如C_TYPE_FIELD_ICMP、C_SRC_FIELD_ICMP)完全不同,DPDK会用field_index来区分不同的匹配字段,重复的话会导致规则混乱。
额外验证小技巧
你可以在匹配前打印出输入的icmp_acl_tuple中code字段对应的32位数据,看看实际读取的是什么值,再和规则中的value、mask对比,这样就能快速定位是不是数据提取或者规则设置的问题。
内容的提问来源于stack exchange,提问作者amigal

