[dpdk-users] ACL library doesn't match reliably

Petr Houska t-pehous at microsoft.com
Thu Aug 16 19:23:13 CEST 2018


Hi,
I managed to find the source of the weird issues described in my previous email
(though the issues from bug #79 still persist), I still have few questions, however.

The problem lied in the order of fields definition in the `ipv4_defs` array. The order has
to correspond with `field_index` (which it didn't in my case and I completely missed that).
Maybe a validation that this precondition is true could be beneficial on rte_acl_build?

That said I have few questions about the ACL library assumptions. The documentations states
` First field in the rule definition has to be one byte long. ` and ` All subsequent fields has to be
grouped into sets of 4 consecutive bytes. `.

Going through the (matching) implementation it seemed to me that not only the first field in the rule
definition has to be one byte long but that it also needs to correspond to the field that is first in
the input buffer.

If that's the case it raises another question. Do the rule's fields have to be (defined) in the order
of their respective positions in input buffer? I.e. the first field in the definition must correspond
to lowest offset, the last to the highest, etc.?

>From my limited testing the matching seem to work even if it's not the case. The matching
Implementation, however, seems to hint (especially with the first 8bit field) that it wouldn't
have to.


From: Petr Houska
Sent: Wednesday, August 15, 2018 3:30 PM
To: 'users at dpdk.org' <users at dpdk.org>
Subject: ACL library doesn't match reliably

Hi,
I've been trying to create a DPDK app that uses the ACL library and came across a really weird behavior.
First I thought it has to be a bug in the ACL library (see bug #79) but when I poked the library a bit more I
found that the matching is extremely unreliable even when having _way_ smaller rulesets. Thus I'm more
inclined to believe the problem lies in the way I use the library and not in the library itself.

I have a structure that I match on, basically a 5tuple:
```
struct fiveTuple
{
    uint8_t transportProtocol;
    uint16_t sourcePort;
    uint16_t destinationPort;
    uint32_t smth;
    IPAddress source;
    IPAddress destination;
} __rte_cache_aligned;

union ipAddress
{
    uint32_t ipv4Address;
    uint8_t  ipv6Address[16];
};
```

Then I have a rule defined in following way:
```
/* Field's indexes in rules */
enum
{
    ACL_RULE_IPV4_PROTO_FIELD,
    ACL_RULE_IPV4_SRC_FIELD,
   ACL_RULE_IPV4_FIELDS_NB
};

/* Indexes of 4-byte chunks in input */
enum
{
    ACL_RULE_IPV4_PROTO_CHUNK,
    ACL_RULE_IPV4_PORTS_CHUNK,
    ACL_RULE_IPV4_SRC_CHUNK,
};

/* IPv4 rule definition */
struct rte_acl_field_def ipv4_defs[ACL_RULE_IPV4_FIELDS_NB] = {
    {
        .type = RTE_ACL_FIELD_TYPE_BITMASK,
        .size = sizeof(uint32_t),
        .field_index = ACL_RULE_IPV4_SRC_FIELD,
        .input_index = ACL_RULE_IPV4_SRC_CHUNK,
        .offset = offsetof(struct fiveTuple, source) + offsetof(union ipAddress, ipv4Address),
    },
    {
        .type = RTE_ACL_FIELD_TYPE_MASK,
        .size = sizeof(uint8_t),
        .field_index = ACL_RULE_IPV4_PROTO_FIELD,
        .input_index = ACL_RULE_IPV4_PROTO_CHUNK,
        .offset = offsetof(struct fiveTuple, transportProtocol),
    },
};
```

And a function that creates these rules & adds them to context:
```
static inline void fillRule2(struct acl4_rule* rule)
{
    rule->field[ACL_RULE_IPV4_SRC_FIELD].value.u32 = IPv4(1,33,65,123);
    rule->field[ACL_RULE_IPV4_SRC_FIELD].mask_range.u32 = 0;
    rule->field[ACL_RULE_IPV4_PROTO_FIELD].value.u8 = 17;
    rule->field[ACL_RULE_IPV4_PROTO_FIELD].mask_range.u8 = -1;
    rule->data.userdata = 15;
    rule->data.category_mask = -1;
    rule->data.priority = 2;
}

static inline void fillRule1(struct acl4_rule* rule)
{
    rule->field[ACL_RULE_IPV4_SRC_FIELD].value.u32 = IPv4(0,0,0,0);
    rule->field[ACL_RULE_IPV4_SRC_FIELD].mask_range.u32 = 0;
    rule->field[ACL_RULE_IPV4_PROTO_FIELD].value.u8 = 0;
    rule->field[ACL_RULE_IPV4_PROTO_FIELD].mask_range.u8 = 0;
    rule->data.userdata = 25;
    rule->data.category_mask = -1;
    rule->data.priority = 1;
}
```

Then I create and build an ACL context with these rules. No errors are shown, it's dump shows two rules with appropriate size and everything.
The problem is with matching. When I send in data that should be matched by both rules, i.e. the one with higher priority should get returned,
the second one (rule1) gets returned even though it has lower priority.

And what's even weirder when I change rule2 in a way so it's the _same_ as rule1, rule1 stops matching and there're no matches reported.

Matching code:
```
    rte_acl_dump(aclCtx);
    printf("ACL for %hhu %u \n",
       *(ptrToFiveTuple + offsetof(struct fiveTuple, transportProtocol)),
       rte_be_to_cpu_32(*(uint32_t*)(ptrToFiveTuple + offsetof(struct fiveTuple, source)) + offsetof(union ipAddress, ipv4Address)));
    if (unlikely(rte_acl_classify(aclCtx, (const uint8_t**)(&ptrToFiveTuple), &result, 1, 1) != 0))
    {
        RTE_LOG(ERR, NATD, "Failed to classify a packet,\n");
        return -EINVAL;
    }
    printf("____RESULT: %u\n", result);
```

Log for the rules as they're defined above:
```
acl context <Context_1234>@0x7f1a0019c8c0
  socket_id=0
  alg=1
  max_rules=10000
  rule_size=48
  num_rules=2
  num_categories=1
  num_tries=1
ACL for 17 18956667 //18956667 is IP: 1.33.65.123
____RESULT: 25
```

Log for the situation when rule2 is changed so that it's the same as rule1:
```
{
    rule->field[ACL_RULE_IPV4_SRC_FIELD].value.u32 = IPv4(0,0,0,0);
    rule->field[ACL_RULE_IPV4_SRC_FIELD].mask_range.u32 = 0;
    rule->field[ACL_RULE_IPV4_PROTO_FIELD].value.u8 = 0;
    rule->field[ACL_RULE_IPV4_PROTO_FIELD].mask_range.u8 = 0;
    rule->data.userdata = 15;
    rule->data.category_mask = -1;
    rule->data.priority = 2;
}

```

```
acl context <Context_1234>@0x7f1a0019c8c0
  socket_id=0
  alg=1
  max_rules=10000
  rule_size=48
  num_rules=2
  num_categories=1
  num_tries=1
ACL for 17 18956667 //18956667 is IP: 1.33.65.123
____RESULT: 0
```

To be perfectly honest I have literally no idea what am I doing wrong or where the problem might lie. Any help would be greatly appreciated.
Petr Houska
Azure Intern



More information about the users mailing list