diff mbox series

[ovs-dev] dp-packet: Reset offload flags when clearing a packet.

Message ID 20240122231144.574781-1-mkp@redhat.com
State Superseded
Delegated to: Ilya Maximets
Headers show
Series [ovs-dev] dp-packet: Reset offload flags when clearing a packet. | expand

Checks

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

Commit Message

Mike Pattrick Jan. 22, 2024, 11:11 p.m. UTC
The OVN test suite identified a bug in dp_packet_ol_send_prepare() where
a BFD packet flagged as double encapsulated would trigger a seg fault.
The problem surfaced because bfd_put_packet was reusing a packet
allocated on the stack that wasn't having its flags reset between calls.

This change will reset OL flags in data_clear(), which should fix this
type of packet reuse issue in general as long as data_clear() is called
in between uses. This change also includes a tangentially related check
in dp_packet_inner_l4_size(), where the correct offset was not being
checked.

Fixes: 8b5fe2dc6080 ("userspace: Add Generic Segmentation Offloading.")
Fixes: 85bcbbed839a ("userspace: Enable tunnel tests with TSO.")
Reported-by: Dumitru Ceara <dceara@redhat.com>
Reported-at: https://issues.redhat.com/browse/FDP-300
Signed-off-by: Mike Pattrick <mkp@redhat.com>
---
 lib/dp-packet.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

Comments

Dumitru Ceara Jan. 23, 2024, 9:17 a.m. UTC | #1
On 1/23/24 00:11, Mike Pattrick wrote:
> The OVN test suite identified a bug in dp_packet_ol_send_prepare() where
> a BFD packet flagged as double encapsulated would trigger a seg fault.
> The problem surfaced because bfd_put_packet was reusing a packet
> allocated on the stack that wasn't having its flags reset between calls.
> 

Thanks for tracking this one down, Mike!

> This change will reset OL flags in data_clear(), which should fix this
> type of packet reuse issue in general as long as data_clear() is called
> in between uses. This change also includes a tangentially related check
> in dp_packet_inner_l4_size(), where the correct offset was not being
> checked.

Up to maintainers but should this tangential fix be a separate patch?

> 
> Fixes: 8b5fe2dc6080 ("userspace: Add Generic Segmentation Offloading.")
> Fixes: 85bcbbed839a ("userspace: Enable tunnel tests with TSO.")
> Reported-by: Dumitru Ceara <dceara@redhat.com>
> Reported-at: https://issues.redhat.com/browse/FDP-300
> Signed-off-by: Mike Pattrick <mkp@redhat.com>
> ---

I'm no expert in this code but the change itself looks correct to me and
OVN tests pass with this applied:

Reviewed-by: Dumitru Ceara <dceara@redhat.com>

