diff mbox series

[ovs-dev,v2,3/4] dp-packet: Include inner offsets in adjustments and checks.

Message ID 20240130221439.24297-3-mkp@redhat.com
State Changes Requested
Headers show
Series [ovs-dev,v2,1/4] dp-packet: Validate correct offset for L4 inner size. | 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

Mike Pattrick Jan. 30, 2024, 10:14 p.m. UTC
Include inner offsets in functions where l3 and l4 offsets are either
modified or checked.

Fixes: 084c8087292c ("userspace: Support VXLAN and GENEVE TSO.")
Signed-off-by: Mike Pattrick <mkp@redhat.com>
---
v2:

 - Prints out new offsets in autovalidator
 - Extends resize_l2 change to avx512

Signed-off-by: Mike Pattrick <mkp@redhat.com>
---
 lib/dp-packet.c          | 18 +++++++++++++-----
 lib/odp-execute-avx512.c | 19 ++++++++++++++-----
 2 files changed, 27 insertions(+), 10 deletions(-)

Comments

David Marchand Jan. 31, 2024, 3:03 p.m. UTC | #1
On Tue, Jan 30, 2024 at 11:15 PM Mike Pattrick <mkp@redhat.com> wrote:
>
> Include inner offsets in functions where l3 and l4 offsets are either
> modified or checked.
>
> Fixes: 084c8087292c ("userspace: Support VXLAN and GENEVE TSO.")
> Signed-off-by: Mike Pattrick <mkp@redhat.com>
> ---
> v2:
>
>  - Prints out new offsets in autovalidator
>  - Extends resize_l2 change to avx512
>
> Signed-off-by: Mike Pattrick <mkp@redhat.com>
> ---
>  lib/dp-packet.c          | 18 +++++++++++++-----
>  lib/odp-execute-avx512.c | 19 ++++++++++++++-----
>  2 files changed, 27 insertions(+), 10 deletions(-)
>
> diff --git a/lib/dp-packet.c b/lib/dp-packet.c
> index 0e23c766e..640b1dfeb 100644
> --- a/lib/dp-packet.c
> +++ b/lib/dp-packet.c
> @@ -507,6 +507,8 @@ dp_packet_resize_l2_5(struct dp_packet *b, int increment)
>      /* Adjust layer offsets after l2_5. */
>      dp_packet_adjust_layer_offset(&b->l3_ofs, increment);
>      dp_packet_adjust_layer_offset(&b->l4_ofs, increment);
> +    dp_packet_adjust_layer_offset(&b->inner_l3_ofs, increment);
> +    dp_packet_adjust_layer_offset(&b->inner_l4_ofs, increment);
>
>      return dp_packet_data(b);
>  }
> @@ -529,17 +531,23 @@ dp_packet_compare_offsets(struct dp_packet *b1, struct dp_packet *b2,
>      if ((b1->l2_pad_size != b2->l2_pad_size) ||
>          (b1->l2_5_ofs != b2->l2_5_ofs) ||
>          (b1->l3_ofs != b2->l3_ofs) ||
> -        (b1->l4_ofs != b2->l4_ofs)) {
> +        (b1->l4_ofs != b2->l4_ofs) ||
> +        (b1->inner_l3_ofs != b2->inner_l3_ofs) ||
> +        (b1->inner_l4_ofs != b2->inner_l4_ofs)) {
>          if (err_str) {
>              ds_put_format(err_str, "Packet offset comparison failed\n");
>              ds_put_format(err_str, "Buffer 1 offsets: l2_pad_size %u,"
> -                          " l2_5_ofs : %u l3_ofs %u, l4_ofs %u\n",
> +                          " l2_5_ofs : %u l3_ofs %u, inner_l3_ofs %u,"
> +                          " l4_ofs %u, inner_l4_ofs %u\n",
>                            b1->l2_pad_size, b1->l2_5_ofs,
> -                          b1->l3_ofs, b1->l4_ofs);
> +                          b1->l3_ofs, b1->inner_l3_ofs,
> +                          b1->l4_ofs, b1->inner_l4_ofs);
>              ds_put_format(err_str, "Buffer 2 offsets: l2_pad_size %u,"
> -                          " l2_5_ofs : %u l3_ofs %u, l4_ofs %u\n",
> +                          " l2_5_ofs : %u l3_ofs %u, inner_l3_ofs %u,"
> +                          " l4_ofs %u, inner_l4_ofs %u\n",
>                            b2->l2_pad_size, b2->l2_5_ofs,
> -                          b2->l3_ofs, b2->l4_ofs);
> +                          b2->l3_ofs, b2->inner_l3_ofs,
> +                          b2->l4_ofs, b2->inner_l4_ofs);
>          }
>          return false;
>      }

