[dpdk-users] Flow director struct rte_flow_item_raw guild

Adrien Mazarguil adrien.mazarguil at 6wind.com
Thu May 9 14:38:33 CEST 2019


Hi,

On Thu, May 09, 2019 at 11:51:14AM +0800, 曾懷恩 wrote:
> Hi, 敬昊,
> 
> Sorry for my question is not clear.
> 
> My question is, should I declare a variable to store the bytes I want to filter and just assign it to the pattern element?

Yes, this is how it should work.

> 
> Therefore, will the result of init flow filter be like 
> 
> 	struct rte_flow_item_raw raw_spec, raw_mask; 

Just make sure to properly initialize these objects, especially unused
fields. I'll assume something like that was done at some point:

 memset(&raw_spec, 0, sizeof(raw_spec));
 memset(&raw_mask, 0, sizeof(raw_mask));

> 	uint8_t spec[12] = {0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}; 
> 	 uint8_t mask[12] = {0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff};

This mask will match the first 1st, 2nd and 12th bytes exactly, with
anything in between, i.e. IPv4's EtherType and ICMP protocol type in
subsequent IPv4 header. Seems correct.

> 	*(uint32_t *)&raw_spec = 0x40000000;
> 	raw_spec.offset = 12;
> 	raw_spec.limit = 12;

Note .limit is only meaningful when .search is enabled.

> 	raw_spec.length = 24;

This is the length of the byte pattern itself (12), it must not cover the
offset (12 + 12). In short raw_spec.length must be sizeof(spec).

> 	raw_spec.pattern = spec;
> 	raw_mask.pattern = mask;
> 	pattern[0].type = RTE_FLOW_ITEM_TYPE_RAW;
> 	pattern[0].spec = &raw_spec;
> 	pattern[0].mask = &raw_mask;
> 
> if i want to filter out icmp packet?

Almost... One issue is that, since you chose to provide your own empty mask
(raw_mask) instead of relying on the default one which happens to match all
fields exactly, you must also mask the relevant spec bits, e.g.:

 raw_mask.offset = -1;
 raw_mask.length = -1;

The only exception to this kind of masking is "raw_mask.pattern", which
should contain a valid pointer instead of a bit-mask when raw_spec.length &
raw_mask.length is nonzero.

Documentation example relies on the default mask so this part may not be
quite clear, so let me clarify:

Bit-masking does not apply to pointers the way it does with other types as
it makes no sense to mask them partially. They are either NULL or valid, so
in this specific case, the engine relies on another field (length) to
determine if spec.pattern can be dereferenced.

If length is nonzero, then mask.pattern is checked. If non-NULL, it can be
dereferenced, otherwise the engine defaults to matching "length" bytes from
spec.pattern exactly, hence the use of NULL as the default value in
rte_flow_item_raw_mask.

To summarize, here's how I'd rewrite your example (relying on C99 syntax to
initialize unspecified fields to zero without explicit memset() calls):

 uint8_t raw_pat_data[] = { [0] = 0x08, [1] = 0x00, [11] = 0x01 };
 uint8_t raw_pat_mask[] = { [0] = 0xff, [1] = 0xff, [11] = 0xff };
 struct rte_flow_item_raw raw_spec = {
     .offset = 12,
     .length = sizeof(raw_pat_data),
     .pattern = raw_pat_data,
 };
 struct rte_flow_item_raw raw_mask = {
     .offset = -1,
     .length = -1,
     .pattern = raw_pat_mask,
 };
 struct rte_flow_item pattern[] = {
     {
         .type = RTE_FLOW_ITEM_TYPE_RAW,
         .spec = &raw_spec,
         .mask = &raw_mask,
     },
     {
         .type = RTE_FLOW_ITEM_TYPE_END,
     },
 };

Or alternatively, using two pattern items and relying on the default mask to
avoid punching holes in the byte pattern:

 struct rte_flow_item_raw raw_spec[] = {
     {
         .offset = 12,
         .length = 2,
         .pattern = (uint8_t []){ 0x08, 0x00 },
     },
     {
         .offset = 23, /* or 11 with .relative = 1 */
         .length = 1,
         .pattern = (uint8_t []){ 0x01 },
     },
 };
 struct rte_flow_item pattern[] = {
     {
         .type = RTE_FLOW_ITEM_TYPE_RAW,
         .spec = &raw_spec[0],
     },
     {
         .type = RTE_FLOW_ITEM_TYPE_RAW,
         .spec = &raw_spec[1],
     },
     {
         .type = RTE_FLOW_ITEM_TYPE_END,
     },
 };

Now in practice I never had a chance to use this pattern item with any PMDs
that support it, so I don't know close their behavior sticks to what I just
described, especially regarding the handling of mask.pattern. Do not
hesitate to report odd or inconsistent behavior in any case.

-- 
Adrien Mazarguil
6WIND


More information about the users mailing list