diff mbox series

[ovs-dev,V2,3/3] netdev-offload-dpdk: Add geneve header pattern match

Message ID 20220207172426.813734-4-elibr@nvidia.com
State Deferred
Headers show
Series Support geneve offloads | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success
ovsrobot/github-robot-_Build_and_Test success github build: passed
ovsrobot/intel-ovs-compilation success test: success

Commit Message

Eli Britstein Feb. 7, 2022, 5:24 p.m. UTC
Add support for matching on geneve header.

Signed-off-by: Eli Britstein <elibr@nvidia.com>
Reviewed-by: Nir Anteby <nanteby@nvidia.com>
Acked-by: Michael Santana <msantana@redhat.com>
---
 NEWS                      |  2 ++
 lib/netdev-offload-dpdk.c | 58 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 60 insertions(+)

Comments

Ilya Maximets May 4, 2022, 11:44 a.m. UTC | #1
On 2/7/22 18:24, Eli Britstein wrote:
> Add support for matching on geneve header.
> 
> Signed-off-by: Eli Britstein <elibr@nvidia.com>
> Reviewed-by: Nir Anteby <nanteby@nvidia.com>
> Acked-by: Michael Santana <msantana@redhat.com>
> ---
>  NEWS                      |  2 ++
>  lib/netdev-offload-dpdk.c | 58 +++++++++++++++++++++++++++++++++++++++
>  2 files changed, 60 insertions(+)
> 
> diff --git a/NEWS b/NEWS
> index e1c48f3a1..41a80d127 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -29,6 +29,8 @@ v2.17.0 - xx xxx xxxx
>       * Add support for DPDK 21.11.
>       * Forbid use of DPDK multiprocess feature.
>       * Add support for running threads on cores >= RTE_MAX_LCORE.
> +     * Add hardware offload support for GENEVE flows (experimental).
> +       Available only if DPDK experimantal APIs enabled during the build.
>     - Python:
>       * For SSL support, the use of the pyOpenSSL library has been replaced
>         with the native 'ssl' module.
> diff --git a/lib/netdev-offload-dpdk.c b/lib/netdev-offload-dpdk.c
> index edd4e009d..0303bd2df 100644
> --- a/lib/netdev-offload-dpdk.c
> +++ b/lib/netdev-offload-dpdk.c
> @@ -638,6 +638,24 @@ dump_flow_pattern(struct ds *s,
>                                ntohl(*key_spec), ntohl(*key_mask), 0);
>          }
>          ds_put_cstr(s, "/ ");
> +    } else if (item->type == RTE_FLOW_ITEM_TYPE_GENEVE) {
> +        const struct rte_flow_item_geneve *geneve_spec = item->spec;
> +        const struct rte_flow_item_geneve *geneve_mask = item->mask;
> +        ovs_be32 spec_vni, mask_vni;
> +
> +        ds_put_cstr(s, "geneve ");
> +        if (geneve_spec) {
> +            if (!geneve_mask) {
> +                geneve_mask = &rte_flow_item_geneve_mask;
> +            }
> +            spec_vni = get_unaligned_be32(ALIGNED_CAST(ovs_be32 *,
> +                                                       geneve_spec->vni));
> +            mask_vni = get_unaligned_be32(ALIGNED_CAST(ovs_be32 *,
> +                                                       geneve_mask->vni));
> +            DUMP_PATTERN_ITEM(geneve_mask->vni, false, "vni", "%"PRIu32,
> +                              ntohl(spec_vni) >> 8, ntohl(mask_vni) >> 8, 0);
> +        }
> +        ds_put_cstr(s, "/ ");
>      } else {
>          ds_put_format(s, "unknown rte flow pattern (%d)\n", item->type);
>      }
> @@ -1351,6 +1369,44 @@ parse_gre_match(struct flow_patterns *patterns,
>      return 0;
>  }
>  
> +static int
> +parse_geneve_match(struct flow_patterns *patterns,
> +                   struct match *match)
> +{
> +    struct rte_flow_item_geneve *geneve_spec, *geneve_mask;
> +    struct flow *consumed_masks;
> +    int ret;
> +
> +    ret = parse_tnl_ip_match(patterns, match, IPPROTO_UDP);
> +    if (ret) {
> +        return -1;
> +    }
> +    parse_tnl_udp_match(patterns, match);
> +
> +    consumed_masks = &match->wc.masks;
> +    /* GENEVE */
> +    geneve_spec = xzalloc(sizeof *geneve_spec);
> +    geneve_mask = xzalloc(sizeof *geneve_mask);
> +
> +    put_unaligned_be32(ALIGNED_CAST(ovs_be32 *, geneve_spec->vni),
> +                       htonl(ntohll(match->flow.tunnel.tun_id) << 8));
> +    put_unaligned_be32(ALIGNED_CAST(ovs_be32 *, geneve_mask->vni),
> +                       htonl(ntohll(match->wc.masks.tunnel.tun_id) << 8));
> +
> +    consumed_masks->tunnel.tun_id = 0;
> +    consumed_masks->tunnel.flags = 0;
> +    /* tunnel.metadata.present.len value indicates the number of
> +     * options, it's mask does not indicate any match on the packet,
> +     * thus masked.

I'm not sure I get that.  Options are part of the geneve header,
so if the match is requested, we have to match on them.  And there
is a special item for them - RTE_FLOW_ITEM_TYPE_GENEVE_OPT, which,
I think, should be used in this patch.

It also not clear why flags are cleared without handling them.

Best regards, Ilya Maximets.
Eli Britstein May 8, 2022, 5:07 a.m. UTC | #2
>-----Original Message-----
>From: Ilya Maximets <i.maximets@ovn.org>
>Sent: Wednesday, May 4, 2022 2:44 PM
>To: Eli Britstein <elibr@nvidia.com>; dev@openvswitch.org
>Cc: i.maximets@ovn.org; Gaetan Rivet <gaetanr@nvidia.com>;
>msantana@redhat.com; Nir Anteby <nanteby@nvidia.com>
>Subject: Re: [PATCH V2 3/3] netdev-offload-dpdk: Add geneve header pattern
>match
>
>External email: Use caution opening links or attachments
>
>
>On 2/7/22 18:24, Eli Britstein wrote:
>> Add support for matching on geneve header.
>>
>> Signed-off-by: Eli Britstein <elibr@nvidia.com>
>> Reviewed-by: Nir Anteby <nanteby@nvidia.com>
>> Acked-by: Michael Santana <msantana@redhat.com>
>> ---
>>  NEWS                      |  2 ++
>>  lib/netdev-offload-dpdk.c | 58
>> +++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 60 insertions(+)
>>
>> diff --git a/NEWS b/NEWS
>> index e1c48f3a1..41a80d127 100644
>> --- a/NEWS
>> +++ b/NEWS
>> @@ -29,6 +29,8 @@ v2.17.0 - xx xxx xxxx
>>       * Add support for DPDK 21.11.
>>       * Forbid use of DPDK multiprocess feature.
>>       * Add support for running threads on cores >= RTE_MAX_LCORE.
>> +     * Add hardware offload support for GENEVE flows (experimental).
>> +       Available only if DPDK experimantal APIs enabled during the build.
>>     - Python:
>>       * For SSL support, the use of the pyOpenSSL library has been replaced
>>         with the native 'ssl' module.
>> diff --git a/lib/netdev-offload-dpdk.c b/lib/netdev-offload-dpdk.c
>> index edd4e009d..0303bd2df 100644
>> --- a/lib/netdev-offload-dpdk.c
>> +++ b/lib/netdev-offload-dpdk.c
>> @@ -638,6 +638,24 @@ dump_flow_pattern(struct ds *s,
>>                                ntohl(*key_spec), ntohl(*key_mask), 0);
>>          }
>>          ds_put_cstr(s, "/ ");
>> +    } else if (item->type == RTE_FLOW_ITEM_TYPE_GENEVE) {
>> +        const struct rte_flow_item_geneve *geneve_spec = item->spec;
>> +        const struct rte_flow_item_geneve *geneve_mask = item->mask;
>> +        ovs_be32 spec_vni, mask_vni;
>> +
>> +        ds_put_cstr(s, "geneve ");
>> +        if (geneve_spec) {
>> +            if (!geneve_mask) {
>> +                geneve_mask = &rte_flow_item_geneve_mask;
>> +            }
>> +            spec_vni = get_unaligned_be32(ALIGNED_CAST(ovs_be32 *,
>> +                                                       geneve_spec->vni));
>> +            mask_vni = get_unaligned_be32(ALIGNED_CAST(ovs_be32 *,
>> +                                                       geneve_mask->vni));
>> +            DUMP_PATTERN_ITEM(geneve_mask->vni, false, "vni", "%"PRIu32,
>> +                              ntohl(spec_vni) >> 8, ntohl(mask_vni) >> 8, 0);
>> +        }
>> +        ds_put_cstr(s, "/ ");
>>      } else {
>>          ds_put_format(s, "unknown rte flow pattern (%d)\n", item->type);
>>      }
>> @@ -1351,6 +1369,44 @@ parse_gre_match(struct flow_patterns
>*patterns,
>>      return 0;
>>  }
>>
>> +static int
>> +parse_geneve_match(struct flow_patterns *patterns,
>> +                   struct match *match) {
>> +    struct rte_flow_item_geneve *geneve_spec, *geneve_mask;
>> +    struct flow *consumed_masks;
>> +    int ret;
>> +
>> +    ret = parse_tnl_ip_match(patterns, match, IPPROTO_UDP);
>> +    if (ret) {
>> +        return -1;
>> +    }
>> +    parse_tnl_udp_match(patterns, match);
>> +
>> +    consumed_masks = &match->wc.masks;
>> +    /* GENEVE */
>> +    geneve_spec = xzalloc(sizeof *geneve_spec);
>> +    geneve_mask = xzalloc(sizeof *geneve_mask);
>> +
>> +    put_unaligned_be32(ALIGNED_CAST(ovs_be32 *, geneve_spec->vni),
>> +                       htonl(ntohll(match->flow.tunnel.tun_id) << 8));
>> +    put_unaligned_be32(ALIGNED_CAST(ovs_be32 *, geneve_mask->vni),
>> +                       htonl(ntohll(match->wc.masks.tunnel.tun_id) <<
>> + 8));
>> +
>> +    consumed_masks->tunnel.tun_id = 0;
>> +    consumed_masks->tunnel.flags = 0;
>> +    /* tunnel.metadata.present.len value indicates the number of
>> +     * options, it's mask does not indicate any match on the packet,
>> +     * thus masked.
>
>I'm not sure I get that.  Options are part of the geneve header, so if the match
>is requested, we have to match on them.  And there is a special item for them
>- RTE_FLOW_ITEM_TYPE_GENEVE_OPT, which, I think, should be used in this
>patch.
It is correct dpdk supports this flow item. However, it doesn't support options in 'struct rte_flow_restore_info'. Therefore, it currently cannot be supported. Options are *optional*. This patch-set can support geneve w/o options only. If there are options to be matched, they are not cleared from the masks, and the parsing fails.
>
>It also not clear why flags are cleared without handling them.
There are no flags field in geneve header, maybe except OAM. I can add it after completing the previous comment.
>
>Best regards, Ilya Maximets.
Hemal Shah May 18, 2022, 3:02 p.m. UTC | #3
Eli,

I'm trying to understand options handling during Geneve encap/decap offload.

   1. This patchset will allow decap offload for Geneve w/o options only. I
   do not think that covers important use cases for Geneve. Geneve was meant
   to be used with options. Why is the limitation of not having options
   support in struct rte_flow_restore_info gating the offload design?
   2. I have not seen companion patch support for encap offload for Geneve.
   Is similar restriction of not offloading Geneve w/ options apply on the
   encap offload?

Hemal

On Sat, May 7, 2022 at 10:07 PM Eli Britstein via dev <
ovs-dev@openvswitch.org> wrote:

>
>
> >-----Original Message-----
> >From: Ilya Maximets <i.maximets@ovn.org>
> >Sent: Wednesday, May 4, 2022 2:44 PM
> >To: Eli Britstein <elibr@nvidia.com>; dev@openvswitch.org
> >Cc: i.maximets@ovn.org; Gaetan Rivet <gaetanr@nvidia.com>;
> >msantana@redhat.com; Nir Anteby <nanteby@nvidia.com>
> >Subject: Re: [PATCH V2 3/3] netdev-offload-dpdk: Add geneve header pattern
> >match
> >
> >External email: Use caution opening links or attachments
> >
> >
> >On 2/7/22 18:24, Eli Britstein wrote:
> >> Add support for matching on geneve header.
> >>
> >> Signed-off-by: Eli Britstein <elibr@nvidia.com>
> >> Reviewed-by: Nir Anteby <nanteby@nvidia.com>
> >> Acked-by: Michael Santana <msantana@redhat.com>
> >> ---
> >>  NEWS                      |  2 ++
> >>  lib/netdev-offload-dpdk.c | 58
> >> +++++++++++++++++++++++++++++++++++++++
> >>  2 files changed, 60 insertions(+)
> >>
> >> diff --git a/NEWS b/NEWS
> >> index e1c48f3a1..41a80d127 100644
> >> --- a/NEWS
> >> +++ b/NEWS
> >> @@ -29,6 +29,8 @@ v2.17.0 - xx xxx xxxx
> >>       * Add support for DPDK 21.11.
> >>       * Forbid use of DPDK multiprocess feature.
> >>       * Add support for running threads on cores >= RTE_MAX_LCORE.
> >> +     * Add hardware offload support for GENEVE flows (experimental).
> >> +       Available only if DPDK experimantal APIs enabled during the
> build.
> >>     - Python:
> >>       * For SSL support, the use of the pyOpenSSL library has been
> replaced
> >>         with the native 'ssl' module.
> >> diff --git a/lib/netdev-offload-dpdk.c b/lib/netdev-offload-dpdk.c
> >> index edd4e009d..0303bd2df 100644
> >> --- a/lib/netdev-offload-dpdk.c
> >> +++ b/lib/netdev-offload-dpdk.c
> >> @@ -638,6 +638,24 @@ dump_flow_pattern(struct ds *s,
> >>                                ntohl(*key_spec), ntohl(*key_mask), 0);
> >>          }
> >>          ds_put_cstr(s, "/ ");
> >> +    } else if (item->type == RTE_FLOW_ITEM_TYPE_GENEVE) {
> >> +        const struct rte_flow_item_geneve *geneve_spec = item->spec;
> >> +        const struct rte_flow_item_geneve *geneve_mask = item->mask;
> >> +        ovs_be32 spec_vni, mask_vni;
> >> +
> >> +        ds_put_cstr(s, "geneve ");
> >> +        if (geneve_spec) {
> >> +            if (!geneve_mask) {
> >> +                geneve_mask = &rte_flow_item_geneve_mask;
> >> +            }
> >> +            spec_vni = get_unaligned_be32(ALIGNED_CAST(ovs_be32 *,
> >> +
>  geneve_spec->vni));
> >> +            mask_vni = get_unaligned_be32(ALIGNED_CAST(ovs_be32 *,
> >> +
>  geneve_mask->vni));
> >> +            DUMP_PATTERN_ITEM(geneve_mask->vni, false, "vni",
> "%"PRIu32,
> >> +                              ntohl(spec_vni) >> 8, ntohl(mask_vni) >>
> 8, 0);
> >> +        }
> >> +        ds_put_cstr(s, "/ ");
> >>      } else {
> >>          ds_put_format(s, "unknown rte flow pattern (%d)\n",
> item->type);
> >>      }
> >> @@ -1351,6 +1369,44 @@ parse_gre_match(struct flow_patterns
> >*patterns,
> >>      return 0;
> >>  }
> >>
> >> +static int
> >> +parse_geneve_match(struct flow_patterns *patterns,
> >> +                   struct match *match) {
> >> +    struct rte_flow_item_geneve *geneve_spec, *geneve_mask;
> >> +    struct flow *consumed_masks;
> >> +    int ret;
> >> +
> >> +    ret = parse_tnl_ip_match(patterns, match, IPPROTO_UDP);
> >> +    if (ret) {
> >> +        return -1;
> >> +    }
> >> +    parse_tnl_udp_match(patterns, match);
> >> +
> >> +    consumed_masks = &match->wc.masks;
> >> +    /* GENEVE */
> >> +    geneve_spec = xzalloc(sizeof *geneve_spec);
> >> +    geneve_mask = xzalloc(sizeof *geneve_mask);
> >> +
> >> +    put_unaligned_be32(ALIGNED_CAST(ovs_be32 *, geneve_spec->vni),
> >> +                       htonl(ntohll(match->flow.tunnel.tun_id) << 8));
> >> +    put_unaligned_be32(ALIGNED_CAST(ovs_be32 *, geneve_mask->vni),
> >> +                       htonl(ntohll(match->wc.masks.tunnel.tun_id) <<
> >> + 8));
> >> +
> >> +    consumed_masks->tunnel.tun_id = 0;
> >> +    consumed_masks->tunnel.flags = 0;
> >> +    /* tunnel.metadata.present.len value indicates the number of
> >> +     * options, it's mask does not indicate any match on the packet,
> >> +     * thus masked.
> >
> >I'm not sure I get that.  Options are part of the geneve header, so if
> the match
> >is requested, we have to match on them.  And there is a special item for
> them
> >- RTE_FLOW_ITEM_TYPE_GENEVE_OPT, which, I think, should be used in this
> >patch.
> It is correct dpdk supports this flow item. However, it doesn't support
> options in 'struct rte_flow_restore_info'. Therefore, it currently cannot
> be supported. Options are *optional*. This patch-set can support geneve w/o
> options only. If there are options to be matched, they are not cleared from
> the masks, and the parsing fails.
> >
> >It also not clear why flags are cleared without handling them.
> There are no flags field in geneve header, maybe except OAM. I can add it
> after completing the previous comment.
> >
> >Best regards, Ilya Maximets.
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
Eli Britstein May 18, 2022, 3:09 p.m. UTC | #4
1.  The focus was VXLAN. Need to enhance DPDK to support it. If this is not important, let’s abandon this patch-set until DPDK is enhanced.
  2.  There is no need. DPDK has only specific encaps for VXLAN/NVGRE. Other encaps are done only by “RAW”. In OVS VXLAN is used if applicable, and fallback to RAW. Geneve is under this category.

From: Hemal Shah <hemal.shah@broadcom.com>
Sent: Wednesday, May 18, 2022 6:02 PM
To: Eli Britstein <elibr@nvidia.com>
Cc: Ilya Maximets <i.maximets@ovn.org>; dev@openvswitch.org
Subject: Re: [ovs-dev] [PATCH V2 3/3] netdev-offload-dpdk: Add geneve header pattern match

Eli,

I'm trying to understand options handling during Geneve encap/decap offload.

  1.  This patchset will allow decap offload for Geneve w/o options only. I do not think that covers important use cases for Geneve. Geneve was meant to be used with options. Why is the limitation of not having options support in struct rte_flow_restore_info gating the offload design?
  2.  I have not seen companion patch support for encap offload for Geneve. Is similar restriction of not offloading Geneve w/ options apply on the encap offload?
Hemal

On Sat, May 7, 2022 at 10:07 PM Eli Britstein via dev <ovs-dev@openvswitch.org<mailto:ovs-dev@openvswitch.org>> wrote:


>-----Original Message-----
>From: Ilya Maximets <i.maximets@ovn.org<mailto:i.maximets@ovn.org>>
>Sent: Wednesday, May 4, 2022 2:44 PM
>To: Eli Britstein <elibr@nvidia.com<mailto:elibr@nvidia.com>>; dev@openvswitch.org<mailto:dev@openvswitch.org>
>Cc: i.maximets@ovn.org<mailto:i.maximets@ovn.org>; Gaetan Rivet <gaetanr@nvidia.com<mailto:gaetanr@nvidia.com>>;
>msantana@redhat.com<mailto:msantana@redhat.com>; Nir Anteby <nanteby@nvidia.com<mailto:nanteby@nvidia.com>>
>Subject: Re: [PATCH V2 3/3] netdev-offload-dpdk: Add geneve header pattern
>match
>
>External email: Use caution opening links or attachments
>
>
>On 2/7/22 18:24, Eli Britstein wrote:
>> Add support for matching on geneve header.
>>
>> Signed-off-by: Eli Britstein <elibr@nvidia.com<mailto:elibr@nvidia.com>>
>> Reviewed-by: Nir Anteby <nanteby@nvidia.com<mailto:nanteby@nvidia.com>>
>> Acked-by: Michael Santana <msantana@redhat.com<mailto:msantana@redhat.com>>
>> ---
>>  NEWS                      |  2 ++
>>  lib/netdev-offload-dpdk.c | 58
>> +++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 60 insertions(+)
>>
>> diff --git a/NEWS b/NEWS
>> index e1c48f3a1..41a80d127 100644
>> --- a/NEWS
>> +++ b/NEWS
>> @@ -29,6 +29,8 @@ v2.17.0 - xx xxx xxxx
>>       * Add support for DPDK 21.11.
>>       * Forbid use of DPDK multiprocess feature.
>>       * Add support for running threads on cores >= RTE_MAX_LCORE.
>> +     * Add hardware offload support for GENEVE flows (experimental).
>> +       Available only if DPDK experimantal APIs enabled during the build.
>>     - Python:
>>       * For SSL support, the use of the pyOpenSSL library has been replaced
>>         with the native 'ssl' module.
>> diff --git a/lib/netdev-offload-dpdk.c b/lib/netdev-offload-dpdk.c
>> index edd4e009d..0303bd2df 100644
>> --- a/lib/netdev-offload-dpdk.c
>> +++ b/lib/netdev-offload-dpdk.c
>> @@ -638,6 +638,24 @@ dump_flow_pattern(struct ds *s,
>>                                ntohl(*key_spec), ntohl(*key_mask), 0);
>>          }
>>          ds_put_cstr(s, "/ ");
>> +    } else if (item->type == RTE_FLOW_ITEM_TYPE_GENEVE) {
>> +        const struct rte_flow_item_geneve *geneve_spec = item->spec;
>> +        const struct rte_flow_item_geneve *geneve_mask = item->mask;
>> +        ovs_be32 spec_vni, mask_vni;
>> +
>> +        ds_put_cstr(s, "geneve ");
>> +        if (geneve_spec) {
>> +            if (!geneve_mask) {
>> +                geneve_mask = &rte_flow_item_geneve_mask;
>> +            }
>> +            spec_vni = get_unaligned_be32(ALIGNED_CAST(ovs_be32 *,
>> +                                                       geneve_spec->vni));
>> +            mask_vni = get_unaligned_be32(ALIGNED_CAST(ovs_be32 *,
>> +                                                       geneve_mask->vni));
>> +            DUMP_PATTERN_ITEM(geneve_mask->vni, false, "vni", "%"PRIu32,
>> +                              ntohl(spec_vni) >> 8, ntohl(mask_vni) >> 8, 0);
>> +        }
>> +        ds_put_cstr(s, "/ ");
>>      } else {
>>          ds_put_format(s, "unknown rte flow pattern (%d)\n", item->type);
>>      }
>> @@ -1351,6 +1369,44 @@ parse_gre_match(struct flow_patterns
>*patterns,
>>      return 0;
>>  }
>>
>> +static int
>> +parse_geneve_match(struct flow_patterns *patterns,
>> +                   struct match *match) {
>> +    struct rte_flow_item_geneve *geneve_spec, *geneve_mask;
>> +    struct flow *consumed_masks;
>> +    int ret;
>> +
>> +    ret = parse_tnl_ip_match(patterns, match, IPPROTO_UDP);
>> +    if (ret) {
>> +        return -1;
>> +    }
>> +    parse_tnl_udp_match(patterns, match);
>> +
>> +    consumed_masks = &match->wc.masks;
>> +    /* GENEVE */
>> +    geneve_spec = xzalloc(sizeof *geneve_spec);
>> +    geneve_mask = xzalloc(sizeof *geneve_mask);
>> +
>> +    put_unaligned_be32(ALIGNED_CAST(ovs_be32 *, geneve_spec->vni),
>> +                       htonl(ntohll(match->flow.tunnel.tun_id) << 8));
>> +    put_unaligned_be32(ALIGNED_CAST(ovs_be32 *, geneve_mask->vni),
>> +                       htonl(ntohll(match->wc.masks.tunnel.tun_id) <<
>> + 8));
>> +
>> +    consumed_masks->tunnel.tun_id = 0;
>> +    consumed_masks->tunnel.flags = 0;
>> +    /* tunnel.metadata.present.len value indicates the number of
>> +     * options, it's mask does not indicate any match on the packet,
>> +     * thus masked.
>
>I'm not sure I get that.  Options are part of the geneve header, so if the match
>is requested, we have to match on them.  And there is a special item for them
>- RTE_FLOW_ITEM_TYPE_GENEVE_OPT, which, I think, should be used in this
>patch.
It is correct dpdk supports this flow item. However, it doesn't support options in 'struct rte_flow_restore_info'. Therefore, it currently cannot be supported. Options are *optional*. This patch-set can support geneve w/o options only. If there are options to be matched, they are not cleared from the masks, and the parsing fails.
>
>It also not clear why flags are cleared without handling them.
There are no flags field in geneve header, maybe except OAM. I can add it after completing the previous comment.
>
>Best regards, Ilya Maximets.
diff mbox series

Patch

diff --git a/NEWS b/NEWS
index e1c48f3a1..41a80d127 100644
--- a/NEWS
+++ b/NEWS
@@ -29,6 +29,8 @@  v2.17.0 - xx xxx xxxx
      * Add support for DPDK 21.11.
      * Forbid use of DPDK multiprocess feature.
      * Add support for running threads on cores >= RTE_MAX_LCORE.
+     * Add hardware offload support for GENEVE flows (experimental).
+       Available only if DPDK experimantal APIs enabled during the build.
    - Python:
      * For SSL support, the use of the pyOpenSSL library has been replaced
        with the native 'ssl' module.
diff --git a/lib/netdev-offload-dpdk.c b/lib/netdev-offload-dpdk.c
index edd4e009d..0303bd2df 100644
--- a/lib/netdev-offload-dpdk.c
+++ b/lib/netdev-offload-dpdk.c
@@ -638,6 +638,24 @@  dump_flow_pattern(struct ds *s,
                               ntohl(*key_spec), ntohl(*key_mask), 0);
         }
         ds_put_cstr(s, "/ ");
+    } else if (item->type == RTE_FLOW_ITEM_TYPE_GENEVE) {
+        const struct rte_flow_item_geneve *geneve_spec = item->spec;
+        const struct rte_flow_item_geneve *geneve_mask = item->mask;
+        ovs_be32 spec_vni, mask_vni;
+
+        ds_put_cstr(s, "geneve ");
+        if (geneve_spec) {
+            if (!geneve_mask) {
+                geneve_mask = &rte_flow_item_geneve_mask;
+            }
+            spec_vni = get_unaligned_be32(ALIGNED_CAST(ovs_be32 *,
+                                                       geneve_spec->vni));
+            mask_vni = get_unaligned_be32(ALIGNED_CAST(ovs_be32 *,
+                                                       geneve_mask->vni));
+            DUMP_PATTERN_ITEM(geneve_mask->vni, false, "vni", "%"PRIu32,
+                              ntohl(spec_vni) >> 8, ntohl(mask_vni) >> 8, 0);
+        }
+        ds_put_cstr(s, "/ ");
     } else {
         ds_put_format(s, "unknown rte flow pattern (%d)\n", item->type);
     }
@@ -1351,6 +1369,44 @@  parse_gre_match(struct flow_patterns *patterns,
     return 0;
 }
 
+static int
+parse_geneve_match(struct flow_patterns *patterns,
+                   struct match *match)
+{
+    struct rte_flow_item_geneve *geneve_spec, *geneve_mask;
+    struct flow *consumed_masks;
+    int ret;
+
+    ret = parse_tnl_ip_match(patterns, match, IPPROTO_UDP);
+    if (ret) {
+        return -1;
+    }
+    parse_tnl_udp_match(patterns, match);
+
+    consumed_masks = &match->wc.masks;
+    /* GENEVE */
+    geneve_spec = xzalloc(sizeof *geneve_spec);
+    geneve_mask = xzalloc(sizeof *geneve_mask);
+
+    put_unaligned_be32(ALIGNED_CAST(ovs_be32 *, geneve_spec->vni),
+                       htonl(ntohll(match->flow.tunnel.tun_id) << 8));
+    put_unaligned_be32(ALIGNED_CAST(ovs_be32 *, geneve_mask->vni),
+                       htonl(ntohll(match->wc.masks.tunnel.tun_id) << 8));
+
+    consumed_masks->tunnel.tun_id = 0;
+    consumed_masks->tunnel.flags = 0;
+    /* tunnel.metadata.present.len value indicates the number of
+     * options, it's mask does not indicate any match on the packet,
+     * thus masked.
+     */
+    memset(&consumed_masks->tunnel.metadata.present, 0,
+           sizeof consumed_masks->tunnel.metadata.present);
+
+    add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_GENEVE, geneve_spec,
+                     geneve_mask, NULL);
+    return 0;
+}
+
 static int OVS_UNUSED
 parse_flow_tnl_match(struct netdev *tnldev,
                      struct flow_patterns *patterns,
@@ -1366,6 +1422,8 @@  parse_flow_tnl_match(struct netdev *tnldev,
 
     if (!strcmp(netdev_get_type(tnldev), "vxlan")) {
         ret = parse_vxlan_match(patterns, match);
+    } else if (!strcmp(netdev_get_type(tnldev), "geneve")) {
+        ret = parse_geneve_match(patterns, match);
     }
     else if (!strcmp(netdev_get_type(tnldev), "gre")) {
         ret = parse_gre_match(patterns, match);