Not a strong opinion, but I prefer keeping those offsets in the same
order than a real packet layout, rather than mix l3 / l4 outer/inner
offsets.
IOW:
-                          " l2_5_ofs : %u l3_ofs %u, l4_ofs %u\n",
+                          " l2_5_ofs : %u l3_ofs %u, l4_ofs %u,"
+                          " inner_l3_ofs : %u, inner_l4_ofs %u\n",


> diff --git a/lib/odp-execute-avx512.c b/lib/odp-execute-avx512.c
> index 747e04014..7f9870669 100644
> --- a/lib/odp-execute-avx512.c
> +++ b/lib/odp-execute-avx512.c
> @@ -35,10 +35,11 @@
>
>  VLOG_DEFINE_THIS_MODULE(odp_execute_avx512);
>
> -/* The below three build asserts make sure that l2_5_ofs, l3_ofs, and l4_ofs
> - * fields remain in the same order and offset to l2_padd_size. This is needed
> - * as the avx512_dp_packet_resize_l2() function will manipulate those fields at
> - * a fixed memory index based on the l2_padd_size offset. */
> +/* The below three build asserts make sure that l2_5_ofs, l3_ofs, l4_ofs,

Counting build asserts is useless in a comment.. and here it gets
wrong after the change.
I suggest a simple: "The below build asserts".


> + * inner_l3_ofs, and inner_l4_ofs fields remain in the same order and offset to
> + * l2_padd_size. This is needed as the avx512_dp_packet_resize_l2() function

l2_pad_size*


> + * will manipulate those fields at a fixed memory index based on the
> + * l2_padd_size offset. */

Idem.


