diff mbox series

[ovs-dev,v4] odp_util: Fix parse_key_and_mask_to_match() vlan parsing

Message ID 164794169091.1116991.17641650221335898623.stgit@ebuild
State Accepted
Commit d632ad0aa1123af8a5bdf679d7a3fbd50ad7784f
Headers show
Series [ovs-dev,v4] odp_util: Fix parse_key_and_mask_to_match() vlan parsing | expand

Checks

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

Commit Message

Eelco Chaudron March 22, 2022, 9:35 a.m. UTC
The parse_key_and_mask_to_match() is a function to translate
a netlink formatted key/mask to match structure. And should
not consider any configuration setting when translating.

In addition we also enforce the encap_eth_type[0] mask as
it's required for the VLAN match.

Signed-off-by: Eelco Chaudron <echaudro@redhat.com>

---
v4:
 - Fixed call to odp_flow_key_to_mask__() to ignore vlan limit.
 - Force encap_eth_type[0] mask as it was used for VLAN matching.

 lib/netdev-offload-tc.c |    2 +-
 lib/odp-util.c          |   41 ++++++++++++++++++++++++++++-------------
 2 files changed, 29 insertions(+), 14 deletions(-)

Comments

Eelco Chaudron April 28, 2022, 2:09 p.m. UTC | #1
On 22 Mar 2022, at 10:35, Eelco Chaudron wrote:

> The parse_key_and_mask_to_match() is a function to translate
> a netlink formatted key/mask to match structure. And should
> not consider any configuration setting when translating.
>
> In addition we also enforce the encap_eth_type[0] mask as
> it's required for the VLAN match.
>
> Signed-off-by: Eelco Chaudron <echaudro@redhat.com>

Ilya, can you take a look at this one, it’s the only remaining patch from the “netdev-offload-tc: Fix various tc-offload related problems” series.

Thanks,

Eelco

