DPDK patches and discussions
 help / color / mirror / Atom feed
* [RFC 0/2] ethdev: update GENEVE option item structure
@ 2024-04-17  7:23 Michael Baum
  2024-04-17  7:23 ` [RFC 1/2] ethdev: fix GENEVE option item conversion Michael Baum
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Michael Baum @ 2024-04-17  7:23 UTC (permalink / raw)
  To: dev; +Cc: Dariusz Sosnowski, Thomas Monjalon, Ferruh Yigit, Ori Kam

The "rte_flow_item_geneve_opt" structure describes the GENEVE TLV option
header according to RFC 8926 [1]:

struct rte_flow_item_geneve_opt {
	rte_be16_t option_class;
	uint8_t option_type;
	uint8_t option_len;
	uint32_t *data;
};

The "option_len" field is used for two different purposes:
 1. item field for matching with value/mask.
 2. descriptor for data array size.

Those two different purposes might limit each other. For example, when
matching on length with full mask (0x1f), the data array in the mask
structure might be taken as size 31 and read invalid memory.

This problem appears in conversion API. In current implementation, the
"rte_flow_conv" API copies the "rte_flow_item_geneve_opt" structure
without taking care about data deep-copy. The attempt to solve this
revealed the problem in determining the size of the mask data array. To
resolve this issue, two solutions are suggested.

Immediate Workaround:
The data array size in the "mask" structure is determined by
"option_len" field in the "spec" structure. This workaround can be
integrated soon to avoid deep-copy missing.

Long Run Solution:
Add a new field into "rte_flow_item_geneve_opt" structure regardless to
"option_len" field. This solution should wait to "24.11" version since
it contains API change.
When the API is changed, I'll take the opportunity to add documentation
for this item in "rte_flow.rst" file and update the data type to
"rte_be32_t".

[1] https://datatracker.ietf.org/doc/html/rfc8926

Michael Baum (2):
  ethdev: fix GENEVE option item conversion
  ethdev: add data size field to GENEVE option item

 app/test-pmd/cmdline_flow.c                 | 10 +++++++
 doc/guides/prog_guide/rte_flow.rst          | 16 ++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  3 ++-
 lib/ethdev/rte_flow.c                       | 29 +++++++++++++++++----
 lib/ethdev/rte_flow.h                       |  3 ++-
 5 files changed, 54 insertions(+), 7 deletions(-)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [RFC 1/2] ethdev: fix GENEVE option item conversion
  2024-04-17  7:23 [RFC 0/2] ethdev: update GENEVE option item structure Michael Baum
@ 2024-04-17  7:23 ` Michael Baum
  2024-04-17  7:23 ` [RFC 2/2] ethdev: add data size field to GENEVE option item Michael Baum
  2024-06-11 17:07 ` [RFC 0/2] ethdev: update GENEVE option item structure Ferruh Yigit
  2 siblings, 0 replies; 4+ messages in thread
From: Michael Baum @ 2024-04-17  7:23 UTC (permalink / raw)
  To: dev; +Cc: Dariusz Sosnowski, Thomas Monjalon, Ferruh Yigit, Ori Kam, shirik

The "rte_flow_conv()" function, enables, among other things, to copy
item list.

For GENEVE option item, the function copies it without considering deep
copy. It copies the "data" pointer without copying the pointed values.

This patch adds deep copy for after regular copy.

Fixes: 2b4c72b4d10d ("ethdev: introduce GENEVE header TLV option item")
Cc: shirik@nvidia.com

Signed-off-by: Michael Baum <michaelba@nvidia.com>
---
 lib/ethdev/rte_flow.c | 29 +++++++++++++++++++++++++----
 1 file changed, 25 insertions(+), 4 deletions(-)

diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c
index 7ab1100ea0..2803507462 100644
--- a/lib/ethdev/rte_flow.c
+++ b/lib/ethdev/rte_flow.c
@@ -622,6 +622,7 @@ rte_flow_conv_item_spec(void *buf, const size_t size,
 	switch (item->type) {
 		union {
 			const struct rte_flow_item_raw *raw;
+			const struct rte_flow_item_geneve_opt *geneve_opt;
 		} spec;
 		union {
 			const struct rte_flow_item_raw *raw;
@@ -631,10 +632,13 @@ rte_flow_conv_item_spec(void *buf, const size_t size,
 		} mask;
 		union {
 			const struct rte_flow_item_raw *raw;
+			const struct rte_flow_item_geneve_opt *geneve_opt;
 		} src;
 		union {
 			struct rte_flow_item_raw *raw;
+			struct rte_flow_item_geneve_opt *geneve_opt;
 		} dst;
+		void *deep_src;
 		size_t tmp;
 
 	case RTE_FLOW_ITEM_TYPE_RAW:
@@ -663,13 +667,30 @@ rte_flow_conv_item_spec(void *buf, const size_t size,
 			tmp = last.raw->length & mask.raw->length;
 		if (tmp) {
 			off = RTE_ALIGN_CEIL(off, sizeof(*dst.raw->pattern));
-			if (size >= off + tmp)
-				dst.raw->pattern = rte_memcpy
-					((void *)((uintptr_t)dst.raw + off),
-					 src.raw->pattern, tmp);
+			if (size >= off + tmp) {
+				deep_src = (void *)((uintptr_t)dst.raw + off);
+				dst.raw->pattern = rte_memcpy(deep_src,
+							      src.raw->pattern,
+							      tmp);
+			}
 			off += tmp;
 		}
 		break;
+	case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
+		off = rte_flow_conv_copy(buf, data, size,
+					 rte_flow_desc_item, item->type);
+		spec.geneve_opt = item->spec;
+		src.geneve_opt = data;
+		dst.geneve_opt = buf;
+		tmp = spec.geneve_opt->option_len << 2;
+		if (size > 0 && src.geneve_opt->data) {
+			deep_src = (void *)((uintptr_t)(dst.geneve_opt + 1));
+			dst.geneve_opt->data = rte_memcpy(deep_src,
+							  src.geneve_opt->data,
+							  tmp);
+		}
+		off += tmp;
+		break;
 	default:
 		off = rte_flow_conv_copy(buf, data, size,
 					 rte_flow_desc_item, item->type);
-- 
2.25.1


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [RFC 2/2] ethdev: add data size field to GENEVE option item
  2024-04-17  7:23 [RFC 0/2] ethdev: update GENEVE option item structure Michael Baum
  2024-04-17  7:23 ` [RFC 1/2] ethdev: fix GENEVE option item conversion Michael Baum
@ 2024-04-17  7:23 ` Michael Baum
  2024-06-11 17:07 ` [RFC 0/2] ethdev: update GENEVE option item structure Ferruh Yigit
  2 siblings, 0 replies; 4+ messages in thread
From: Michael Baum @ 2024-04-17  7:23 UTC (permalink / raw)
  To: dev; +Cc: Dariusz Sosnowski, Thomas Monjalon, Ferruh Yigit, Ori Kam

The "rte_flow_item_geneve_opt" structure has field for option length.
This field has 2 different usages which might limit each other:

 1. field to matching with value/mask.
 2. descriptor for data array size.

This patch adds a new field "data_array_size" into
"rte_flow_item_geneve_opt" structure in addition to existing
"option_len" field.

Signed-off-by: Michael Baum <michaelba@nvidia.com>
---
 app/test-pmd/cmdline_flow.c                 | 10 ++++++
 doc/guides/prog_guide/rte_flow.rst          | 16 +++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  3 +-
 lib/ethdev/rte_flow.c                       | 36 ++++++++++-----------
 lib/ethdev/rte_flow.h                       |  3 +-
 5 files changed, 47 insertions(+), 21 deletions(-)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 60ee9337cf..966a47936a 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -492,6 +492,7 @@ enum index {
 	ITEM_GENEVE_OPT_TYPE,
 	ITEM_GENEVE_OPT_LENGTH,
 	ITEM_GENEVE_OPT_DATA,
+	ITEM_GENEVE_OPT_DATA_ARRAY_SIZE,
 	ITEM_INTEGRITY,
 	ITEM_INTEGRITY_LEVEL,
 	ITEM_INTEGRITY_VALUE,
@@ -2032,6 +2033,7 @@ static const enum index item_geneve_opt[] = {
 	ITEM_GENEVE_OPT_TYPE,
 	ITEM_GENEVE_OPT_LENGTH,
 	ITEM_GENEVE_OPT_DATA,
+	ITEM_GENEVE_OPT_DATA_ARRAY_SIZE,
 	ITEM_NEXT,
 	ZERO,
 };
@@ -5772,6 +5774,14 @@ static const struct token token_list[] = {
 				(sizeof(struct rte_flow_item_geneve_opt),
 				ITEM_GENEVE_OPT_DATA_SIZE)),
 	},
+	[ITEM_GENEVE_OPT_DATA_ARRAY_SIZE] = {
+		.name = "data_size",
+		.help = "GENEVE option data array size",
+		.next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt,
+					data_array_size)),
+	},
 	[ITEM_INTEGRITY] = {
 		.name = "integrity",
 		.help = "match packet integrity",
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index dad588763f..cce02fe1d6 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -1092,6 +1092,22 @@ Matches a GENEVE header.
 - ``rsvd1``: reserved, normally 0x00.
 - Default ``mask`` matches VNI only.
 
+
+Item: ``GENEVE_OPT``
+^^^^^^^^^^^^^^^^^^^^
+
+Matches a GENEVE TLV option header.
+
+- ``option_class``: option class ID.
+- ``option_type``: option type.
+- ``option_len``: option data length in 4-bytes granularity.
+- ``data``: option data array.
+- ``data_array_size``: option data array size.
+  This field is not matchable, it is descriptor how to read the array.
+  It should be specified in ``mask`` as well.
+- Default ``mask`` matches type only.
+
+
 Item: ``VXLAN-GPE``
 ^^^^^^^^^^^^^^^^^^^
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 2fbf9220d8..97623044e9 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -3743,7 +3743,8 @@ This section lists supported pattern items and their attributes, if any.
   - ``type {unsigned}``: GENEVE option type.
   - ``length {unsigned}``: GENEVE option length in 32-bit words.
   - ``data {hex string}``: GENEVE option data, the length is defined by
-    ``length`` field.
+    ``data_size`` field.
+  - ``data_size {unsigned}``: GENEVE option data size in 32-bit words.
 
 - ``vxlan-gpe``: match VXLAN-GPE header.
 
diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c
index 2803507462..d68359961d 100644
--- a/lib/ethdev/rte_flow.c
+++ b/lib/ethdev/rte_flow.c
@@ -81,6 +81,21 @@ rte_flow_item_flex_conv(void *buf, const void *data)
 	return src->length;
 }
 
+static size_t
+rte_flow_item_geneve_opt_conv(void *buf, const void *data)
+{
+	const struct rte_flow_item_geneve_opt *src = data;
+	uint16_t byte_size = src->data_array_size << 2;
+
+	if (buf) {
+		struct rte_flow_item_geneve_opt *dst = buf;
+		void *deep_src = (void *)((uintptr_t)(dst + 1));
+
+		dst->data = rte_memcpy(deep_src, src->data, byte_size);
+	}
+	return byte_size;
+}
+
 /** Generate flow_item[] entry. */
 #define MK_FLOW_ITEM(t, s) \
 	[RTE_FLOW_ITEM_TYPE_ ## t] = { \
@@ -155,7 +170,8 @@ static const struct rte_flow_desc_data rte_flow_desc_item[] = {
 	MK_FLOW_ITEM(L2TPV3OIP, sizeof(struct rte_flow_item_l2tpv3oip)),
 	MK_FLOW_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
 	MK_FLOW_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)),
-	MK_FLOW_ITEM(GENEVE_OPT, sizeof(struct rte_flow_item_geneve_opt)),
+	MK_FLOW_ITEM_FN(GENEVE_OPT, sizeof(struct rte_flow_item_geneve_opt),
+			rte_flow_item_geneve_opt_conv),
 	MK_FLOW_ITEM(INTEGRITY, sizeof(struct rte_flow_item_integrity)),
 	MK_FLOW_ITEM(CONNTRACK, sizeof(uint32_t)),
 	MK_FLOW_ITEM(PORT_REPRESENTOR, sizeof(struct rte_flow_item_ethdev)),
@@ -622,7 +638,6 @@ rte_flow_conv_item_spec(void *buf, const size_t size,
 	switch (item->type) {
 		union {
 			const struct rte_flow_item_raw *raw;
-			const struct rte_flow_item_geneve_opt *geneve_opt;
 		} spec;
 		union {
 			const struct rte_flow_item_raw *raw;
@@ -632,11 +647,9 @@ rte_flow_conv_item_spec(void *buf, const size_t size,
 		} mask;
 		union {
 			const struct rte_flow_item_raw *raw;
-			const struct rte_flow_item_geneve_opt *geneve_opt;
 		} src;
 		union {
 			struct rte_flow_item_raw *raw;
-			struct rte_flow_item_geneve_opt *geneve_opt;
 		} dst;
 		void *deep_src;
 		size_t tmp;
@@ -676,21 +689,6 @@ rte_flow_conv_item_spec(void *buf, const size_t size,
 			off += tmp;
 		}
 		break;
-	case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
-		off = rte_flow_conv_copy(buf, data, size,
-					 rte_flow_desc_item, item->type);
-		spec.geneve_opt = item->spec;
-		src.geneve_opt = data;
-		dst.geneve_opt = buf;
-		tmp = spec.geneve_opt->option_len << 2;
-		if (size > 0 && src.geneve_opt->data) {
-			deep_src = (void *)((uintptr_t)(dst.geneve_opt + 1));
-			dst.geneve_opt->data = rte_memcpy(deep_src,
-							  src.geneve_opt->data,
-							  tmp);
-		}
-		off += tmp;
-		break;
 	default:
 		off = rte_flow_conv_copy(buf, data, size,
 					 rte_flow_desc_item, item->type);
diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
index 6e8ab1d4c7..0ccb7562bd 100644
--- a/lib/ethdev/rte_flow.h
+++ b/lib/ethdev/rte_flow.h
@@ -1876,7 +1876,8 @@ struct rte_flow_item_geneve_opt {
 	rte_be16_t option_class;
 	uint8_t option_type;
 	uint8_t option_len;
-	uint32_t *data;
+	rte_be32_t *data;
+	uint8_t data_array_size;
 };
 
 /** Default mask for RTE_FLOW_ITEM_TYPE_GENEVE_OPT. */
-- 
2.25.1


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC 0/2] ethdev: update GENEVE option item structure
  2024-04-17  7:23 [RFC 0/2] ethdev: update GENEVE option item structure Michael Baum
  2024-04-17  7:23 ` [RFC 1/2] ethdev: fix GENEVE option item conversion Michael Baum
  2024-04-17  7:23 ` [RFC 2/2] ethdev: add data size field to GENEVE option item Michael Baum
@ 2024-06-11 17:07 ` Ferruh Yigit
  2 siblings, 0 replies; 4+ messages in thread
From: Ferruh Yigit @ 2024-06-11 17:07 UTC (permalink / raw)
  To: Michael Baum, dev; +Cc: Dariusz Sosnowski, Thomas Monjalon, Ori Kam

On 4/17/2024 8:23 AM, Michael Baum wrote:
> The "rte_flow_item_geneve_opt" structure describes the GENEVE TLV option
> header according to RFC 8926 [1]:
> 
> struct rte_flow_item_geneve_opt {
> 	rte_be16_t option_class;
> 	uint8_t option_type;
> 	uint8_t option_len;
> 	uint32_t *data;
> };
> 
> The "option_len" field is used for two different purposes:
>  1. item field for matching with value/mask.
>  2. descriptor for data array size.
> 

For the long run solution, we may consider adding geneve option header
to net/rte_geneve.h and make "struct rte_flow_item_geneve_opt" + data size ?

> Those two different purposes might limit each other. For example, when
> matching on length with full mask (0x1f), the data array in the mask
> structure might be taken as size 31 and read invalid memory.
> 
> This problem appears in conversion API. In current implementation, the
> "rte_flow_conv" API copies the "rte_flow_item_geneve_opt" structure
> without taking care about data deep-copy. The attempt to solve this
> revealed the problem in determining the size of the mask data array. To
> resolve this issue, two solutions are suggested.
> 

Are we having this problem only with geneve options because data size is
not fixed / defined for the header?

> Immediate Workaround:
> The data array size in the "mask" structure is determined by
> "option_len" field in the "spec" structure. This workaround can be
> integrated soon to avoid deep-copy missing.
> 

This requires a geneve specific pointer in the item spec, which is not
really nice, although it is temporary solution. Perhaps we can skip
this, can you please check below comment.

> Long Run Solution:
> Add a new field into "rte_flow_item_geneve_opt" structure regardless to
> "option_len" field. This solution should wait to "24.11" version since
> it contains API change.
>

I was expecting the same, but CI seems passed ABI test case [1], it may
be because new field appended end of the struct.
Can you please double check, if ABI is not broken, we can go with this
solution directly?

[1]
https://mails.dpdk.org/archives/test-report/2024-April/643570.html

> When the API is changed, I'll take the opportunity to add documentation
> for this item in "rte_flow.rst" file and update the data type to
> "rte_be32_t".
> 

If we can go with updating struct in this release, adding protocol
option struct in net library can wait v24.11 release.
So "rte_be32_t" type change in this struct won't be a thing.

> [1] https://datatracker.ietf.org/doc/html/rfc8926
> 
> Michael Baum (2):
>   ethdev: fix GENEVE option item conversion
>   ethdev: add data size field to GENEVE option item
> 
> 

@Ori, Can you please help reviewing this patch?
At worst, it can be good to address the fix in this release.


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2024-06-11 17:07 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-04-17  7:23 [RFC 0/2] ethdev: update GENEVE option item structure Michael Baum
2024-04-17  7:23 ` [RFC 1/2] ethdev: fix GENEVE option item conversion Michael Baum
2024-04-17  7:23 ` [RFC 2/2] ethdev: add data size field to GENEVE option item Michael Baum
2024-06-11 17:07 ` [RFC 0/2] ethdev: update GENEVE option item structure Ferruh Yigit

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).