>  BUILD_ASSERT_DECL(offsetof(struct dp_packet, l2_pad_size) +
>                    MEMBER_SIZEOF(struct dp_packet, l2_pad_size) ==
>                    offsetof(struct dp_packet, l2_5_ofs));
> @@ -51,6 +52,14 @@ BUILD_ASSERT_DECL(offsetof(struct dp_packet, l3_ofs) +
>                             MEMBER_SIZEOF(struct dp_packet, l3_ofs) ==
>                             offsetof(struct dp_packet, l4_ofs));
>
> +BUILD_ASSERT_DECL(offsetof(struct dp_packet, l4_ofs) +
> +                           MEMBER_SIZEOF(struct dp_packet, l4_ofs) ==
> +                           offsetof(struct dp_packet, inner_l3_ofs));
> +
> +BUILD_ASSERT_DECL(offsetof(struct dp_packet, inner_l3_ofs) +
> +                           MEMBER_SIZEOF(struct dp_packet, inner_l3_ofs) ==
> +                           offsetof(struct dp_packet, inner_l4_ofs));
> +
>  /* The below build assert makes sure it's safe to read/write 128-bits starting
>   * at the l2_pad_size location. */
>  BUILD_ASSERT_DECL(sizeof(struct dp_packet) -
> @@ -125,7 +134,7 @@ avx512_dp_packet_resize_l2(struct dp_packet *b, int resize_by_bytes)
>      /* Each lane represents 16 bits in a 12-bit register. In this case the
>       * first three 16-bit values, which will map to the l2_5_ofs, l3_ofs and
>       * l4_ofs fields. */
> -    const uint8_t k_lanes = 0b1110;
> +    const uint8_t k_lanes = 0b111110;
>
>      /* Set all 16-bit words in the 128-bits v_offset register to the value we
>       * need to add/substract from the l2_5_ofs, l3_ofs, and l4_ofs fields. */

Touching this part scares me.
I think some comments are wrong, and otherwise I hope Intel CI will be
enough to check nothing gets broken here :-).
Mike Pattrick Jan. 31, 2024, 4:07 p.m. UTC | #2
On Wed, Jan 31, 2024 at 10:04 AM David Marchand
<david.marchand@redhat.com> wrote:
>
> On Tue, Jan 30, 2024 at 11:15 PM Mike Pattrick <mkp@redhat.com> wrote:
> >
> > Include inner offsets in functions where l3 and l4 offsets are either
> > modified or checked.
> >
> > Fixes: 084c8087292c ("userspace: Support VXLAN and GENEVE TSO.")
> > Signed-off-by: Mike Pattrick <mkp@redhat.com>
> > ---
> > v2:
> >
> >  - Prints out new offsets in autovalidator
> >  - Extends resize_l2 change to avx512
> >
> > Signed-off-by: Mike Pattrick <mkp@redhat.com>
> > ---
> >  lib/dp-packet.c          | 18 +++++++++++++-----
> >  lib/odp-execute-avx512.c | 19 ++++++++++++++-----
> >  2 files changed, 27 insertions(+), 10 deletions(-)
> >
> > diff --git a/lib/dp-packet.c b/lib/dp-packet.c
> > index 0e23c766e..640b1dfeb 100644
> > --- a/lib/dp-packet.c
> > +++ b/lib/dp-packet.c
> > @@ -507,6 +507,8 @@ dp_packet_resize_l2_5(struct dp_packet *b, int increment)
> >      /* Adjust layer offsets after l2_5. */
> >      dp_packet_adjust_layer_offset(&b->l3_ofs, increment);
> >      dp_packet_adjust_layer_offset(&b->l4_ofs, increment);
> > +    dp_packet_adjust_layer_offset(&b->inner_l3_ofs, increment);
> > +    dp_packet_adjust_layer_offset(&b->inner_l4_ofs, increment);
> >
> >      return dp_packet_data(b);
> >  }
> > @@ -529,17 +531,23 @@ dp_packet_compare_offsets(struct dp_packet *b1, struct dp_packet *b2,
> >      if ((b1->l2_pad_size != b2->l2_pad_size) ||
> >          (b1->l2_5_ofs != b2->l2_5_ofs) ||
> >          (b1->l3_ofs != b2->l3_ofs) ||
> > -        (b1->l4_ofs != b2->l4_ofs)) {
> > +        (b1->l4_ofs != b2->l4_ofs) ||
> > +        (b1->inner_l3_ofs != b2->inner_l3_ofs) ||
> > +        (b1->inner_l4_ofs != b2->inner_l4_ofs)) {
> >          if (err_str) {
> >              ds_put_format(err_str, "Packet offset comparison failed\n");
> >              ds_put_format(err_str, "Buffer 1 offsets: l2_pad_size %u,"
> > -                          " l2_5_ofs : %u l3_ofs %u, l4_ofs %u\n",
> > +                          " l2_5_ofs : %u l3_ofs %u, inner_l3_ofs %u,"
> > +                          " l4_ofs %u, inner_l4_ofs %u\n",
> >                            b1->l2_pad_size, b1->l2_5_ofs,
> > -                          b1->l3_ofs, b1->l4_ofs);
> > +                          b1->l3_ofs, b1->inner_l3_ofs,
> > +                          b1->l4_ofs, b1->inner_l4_ofs);
> >              ds_put_format(err_str, "Buffer 2 offsets: l2_pad_size %u,"
> > -                          " l2_5_ofs : %u l3_ofs %u, l4_ofs %u\n",
> > +                          " l2_5_ofs : %u l3_ofs %u, inner_l3_ofs %u,"
> > +                          " l4_ofs %u, inner_l4_ofs %u\n",
> >                            b2->l2_pad_size, b2->l2_5_ofs,
> > -                          b2->l3_ofs, b2->l4_ofs);
> > +                          b2->l3_ofs, b2->inner_l3_ofs,
> > +                          b2->l4_ofs, b2->inner_l4_ofs);
> >          }
> >          return false;
> >      }
>
> Not a strong opinion, but I prefer keeping those offsets in the same
> order than a real packet layout, rather than mix l3 / l4 outer/inner
> offsets.
> IOW:
> -                          " l2_5_ofs : %u l3_ofs %u, l4_ofs %u\n",
> +                          " l2_5_ofs : %u l3_ofs %u, l4_ofs %u,"
> +                          " inner_l3_ofs : %u, inner_l4_ofs %u\n",
>
>
> > diff --git a/lib/odp-execute-avx512.c b/lib/odp-execute-avx512.c
> > index 747e04014..7f9870669 100644
> > --- a/lib/odp-execute-avx512.c
> > +++ b/lib/odp-execute-avx512.c
> > @@ -35,10 +35,11 @@
> >
> >  VLOG_DEFINE_THIS_MODULE(odp_execute_avx512);
> >
> > -/* The below three build asserts make sure that l2_5_ofs, l3_ofs, and l4_ofs
> > - * fields remain in the same order and offset to l2_padd_size. This is needed
> > - * as the avx512_dp_packet_resize_l2() function will manipulate those fields at
> > - * a fixed memory index based on the l2_padd_size offset. */
> > +/* The below three build asserts make sure that l2_5_ofs, l3_ofs, l4_ofs,
>
> Counting build asserts is useless in a comment.. and here it gets
> wrong after the change.
> I suggest a simple: "The below build asserts".
>
>
> > + * inner_l3_ofs, and inner_l4_ofs fields remain in the same order and offset to
> > + * l2_padd_size. This is needed as the avx512_dp_packet_resize_l2() function
>
> l2_pad_size*
>
>
> > + * will manipulate those fields at a fixed memory index based on the
> > + * l2_padd_size offset. */
>
> Idem.
>
>
> >  BUILD_ASSERT_DECL(offsetof(struct dp_packet, l2_pad_size) +
> >                    MEMBER_SIZEOF(struct dp_packet, l2_pad_size) ==
> >                    offsetof(struct dp_packet, l2_5_ofs));
> > @@ -51,6 +52,14 @@ BUILD_ASSERT_DECL(offsetof(struct dp_packet, l3_ofs) +
> >                             MEMBER_SIZEOF(struct dp_packet, l3_ofs) ==
> >                             offsetof(struct dp_packet, l4_ofs));
> >
> > +BUILD_ASSERT_DECL(offsetof(struct dp_packet, l4_ofs) +
> > +                           MEMBER_SIZEOF(struct dp_packet, l4_ofs) ==
> > +                           offsetof(struct dp_packet, inner_l3_ofs));
> > +
> > +BUILD_ASSERT_DECL(offsetof(struct dp_packet, inner_l3_ofs) +
> > +                           MEMBER_SIZEOF(struct dp_packet, inner_l3_ofs) ==
> > +                           offsetof(struct dp_packet, inner_l4_ofs));
> > +
> >  /* The below build assert makes sure it's safe to read/write 128-bits starting
> >   * at the l2_pad_size location. */
> >  BUILD_ASSERT_DECL(sizeof(struct dp_packet) -
> > @@ -125,7 +134,7 @@ avx512_dp_packet_resize_l2(struct dp_packet *b, int resize_by_bytes)
> >      /* Each lane represents 16 bits in a 12-bit register. In this case the
> >       * first three 16-bit values, which will map to the l2_5_ofs, l3_ofs and
> >       * l4_ofs fields. */
> > -    const uint8_t k_lanes = 0b1110;
> > +    const uint8_t k_lanes = 0b111110;
> >
> >      /* Set all 16-bit words in the 128-bits v_offset register to the value we
> >       * need to add/substract from the l2_5_ofs, l3_ofs, and l4_ofs fields. */
>
> Touching this part scares me.
> I think some comments are wrong, and otherwise I hope Intel CI will be
> enough to check nothing gets broken here :-).