>  lib/dp-packet.h | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/lib/dp-packet.h b/lib/dp-packet.h
> index 939bec5c8..f328a6637 100644
> --- a/lib/dp-packet.h
> +++ b/lib/dp-packet.h
> @@ -207,6 +207,7 @@ void *dp_packet_resize_l2(struct dp_packet *, int increment);
>  void *dp_packet_resize_l2_5(struct dp_packet *, int increment);
>  static inline void *dp_packet_eth(const struct dp_packet *);
>  static inline void dp_packet_reset_offsets(struct dp_packet *);
> +static inline void dp_packet_reset_offload(struct dp_packet *);
>  static inline uint16_t dp_packet_l2_pad_size(const struct dp_packet *);
>  static inline void dp_packet_set_l2_pad_size(struct dp_packet *, uint16_t);
>  static inline void *dp_packet_l2_5(const struct dp_packet *);
> @@ -380,6 +381,7 @@ dp_packet_clear(struct dp_packet *b)
>  {
>      dp_packet_set_data(b, dp_packet_base(b));
>      dp_packet_set_size(b, 0);
> +    dp_packet_reset_offload(b);
>  }
>  
>  /* Removes 'size' bytes from the head end of 'b', which must contain at least
> @@ -537,7 +539,7 @@ dp_packet_inner_l4(const struct dp_packet *b)
>  static inline size_t
>  dp_packet_inner_l4_size(const struct dp_packet *b)
>  {
> -    return OVS_LIKELY(b->l4_ofs != UINT16_MAX)
> +    return OVS_LIKELY(b->inner_l4_ofs != UINT16_MAX)
>             ? (const char *) dp_packet_tail(b)
>             - (const char *) dp_packet_inner_l4(b)
>             - dp_packet_l2_pad_size(b)

Regards,
Dumitru
Aaron Conole Jan. 24, 2024, 4:39 p.m. UTC | #2
Dumitru Ceara <dceara@redhat.com> writes:

> On 1/23/24 00:11, Mike Pattrick wrote:
>> The OVN test suite identified a bug in dp_packet_ol_send_prepare() where
>> a BFD packet flagged as double encapsulated would trigger a seg fault.
>> The problem surfaced because bfd_put_packet was reusing a packet
>> allocated on the stack that wasn't having its flags reset between calls.
>> 
>
> Thanks for tracking this one down, Mike!
>
>> This change will reset OL flags in data_clear(), which should fix this
>> type of packet reuse issue in general as long as data_clear() is called
>> in between uses. This change also includes a tangentially related check
>> in dp_packet_inner_l4_size(), where the correct offset was not being
>> checked.
>
> Up to maintainers but should this tangential fix be a separate patch?

I think it makes sense.  These are two different issues, so probably
should go as two separate patches.

>> 
>> Fixes: 8b5fe2dc6080 ("userspace: Add Generic Segmentation Offloading.")
>> Fixes: 85bcbbed839a ("userspace: Enable tunnel tests with TSO.")
>> Reported-by: Dumitru Ceara <dceara@redhat.com>
>> Reported-at: https://issues.redhat.com/browse/FDP-300
>> Signed-off-by: Mike Pattrick <mkp@redhat.com>
>> ---
>
> I'm no expert in this code but the change itself looks correct to me and
> OVN tests pass with this applied:
>
> Reviewed-by: Dumitru Ceara <dceara@redhat.com>
>
>>  lib/dp-packet.h | 4 +++-
>>  1 file changed, 3 insertions(+), 1 deletion(-)
>> 
>> diff --git a/lib/dp-packet.h b/lib/dp-packet.h
>> index 939bec5c8..f328a6637 100644
>> --- a/lib/dp-packet.h
>> +++ b/lib/dp-packet.h
>> @@ -207,6 +207,7 @@ void *dp_packet_resize_l2(struct dp_packet *, int increment);
>>  void *dp_packet_resize_l2_5(struct dp_packet *, int increment);
>>  static inline void *dp_packet_eth(const struct dp_packet *);
>>  static inline void dp_packet_reset_offsets(struct dp_packet *);
>> +static inline void dp_packet_reset_offload(struct dp_packet *);
>>  static inline uint16_t dp_packet_l2_pad_size(const struct dp_packet *);
>>  static inline void dp_packet_set_l2_pad_size(struct dp_packet *, uint16_t);
>>  static inline void *dp_packet_l2_5(const struct dp_packet *);
>> @@ -380,6 +381,7 @@ dp_packet_clear(struct dp_packet *b)
>>  {
>>      dp_packet_set_data(b, dp_packet_base(b));
>>      dp_packet_set_size(b, 0);
>> +    dp_packet_reset_offload(b);
>>  }
>>  
>>  /* Removes 'size' bytes from the head end of 'b', which must contain at least
>> @@ -537,7 +539,7 @@ dp_packet_inner_l4(const struct dp_packet *b)
>>  static inline size_t
>>  dp_packet_inner_l4_size(const struct dp_packet *b)
>>  {
>> -    return OVS_LIKELY(b->l4_ofs != UINT16_MAX)
>> +    return OVS_LIKELY(b->inner_l4_ofs != UINT16_MAX)
>>             ? (const char *) dp_packet_tail(b)
>>             - (const char *) dp_packet_inner_l4(b)
>>             - dp_packet_l2_pad_size(b)
>
> Regards,
> Dumitru
>
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Ilya Maximets Jan. 24, 2024, 7 p.m. UTC | #3
On 1/24/24 17:39, Aaron Conole wrote:
> Dumitru Ceara <dceara@redhat.com> writes:
> 
>> On 1/23/24 00:11, Mike Pattrick wrote:
>>> The OVN test suite identified a bug in dp_packet_ol_send_prepare() where
>>> a BFD packet flagged as double encapsulated would trigger a seg fault.
>>> The problem surfaced because bfd_put_packet was reusing a packet
>>> allocated on the stack that wasn't having its flags reset between calls.
>>>
>>
>> Thanks for tracking this one down, Mike!
>>
>>> This change will reset OL flags in data_clear(), which should fix this
>>> type of packet reuse issue in general as long as data_clear() is called
>>> in between uses. This change also includes a tangentially related check
>>> in dp_packet_inner_l4_size(), where the correct offset was not being
>>> checked.
>>
>> Up to maintainers but should this tangential fix be a separate patch?
> 
> I think it makes sense.  These are two different issues, so probably
> should go as two separate patches.

+1

> 
>>>
>>> Fixes: 8b5fe2dc6080 ("userspace: Add Generic Segmentation Offloading.")
>>> Fixes: 85bcbbed839a ("userspace: Enable tunnel tests with TSO.")
>>> Reported-by: Dumitru Ceara <dceara@redhat.com>
>>> Reported-at: https://issues.redhat.com/browse/FDP-300
>>> Signed-off-by: Mike Pattrick <mkp@redhat.com>
>>> ---
>>
>> I'm no expert in this code but the change itself looks correct to me and
>> OVN tests pass with this applied:
>>
>> Reviewed-by: Dumitru Ceara <dceara@redhat.com>
>>
>>>  lib/dp-packet.h | 4 +++-
>>>  1 file changed, 3 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/lib/dp-packet.h b/lib/dp-packet.h
>>> index 939bec5c8..f328a6637 100644
>>> --- a/lib/dp-packet.h
>>> +++ b/lib/dp-packet.h
>>> @@ -207,6 +207,7 @@ void *dp_packet_resize_l2(struct dp_packet *, int increment);
>>>  void *dp_packet_resize_l2_5(struct dp_packet *, int increment);
>>>  static inline void *dp_packet_eth(const struct dp_packet *);
>>>  static inline void dp_packet_reset_offsets(struct dp_packet *);
>>> +static inline void dp_packet_reset_offload(struct dp_packet *);
>>>  static inline uint16_t dp_packet_l2_pad_size(const struct dp_packet *);
>>>  static inline void dp_packet_set_l2_pad_size(struct dp_packet *, uint16_t);
>>>  static inline void *dp_packet_l2_5(const struct dp_packet *);
>>> @@ -380,6 +381,7 @@ dp_packet_clear(struct dp_packet *b)
>>>  {
>>>      dp_packet_set_data(b, dp_packet_base(b));
>>>      dp_packet_set_size(b, 0);
>>> +    dp_packet_reset_offload(b);

Should we also reset offsets here?  They are also not valid after
clearing the packet data.

Looking through the different dp-packet functions it seems we're
missing adjustments for inner offsets in dp_packet_resize_l2_5().
May be a problem if we would also need to push a vlan after
encapsulation of packet with checksum offload.
May be a separate fix as well.


>>>  }
>>>  
>>>  /* Removes 'size' bytes from the head end of 'b', which must contain at least
>>> @@ -537,7 +539,7 @@ dp_packet_inner_l4(const struct dp_packet *b)
>>>  static inline size_t
>>>  dp_packet_inner_l4_size(const struct dp_packet *b)
>>>  {
>>> -    return OVS_LIKELY(b->l4_ofs != UINT16_MAX)
>>> +    return OVS_LIKELY(b->inner_l4_ofs != UINT16_MAX)
>>>             ? (const char *) dp_packet_tail(b)
>>>             - (const char *) dp_packet_inner_l4(b)
>>>             - dp_packet_l2_pad_size(b)
>>
>> Regards,
>> Dumitru
diff mbox series

Patch

diff --git a/lib/dp-packet.h b/lib/dp-packet.h
index 939bec5c8..f328a6637 100644
--- a/lib/dp-packet.h
+++ b/lib/dp-packet.h
@@ -207,6 +207,7 @@  void *dp_packet_resize_l2(struct dp_packet *, int increment);
 void *dp_packet_resize_l2_5(struct dp_packet *, int increment);
 static inline void *dp_packet_eth(const struct dp_packet *);
 static inline void dp_packet_reset_offsets(struct dp_packet *);
+static inline void dp_packet_reset_offload(struct dp_packet *);
 static inline uint16_t dp_packet_l2_pad_size(const struct dp_packet *);
 static inline void dp_packet_set_l2_pad_size(struct dp_packet *, uint16_t);
 static inline void *dp_packet_l2_5(const struct dp_packet *);
@@ -380,6 +381,7 @@  dp_packet_clear(struct dp_packet *b)
 {
     dp_packet_set_data(b, dp_packet_base(b));
     dp_packet_set_size(b, 0);
+    dp_packet_reset_offload(b);
 }
 
 /* Removes 'size' bytes from the head end of 'b', which must contain at least
@@ -537,7 +539,7 @@  dp_packet_inner_l4(const struct dp_packet *b)
 static inline size_t
 dp_packet_inner_l4_size(const struct dp_packet *b)
 {
-    return OVS_LIKELY(b->l4_ofs != UINT16_MAX)
+    return OVS_LIKELY(b->inner_l4_ofs != UINT16_MAX)
            ? (const char *) dp_packet_tail(b)
            - (const char *) dp_packet_inner_l4(b)
            - dp_packet_l2_pad_size(b)