DPDK usage discussions
 help / color / mirror / Atom feed
From: Petr Houska <t-pehous@microsoft.com>
To: "users@dpdk.org" <users@dpdk.org>
Subject: Re: [dpdk-users] ACL library doesn't match reliably
Date: Thu, 16 Aug 2018 17:23:13 +0000	[thread overview]
Message-ID: <CY4PR2101MB08667F9113EEF821CFCEDF918C3E0@CY4PR2101MB0866.namprd21.prod.outlook.com> (raw)
In-Reply-To: <CY4PR2101MB0866490971C2C4817A5D21D08C3F0@CY4PR2101MB0866.namprd21.prod.outlook.com>

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@dpdk.org' <users@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

      reply	other threads:[~2018-08-16 17:23 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-08-15 22:30 Petr Houska
2018-08-16 17:23 ` Petr Houska [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CY4PR2101MB08667F9113EEF821CFCEDF918C3E0@CY4PR2101MB0866.namprd21.prod.outlook.com \
    --to=t-pehous@microsoft.com \
    --cc=users@dpdk.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).