A lot of thought and apprehension went into flipping two bits. One of
the reasons that I didn't catch this before is because the normal
machine I dev and test on doesn't have AVX512. However, I now have a
VM on a newer CPU, this change satisfies the autovalidator with actual
traffic flowing.

But as you point out, various comments are incorrect. I'll send in a
newer version with comments corrected.

-M

>
>
>
> --
> David Marchand
>
diff mbox series

Patch

diff --git a/lib/dp-packet.c b/lib/dp-packet.c
index 0e23c766e..640b1dfeb 100644
--- a/lib/dp-packet.c
+++ b/lib/dp-packet.c
@@ -507,6 +507,8 @@  dp_packet_resize_l2_5(struct dp_packet *b, int increment)
     /* Adjust layer offsets after l2_5. */
     dp_packet_adjust_layer_offset(&b->l3_ofs, increment);
     dp_packet_adjust_layer_offset(&b->l4_ofs, increment);
+    dp_packet_adjust_layer_offset(&b->inner_l3_ofs, increment);
+    dp_packet_adjust_layer_offset(&b->inner_l4_ofs, increment);
 
     return dp_packet_data(b);
 }
@@ -529,17 +531,23 @@  dp_packet_compare_offsets(struct dp_packet *b1, struct dp_packet *b2,
     if ((b1->l2_pad_size != b2->l2_pad_size) ||
         (b1->l2_5_ofs != b2->l2_5_ofs) ||
         (b1->l3_ofs != b2->l3_ofs) ||
-        (b1->l4_ofs != b2->l4_ofs)) {
+        (b1->l4_ofs != b2->l4_ofs) ||
+        (b1->inner_l3_ofs != b2->inner_l3_ofs) ||
+        (b1->inner_l4_ofs != b2->inner_l4_ofs)) {
         if (err_str) {
             ds_put_format(err_str, "Packet offset comparison failed\n");
             ds_put_format(err_str, "Buffer 1 offsets: l2_pad_size %u,"
-                          " l2_5_ofs : %u l3_ofs %u, l4_ofs %u\n",
+                          " l2_5_ofs : %u l3_ofs %u, inner_l3_ofs %u,"
+                          " l4_ofs %u, inner_l4_ofs %u\n",
                           b1->l2_pad_size, b1->l2_5_ofs,
-                          b1->l3_ofs, b1->l4_ofs);
+                          b1->l3_ofs, b1->inner_l3_ofs,
+                          b1->l4_ofs, b1->inner_l4_ofs);
             ds_put_format(err_str, "Buffer 2 offsets: l2_pad_size %u,"
-                          " l2_5_ofs : %u l3_ofs %u, l4_ofs %u\n",
+                          " l2_5_ofs : %u l3_ofs %u, inner_l3_ofs %u,"
+                          " l4_ofs %u, inner_l4_ofs %u\n",
                           b2->l2_pad_size, b2->l2_5_ofs,
-                          b2->l3_ofs, b2->l4_ofs);
+                          b2->l3_ofs, b2->inner_l3_ofs,
+                          b2->l4_ofs, b2->inner_l4_ofs);
         }
         return false;
     }
