diff mbox series

[ovs-dev] dpif-netdev: improve loading of packet data for undersized packets

Message ID 20220106114551.3779260-1-harry.van.haaren@intel.com
State Accepted
Headers show
Series [ovs-dev] dpif-netdev: improve loading of packet data for undersized packets | expand

Checks

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

Commit Message

Van Haaren, Harry Jan. 6, 2022, 11:45 a.m. UTC
This commit improves handling of packets where the allocated memory
is less than 64 bytes. In the DPDK datapath this never matters, as
an mbuf always pre-allocates enough space, however this can occur in
test environments such as the dummy netdev. The fix is required to
ensure ASAN enabled builds don't error on testing this, hence the
fix is valuable.

The solution implemented uses a mask-to-zero if the available buffer
size is less than 64 bytes, and a branch for which type of load is used.

Fixes: 250ceddcc2d0 ("dpif-netdev/mfex: Add AVX512 based optimized miniflow extract")

Reported-by: Ilya Maximets <i.maximets@ovn.org>
Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
---
 lib/dpif-netdev-extract-avx512.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

Comments

Eelco Chaudron Jan. 6, 2022, 1:01 p.m. UTC | #1
On 6 Jan 2022, at 12:45, Harry van Haaren wrote:

> This commit improves handling of packets where the allocated memory
> is less than 64 bytes. In the DPDK datapath this never matters, as
> an mbuf always pre-allocates enough space, however this can occur in
> test environments such as the dummy netdev. The fix is required to
> ensure ASAN enabled builds don't error on testing this, hence the
> fix is valuable.
>
> The solution implemented uses a mask-to-zero if the available buffer
> size is less than 64 bytes, and a branch for which type of load is used.
>
> Fixes: 250ceddcc2d0 ("dpif-netdev/mfex: Add AVX512 based optimized miniflow extract")
>
> Reported-by: Ilya Maximets <i.maximets@ovn.org>
> Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>

The change looks fine to me, can’t test, as I lack an AVX machine.
However, one small comment below.

//Eelco