> ---
> v4:
>  - Fixed call to odp_flow_key_to_mask__() to ignore vlan limit.
>  - Force encap_eth_type[0] mask as it was used for VLAN matching.
>
>  lib/netdev-offload-tc.c |    2 +-
>  lib/odp-util.c          |   41 ++++++++++++++++++++++++++++-------------
>  2 files changed, 29 insertions(+), 14 deletions(-)
>
> diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c
> index 9845e8d3f..7f0d4bbff 100644
> --- a/lib/netdev-offload-tc.c
> +++ b/lib/netdev-offload-tc.c
> @@ -1638,7 +1638,7 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match,
>
>      if (mask->vlans[0].tpid && eth_type_vlan(key->vlans[0].tpid)) {
>          flower.key.encap_eth_type[0] = flower.key.eth_type;
> -        flower.mask.encap_eth_type[0] = flower.mask.eth_type;
> +        flower.mask.encap_eth_type[0] = CONSTANT_HTONS(0xffff);
>          flower.key.eth_type = key->vlans[0].tpid;
>          flower.mask.eth_type = mask->vlans[0].tpid;
>      }
> diff --git a/lib/odp-util.c b/lib/odp-util.c
> index 0ff302856..4389df6a6 100644
> --- a/lib/odp-util.c
> +++ b/lib/odp-util.c
> @@ -7188,7 +7188,8 @@ parse_8021q_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1],
>                     uint64_t present_attrs, int out_of_range_attr,
>                     uint64_t expected_attrs, struct flow *flow,
>                     const struct nlattr *key, size_t key_len,
> -                   const struct flow *src_flow, char **errorp)
> +                   const struct flow *src_flow, char **errorp,
> +                   bool ignore_vlan_limit)
>  {
>      static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
>      bool is_mask = src_flow != flow;
> @@ -7196,9 +7197,11 @@ parse_8021q_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1],
>      const struct nlattr *encap;
>      enum odp_key_fitness encap_fitness;
>      enum odp_key_fitness fitness = ODP_FIT_ERROR;
> +    int vlan_limit;
>      int encaps = 0;
>
> -    while (encaps < flow_vlan_limit &&
> +    vlan_limit = ignore_vlan_limit ? FLOW_MAX_VLAN_HEADERS : flow_vlan_limit;
> +    while (encaps < vlan_limit &&
>             (is_mask
>              ? (src_flow->vlans[encaps].tci & htons(VLAN_CFI)) != 0
>              : eth_type_vlan(flow->dl_type))) {
> @@ -7281,7 +7284,7 @@ parse_8021q_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1],
>  static enum odp_key_fitness
>  odp_flow_key_to_flow__(const struct nlattr *key, size_t key_len,
>                         struct flow *flow, const struct flow *src_flow,
> -                       char **errorp)
> +                       char **errorp, bool ignore_vlan_limit)
>  {
>      /* New "struct flow" fields that are visible to the datapath (including all
>       * data fields) should be translated from equivalent datapath flow fields
> @@ -7431,7 +7434,7 @@ odp_flow_key_to_flow__(const struct nlattr *key, size_t key_len,
>          : eth_type_vlan(src_flow->dl_type)) {
>          fitness = parse_8021q_onward(attrs, present_attrs, out_of_range_attr,
>                                       expected_attrs, flow, key, key_len,
> -                                     src_flow, errorp);
> +                                     src_flow, errorp, ignore_vlan_limit);
>      } else {
>          if (is_mask) {
>              /* A missing VLAN mask means exact match on vlan_tci 0 (== no
> @@ -7497,7 +7500,7 @@ enum odp_key_fitness
>  odp_flow_key_to_flow(const struct nlattr *key, size_t key_len,
>                       struct flow *flow, char **errorp)
>  {
> -    return odp_flow_key_to_flow__(key, key_len, flow, flow, errorp);
> +    return odp_flow_key_to_flow__(key, key_len, flow, flow, errorp, false);
>  }
>
>  /* Converts the 'mask_key_len' bytes of OVS_KEY_ATTR_* attributes in 'mask_key'
> @@ -7509,14 +7512,16 @@ odp_flow_key_to_flow(const struct nlattr *key, size_t key_len,
>   * If 'errorp' is nonnull, this function uses it for detailed error reports: if
>   * the return value is ODP_FIT_ERROR, it stores a malloc()'d error string in
>   * '*errorp', otherwise NULL. */
> -enum odp_key_fitness
> -odp_flow_key_to_mask(const struct nlattr *mask_key, size_t mask_key_len,
> -                     struct flow_wildcards *mask, const struct flow *src_flow,
> -                     char **errorp)
> +static enum odp_key_fitness
> +odp_flow_key_to_mask__(const struct nlattr *mask_key, size_t mask_key_len,
> +                       struct flow_wildcards *mask,
> +                       const struct flow *src_flow,
> +                       char **errorp, bool ignore_vlan_limit)
>  {
>      if (mask_key_len) {
>          return odp_flow_key_to_flow__(mask_key, mask_key_len,
> -                                      &mask->masks, src_flow, errorp);
> +                                      &mask->masks, src_flow, errorp,
> +                                      ignore_vlan_limit);
>      } else {
>          if (errorp) {
>              *errorp = NULL;
> @@ -7530,6 +7535,15 @@ odp_flow_key_to_mask(const struct nlattr *mask_key, size_t mask_key_len,
>      }
>  }
>
> +enum odp_key_fitness
> +odp_flow_key_to_mask(const struct nlattr *mask_key, size_t mask_key_len,
> +                     struct flow_wildcards *mask,
> +                     const struct flow *src_flow, char **errorp)
> +{
> +    return odp_flow_key_to_mask__(mask_key, mask_key_len, mask, src_flow,
> +                                  errorp, false);
> +}
> +
>  /* Converts the netlink formated key/mask to match.
>   * Fails if odp_flow_key_from_key/mask and odp_flow_key_key/mask
>   * disagree on the acceptable form of flow */
> @@ -7540,7 +7554,8 @@ parse_key_and_mask_to_match(const struct nlattr *key, size_t key_len,
>  {
>      enum odp_key_fitness fitness;
>
> -    fitness = odp_flow_key_to_flow(key, key_len, &match->flow, NULL);
> +    fitness = odp_flow_key_to_flow__(key, key_len, &match->flow, &match->flow,
> +                                     NULL, true);
>      if (fitness) {
>          /* This should not happen: it indicates that
>           * odp_flow_key_from_flow() and odp_flow_key_to_flow() disagree on
> @@ -7561,8 +7576,8 @@ parse_key_and_mask_to_match(const struct nlattr *key, size_t key_len,
>          return EINVAL;
>      }
>
> -    fitness = odp_flow_key_to_mask(mask, mask_len, &match->wc, &match->flow,
> -                                   NULL);
> +    fitness = odp_flow_key_to_mask__(mask, mask_len, &match->wc, &match->flow,
> +                                     NULL, true);
>      if (fitness) {
>          /* This should not happen: it indicates that
>           * odp_flow_key_from_mask() and odp_flow_key_to_mask()
>
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Roi Dayan May 30, 2022, 12:42 p.m. UTC | #2
On 2022-03-22 11:35 AM, Eelco Chaudron wrote:
> The parse_key_and_mask_to_match() is a function to translate
> a netlink formatted key/mask to match structure. And should
> not consider any configuration setting when translating.
> 
> In addition we also enforce the encap_eth_type[0] mask as
> it's required for the VLAN match.
> 
> Signed-off-by: Eelco Chaudron <echaudro@redhat.com>
> 
> ---
> v4:
>   - Fixed call to odp_flow_key_to_mask__() to ignore vlan limit.
>   - Force encap_eth_type[0] mask as it was used for VLAN matching.
> 
>   lib/netdev-offload-tc.c |    2 +-
>   lib/odp-util.c          |   41 ++++++++++++++++++++++++++++-------------
>   2 files changed, 29 insertions(+), 14 deletions(-)
> 
> diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c
> index 9845e8d3f..7f0d4bbff 100644
> --- a/lib/netdev-offload-tc.c
> +++ b/lib/netdev-offload-tc.c
> @@ -1638,7 +1638,7 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match,
>   
>       if (mask->vlans[0].tpid && eth_type_vlan(key->vlans[0].tpid)) {
>           flower.key.encap_eth_type[0] = flower.key.eth_type;
> -        flower.mask.encap_eth_type[0] = flower.mask.eth_type;
> +        flower.mask.encap_eth_type[0] = CONSTANT_HTONS(0xffff);
>           flower.key.eth_type = key->vlans[0].tpid;
>           flower.mask.eth_type = mask->vlans[0].tpid;
>       }
> diff --git a/lib/odp-util.c b/lib/odp-util.c
> index 0ff302856..4389df6a6 100644
> --- a/lib/odp-util.c
> +++ b/lib/odp-util.c
> @@ -7188,7 +7188,8 @@ parse_8021q_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1],
>                      uint64_t present_attrs, int out_of_range_attr,
>                      uint64_t expected_attrs, struct flow *flow,
>                      const struct nlattr *key, size_t key_len,
> -                   const struct flow *src_flow, char **errorp)
> +                   const struct flow *src_flow, char **errorp,
> +                   bool ignore_vlan_limit)
>   {
>       static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
>       bool is_mask = src_flow != flow;
> @@ -7196,9 +7197,11 @@ parse_8021q_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1],
>       const struct nlattr *encap;
>       enum odp_key_fitness encap_fitness;
>       enum odp_key_fitness fitness = ODP_FIT_ERROR;
> +    int vlan_limit;
>       int encaps = 0;
>   
> -    while (encaps < flow_vlan_limit &&
> +    vlan_limit = ignore_vlan_limit ? FLOW_MAX_VLAN_HEADERS : flow_vlan_limit;
> +    while (encaps < vlan_limit &&
>              (is_mask
>               ? (src_flow->vlans[encaps].tci & htons(VLAN_CFI)) != 0
>               : eth_type_vlan(flow->dl_type))) {
> @@ -7281,7 +7284,7 @@ parse_8021q_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1],
>   static enum odp_key_fitness
>   odp_flow_key_to_flow__(const struct nlattr *key, size_t key_len,
>                          struct flow *flow, const struct flow *src_flow,
> -                       char **errorp)
> +                       char **errorp, bool ignore_vlan_limit)
>   {
>       /* New "struct flow" fields that are visible to the datapath (including all
>        * data fields) should be translated from equivalent datapath flow fields
> @@ -7431,7 +7434,7 @@ odp_flow_key_to_flow__(const struct nlattr *key, size_t key_len,
>           : eth_type_vlan(src_flow->dl_type)) {
>           fitness = parse_8021q_onward(attrs, present_attrs, out_of_range_attr,
>                                        expected_attrs, flow, key, key_len,
> -                                     src_flow, errorp);
> +                                     src_flow, errorp, ignore_vlan_limit);
>       } else {
>           if (is_mask) {
>               /* A missing VLAN mask means exact match on vlan_tci 0 (== no
> @@ -7497,7 +7500,7 @@ enum odp_key_fitness
>   odp_flow_key_to_flow(const struct nlattr *key, size_t key_len,
>                        struct flow *flow, char **errorp)
>   {
> -    return odp_flow_key_to_flow__(key, key_len, flow, flow, errorp);
> +    return odp_flow_key_to_flow__(key, key_len, flow, flow, errorp, false);
>   }
>   
>   /* Converts the 'mask_key_len' bytes of OVS_KEY_ATTR_* attributes in 'mask_key'
> @@ -7509,14 +7512,16 @@ odp_flow_key_to_flow(const struct nlattr *key, size_t key_len,
>    * If 'errorp' is nonnull, this function uses it for detailed error reports: if
>    * the return value is ODP_FIT_ERROR, it stores a malloc()'d error string in
>    * '*errorp', otherwise NULL. */
> -enum odp_key_fitness
> -odp_flow_key_to_mask(const struct nlattr *mask_key, size_t mask_key_len,
> -                     struct flow_wildcards *mask, const struct flow *src_flow,
> -                     char **errorp)
> +static enum odp_key_fitness
> +odp_flow_key_to_mask__(const struct nlattr *mask_key, size_t mask_key_len,
> +                       struct flow_wildcards *mask,
> +                       const struct flow *src_flow,
> +                       char **errorp, bool ignore_vlan_limit)
>   {
>       if (mask_key_len) {
>           return odp_flow_key_to_flow__(mask_key, mask_key_len,
> -                                      &mask->masks, src_flow, errorp);
> +                                      &mask->masks, src_flow, errorp,
> +                                      ignore_vlan_limit);
>       } else {
>           if (errorp) {
>               *errorp = NULL;
> @@ -7530,6 +7535,15 @@ odp_flow_key_to_mask(const struct nlattr *mask_key, size_t mask_key_len,
>       }
>   }
>   
> +enum odp_key_fitness
> +odp_flow_key_to_mask(const struct nlattr *mask_key, size_t mask_key_len,
> +                     struct flow_wildcards *mask,
> +                     const struct flow *src_flow, char **errorp)
> +{
> +    return odp_flow_key_to_mask__(mask_key, mask_key_len, mask, src_flow,
> +                                  errorp, false);
> +}
> +
>   /* Converts the netlink formated key/mask to match.
>    * Fails if odp_flow_key_from_key/mask and odp_flow_key_key/mask
>    * disagree on the acceptable form of flow */
> @@ -7540,7 +7554,8 @@ parse_key_and_mask_to_match(const struct nlattr *key, size_t key_len,
>   {
>       enum odp_key_fitness fitness;
>   
> -    fitness = odp_flow_key_to_flow(key, key_len, &match->flow, NULL);
> +    fitness = odp_flow_key_to_flow__(key, key_len, &match->flow, &match->flow,
> +                                     NULL, true);
>       if (fitness) {
>           /* This should not happen: it indicates that
>            * odp_flow_key_from_flow() and odp_flow_key_to_flow() disagree on
> @@ -7561,8 +7576,8 @@ parse_key_and_mask_to_match(const struct nlattr *key, size_t key_len,
>           return EINVAL;
>       }
>   
> -    fitness = odp_flow_key_to_mask(mask, mask_len, &match->wc, &match->flow,
> -                                   NULL);
> +    fitness = odp_flow_key_to_mask__(mask, mask_len, &match->wc, &match->flow,
> +                                     NULL, true);
>       if (fitness) {
>           /* This should not happen: it indicates that
>            * odp_flow_key_from_mask() and odp_flow_key_to_mask()
> 

seems fine to me. thanks.

Acked-by: Roi Dayan <roid@nvidia.com>
Ilya Maximets June 24, 2022, 8:26 p.m. UTC | #3
On 5/30/22 14:42, Roi Dayan wrote:
> 
> 
> On 2022-03-22 11:35 AM, Eelco Chaudron wrote:
>> The parse_key_and_mask_to_match() is a function to translate
>> a netlink formatted key/mask to match structure. And should
>> not consider any configuration setting when translating.
>>
>> In addition we also enforce the encap_eth_type[0] mask as
>> it's required for the VLAN match.
>>
>> Signed-off-by: Eelco Chaudron <echaudro@redhat.com>
>>
>> ---
>> v4:
>>   - Fixed call to odp_flow_key_to_mask__() to ignore vlan limit.
>>   - Force encap_eth_type[0] mask as it was used for VLAN matching.
>>
>>   lib/netdev-offload-tc.c |    2 +-
>>   lib/odp-util.c          |   41 ++++++++++++++++++++++++++++-------------
>>   2 files changed, 29 insertions(+), 14 deletions(-)
> 
> seems fine to me. thanks.
> 
> Acked-by: Roi Dayan <roid@nvidia.com>

Thanks!  Applied to master and branch-2.17.

Best regards, Ilya Maximets.
diff mbox series

Patch

diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c
index 9845e8d3f..7f0d4bbff 100644
--- a/lib/netdev-offload-tc.c
+++ b/lib/netdev-offload-tc.c
@@ -1638,7 +1638,7 @@  netdev_tc_flow_put(struct netdev *netdev, struct match *match,
 
     if (mask->vlans[0].tpid && eth_type_vlan(key->vlans[0].tpid)) {
         flower.key.encap_eth_type[0] = flower.key.eth_type;
-        flower.mask.encap_eth_type[0] = flower.mask.eth_type;
+        flower.mask.encap_eth_type[0] = CONSTANT_HTONS(0xffff);
         flower.key.eth_type = key->vlans[0].tpid;
         flower.mask.eth_type = mask->vlans[0].tpid;
     }
diff --git a/lib/odp-util.c b/lib/odp-util.c
index 0ff302856..4389df6a6 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -7188,7 +7188,8 @@  parse_8021q_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1],
                    uint64_t present_attrs, int out_of_range_attr,
                    uint64_t expected_attrs, struct flow *flow,
                    const struct nlattr *key, size_t key_len,
-                   const struct flow *src_flow, char **errorp)
+                   const struct flow *src_flow, char **errorp,
+                   bool ignore_vlan_limit)
 {
     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
     bool is_mask = src_flow != flow;
@@ -7196,9 +7197,11 @@  parse_8021q_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1],
     const struct nlattr *encap;
     enum odp_key_fitness encap_fitness;
     enum odp_key_fitness fitness = ODP_FIT_ERROR;
+    int vlan_limit;
     int encaps = 0;
 
-    while (encaps < flow_vlan_limit &&
+    vlan_limit = ignore_vlan_limit ? FLOW_MAX_VLAN_HEADERS : flow_vlan_limit;
+    while (encaps < vlan_limit &&
            (is_mask
             ? (src_flow->vlans[encaps].tci & htons(VLAN_CFI)) != 0
             : eth_type_vlan(flow->dl_type))) {
@@ -7281,7 +7284,7 @@  parse_8021q_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1],
 static enum odp_key_fitness
 odp_flow_key_to_flow__(const struct nlattr *key, size_t key_len,
                        struct flow *flow, const struct flow *src_flow,
-                       char **errorp)
+                       char **errorp, bool ignore_vlan_limit)
 {
     /* New "struct flow" fields that are visible to the datapath (including all
      * data fields) should be translated from equivalent datapath flow fields
@@ -7431,7 +7434,7 @@  odp_flow_key_to_flow__(const struct nlattr *key, size_t key_len,
         : eth_type_vlan(src_flow->dl_type)) {
         fitness = parse_8021q_onward(attrs, present_attrs, out_of_range_attr,
                                      expected_attrs, flow, key, key_len,
-                                     src_flow, errorp);
+                                     src_flow, errorp, ignore_vlan_limit);
     } else {
         if (is_mask) {
             /* A missing VLAN mask means exact match on vlan_tci 0 (== no
@@ -7497,7 +7500,7 @@  enum odp_key_fitness
 odp_flow_key_to_flow(const struct nlattr *key, size_t key_len,
                      struct flow *flow, char **errorp)
 {
-    return odp_flow_key_to_flow__(key, key_len, flow, flow, errorp);
+    return odp_flow_key_to_flow__(key, key_len, flow, flow, errorp, false);
 }
 
 /* Converts the 'mask_key_len' bytes of OVS_KEY_ATTR_* attributes in 'mask_key'
@@ -7509,14 +7512,16 @@  odp_flow_key_to_flow(const struct nlattr *key, size_t key_len,
  * If 'errorp' is nonnull, this function uses it for detailed error reports: if
  * the return value is ODP_FIT_ERROR, it stores a malloc()'d error string in
  * '*errorp', otherwise NULL. */
-enum odp_key_fitness
-odp_flow_key_to_mask(const struct nlattr *mask_key, size_t mask_key_len,
-                     struct flow_wildcards *mask, const struct flow *src_flow,
-                     char **errorp)
+static enum odp_key_fitness
+odp_flow_key_to_mask__(const struct nlattr *mask_key, size_t mask_key_len,
+                       struct flow_wildcards *mask,
+                       const struct flow *src_flow,
+                       char **errorp, bool ignore_vlan_limit)
 {
     if (mask_key_len) {
         return odp_flow_key_to_flow__(mask_key, mask_key_len,
-                                      &mask->masks, src_flow, errorp);
+                                      &mask->masks, src_flow, errorp,
+                                      ignore_vlan_limit);
     } else {
         if (errorp) {
             *errorp = NULL;
@@ -7530,6 +7535,15 @@  odp_flow_key_to_mask(const struct nlattr *mask_key, size_t mask_key_len,
     }
 }
 
+enum odp_key_fitness
+odp_flow_key_to_mask(const struct nlattr *mask_key, size_t mask_key_len,
+                     struct flow_wildcards *mask,
+                     const struct flow *src_flow, char **errorp)
+{
+    return odp_flow_key_to_mask__(mask_key, mask_key_len, mask, src_flow,
+                                  errorp, false);
+}
+
 /* Converts the netlink formated key/mask to match.
  * Fails if odp_flow_key_from_key/mask and odp_flow_key_key/mask
  * disagree on the acceptable form of flow */
@@ -7540,7 +7554,8 @@  parse_key_and_mask_to_match(const struct nlattr *key, size_t key_len,
 {
     enum odp_key_fitness fitness;
 
-    fitness = odp_flow_key_to_flow(key, key_len, &match->flow, NULL);
+    fitness = odp_flow_key_to_flow__(key, key_len, &match->flow, &match->flow,
+                                     NULL, true);
     if (fitness) {
         /* This should not happen: it indicates that
          * odp_flow_key_from_flow() and odp_flow_key_to_flow() disagree on
@@ -7561,8 +7576,8 @@  parse_key_and_mask_to_match(const struct nlattr *key, size_t key_len,
         return EINVAL;
     }
 
-    fitness = odp_flow_key_to_mask(mask, mask_len, &match->wc, &match->flow,
-                                   NULL);
+    fitness = odp_flow_key_to_mask__(mask, mask_len, &match->wc, &match->flow,
+                                     NULL, true);
     if (fitness) {
         /* This should not happen: it indicates that
          * odp_flow_key_from_mask() and odp_flow_key_to_mask()