diff --git a/lib/odp-execute-avx512.c b/lib/odp-execute-avx512.c
index 747e04014..7f9870669 100644
--- a/lib/odp-execute-avx512.c
+++ b/lib/odp-execute-avx512.c
@@ -35,10 +35,11 @@ 
 
 VLOG_DEFINE_THIS_MODULE(odp_execute_avx512);
 
-/* The below three build asserts make sure that l2_5_ofs, l3_ofs, and l4_ofs
- * fields remain in the same order and offset to l2_padd_size. This is needed
- * as the avx512_dp_packet_resize_l2() function will manipulate those fields at
- * a fixed memory index based on the l2_padd_size offset. */
+/* The below three build asserts make sure that l2_5_ofs, l3_ofs, l4_ofs,
+ * inner_l3_ofs, and inner_l4_ofs fields remain in the same order and offset to
+ * l2_padd_size. This is needed as the avx512_dp_packet_resize_l2() function
+ * will manipulate those fields at a fixed memory index based on the
+ * l2_padd_size offset. */
 BUILD_ASSERT_DECL(offsetof(struct dp_packet, l2_pad_size) +
                   MEMBER_SIZEOF(struct dp_packet, l2_pad_size) ==
                   offsetof(struct dp_packet, l2_5_ofs));
@@ -51,6 +52,14 @@  BUILD_ASSERT_DECL(offsetof(struct dp_packet, l3_ofs) +
                            MEMBER_SIZEOF(struct dp_packet, l3_ofs) ==
                            offsetof(struct dp_packet, l4_ofs));
 
+BUILD_ASSERT_DECL(offsetof(struct dp_packet, l4_ofs) +
+                           MEMBER_SIZEOF(struct dp_packet, l4_ofs) ==
+                           offsetof(struct dp_packet, inner_l3_ofs));
+
+BUILD_ASSERT_DECL(offsetof(struct dp_packet, inner_l3_ofs) +
+                           MEMBER_SIZEOF(struct dp_packet, inner_l3_ofs) ==
+                           offsetof(struct dp_packet, inner_l4_ofs));
+
 /* The below build assert makes sure it's safe to read/write 128-bits starting
  * at the l2_pad_size location. */
 BUILD_ASSERT_DECL(sizeof(struct dp_packet) -
@@ -125,7 +134,7 @@  avx512_dp_packet_resize_l2(struct dp_packet *b, int resize_by_bytes)
     /* Each lane represents 16 bits in a 12-bit register. In this case the
      * first three 16-bit values, which will map to the l2_5_ofs, l3_ofs and
      * l4_ofs fields. */
-    const uint8_t k_lanes = 0b1110;
+    const uint8_t k_lanes = 0b111110;
 
     /* Set all 16-bit words in the 128-bits v_offset register to the value we
      * need to add/substract from the l2_5_ofs, l3_ofs, and l4_ofs fields. */