The output of the following code
static int test(void) {
struct rte_acl_param param = {
.name = "ctx",
.socket_id = 0,
.rule_size = RTE_ACL_RULE_SZ(3),
.max_rule_num = 10,
};
struct rte_acl_ctx *ctx = rte_acl_create(¶m);
struct rte_acl_rule *rule;
rule = rte_zmalloc_socket(NULL, RTE_ACL_RULE_SZ(3), 0, 0);
rule->data.category_mask = 1;
rule->data.priority = 1;
rule->data.userdata = 1;
rule->field[0].value.u8 = 6;
rule->field[0].mask_range.u8 = 0xff;
rule->field[1].value.u32 = RTE_IPV4(192, 168, 1, 1);
rule->field[1].mask_range.u8 = 32;
rule->field[2].value.u32 = RTE_IPV4(192, 168, 1, 2);
rule->field[2].mask_range.u8 = 32;
if (rte_acl_add_rules(ctx, rule, 1)) {
printf("can't add rule #1\n");
return -1;
}
rule = rte_zmalloc_socket(NULL, RTE_ACL_RULE_SZ(3), 0, 0);
rule->data.category_mask = 1;
rule->data.priority = 1;
rule->data.userdata = 2;
rule->field[0].value.u8 = 6;
rule->field[0].mask_range.u8 = 0xff;
rule->field[1].value.u32 = RTE_IPV4(192, 168, 1, 0);
rule->field[1].mask_range.u8 = 24;
rule->field[2].value.u32 = RTE_IPV4(192, 168, 1, 0);
rule->field[2].mask_range.u8 = 24;
if (rte_acl_add_rules(ctx, rule, 1)) {
printf("can't add rule #2\n");
return -1;
}
typedef struct {
uint8_t proto;
uint32_t ip_src;
uint32_t ip_dst;
} ThreeTuple;
ThreeTuple test_data[] = {
{
.proto = 6,
.ip_src = RTE_IPV4(192, 168, 1, 1),
.ip_dst = RTE_IPV4(192, 168, 1, 2),
},
{
.proto = 6,
.ip_src = RTE_IPV4(192, 168, 1, 2),
.ip_dst = RTE_IPV4(192, 168, 1, 1),
},
};
uint32_t results[RTE_DIM(test_data)];
const uint8_t *data[RTE_DIM(test_data)];
for (size_t i = 0; i < RTE_DIM(test_data); i++) {
test_data[i].ip_src = rte_cpu_to_be_32(test_data[i].ip_src);
test_data[i].ip_dst = rte_cpu_to_be_32(test_data[i].ip_dst);
}
for (size_t i = 0; i != RTE_DIM(test_data); i++) data[i] = (uint8_t *)&test_data[i];
struct rte_acl_config cfg;
memset(&cfg, 0, sizeof(cfg));
static const struct rte_acl_field_def fieldDefs[] = {
{
.type = RTE_ACL_FIELD_TYPE_BITMASK,
.size = sizeof(uint8_t),
.field_index = 0,
.input_index = 0,
.offset = offsetof(ThreeTuple, proto),
},
{
.type = RTE_ACL_FIELD_TYPE_MASK,
.size = sizeof(uint32_t),
.field_index = 1,
.input_index = 1,
.offset = offsetof(ThreeTuple, ip_src),
},
{
.type = RTE_ACL_FIELD_TYPE_MASK,
.size = sizeof(uint32_t),
.field_index = 2,
.input_index = 2,
.offset = offsetof(ThreeTuple, ip_dst),
},
};
memcpy(&cfg.defs, fieldDefs, sizeof(fieldDefs));
cfg.num_fields = RTE_DIM(fieldDefs);
cfg.num_categories = 1;
if (rte_acl_build(ctx, &cfg)) {
printf("rte_acl_build failed\n");
return -1;
}
rte_acl_classify(ctx, data, results, RTE_DIM(data), 1);
printf("results: ");
for (size_t i = 0; i < RTE_DIM(results); i++) printf("%d, ", results[i]);
printf("\n");
rte_free(rule);
rte_acl_reset(ctx);
rte_acl_free(ctx);
return 0;
}
is
results: 2, 2,
while the first rule exactly matches the first test data. I expect longest prefix match, as in LPM library. If it's not so, how can I obtain the LPM behavior with ACL library?
What I have tried:
I tried changing the ips and fields types, but couldn't find what's wrong.