diff mbox series

[ovs-dev] odp-util: Ignore unknown attributes in parse_key_and_mask_to_match()

Message ID 165400753240.2054605.12815593709246812392.stgit@ebuild
State Accepted
Commit 299050c2d07ea8a3afc2aa04b98dccd6f2f97402
Headers show
Series [ovs-dev] odp-util: Ignore unknown attributes in parse_key_and_mask_to_match() | 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

Eelco Chaudron May 31, 2022, 2:34 p.m. UTC
When processing netlink messages, we should ignore unknown OVS_KEY_ATTR
as we can assume if newer attributes are present, they are backward
compatible.

This patch also updates the existing comments to better explain what
happens in the error cases. At this place in the code, we can not
ignore the TOO_LITTLE/MUCH errors as some instances could have
canceled processing leaving the returning match data incomplete.

Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2089331
Signed-off-by: Eelco Chaudron <echaudro@redhat.com>
---
 lib/odp-util.c |   34 +++++++++++++++++++++++++---------
 1 file changed, 25 insertions(+), 9 deletions(-)

Comments

Roi Dayan June 1, 2022, 7:02 a.m. UTC | #1
On 2022-05-31 5:34 PM, Eelco Chaudron wrote:
> When processing netlink messages, we should ignore unknown OVS_KEY_ATTR
> as we can assume if newer attributes are present, they are backward
> compatible.
> 
> This patch also updates the existing comments to better explain what
> happens in the error cases. At this place in the code, we can not
> ignore the TOO_LITTLE/MUCH errors as some instances could have
> canceled processing leaving the returning match data incomplete.
> 
> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2089331
> Signed-off-by: Eelco Chaudron <echaudro@redhat.com>
> ---
>   lib/odp-util.c |   34 +++++++++++++++++++++++++---------
>   1 file changed, 25 insertions(+), 9 deletions(-)
> 
> diff --git a/lib/odp-util.c b/lib/odp-util.c
> index 40e89a7cf..0e6614bd8 100644
> --- a/lib/odp-util.c
> +++ b/lib/odp-util.c
> @@ -7263,6 +7263,14 @@ parse_8021q_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1],
>           }
>           expected_attrs = 0;
>   
> +        /* For OVS to be backward compatible with newer datapath
> +         * implementations, we should ignore out of range attributes. */
> +        if (out_of_range_attr) {
> +            VLOG_DBG("Flow key decode found unknown OVS_KEY_ATTR, %d",
> +                     out_of_range_attr);
> +            out_of_range_attr = 0;
> +        }
> +
>           if (!parse_ethertype(attrs, present_attrs, &expected_attrs,
>                                flow, src_flow, errorp)) {
>               return ODP_FIT_ERROR;
> @@ -7312,6 +7320,14 @@ odp_flow_key_to_flow__(const struct nlattr *key, size_t key_len,
>       }
>       expected_attrs = 0;
>   
> +    /* For OVS to be backward compatible with newer datapath implementations,
> +     * we should ignore out of range attributes. */
> +    if (out_of_range_attr) {
> +        VLOG_DBG("Flow key decode found unknown OVS_KEY_ATTR, %d",
> +                 out_of_range_attr);
> +        out_of_range_attr = 0;
> +    }
> +
>       /* Metadata. */
>       if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_RECIRC_ID)) {
>           flow->recirc_id = nl_attr_get_u32(attrs[OVS_KEY_ATTR_RECIRC_ID]);
> @@ -7546,10 +7562,12 @@ parse_key_and_mask_to_match(const struct nlattr *key, size_t key_len,
>   
>       fitness = odp_flow_key_to_flow(key, key_len, &match->flow, NULL);
>       if (fitness) {
> -        /* This should not happen: it indicates that
> -         * odp_flow_key_from_flow() and odp_flow_key_to_flow() disagree on
> -         * the acceptable form of a flow.  Log the problem as an error,
> -         * with enough details to enable debugging. */
> +        /* This will happen when the odp_flow_key_to_flow() function can't
> +         * parse the netlink message to a match structure. It will return
> +         * ODP_FIT_TOO_LITTLE if there is not enough information to parse the
> +         * content successfully, ODP_FIT_TOO_MUCH if there is too much netlink
> +         * data and we do not know how to safely ignore it, and ODP_FIT_ERROR
> +         * in any other case. */
>           static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
>   
>           if (!VLOG_DROP_ERR(&rl)) {
> @@ -7557,7 +7575,8 @@ parse_key_and_mask_to_match(const struct nlattr *key, size_t key_len,
>   
>               ds_init(&s);
>               odp_flow_format(key, key_len, NULL, 0, NULL, &s, true);
> -            VLOG_ERR("internal error parsing flow key %s", ds_cstr(&s));
> +            VLOG_ERR("internal error parsing flow key %s (%s)",
> +                     ds_cstr(&s), odp_key_fitness_to_string(fitness));
>               ds_destroy(&s);
>           }
>   
> @@ -7567,10 +7586,7 @@ parse_key_and_mask_to_match(const struct nlattr *key, size_t key_len,
>       fitness = odp_flow_key_to_mask(mask, mask_len, &match->wc, &match->flow,
>                                      NULL);
>       if (fitness) {
> -        /* This should not happen: it indicates that
> -         * odp_flow_key_from_mask() and odp_flow_key_to_mask()
> -         * disagree on the acceptable form of a mask.  Log the problem
> -         * as an error, with enough details to enable debugging. */
> +        /* This should not happen, see comment above. */
>           static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
>   
>           if (!VLOG_DROP_ERR(&rl)) {
> 
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev

thanks! also verified with simple ipv6 traffic.

Acked-by: Roi Dayan <roid@nvidia.com>

note this conflict with your other patch
"[PATCH v4] odp_util: Fix parse_key_and_mask_to_match() vlan parsing"
Eelco Chaudron June 1, 2022, 7:52 a.m. UTC | #2
On 1 Jun 2022, at 9:02, Roi Dayan wrote:

> On 2022-05-31 5:34 PM, Eelco Chaudron wrote:
>> When processing netlink messages, we should ignore unknown OVS_KEY_ATTR
>> as we can assume if newer attributes are present, they are backward
>> compatible.
>>
>> This patch also updates the existing comments to better explain what
>> happens in the error cases. At this place in the code, we can not
>> ignore the TOO_LITTLE/MUCH errors as some instances could have
>> canceled processing leaving the returning match data incomplete.
>>
>> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2089331
>> Signed-off-by: Eelco Chaudron <echaudro@redhat.com>
>> ---
>>   lib/odp-util.c |   34 +++++++++++++++++++++++++---------
>>   1 file changed, 25 insertions(+), 9 deletions(-)
>>
>> diff --git a/lib/odp-util.c b/lib/odp-util.c
>> index 40e89a7cf..0e6614bd8 100644
>> --- a/lib/odp-util.c
>> +++ b/lib/odp-util.c
>> @@ -7263,6 +7263,14 @@ parse_8021q_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1],
>>           }
>>           expected_attrs = 0;
>>  +        /* For OVS to be backward compatible with newer datapath
>> +         * implementations, we should ignore out of range attributes. */
>> +        if (out_of_range_attr) {
>> +            VLOG_DBG("Flow key decode found unknown OVS_KEY_ATTR, %d",
>> +                     out_of_range_attr);
>> +            out_of_range_attr = 0;
>> +        }
>> +
>>           if (!parse_ethertype(attrs, present_attrs, &expected_attrs,
>>                                flow, src_flow, errorp)) {
>>               return ODP_FIT_ERROR;
>> @@ -7312,6 +7320,14 @@ odp_flow_key_to_flow__(const struct nlattr *key, size_t key_len,
>>       }
>>       expected_attrs = 0;
>>  +    /* For OVS to be backward compatible with newer datapath implementations,
>> +     * we should ignore out of range attributes. */
>> +    if (out_of_range_attr) {
>> +        VLOG_DBG("Flow key decode found unknown OVS_KEY_ATTR, %d",
>> +                 out_of_range_attr);
>> +        out_of_range_attr = 0;
>> +    }
>> +
>>       /* Metadata. */
>>       if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_RECIRC_ID)) {
>>           flow->recirc_id = nl_attr_get_u32(attrs[OVS_KEY_ATTR_RECIRC_ID]);
>> @@ -7546,10 +7562,12 @@ parse_key_and_mask_to_match(const struct nlattr *key, size_t key_len,
>>        fitness = odp_flow_key_to_flow(key, key_len, &match->flow, NULL);
>>       if (fitness) {
>> -        /* This should not happen: it indicates that
>> -         * odp_flow_key_from_flow() and odp_flow_key_to_flow() disagree on
>> -         * the acceptable form of a flow.  Log the problem as an error,
>> -         * with enough details to enable debugging. */
>> +        /* This will happen when the odp_flow_key_to_flow() function can't
>> +         * parse the netlink message to a match structure. It will return
>> +         * ODP_FIT_TOO_LITTLE if there is not enough information to parse the
>> +         * content successfully, ODP_FIT_TOO_MUCH if there is too much netlink
>> +         * data and we do not know how to safely ignore it, and ODP_FIT_ERROR
>> +         * in any other case. */
>>           static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
>>            if (!VLOG_DROP_ERR(&rl)) {
>> @@ -7557,7 +7575,8 @@ parse_key_and_mask_to_match(const struct nlattr *key, size_t key_len,
>>                ds_init(&s);
>>               odp_flow_format(key, key_len, NULL, 0, NULL, &s, true);
>> -            VLOG_ERR("internal error parsing flow key %s", ds_cstr(&s));
>> +            VLOG_ERR("internal error parsing flow key %s (%s)",
>> +                     ds_cstr(&s), odp_key_fitness_to_string(fitness));
>>               ds_destroy(&s);
>>           }
>>  @@ -7567,10 +7586,7 @@ parse_key_and_mask_to_match(const struct nlattr *key, size_t key_len,
>>       fitness = odp_flow_key_to_mask(mask, mask_len, &match->wc, &match->flow,
>>                                      NULL);
>>       if (fitness) {
>> -        /* This should not happen: it indicates that
>> -         * odp_flow_key_from_mask() and odp_flow_key_to_mask()
>> -         * disagree on the acceptable form of a mask.  Log the problem
>> -         * as an error, with enough details to enable debugging. */
>> +        /* This should not happen, see comment above. */
>>           static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
>>            if (!VLOG_DROP_ERR(&rl)) {
>>
>> _______________________________________________
>> dev mailing list
>> dev@openvswitch.org
>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
> thanks! also verified with simple ipv6 traffic.
>
> Acked-by: Roi Dayan <roid@nvidia.com>
>
> note this conflict with your other patch
> "[PATCH v4] odp_util: Fix parse_key_and_mask_to_match() vlan parsing"

Thanks for the review!! Yes, I noticed but did not want to make this dependent as I think this needs to go in asap as Linux 5.18 is out.

//Eelco
Michael Santana June 15, 2022, 3:02 p.m. UTC | #3
On Tue, May 31, 2022 at 10:35 AM Eelco Chaudron <echaudro@redhat.com> wrote:
>
> When processing netlink messages, we should ignore unknown OVS_KEY_ATTR
> as we can assume if newer attributes are present, they are backward
> compatible.
>
> This patch also updates the existing comments to better explain what
> happens in the error cases. At this place in the code, we can not
> ignore the TOO_LITTLE/MUCH errors as some instances could have
> canceled processing leaving the returning match data incomplete.
>
> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2089331
> Signed-off-by: Eelco Chaudron <echaudro@redhat.com>
Reviewed-by: Michael Santana <msantana@redhat.com>

I would probably just have gotten rid of out_of_range_attr entirely in
the code base, but I guess this requires a little more work and has a
higher chance of breaking things. Your approach is safer and it gets
the job done

> ---
>  lib/odp-util.c |   34 +++++++++++++++++++++++++---------
>  1 file changed, 25 insertions(+), 9 deletions(-)
>
> diff --git a/lib/odp-util.c b/lib/odp-util.c
> index 40e89a7cf..0e6614bd8 100644
> --- a/lib/odp-util.c
> +++ b/lib/odp-util.c
> @@ -7263,6 +7263,14 @@ parse_8021q_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1],
>          }
>          expected_attrs = 0;
>
> +        /* For OVS to be backward compatible with newer datapath
> +         * implementations, we should ignore out of range attributes. */
> +        if (out_of_range_attr) {
> +            VLOG_DBG("Flow key decode found unknown OVS_KEY_ATTR, %d",
> +                     out_of_range_attr);
> +            out_of_range_attr = 0;
> +        }
> +
>          if (!parse_ethertype(attrs, present_attrs, &expected_attrs,
>                               flow, src_flow, errorp)) {
>              return ODP_FIT_ERROR;
> @@ -7312,6 +7320,14 @@ odp_flow_key_to_flow__(const struct nlattr *key, size_t key_len,
>      }
>      expected_attrs = 0;
>
> +    /* For OVS to be backward compatible with newer datapath implementations,
> +     * we should ignore out of range attributes. */
> +    if (out_of_range_attr) {
> +        VLOG_DBG("Flow key decode found unknown OVS_KEY_ATTR, %d",
> +                 out_of_range_attr);
> +        out_of_range_attr = 0;
> +    }
> +
>      /* Metadata. */
>      if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_RECIRC_ID)) {
>          flow->recirc_id = nl_attr_get_u32(attrs[OVS_KEY_ATTR_RECIRC_ID]);
> @@ -7546,10 +7562,12 @@ parse_key_and_mask_to_match(const struct nlattr *key, size_t key_len,
>
>      fitness = odp_flow_key_to_flow(key, key_len, &match->flow, NULL);
>      if (fitness) {
> -        /* This should not happen: it indicates that
> -         * odp_flow_key_from_flow() and odp_flow_key_to_flow() disagree on
> -         * the acceptable form of a flow.  Log the problem as an error,
> -         * with enough details to enable debugging. */
> +        /* This will happen when the odp_flow_key_to_flow() function can't
> +         * parse the netlink message to a match structure. It will return
> +         * ODP_FIT_TOO_LITTLE if there is not enough information to parse the
> +         * content successfully, ODP_FIT_TOO_MUCH if there is too much netlink
> +         * data and we do not know how to safely ignore it, and ODP_FIT_ERROR
> +         * in any other case. */
>          static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
>
>          if (!VLOG_DROP_ERR(&rl)) {
> @@ -7557,7 +7575,8 @@ parse_key_and_mask_to_match(const struct nlattr *key, size_t key_len,
>
>              ds_init(&s);
>              odp_flow_format(key, key_len, NULL, 0, NULL, &s, true);
> -            VLOG_ERR("internal error parsing flow key %s", ds_cstr(&s));
> +            VLOG_ERR("internal error parsing flow key %s (%s)",
> +                     ds_cstr(&s), odp_key_fitness_to_string(fitness));
>              ds_destroy(&s);
>          }
>
> @@ -7567,10 +7586,7 @@ parse_key_and_mask_to_match(const struct nlattr *key, size_t key_len,
>      fitness = odp_flow_key_to_mask(mask, mask_len, &match->wc, &match->flow,
>                                     NULL);
>      if (fitness) {
> -        /* This should not happen: it indicates that
> -         * odp_flow_key_from_mask() and odp_flow_key_to_mask()
> -         * disagree on the acceptable form of a mask.  Log the problem
> -         * as an error, with enough details to enable debugging. */
> +        /* This should not happen, see comment above. */
>          static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
>
>          if (!VLOG_DROP_ERR(&rl)) {
>
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
Roi Dayan June 23, 2022, 9:47 a.m. UTC | #4
On 2022-06-01 10:52 AM, Eelco Chaudron wrote:
> 
> 
> On 1 Jun 2022, at 9:02, Roi Dayan wrote:
> 
>> On 2022-05-31 5:34 PM, Eelco Chaudron wrote:
>>> When processing netlink messages, we should ignore unknown OVS_KEY_ATTR
>>> as we can assume if newer attributes are present, they are backward
>>> compatible.
>>>
>>> This patch also updates the existing comments to better explain what
>>> happens in the error cases. At this place in the code, we can not
>>> ignore the TOO_LITTLE/MUCH errors as some instances could have
>>> canceled processing leaving the returning match data incomplete.
>>>
>>> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2089331
>>> Signed-off-by: Eelco Chaudron <echaudro@redhat.com>
>>> ---
>>>    lib/odp-util.c |   34 +++++++++++++++++++++++++---------
>>>    1 file changed, 25 insertions(+), 9 deletions(-)
>>>
>>> diff --git a/lib/odp-util.c b/lib/odp-util.c
>>> index 40e89a7cf..0e6614bd8 100644
>>> --- a/lib/odp-util.c
>>> +++ b/lib/odp-util.c
>>> @@ -7263,6 +7263,14 @@ parse_8021q_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1],
>>>            }
>>>            expected_attrs = 0;
>>>   +        /* For OVS to be backward compatible with newer datapath
>>> +         * implementations, we should ignore out of range attributes. */
>>> +        if (out_of_range_attr) {
>>> +            VLOG_DBG("Flow key decode found unknown OVS_KEY_ATTR, %d",
>>> +                     out_of_range_attr);
>>> +            out_of_range_attr = 0;
>>> +        }
>>> +
>>>            if (!parse_ethertype(attrs, present_attrs, &expected_attrs,
>>>                                 flow, src_flow, errorp)) {
>>>                return ODP_FIT_ERROR;
>>> @@ -7312,6 +7320,14 @@ odp_flow_key_to_flow__(const struct nlattr *key, size_t key_len,
>>>        }
>>>        expected_attrs = 0;
>>>   +    /* For OVS to be backward compatible with newer datapath implementations,
>>> +     * we should ignore out of range attributes. */
>>> +    if (out_of_range_attr) {
>>> +        VLOG_DBG("Flow key decode found unknown OVS_KEY_ATTR, %d",
>>> +                 out_of_range_attr);
>>> +        out_of_range_attr = 0;
>>> +    }
>>> +
>>>        /* Metadata. */
>>>        if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_RECIRC_ID)) {
>>>            flow->recirc_id = nl_attr_get_u32(attrs[OVS_KEY_ATTR_RECIRC_ID]);
>>> @@ -7546,10 +7562,12 @@ parse_key_and_mask_to_match(const struct nlattr *key, size_t key_len,
>>>         fitness = odp_flow_key_to_flow(key, key_len, &match->flow, NULL);
>>>        if (fitness) {
>>> -        /* This should not happen: it indicates that
>>> -         * odp_flow_key_from_flow() and odp_flow_key_to_flow() disagree on
>>> -         * the acceptable form of a flow.  Log the problem as an error,
>>> -         * with enough details to enable debugging. */
>>> +        /* This will happen when the odp_flow_key_to_flow() function can't
>>> +         * parse the netlink message to a match structure. It will return
>>> +         * ODP_FIT_TOO_LITTLE if there is not enough information to parse the
>>> +         * content successfully, ODP_FIT_TOO_MUCH if there is too much netlink
>>> +         * data and we do not know how to safely ignore it, and ODP_FIT_ERROR
>>> +         * in any other case. */
>>>            static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
>>>             if (!VLOG_DROP_ERR(&rl)) {
>>> @@ -7557,7 +7575,8 @@ parse_key_and_mask_to_match(const struct nlattr *key, size_t key_len,
>>>                 ds_init(&s);
>>>                odp_flow_format(key, key_len, NULL, 0, NULL, &s, true);
>>> -            VLOG_ERR("internal error parsing flow key %s", ds_cstr(&s));
>>> +            VLOG_ERR("internal error parsing flow key %s (%s)",
>>> +                     ds_cstr(&s), odp_key_fitness_to_string(fitness));
>>>                ds_destroy(&s);
>>>            }
>>>   @@ -7567,10 +7586,7 @@ parse_key_and_mask_to_match(const struct nlattr *key, size_t key_len,
>>>        fitness = odp_flow_key_to_mask(mask, mask_len, &match->wc, &match->flow,
>>>                                       NULL);
>>>        if (fitness) {
>>> -        /* This should not happen: it indicates that
>>> -         * odp_flow_key_from_mask() and odp_flow_key_to_mask()
>>> -         * disagree on the acceptable form of a mask.  Log the problem
>>> -         * as an error, with enough details to enable debugging. */
>>> +        /* This should not happen, see comment above. */
>>>            static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
>>>             if (!VLOG_DROP_ERR(&rl)) {
>>>
>>> _______________________________________________
>>> dev mailing list
>>> dev@openvswitch.org
>>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>>
>> thanks! also verified with simple ipv6 traffic.
>>
>> Acked-by: Roi Dayan <roid@nvidia.com>
>>
>> note this conflict with your other patch
>> "[PATCH v4] odp_util: Fix parse_key_and_mask_to_match() vlan parsing"
> 
> Thanks for the review!! Yes, I noticed but did not want to make this dependent as I think this needs to go in asap as Linux 5.18 is out.
> 
> //Eelco
> 

Hi Ilya,

just pinging about this patch.

Thanks,
Roi
Ilya Maximets June 28, 2022, 4:17 p.m. UTC | #5
On 5/31/22 16:34, Eelco Chaudron wrote:
> When processing netlink messages, we should ignore unknown OVS_KEY_ATTR
> as we can assume if newer attributes are present, they are backward
> compatible.
> 
> This patch also updates the existing comments to better explain what
> happens in the error cases. At this place in the code, we can not
> ignore the TOO_LITTLE/MUCH errors as some instances could have
> canceled processing leaving the returning match data incomplete.
> 
> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2089331
> Signed-off-by: Eelco Chaudron <echaudro@redhat.com>
> ---
>  lib/odp-util.c |   34 +++++++++++++++++++++++++---------
>  1 file changed, 25 insertions(+), 9 deletions(-)

Thanks, Eelco, Roi and Michael!  Applied and backported down to 2.13.

Best regards, Ilya Maximets.
diff mbox series

Patch

diff --git a/lib/odp-util.c b/lib/odp-util.c
index 40e89a7cf..0e6614bd8 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -7263,6 +7263,14 @@  parse_8021q_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1],
         }
         expected_attrs = 0;
 
+        /* For OVS to be backward compatible with newer datapath
+         * implementations, we should ignore out of range attributes. */
+        if (out_of_range_attr) {
+            VLOG_DBG("Flow key decode found unknown OVS_KEY_ATTR, %d",
+                     out_of_range_attr);
+            out_of_range_attr = 0;
+        }
+
         if (!parse_ethertype(attrs, present_attrs, &expected_attrs,
                              flow, src_flow, errorp)) {
             return ODP_FIT_ERROR;
@@ -7312,6 +7320,14 @@  odp_flow_key_to_flow__(const struct nlattr *key, size_t key_len,
     }
     expected_attrs = 0;
 
+    /* For OVS to be backward compatible with newer datapath implementations,
+     * we should ignore out of range attributes. */
+    if (out_of_range_attr) {
+        VLOG_DBG("Flow key decode found unknown OVS_KEY_ATTR, %d",
+                 out_of_range_attr);
+        out_of_range_attr = 0;
+    }
+
     /* Metadata. */
     if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_RECIRC_ID)) {
         flow->recirc_id = nl_attr_get_u32(attrs[OVS_KEY_ATTR_RECIRC_ID]);
@@ -7546,10 +7562,12 @@  parse_key_and_mask_to_match(const struct nlattr *key, size_t key_len,
 
     fitness = odp_flow_key_to_flow(key, key_len, &match->flow, NULL);
     if (fitness) {
-        /* This should not happen: it indicates that
-         * odp_flow_key_from_flow() and odp_flow_key_to_flow() disagree on
-         * the acceptable form of a flow.  Log the problem as an error,
-         * with enough details to enable debugging. */
+        /* This will happen when the odp_flow_key_to_flow() function can't
+         * parse the netlink message to a match structure. It will return
+         * ODP_FIT_TOO_LITTLE if there is not enough information to parse the
+         * content successfully, ODP_FIT_TOO_MUCH if there is too much netlink
+         * data and we do not know how to safely ignore it, and ODP_FIT_ERROR
+         * in any other case. */
         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
 
         if (!VLOG_DROP_ERR(&rl)) {
@@ -7557,7 +7575,8 @@  parse_key_and_mask_to_match(const struct nlattr *key, size_t key_len,
 
             ds_init(&s);
             odp_flow_format(key, key_len, NULL, 0, NULL, &s, true);
-            VLOG_ERR("internal error parsing flow key %s", ds_cstr(&s));
+            VLOG_ERR("internal error parsing flow key %s (%s)",
+                     ds_cstr(&s), odp_key_fitness_to_string(fitness));
             ds_destroy(&s);
         }
 
@@ -7567,10 +7586,7 @@  parse_key_and_mask_to_match(const struct nlattr *key, size_t key_len,
     fitness = odp_flow_key_to_mask(mask, mask_len, &match->wc, &match->flow,
                                    NULL);
     if (fitness) {
-        /* This should not happen: it indicates that
-         * odp_flow_key_from_mask() and odp_flow_key_to_mask()
-         * disagree on the acceptable form of a mask.  Log the problem
-         * as an error, with enough details to enable debugging. */
+        /* This should not happen, see comment above. */
         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
 
         if (!VLOG_DROP_ERR(&rl)) {