> ---
>  lib/dpif-netdev-extract-avx512.c | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/lib/dpif-netdev-extract-avx512.c b/lib/dpif-netdev-extract-avx512.c
> index e060ab14a..d23349482 100644
> --- a/lib/dpif-netdev-extract-avx512.c
> +++ b/lib/dpif-netdev-extract-avx512.c
> @@ -488,7 +488,14 @@ mfex_avx512_process(struct dp_packet_batch *packets,
>
>          /* Load packet data and probe with AVX512 mask & compare. */
>          const uint8_t *pkt = dp_packet_data(packet);
> -        __m512i v_pkt0 = _mm512_loadu_si512(pkt);
> +        __m512i v_pkt0;
> +        if (size >= 64) {

Does it make sense to add an OVS_LIKELY() here?

> +            v_pkt0 = _mm512_loadu_si512(pkt);
> +        } else {
> +            uint64_t load_kmask = (1ULL << size) - 1;
> +            v_pkt0 = _mm512_maskz_loadu_epi8(load_kmask, pkt);
> +        }
> +
>          __m512i v_pkt0_masked = _mm512_and_si512(v_pkt0, v_mask);
>          __mmask64 k_cmp = _mm512_cmpeq_epi8_mask(v_pkt0_masked, v_vals);
>          if (k_cmp != UINT64_MAX) {
> -- 
> 2.25.1
>
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Van Haaren, Harry Jan. 6, 2022, 1:32 p.m. UTC | #2
> -----Original Message-----
> From: Eelco Chaudron <echaudro@redhat.com>
> Sent: Thursday, January 6, 2022 1:01 PM
> To: Van Haaren, Harry <harry.van.haaren@intel.com>
> Cc: ovs-dev@openvswitch.org; i.maximets@ovn.org
> Subject: Re: [ovs-dev] [PATCH] dpif-netdev: improve loading of packet data for
> undersized packets
> 
> 
> 
> On 6 Jan 2022, at 12:45, Harry van Haaren wrote:
> 
> > This commit improves handling of packets where the allocated memory
> > is less than 64 bytes. In the DPDK datapath this never matters, as
> > an mbuf always pre-allocates enough space, however this can occur in
> > test environments such as the dummy netdev. The fix is required to
> > ensure ASAN enabled builds don't error on testing this, hence the
> > fix is valuable.
> >
> > The solution implemented uses a mask-to-zero if the available buffer
> > size is less than 64 bytes, and a branch for which type of load is used.
> >
> > Fixes: 250ceddcc2d0 ("dpif-netdev/mfex: Add AVX512 based optimized
> miniflow extract")
> >
> > Reported-by: Ilya Maximets <i.maximets@ovn.org>
> > Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
> 
> The change looks fine to me, can’t test, as I lack an AVX machine.

For those interested, the SDE tool should allow testing this if hardware is lacking;
https://www.intel.com/content/www/us/en/developer/articles/tool/software-development-emulator.html

> However, one small comment below.
> 
> //Eelco

Thanks for having a look, detailed reply below.

Regards, -Harry

> > ---
> >  lib/dpif-netdev-extract-avx512.c | 9 ++++++++-
> >  1 file changed, 8 insertions(+), 1 deletion(-)
> >
> > diff --git a/lib/dpif-netdev-extract-avx512.c b/lib/dpif-netdev-extract-avx512.c
> > index e060ab14a..d23349482 100644
> > --- a/lib/dpif-netdev-extract-avx512.c
> > +++ b/lib/dpif-netdev-extract-avx512.c
> > @@ -488,7 +488,14 @@ mfex_avx512_process(struct dp_packet_batch
> *packets,
> >
> >          /* Load packet data and probe with AVX512 mask & compare. */
> >          const uint8_t *pkt = dp_packet_data(packet);
> > -        __m512i v_pkt0 = _mm512_loadu_si512(pkt);
> > +        __m512i v_pkt0;
> > +        if (size >= 64) {
> 
> Does it make sense to add an OVS_LIKELY() here?

Nope, not really a good candidate in my opinion.

So OVS_LIKELY() does not influence *runtime* branch prediction, it influences the compilers
generated code layout. As a result, LIKELY() basically says "put this on the linear-instructions
path, and *jump far away* for the unlikely case (because its unlikely, perf shouldn't matter!)

In the case of this branch, packet-after-packet could be taken/not-taken, so we
really just don't know which is better. Often the compiler will interleave the two
code-paths, and both will have a jump (one "into" its start point, the other "out").

Overally, LIKELY() should only be used when we *know* something to be an error
condition, and is *invalid* to occur on the datapath. This isn't branch does not handle
any invalid case, so no LIKELY/UNLIKELY here.

Thanks for read-review & checking though!

<snip>
Eelco Chaudron Jan. 6, 2022, 1:44 p.m. UTC | #3
On 6 Jan 2022, at 14:32, Van Haaren, Harry wrote:

>> -----Original Message-----
>> From: Eelco Chaudron <echaudro@redhat.com>
>> Sent: Thursday, January 6, 2022 1:01 PM
>> To: Van Haaren, Harry <harry.van.haaren@intel.com>
>> Cc: ovs-dev@openvswitch.org; i.maximets@ovn.org
>> Subject: Re: [ovs-dev] [PATCH] dpif-netdev: improve loading of packet data for
>> undersized packets
>>
>>
>>
>> On 6 Jan 2022, at 12:45, Harry van Haaren wrote:
>>
>>> This commit improves handling of packets where the allocated memory
>>> is less than 64 bytes. In the DPDK datapath this never matters, as
>>> an mbuf always pre-allocates enough space, however this can occur in
>>> test environments such as the dummy netdev. The fix is required to
>>> ensure ASAN enabled builds don't error on testing this, hence the
>>> fix is valuable.
>>>
>>> The solution implemented uses a mask-to-zero if the available buffer
>>> size is less than 64 bytes, and a branch for which type of load is used.
>>>
>>> Fixes: 250ceddcc2d0 ("dpif-netdev/mfex: Add AVX512 based optimized
>> miniflow extract")
>>>
>>> Reported-by: Ilya Maximets <i.maximets@ovn.org>
>>> Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
>>
>> The change looks fine to me, can’t test, as I lack an AVX machine.
>
> For those interested, the SDE tool should allow testing this if hardware is lacking;
> https://www.intel.com/content/www/us/en/developer/articles/tool/software-development-emulator.html

Interesting, if I get some time I’ll try it out!

>> However, one small comment below.
>>
>> //Eelco
>
> Thanks for having a look, detailed reply below.
>
> Regards, -Harry
>
>>> ---
>>>  lib/dpif-netdev-extract-avx512.c | 9 ++++++++-
>>>  1 file changed, 8 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/lib/dpif-netdev-extract-avx512.c b/lib/dpif-netdev-extract-avx512.c
>>> index e060ab14a..d23349482 100644
>>> --- a/lib/dpif-netdev-extract-avx512.c
>>> +++ b/lib/dpif-netdev-extract-avx512.c
>>> @@ -488,7 +488,14 @@ mfex_avx512_process(struct dp_packet_batch
>> *packets,
>>>
>>>          /* Load packet data and probe with AVX512 mask & compare. */
>>>          const uint8_t *pkt = dp_packet_data(packet);
>>> -        __m512i v_pkt0 = _mm512_loadu_si512(pkt);
>>> +        __m512i v_pkt0;
>>> +        if (size >= 64) {
>>
>> Does it make sense to add an OVS_LIKELY() here?
>
> Nope, not really a good candidate in my opinion.
>
> So OVS_LIKELY() does not influence *runtime* branch prediction, it influences the compilers
> generated code layout. As a result, LIKELY() basically says "put this on the linear-instructions
> path, and *jump far away* for the unlikely case (because its unlikely, perf shouldn't matter!)
>
> In the case of this branch, packet-after-packet could be taken/not-taken, so we
> really just don't know which is better. Often the compiler will interleave the two
> code-paths, and both will have a jump (one "into" its start point, the other "out").
>
> Overally, LIKELY() should only be used when we *know* something to be an error
> condition, and is *invalid* to occur on the datapath. This isn't branch does not handle
> any invalid case, so no LIKELY/UNLIKELY here.

This is what I was thinking about, this is an “ERROR” case in normal operations, and this path is only taken in the test cases, which are not high performance (or performance should not matter).

But anyway I’m fine, assuming you have not seen any performance impact with the change.


As it compiles and runs :)

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

> Thanks for read-review & checking though!
>
> <snip>
Ilya Maximets Jan. 12, 2022, 1:28 p.m. UTC | #4
On 1/6/22 12:45, Harry van Haaren wrote:
> This commit improves handling of packets where the allocated memory
> is less than 64 bytes. In the DPDK datapath this never matters, as
> an mbuf always pre-allocates enough space, however this can occur in
> test environments such as the dummy netdev.

This statement is not correct.  Few reasons:

1. Nitpick: there is no such thing as 'DPDK datapath'.

2. The issue is easily reproducible in production environments, i.e.
   it's not test-only.  The reason for that is netdev-linux and other
   ports which are present in every OVS setup (at least the bridge port
   in userspace datapath is a tap interface).  In a vast majority of
   setups these ports are actually up and has ip addresses.  E.g.
   OpenStack is using tap/veth interfaces for DHCP and other stuff.
   And locally delivered packets (packets that never left the hypervisor)
   are not obliged to be padded up to 64 bytes.  You may find that
   local ARP packets, for example, are typically 42 bytes long and that
   triggers the memory over-read in our case.

> The fix is required to
> ensure ASAN enabled builds don't error on testing this, hence the
> fix is valuable.
> 
> The solution implemented uses a mask-to-zero if the available buffer
> size is less than 64 bytes, and a branch for which type of load is used.
> 
> Fixes: 250ceddcc2d0 ("dpif-netdev/mfex: Add AVX512 based optimized miniflow extract")
> 
> Reported-by: Ilya Maximets <i.maximets@ovn.org>
> Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
> ---
>  lib/dpif-netdev-extract-avx512.c | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)

Thanks, Harry and Eelco.  The change itself looks good to me and it
fixes ASAN errors while running a few tests under SDE.  So, I fixed
the commit message and applied the patch.  Also backported to 2.16.

Best regards, Ilya Maximets.
diff mbox series

Patch

diff --git a/lib/dpif-netdev-extract-avx512.c b/lib/dpif-netdev-extract-avx512.c
index e060ab14a..d23349482 100644
--- a/lib/dpif-netdev-extract-avx512.c
+++ b/lib/dpif-netdev-extract-avx512.c
@@ -488,7 +488,14 @@  mfex_avx512_process(struct dp_packet_batch *packets,
 
         /* Load packet data and probe with AVX512 mask & compare. */
         const uint8_t *pkt = dp_packet_data(packet);
-        __m512i v_pkt0 = _mm512_loadu_si512(pkt);
+        __m512i v_pkt0;
+        if (size >= 64) {
+            v_pkt0 = _mm512_loadu_si512(pkt);
+        } else {
+            uint64_t load_kmask = (1ULL << size) - 1;
+            v_pkt0 = _mm512_maskz_loadu_epi8(load_kmask, pkt);
+        }
+
         __m512i v_pkt0_masked = _mm512_and_si512(v_pkt0, v_mask);
         __mmask64 k_cmp = _mm512_cmpeq_epi8_mask(v_pkt0_masked, v_vals);
         if (k_cmp != UINT64_MAX) {