[v3,2/8] app/testpmd: add GENEVE option item support

Message ID 20210107083838.7355-3-shirik@nvidia.com (mailing list archive)
State Superseded, archived
Delegated to: Ferruh Yigit
Headers
Series ethdev: introduce GENEVE header TLV option item |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Shiri Kuzin Jan. 7, 2021, 8:38 a.m. UTC
  From: Viacheslav Ovsiienko <viacheslavo@nvidia.com>

The patch adds the GENEVE option rte flow item support to
command line interpreter. The flow command with GENEVE
option items looks like:

  flow create 0 ingress pattern eth / ipv4 / udp / geneve vni is 100 /
       geneve-opt class is 99 length is 1 type is 0 data is 0x669988 /
       end actions drop / end

The option length should be specified in 32-bit words, this
value specifies the length of the data pattern/mask arrays (should be
multiplied by sizeof(uint32_t) to be expressed in bytes. If match
on the length itself is not needed the mask should be set to zero, in
this case length is used to specify the pattern/mask array lengths only.

Signed-off-by: Viacheslav Ovsiienko <viacheslavo@nvidia.com>
---
 app/test-pmd/cmdline_flow.c                 | 102 ++++++++++++++++++--
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |   8 ++
 2 files changed, 104 insertions(+), 6 deletions(-)
  

Comments

Suanming Mou Jan. 8, 2021, 12:10 p.m. UTC | #1
Hi,

> -----Original Message-----
> From: dev <dev-bounces@dpdk.org> On Behalf Of Shiri Kuzin
> Sent: Thursday, January 7, 2021 4:39 PM
> To: dev@dpdk.org
> Cc: Slava Ovsiienko <viacheslavo@nvidia.com>; NBU-Contact-Adrien Mazarguil
> <adrien.mazarguil@6wind.com>; Ori Kam <orika@nvidia.com>;
> ferruh.yigit@intel.com; NBU-Contact-Thomas Monjalon
> <thomas@monjalon.net>; Raslan Darawsheh <rasland@nvidia.com>
> Subject: [dpdk-dev] [PATCH v3 2/8] app/testpmd: add GENEVE option item
> support
> 
> From: Viacheslav Ovsiienko <viacheslavo@nvidia.com>
> 
> The patch adds the GENEVE option rte flow item support to command line
> interpreter. The flow command with GENEVE option items looks like:
> 
>   flow create 0 ingress pattern eth / ipv4 / udp / geneve vni is 100 /
>        geneve-opt class is 99 length is 1 type is 0 data is 0x669988 /
>        end actions drop / end
> 
> The option length should be specified in 32-bit words, this value specifies the
> length of the data pattern/mask arrays (should be multiplied by sizeof(uint32_t)
> to be expressed in bytes. If match on the length itself is not needed the mask
> should be set to zero, in this case length is used to specify the pattern/mask
> array lengths only.
> 
> Signed-off-by: Viacheslav Ovsiienko <viacheslavo@nvidia.com>
> ---
>  app/test-pmd/cmdline_flow.c                 | 102 ++++++++++++++++++--
>  doc/guides/testpmd_app_ug/testpmd_funcs.rst |   8 ++
>  2 files changed, 104 insertions(+), 6 deletions(-)
>

snip

>  	/* Output buffer is not necessarily NUL-terminated. */ @@ -7486,6
> +7558,9 @@ flow_item_default_mask(const struct rte_flow_item *item)
>  	case RTE_FLOW_ITEM_TYPE_GENEVE:
>  		mask = &rte_flow_item_geneve_mask;
>  		break;
> +	case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
> +		mask = &rte_flow_item_geneve_opt_mask;
> +		break;
>  	case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
>  		mask = &rte_flow_item_pppoe_proto_id_mask;
>  		break;
> @@ -7598,6 +7673,8 @@ cmd_set_raw_parsed(const struct buffer *in)
>  	/* process hdr from upper layer to low layer (L3/L4 -> L2). */
>  	data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
>  	for (i = n - 1 ; i >= 0; --i) {
> +		const struct rte_flow_item_geneve_opt *opt;
> +
>  		item = in->args.vc.pattern + i;
>  		if (item->spec == NULL)
>  			item->spec = flow_item_default_mask(item); @@ -
> 7650,6 +7727,19 @@ cmd_set_raw_parsed(const struct buffer *in)
>  		case RTE_FLOW_ITEM_TYPE_GENEVE:
>  			size = sizeof(struct rte_geneve_hdr);
>  			break;
> +		case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
> +			opt = (const struct rte_flow_item_geneve_opt *)
> +								item->spec;
> +			size = sizeof(struct rte_flow_item_geneve_opt) -
> +			       sizeof(opt->data);

If I understand correctly, the potential here is to calculate the geneve option size, right?
Have we confirmed the struct is well aligned for all arch, and will not be aligned to other size?
Or is it better to use "offsetof" here?

> +			if (opt->option_len && opt->data) {
> +				*total_size += opt->option_len *
> +					       sizeof(uint32_t);
> +				rte_memcpy(data_tail - (*total_size),
> +					   opt->data,
> +					   opt->option_len * sizeof(uint32_t));
> +			}
> +			break;
>  		case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
>  			size = sizeof(rte_be32_t);
>  			proto = 0x73;
> diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> index 9be450066e..37278d31d6 100644
> --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> @@ -3680,6 +3680,14 @@ This section lists supported pattern items and their
> attributes, if any.
>    - ``vni {unsigned}``: virtual network identifier.
>    - ``protocol {unsigned}``: protocol type.
> 
> +- ``geneve-opt``: match GENEVE header option.
> +
> +  - ``class {unsigned}``: GENEVE option class.
> +  - ``type {unsigned}``: GENEVE option type.
> +  - ``length {unsigned}``: GENEVE option length in 32-bit words.
> +  - ``data {hex string}``: GENEVE option data, the legnt is defined by
> +    ``length`` field
> +
>  - ``vxlan-gpe``: match VXLAN-GPE header.
> 
>    - ``vni {unsigned}``: VXLAN-GPE identifier.
> --
> 2.21.0
  
Slava Ovsiienko Jan. 8, 2021, 12:21 p.m. UTC | #2
Hi,

> -----Original Message-----
> From: Suanming Mou <suanmingm@nvidia.com>
> Sent: Friday, January 8, 2021 14:11
> To: Shiri Kuzin <shirik@nvidia.com>; dev@dpdk.org
> Cc: Slava Ovsiienko <viacheslavo@nvidia.com>; NBU-Contact-Adrien Mazarguil
> <adrien.mazarguil@6wind.com>; Ori Kam <orika@nvidia.com>;
> ferruh.yigit@intel.com; NBU-Contact-Thomas Monjalon
> <thomas@monjalon.net>; Raslan Darawsheh <rasland@nvidia.com>
> Subject: RE: [dpdk-dev] [PATCH v3 2/8] app/testpmd: add GENEVE option item
> support
> 
> Hi,
> 
> > -----Original Message-----
> > From: dev <dev-bounces@dpdk.org> On Behalf Of Shiri Kuzin
> > Sent: Thursday, January 7, 2021 4:39 PM
> > To: dev@dpdk.org
> > Cc: Slava Ovsiienko <viacheslavo@nvidia.com>; NBU-Contact-Adrien
> > Mazarguil <adrien.mazarguil@6wind.com>; Ori Kam <orika@nvidia.com>;
> > ferruh.yigit@intel.com; NBU-Contact-Thomas Monjalon
> > <thomas@monjalon.net>; Raslan Darawsheh <rasland@nvidia.com>
> > Subject: [dpdk-dev] [PATCH v3 2/8] app/testpmd: add GENEVE option item
> > support
> >
> > From: Viacheslav Ovsiienko <viacheslavo@nvidia.com>
> >
> > The patch adds the GENEVE option rte flow item support to command line
> > interpreter. The flow command with GENEVE option items looks like:
> >
> >   flow create 0 ingress pattern eth / ipv4 / udp / geneve vni is 100 /
> >        geneve-opt class is 99 length is 1 type is 0 data is 0x669988 /
> >        end actions drop / end
> >
> > The option length should be specified in 32-bit words, this value
> > specifies the length of the data pattern/mask arrays (should be
> > multiplied by sizeof(uint32_t) to be expressed in bytes. If match on
> > the length itself is not needed the mask should be set to zero, in
> > this case length is used to specify the pattern/mask array lengths only.
> >
> > Signed-off-by: Viacheslav Ovsiienko <viacheslavo@nvidia.com>
> > ---
> >  app/test-pmd/cmdline_flow.c                 | 102 ++++++++++++++++++--
> >  doc/guides/testpmd_app_ug/testpmd_funcs.rst |   8 ++
> >  2 files changed, 104 insertions(+), 6 deletions(-)
> >
> 
> snip
> 
> >  	/* Output buffer is not necessarily NUL-terminated. */ @@ -7486,6
> > +7558,9 @@ flow_item_default_mask(const struct rte_flow_item *item)
> >  	case RTE_FLOW_ITEM_TYPE_GENEVE:
> >  		mask = &rte_flow_item_geneve_mask;
> >  		break;
> > +	case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
> > +		mask = &rte_flow_item_geneve_opt_mask;
> > +		break;
> >  	case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
> >  		mask = &rte_flow_item_pppoe_proto_id_mask;
> >  		break;
> > @@ -7598,6 +7673,8 @@ cmd_set_raw_parsed(const struct buffer *in)
> >  	/* process hdr from upper layer to low layer (L3/L4 -> L2). */
> >  	data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
> >  	for (i = n - 1 ; i >= 0; --i) {
> > +		const struct rte_flow_item_geneve_opt *opt;
> > +
> >  		item = in->args.vc.pattern + i;
> >  		if (item->spec == NULL)
> >  			item->spec = flow_item_default_mask(item); @@ -
> > 7650,6 +7727,19 @@ cmd_set_raw_parsed(const struct buffer *in)
> >  		case RTE_FLOW_ITEM_TYPE_GENEVE:
> >  			size = sizeof(struct rte_geneve_hdr);
> >  			break;
> > +		case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
> > +			opt = (const struct rte_flow_item_geneve_opt *)
> > +								item->spec;
> > +			size = sizeof(struct rte_flow_item_geneve_opt) -
> > +			       sizeof(opt->data);
> 
> If I understand correctly, the potential here is to calculate the geneve option
> size, right?
> Have we confirmed the struct is well aligned for all arch, and will not be aligned
> to other size?
> Or is it better to use "offsetof" here?

Yes, you are right, "offsetof" would be more relevant, thank you the catching,

With best regards,
Slava

> 
> > +			if (opt->option_len && opt->data) {
> > +				*total_size += opt->option_len *
> > +					       sizeof(uint32_t);
> > +				rte_memcpy(data_tail - (*total_size),
> > +					   opt->data,
> > +					   opt->option_len * sizeof(uint32_t));
> > +			}
> > +			break;
> >  		case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
> >  			size = sizeof(rte_be32_t);
> >  			proto = 0x73;
> > diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > index 9be450066e..37278d31d6 100644
> > --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > @@ -3680,6 +3680,14 @@ This section lists supported pattern items and
> > their attributes, if any.
> >    - ``vni {unsigned}``: virtual network identifier.
> >    - ``protocol {unsigned}``: protocol type.
> >
> > +- ``geneve-opt``: match GENEVE header option.
> > +
> > +  - ``class {unsigned}``: GENEVE option class.
> > +  - ``type {unsigned}``: GENEVE option type.
> > +  - ``length {unsigned}``: GENEVE option length in 32-bit words.
> > +  - ``data {hex string}``: GENEVE option data, the legnt is defined by
> > +    ``length`` field
> > +
> >  - ``vxlan-gpe``: match VXLAN-GPE header.
> >
> >    - ``vni {unsigned}``: VXLAN-GPE identifier.
> > --
> > 2.21.0
  

Patch

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 585cab98b4..8bb2cb1b2d 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -283,6 +283,11 @@  enum index {
 	ITEM_ECPRI_MSG_IQ_DATA_PCID,
 	ITEM_ECPRI_MSG_RTC_CTRL_RTCID,
 	ITEM_ECPRI_MSG_DLY_MSR_MSRID,
+	ITEM_GENEVE_OPT,
+	ITEM_GENEVE_OPT_CLASS,
+	ITEM_GENEVE_OPT_TYPE,
+	ITEM_GENEVE_OPT_LENGTH,
+	ITEM_GENEVE_OPT_DATA,
 
 	/* Validate/create actions. */
 	ACTIONS,
@@ -413,6 +418,9 @@  enum index {
 /** Maximum size for pattern in struct rte_flow_item_raw. */
 #define ITEM_RAW_PATTERN_SIZE 40
 
+/** Maximum size for GENEVE option data pattern in bytes. */
+#define ITEM_GENEVE_OPT_DATA_SIZE 124
+
 /** Storage size for struct rte_flow_item_raw including pattern. */
 #define ITEM_RAW_SIZE \
 	(sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
@@ -428,7 +436,7 @@  struct action_rss_data {
 };
 
 /** Maximum data size in struct rte_flow_action_raw_encap. */
-#define ACTION_RAW_ENCAP_MAX_DATA 128
+#define ACTION_RAW_ENCAP_MAX_DATA 512
 #define RAW_ENCAP_CONFS_MAX_NUM 8
 
 /** Storage for struct rte_flow_action_raw_encap. */
@@ -658,6 +666,16 @@  struct token {
 		.mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
 	})
 
+/** Static initializer for ARGS() to target a field with limits. */
+#define ARGS_ENTRY_BOUNDED(s, f, i, a) \
+	(&(const struct arg){ \
+		.bounded = 1, \
+		.min = (i), \
+		.max = (a), \
+		.offset = offsetof(s, f), \
+		.size = sizeof(((s *)0)->f), \
+	})
+
 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
 #define ARGS_ENTRY_MASK(s, f, m) \
 	(&(const struct arg){ \
@@ -903,6 +921,7 @@  static const enum index next_item[] = {
 	ITEM_AH,
 	ITEM_PFCP,
 	ITEM_ECPRI,
+	ITEM_GENEVE_OPT,
 	END_SET,
 	ZERO,
 };
@@ -1244,6 +1263,15 @@  static const enum index item_ecpri_common_type[] = {
 	ZERO,
 };
 
+static const enum index item_geneve_opt[] = {
+	ITEM_GENEVE_OPT_CLASS,
+	ITEM_GENEVE_OPT_TYPE,
+	ITEM_GENEVE_OPT_LENGTH,
+	ITEM_GENEVE_OPT_DATA,
+	ITEM_NEXT,
+	ZERO,
+};
+
 static const enum index next_action[] = {
 	ACTION_END,
 	ACTION_VOID,
@@ -3230,6 +3258,47 @@  static const struct token token_list[] = {
 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri,
 				hdr.type5.msr_id)),
 	},
+	[ITEM_GENEVE_OPT] = {
+		.name = "geneve-opt",
+		.help = "GENEVE header option",
+		.priv = PRIV_ITEM(GENEVE_OPT,
+				  sizeof(struct rte_flow_item_geneve_opt) +
+				  ITEM_GENEVE_OPT_DATA_SIZE),
+		.next = NEXT(item_geneve_opt),
+		.call = parse_vc,
+	},
+	[ITEM_GENEVE_OPT_CLASS]	= {
+		.name = "class",
+		.help = "GENEVE option class",
+		.next = NEXT(item_geneve_opt, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt,
+					     option_class)),
+	},
+	[ITEM_GENEVE_OPT_TYPE] = {
+		.name = "type",
+		.help = "GENEVE option type",
+		.next = NEXT(item_geneve_opt, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt,
+					option_type)),
+	},
+	[ITEM_GENEVE_OPT_LENGTH] = {
+		.name = "length",
+		.help = "GENEVE option data length (in 32b words)",
+		.next = NEXT(item_geneve_opt, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_BOUNDED(
+				struct rte_flow_item_geneve_opt, option_len,
+				0, 31)),
+	},
+	[ITEM_GENEVE_OPT_DATA] = {
+		.name = "data",
+		.help = "GENEVE option data pattern",
+		.next = NEXT(item_geneve_opt, NEXT_ENTRY(HEX), item_param),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data),
+			     ARGS_ENTRY_ARB(0, 0),
+			     ARGS_ENTRY_ARB
+				(sizeof(struct rte_flow_item_geneve_opt),
+				ITEM_GENEVE_OPT_DATA_SIZE)),
+	},
 	/* Validate/create actions. */
 	[ACTIONS] = {
 		.name = "actions",
@@ -6482,11 +6551,14 @@  parse_hex(struct context *ctx, const struct token *token,
 	ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
 	if (ret < 0)
 		goto error;
-	push_args(ctx, arg_len);
-	ret = parse_int(ctx, token, tmp, ret, NULL, 0);
-	if (ret < 0) {
-		pop_args(ctx);
-		goto error;
+	/* Save length if requested. */
+	if (arg_len->size) {
+		push_args(ctx, arg_len);
+		ret = parse_int(ctx, token, tmp, ret, NULL, 0);
+		if (ret < 0) {
+			pop_args(ctx);
+			goto error;
+		}
 	}
 	buf = (uint8_t *)ctx->object + arg_data->offset;
 	/* Output buffer is not necessarily NUL-terminated. */
@@ -7486,6 +7558,9 @@  flow_item_default_mask(const struct rte_flow_item *item)
 	case RTE_FLOW_ITEM_TYPE_GENEVE:
 		mask = &rte_flow_item_geneve_mask;
 		break;
+	case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
+		mask = &rte_flow_item_geneve_opt_mask;
+		break;
 	case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
 		mask = &rte_flow_item_pppoe_proto_id_mask;
 		break;
@@ -7598,6 +7673,8 @@  cmd_set_raw_parsed(const struct buffer *in)
 	/* process hdr from upper layer to low layer (L3/L4 -> L2). */
 	data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
 	for (i = n - 1 ; i >= 0; --i) {
+		const struct rte_flow_item_geneve_opt *opt;
+
 		item = in->args.vc.pattern + i;
 		if (item->spec == NULL)
 			item->spec = flow_item_default_mask(item);
@@ -7650,6 +7727,19 @@  cmd_set_raw_parsed(const struct buffer *in)
 		case RTE_FLOW_ITEM_TYPE_GENEVE:
 			size = sizeof(struct rte_geneve_hdr);
 			break;
+		case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
+			opt = (const struct rte_flow_item_geneve_opt *)
+								item->spec;
+			size = sizeof(struct rte_flow_item_geneve_opt) -
+			       sizeof(opt->data);
+			if (opt->option_len && opt->data) {
+				*total_size += opt->option_len *
+					       sizeof(uint32_t);
+				rte_memcpy(data_tail - (*total_size),
+					   opt->data,
+					   opt->option_len * sizeof(uint32_t));
+			}
+			break;
 		case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
 			size = sizeof(rte_be32_t);
 			proto = 0x73;
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 9be450066e..37278d31d6 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -3680,6 +3680,14 @@  This section lists supported pattern items and their attributes, if any.
   - ``vni {unsigned}``: virtual network identifier.
   - ``protocol {unsigned}``: protocol type.
 
+- ``geneve-opt``: match GENEVE header option.
+
+  - ``class {unsigned}``: GENEVE option class.
+  - ``type {unsigned}``: GENEVE option type.
+  - ``length {unsigned}``: GENEVE option length in 32-bit words.
+  - ``data {hex string}``: GENEVE option data, the legnt is defined by
+    ``length`` field
+
 - ``vxlan-gpe``: match VXLAN-GPE header.
 
   - ``vni {unsigned}``: VXLAN-GPE identifier.