net/mlx5: support the new VLAN matching fields
diff mbox series

Message ID 1603641819-290447-1-git-send-email-matan@nvidia.com
State Accepted, archived
Delegated to: Raslan Darawsheh
Headers show
Series
  • net/mlx5: support the new VLAN matching fields
Related show

Checks

Context Check Description
ci/iol-mellanox-Performance success Performance Testing PASS
ci/iol-intel-Performance success Performance Testing PASS
ci/iol-testing success Testing PASS
ci/Intel-compilation success Compilation OK
ci/iol-intel-Functional success Functional Testing PASS
ci/iol-broadcom-Performance success Performance Testing PASS
ci/iol-broadcom-Functional success Functional Testing PASS
ci/checkpatch success coding style OK

Commit Message

Matan Azrad Oct. 25, 2020, 4:03 p.m. UTC
The fields ``has_vlan`` and ``has_more_vlan`` were added in rte_flow by
patch [1].

Using these fields, the application can match all the VLAN options by
single flow: any, VLAN only and non-VLAN only.

Add the support for the fields.
By the way, add the support for QinQ packets matching.

VLAN\QinQ limitations are listed in the driver document.

[1] https://patches.dpdk.org/patch/80965/

Signed-off-by: Matan Azrad <matan@nvidia.com>
Acked-by: Dekel Peled <dekelp@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
---
 doc/guides/nics/mlx5.rst               |  24 +++--
 doc/guides/rel_notes/release_20_11.rst |   3 +
 drivers/net/mlx5/mlx5_flow.c           |   5 +-
 drivers/net/mlx5/mlx5_flow.h           |   2 +-
 drivers/net/mlx5/mlx5_flow_dv.c        | 176 +++++++++++++++++----------------
 drivers/net/mlx5/mlx5_flow_verbs.c     |   2 +-
 6 files changed, 117 insertions(+), 95 deletions(-)

Comments

Raslan Darawsheh Oct. 26, 2020, 11:19 p.m. UTC | #1
Hi,
> -----Original Message-----
> From: dev <dev-bounces@dpdk.org> On Behalf Of Matan Azrad
> Sent: Sunday, October 25, 2020 6:04 PM
> To: Slava Ovsiienko <viacheslavo@nvidia.com>
> Cc: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH] net/mlx5: support the new VLAN matching
> fields
> 
> The fields ``has_vlan`` and ``has_more_vlan`` were added in rte_flow by
> patch [1].
> 
> Using these fields, the application can match all the VLAN options by
> single flow: any, VLAN only and non-VLAN only.
> 
> Add the support for the fields.
> By the way, add the support for QinQ packets matching.
> 
> VLAN\QinQ limitations are listed in the driver document.
> 
> [1]
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatc
> hes.dpdk.org%2Fpatch%2F80965%2F&amp;data=04%7C01%7Crasland%40nvi
> dia.com%7C94645c5c01464724cccc08d878ff9f90%7C43083d15727340c1b7db39
> efd9ccc17a%7C0%7C0%7C637392386576427312%7CUnknown%7CTWFpbGZs
> b3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn
> 0%3D%7C1000&amp;sdata=V7AAqp8X8hOEdSq51wGtPSYVOucQi2gEcFExhua
> Sjls%3D&amp;reserved=0
> 
> Signed-off-by: Matan Azrad <matan@nvidia.com>
> Acked-by: Dekel Peled <dekelp@nvidia.com>
> Acked-by: Ori Kam <orika@nvidia.com>
> ---
>  doc/guides/nics/mlx5.rst               |  24 +++--
>  doc/guides/rel_notes/release_20_11.rst |   3 +
>  drivers/net/mlx5/mlx5_flow.c           |   5 +-
>  drivers/net/mlx5/mlx5_flow.h           |   2 +-
>  drivers/net/mlx5/mlx5_flow_dv.c        | 176 +++++++++++++++++-------------
> ---
>  drivers/net/mlx5/mlx5_flow_verbs.c     |   2 +-
>  6 files changed, 117 insertions(+), 95 deletions(-)
> 
> diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst
> index 66524f1..79cb436 100644
> --- a/doc/guides/nics/mlx5.rst
> +++ b/doc/guides/nics/mlx5.rst
> @@ -122,23 +122,29 @@ Limitations
> 
>    Will match any ipv4 packet (VLAN included).
> 
> -- When using DV flow engine (``dv_flow_en`` = 1), flow pattern without
> VLAN item
> -  will match untagged packets only.
> +- When using Verbs flow engine (``dv_flow_en`` = 0), multi-tagged(QinQ)
> match is not supported.
> +
> +- When using DV flow engine (``dv_flow_en`` = 1), flow pattern with any
> VLAN specification will match only single-tagged packets unless the ETH item
> ``type`` field is 0x88A8 or the VLAN item ``has_more_vlan`` field is 1.
>    The flow rule::
> 
>          flow create 0 ingress pattern eth / ipv4 / end ...
> 
> -  Will match untagged packets only.
> -  The flow rule::
> +  Will match any ipv4 packet.
> +  The flow rules::
> 
> -        flow create 0 ingress pattern eth / vlan / ipv4 / end ...
> +        flow create 0 ingress pattern eth / vlan / end ...
> +        flow create 0 ingress pattern eth has_vlan is 1 / end ...
> +        flow create 0 ingress pattern eth type is 0x8100 / end ...
> 
> -  Will match tagged packets only, with any VLAN ID value.
> -  The flow rule::
> +  Will match single-tagged packets only, with any VLAN ID value.
> +  The flow rules::
> 
> -        flow create 0 ingress pattern eth / vlan vid is 3 / ipv4 / end ...
> +        flow create 0 ingress pattern eth type is 0x88A8 / end ...
> +        flow create 0 ingress pattern eth / vlan has_more_vlan is 1 / end ...
> +
> +  Will match multi-tagged packets only, with any VLAN ID value.
> 
> -  Will only match tagged packets with VLAN ID 3.
> +- A flow pattern with 2 sequential VLAN items is not supported.
> 
>  - VLAN pop offload command:
> 
> diff --git a/doc/guides/rel_notes/release_20_11.rst
> b/doc/guides/rel_notes/release_20_11.rst
> index dd59fe8..56b3198 100644
> --- a/doc/guides/rel_notes/release_20_11.rst
> +++ b/doc/guides/rel_notes/release_20_11.rst
> @@ -353,6 +353,9 @@ New Features
>    * Updated the supported timeout for Age action to the maximal value
> supported
>      by rte_flow API.
>    * Added support of Age action query.
> +  * Added support for QinQ packets matching.
> +  * Added support for the new vlan fields ``has_vlan`` in the eth item and
> +    ``has_more_vlan`` in the vlan item.
> 
>  Removed Items
>  -------------
> diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
> index 949b9ce..9bc1465 100644
> --- a/drivers/net/mlx5/mlx5_flow.c
> +++ b/drivers/net/mlx5/mlx5_flow.c
> @@ -1794,6 +1794,8 @@ struct mlx5_flow_tunnel_info {
>   *   Item specification.
>   * @param[in] item_flags
>   *   Bit-fields that holds the items detected until now.
> + * @param[in] ext_vlan_sup
> + *   Whether extended VLAN features are supported or not.
>   * @param[out] error
>   *   Pointer to error structure.
>   *
> @@ -1914,7 +1916,7 @@ struct mlx5_flow_tunnel_info {
>   */
>  int
>  mlx5_flow_validate_item_eth(const struct rte_flow_item *item,
> -			    uint64_t item_flags,
> +			    uint64_t item_flags, bool ext_vlan_sup,
>  			    struct rte_flow_error *error)
>  {
>  	const struct rte_flow_item_eth *mask = item->mask;
> @@ -1922,6 +1924,7 @@ struct mlx5_flow_tunnel_info {
>  		.dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
>  		.src.addr_bytes = "\xff\xff\xff\xff\xff\xff",
>  		.type = RTE_BE16(0xffff),
> +		.has_vlan = ext_vlan_sup ? 1 : 0,
>  	};
>  	int ret;
>  	int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
> diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
> index 20beb96..8b5a93f 100644
> --- a/drivers/net/mlx5/mlx5_flow.h
> +++ b/drivers/net/mlx5/mlx5_flow.h
> @@ -1306,7 +1306,7 @@ int mlx5_flow_item_acceptable(const struct
> rte_flow_item *item,
>  			      bool range_accepted,
>  			      struct rte_flow_error *error);
>  int mlx5_flow_validate_item_eth(const struct rte_flow_item *item,
> -				uint64_t item_flags,
> +				uint64_t item_flags, bool ext_vlan_sup,
>  				struct rte_flow_error *error);
>  int mlx5_flow_validate_item_gre(const struct rte_flow_item *item,
>  				uint64_t item_flags,
> diff --git a/drivers/net/mlx5/mlx5_flow_dv.c
> b/drivers/net/mlx5/mlx5_flow_dv.c
> index 504d842..7bfab7d 100644
> --- a/drivers/net/mlx5/mlx5_flow_dv.c
> +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> @@ -1676,6 +1676,7 @@ struct field_modify_info modify_tcp[] = {
>  	const struct rte_flow_item_vlan nic_mask = {
>  		.tci = RTE_BE16(UINT16_MAX),
>  		.inner_type = RTE_BE16(UINT16_MAX),
> +		.has_more_vlan = 1,
>  	};
>  	const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
>  	int ret;
> @@ -5358,7 +5359,7 @@ struct field_modify_info modify_tcp[] = {
>  			break;
>  		case RTE_FLOW_ITEM_TYPE_ETH:
>  			ret = mlx5_flow_validate_item_eth(items,
> item_flags,
> -							  error);
> +							  true, error);
>  			if (ret < 0)
>  				return ret;
>  			last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L2 :
> @@ -6360,9 +6361,10 @@ struct field_modify_info modify_tcp[] = {
>  		.dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
>  		.src.addr_bytes = "\xff\xff\xff\xff\xff\xff",
>  		.type = RTE_BE16(0xffff),
> +		.has_vlan = 0,
>  	};
> -	void *headers_m;
> -	void *headers_v;
> +	void *hdrs_m;
> +	void *hdrs_v;
>  	char *l24_v;
>  	unsigned int i;
> 
> @@ -6371,38 +6373,26 @@ struct field_modify_info modify_tcp[] = {
>  	if (!eth_m)
>  		eth_m = &nic_mask;
>  	if (inner) {
> -		headers_m = MLX5_ADDR_OF(fte_match_param, matcher,
> +		hdrs_m = MLX5_ADDR_OF(fte_match_param, matcher,
>  					 inner_headers);
> -		headers_v = MLX5_ADDR_OF(fte_match_param, key,
> inner_headers);
> +		hdrs_v = MLX5_ADDR_OF(fte_match_param, key,
> inner_headers);
>  	} else {
> -		headers_m = MLX5_ADDR_OF(fte_match_param, matcher,
> +		hdrs_m = MLX5_ADDR_OF(fte_match_param, matcher,
>  					 outer_headers);
> -		headers_v = MLX5_ADDR_OF(fte_match_param, key,
> outer_headers);
> +		hdrs_v = MLX5_ADDR_OF(fte_match_param, key,
> outer_headers);
>  	}
> -	memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_m,
> dmac_47_16),
> +	memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_m,
> dmac_47_16),
>  	       &eth_m->dst, sizeof(eth_m->dst));
>  	/* The value must be in the range of the mask. */
> -	l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
> dmac_47_16);
> +	l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_v,
> dmac_47_16);
>  	for (i = 0; i < sizeof(eth_m->dst); ++i)
>  		l24_v[i] = eth_m->dst.addr_bytes[i] & eth_v-
> >dst.addr_bytes[i];
> -	memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_m,
> smac_47_16),
> +	memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_m,
> smac_47_16),
>  	       &eth_m->src, sizeof(eth_m->src));
> -	l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
> smac_47_16);
> +	l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_v,
> smac_47_16);
>  	/* The value must be in the range of the mask. */
>  	for (i = 0; i < sizeof(eth_m->dst); ++i)
>  		l24_v[i] = eth_m->src.addr_bytes[i] & eth_v-
> >src.addr_bytes[i];
> -	if (eth_v->type) {
> -		/* When ethertype is present set mask for tagged VLAN. */
> -		MLX5_SET(fte_match_set_lyr_2_4, headers_m, cvlan_tag,
> 1);
> -		/* Set value for tagged VLAN if ethertype is 802.1Q. */
> -		if (eth_v->type == RTE_BE16(RTE_ETHER_TYPE_VLAN) ||
> -		    eth_v->type == RTE_BE16(RTE_ETHER_TYPE_QINQ)) {
> -			MLX5_SET(fte_match_set_lyr_2_4, headers_v,
> cvlan_tag,
> -				 1);
> -			/* Return here to avoid setting match on ethertype.
> */
> -			return;
> -		}
> -	}
>  	/*
>  	 * HW supports match on one Ethertype, the Ethertype following the
> last
>  	 * VLAN tag of the packet (see PRM).
> @@ -6411,19 +6401,42 @@ struct field_modify_info modify_tcp[] = {
>  	 * ethertype, and use ip_version field instead.
>  	 * eCPRI over Ether layer will use type value 0xAEFE.
>  	 */
> -	if (eth_v->type == RTE_BE16(RTE_ETHER_TYPE_IPV4) &&
> -	    eth_m->type == 0xFFFF) {
> -		flow_dv_set_match_ip_version(group, headers_v,
> headers_m, 4);
> -	} else if (eth_v->type == RTE_BE16(RTE_ETHER_TYPE_IPV6) &&
> -		   eth_m->type == 0xFFFF) {
> -		flow_dv_set_match_ip_version(group, headers_v,
> headers_m, 6);
> -	} else {
> -		MLX5_SET(fte_match_set_lyr_2_4, headers_m, ethertype,
> -			 rte_be_to_cpu_16(eth_m->type));
> -		l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
> -				     ethertype);
> -		*(uint16_t *)(l24_v) = eth_m->type & eth_v->type;
> +	if (eth_m->type == 0xFFFF) {
> +		/* Set cvlan_tag mask for any single\multi\un-tagged case. */
> +		MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, cvlan_tag, 1);
> +		switch (eth_v->type) {
> +		case RTE_BE16(RTE_ETHER_TYPE_VLAN):
> +			MLX5_SET(fte_match_set_lyr_2_4, hdrs_v,
> cvlan_tag, 1);
> +			return;
> +		case RTE_BE16(RTE_ETHER_TYPE_QINQ):
> +			MLX5_SET(fte_match_set_lyr_2_4, hdrs_m,
> svlan_tag, 1);
> +			MLX5_SET(fte_match_set_lyr_2_4, hdrs_v,
> svlan_tag, 1);
> +			return;
> +		case RTE_BE16(RTE_ETHER_TYPE_IPV4):
> +			flow_dv_set_match_ip_version(group, hdrs_v,
> hdrs_m, 4);
> +			return;
> +		case RTE_BE16(RTE_ETHER_TYPE_IPV6):
> +			flow_dv_set_match_ip_version(group, hdrs_v,
> hdrs_m, 6);
> +			return;
> +		default:
> +			break;
> +		}
> +	}
> +	if (eth_m->has_vlan) {
> +		MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, cvlan_tag, 1);
> +		if (eth_v->has_vlan) {
> +			/*
> +			 * Here, when also has_more_vlan field in VLAN item
> is
> +			 * not set, only single-tagged packets will be
> matched.
> +			 */
> +			MLX5_SET(fte_match_set_lyr_2_4, hdrs_v,
> cvlan_tag, 1);
> +			return;
> +		}
>  	}
> +	MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, ethertype,
> +		 rte_be_to_cpu_16(eth_m->type));
> +	l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_v,
> ethertype);
> +	*(uint16_t *)(l24_v) = eth_m->type & eth_v->type;
>  }
> 
>  /**
> @@ -6448,19 +6461,19 @@ struct field_modify_info modify_tcp[] = {
>  {
>  	const struct rte_flow_item_vlan *vlan_m = item->mask;
>  	const struct rte_flow_item_vlan *vlan_v = item->spec;
> -	void *headers_m;
> -	void *headers_v;
> +	void *hdrs_m;
> +	void *hdrs_v;
>  	uint16_t tci_m;
>  	uint16_t tci_v;
> 
>  	if (inner) {
> -		headers_m = MLX5_ADDR_OF(fte_match_param, matcher,
> +		hdrs_m = MLX5_ADDR_OF(fte_match_param, matcher,
>  					 inner_headers);
> -		headers_v = MLX5_ADDR_OF(fte_match_param, key,
> inner_headers);
> +		hdrs_v = MLX5_ADDR_OF(fte_match_param, key,
> inner_headers);
>  	} else {
> -		headers_m = MLX5_ADDR_OF(fte_match_param, matcher,
> +		hdrs_m = MLX5_ADDR_OF(fte_match_param, matcher,
>  					 outer_headers);
> -		headers_v = MLX5_ADDR_OF(fte_match_param, key,
> outer_headers);
> +		hdrs_v = MLX5_ADDR_OF(fte_match_param, key,
> outer_headers);
>  		/*
>  		 * This is workaround, masks are not supported,
>  		 * and pre-validated.
> @@ -6473,37 +6486,54 @@ struct field_modify_info modify_tcp[] = {
>  	 * When VLAN item exists in flow, mark packet as tagged,
>  	 * even if TCI is not specified.
>  	 */
> -	MLX5_SET(fte_match_set_lyr_2_4, headers_m, cvlan_tag, 1);
> -	MLX5_SET(fte_match_set_lyr_2_4, headers_v, cvlan_tag, 1);
> +	if (!MLX5_GET(fte_match_set_lyr_2_4, hdrs_v, svlan_tag)) {
> +		MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, cvlan_tag, 1);
> +		MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 1);
> +	}
>  	if (!vlan_v)
>  		return;
>  	if (!vlan_m)
>  		vlan_m = &rte_flow_item_vlan_mask;
>  	tci_m = rte_be_to_cpu_16(vlan_m->tci);
>  	tci_v = rte_be_to_cpu_16(vlan_m->tci & vlan_v->tci);
> -	MLX5_SET(fte_match_set_lyr_2_4, headers_m, first_vid, tci_m);
> -	MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_vid, tci_v);
> -	MLX5_SET(fte_match_set_lyr_2_4, headers_m, first_cfi, tci_m >>
> 12);
> -	MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_cfi, tci_v >> 12);
> -	MLX5_SET(fte_match_set_lyr_2_4, headers_m, first_prio, tci_m >>
> 13);
> -	MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_prio, tci_v >>
> 13);
> +	MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, first_vid, tci_m);
> +	MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, first_vid, tci_v);
> +	MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, first_cfi, tci_m >> 12);
> +	MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, first_cfi, tci_v >> 12);
> +	MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, first_prio, tci_m >> 13);
> +	MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, first_prio, tci_v >> 13);
>  	/*
>  	 * HW is optimized for IPv4/IPv6. In such cases, avoid setting
>  	 * ethertype, and use ip_version field instead.
>  	 */
> -	if (vlan_v->inner_type == RTE_BE16(RTE_ETHER_TYPE_IPV4) &&
> -	    vlan_m->inner_type == 0xFFFF) {
> -		flow_dv_set_match_ip_version(group, headers_v,
> headers_m, 4);
> -	} else if (vlan_v->inner_type == RTE_BE16(RTE_ETHER_TYPE_IPV6)
> &&
> -		   vlan_m->inner_type == 0xFFFF) {
> -		flow_dv_set_match_ip_version(group, headers_v,
> headers_m, 6);
> -	} else {
> -		MLX5_SET(fte_match_set_lyr_2_4, headers_m, ethertype,
> -			 rte_be_to_cpu_16(vlan_m->inner_type));
> -		MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype,
> -			 rte_be_to_cpu_16(vlan_m->inner_type &
> -					  vlan_v->inner_type));
> +	if (vlan_m->inner_type == 0xFFFF) {
> +		switch (vlan_v->inner_type) {
> +		case RTE_BE16(RTE_ETHER_TYPE_VLAN):
> +			MLX5_SET(fte_match_set_lyr_2_4, hdrs_m,
> svlan_tag, 1);
> +			MLX5_SET(fte_match_set_lyr_2_4, hdrs_v,
> svlan_tag, 1);
> +			MLX5_SET(fte_match_set_lyr_2_4, hdrs_v,
> cvlan_tag, 0);
> +			return;
> +		case RTE_BE16(RTE_ETHER_TYPE_IPV4):
> +			flow_dv_set_match_ip_version(group, hdrs_v,
> hdrs_m, 4);
> +			return;
> +		case RTE_BE16(RTE_ETHER_TYPE_IPV6):
> +			flow_dv_set_match_ip_version(group, hdrs_v,
> hdrs_m, 6);
> +			return;
> +		default:
> +			break;
> +		}
>  	}
> +	if (vlan_m->has_more_vlan && vlan_v->has_more_vlan) {
> +		MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, svlan_tag, 1);
> +		MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, svlan_tag, 1);
> +		/* Only one vlan_tag bit can be set. */
> +		MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 0);
> +		return;
> +	}
> +	MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, ethertype,
> +		 rte_be_to_cpu_16(vlan_m->inner_type));
> +	MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, ethertype,
> +		 rte_be_to_cpu_16(vlan_m->inner_type & vlan_v-
> >inner_type));
>  }
> 
>  /**
> @@ -6515,8 +6545,6 @@ struct field_modify_info modify_tcp[] = {
>   *   Flow matcher value.
>   * @param[in] item
>   *   Flow pattern to translate.
> - * @param[in] item_flags
> - *   Bit-fields that holds the items detected until now.
>   * @param[in] inner
>   *   Item is inner pattern.
>   * @param[in] group
> @@ -6525,7 +6553,6 @@ struct field_modify_info modify_tcp[] = {
>  static void
>  flow_dv_translate_item_ipv4(void *matcher, void *key,
>  			    const struct rte_flow_item *item,
> -			    const uint64_t item_flags,
>  			    int inner, uint32_t group)
>  {
>  	const struct rte_flow_item_ipv4 *ipv4_m = item->mask;
> @@ -6555,13 +6582,6 @@ struct field_modify_info modify_tcp[] = {
>  		headers_v = MLX5_ADDR_OF(fte_match_param, key,
> outer_headers);
>  	}
>  	flow_dv_set_match_ip_version(group, headers_v, headers_m, 4);
> -	/*
> -	 * On outer header (which must contains L2), or inner header with L2,
> -	 * set cvlan_tag mask bit to mark this packet as untagged.
> -	 * This should be done even if item->spec is empty.
> -	 */
> -	if (!inner || item_flags & MLX5_FLOW_LAYER_INNER_L2)
> -		MLX5_SET(fte_match_set_lyr_2_4, headers_m, cvlan_tag,
> 1);
>  	if (!ipv4_v)
>  		return;
>  	if (!ipv4_m)
> @@ -6608,8 +6628,6 @@ struct field_modify_info modify_tcp[] = {
>   *   Flow matcher value.
>   * @param[in] item
>   *   Flow pattern to translate.
> - * @param[in] item_flags
> - *   Bit-fields that holds the items detected until now.
>   * @param[in] inner
>   *   Item is inner pattern.
>   * @param[in] group
> @@ -6618,7 +6636,6 @@ struct field_modify_info modify_tcp[] = {
>  static void
>  flow_dv_translate_item_ipv6(void *matcher, void *key,
>  			    const struct rte_flow_item *item,
> -			    const uint64_t item_flags,
>  			    int inner, uint32_t group)
>  {
>  	const struct rte_flow_item_ipv6 *ipv6_m = item->mask;
> @@ -6657,13 +6674,6 @@ struct field_modify_info modify_tcp[] = {
>  		headers_v = MLX5_ADDR_OF(fte_match_param, key,
> outer_headers);
>  	}
>  	flow_dv_set_match_ip_version(group, headers_v, headers_m, 6);
> -	/*
> -	 * On outer header (which must contains L2), or inner header with L2,
> -	 * set cvlan_tag mask bit to mark this packet as untagged.
> -	 * This should be done even if item->spec is empty.
> -	 */
> -	if (!inner || item_flags & MLX5_FLOW_LAYER_INNER_L2)
> -		MLX5_SET(fte_match_set_lyr_2_4, headers_m, cvlan_tag,
> 1);
>  	if (!ipv6_v)
>  		return;
>  	if (!ipv6_m)
> @@ -9915,7 +9925,7 @@ struct field_modify_info modify_tcp[] = {
>  			mlx5_flow_tunnel_ip_check(items, next_protocol,
>  						  &item_flags, &tunnel);
>  			flow_dv_translate_item_ipv4(match_mask,
> match_value,
> -						    items, item_flags, tunnel,
> +						    items, tunnel,
>  						    dev_flow->dv.group);
>  			matcher.priority = MLX5_PRIORITY_MAP_L3;
>  			last_item = tunnel ?
> MLX5_FLOW_LAYER_INNER_L3_IPV4 :
> @@ -9938,7 +9948,7 @@ struct field_modify_info modify_tcp[] = {
>  			mlx5_flow_tunnel_ip_check(items, next_protocol,
>  						  &item_flags, &tunnel);
>  			flow_dv_translate_item_ipv6(match_mask,
> match_value,
> -						    items, item_flags, tunnel,
> +						    items, tunnel,
>  						    dev_flow->dv.group);
>  			matcher.priority = MLX5_PRIORITY_MAP_L3;
>  			last_item = tunnel ?
> MLX5_FLOW_LAYER_INNER_L3_IPV6 :
> diff --git a/drivers/net/mlx5/mlx5_flow_verbs.c
> b/drivers/net/mlx5/mlx5_flow_verbs.c
> index 9cc4410..f0e1bca 100644
> --- a/drivers/net/mlx5/mlx5_flow_verbs.c
> +++ b/drivers/net/mlx5/mlx5_flow_verbs.c
> @@ -1263,7 +1263,7 @@
>  			break;
>  		case RTE_FLOW_ITEM_TYPE_ETH:
>  			ret = mlx5_flow_validate_item_eth(items,
> item_flags,
> -							  error);
> +							  false, error);
>  			if (ret < 0)
>  				return ret;
>  			last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L2 :
> --
> 1.8.3.1

Patch applied to next-net-mlx,

Kindest regards,
Raslan Darawsheh

Patch
diff mbox series

diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst
index 66524f1..79cb436 100644
--- a/doc/guides/nics/mlx5.rst
+++ b/doc/guides/nics/mlx5.rst
@@ -122,23 +122,29 @@  Limitations
 
   Will match any ipv4 packet (VLAN included).
 
-- When using DV flow engine (``dv_flow_en`` = 1), flow pattern without VLAN item
-  will match untagged packets only.
+- When using Verbs flow engine (``dv_flow_en`` = 0), multi-tagged(QinQ) match is not supported.
+
+- When using DV flow engine (``dv_flow_en`` = 1), flow pattern with any VLAN specification will match only single-tagged packets unless the ETH item ``type`` field is 0x88A8 or the VLAN item ``has_more_vlan`` field is 1.
   The flow rule::
 
         flow create 0 ingress pattern eth / ipv4 / end ...
 
-  Will match untagged packets only.
-  The flow rule::
+  Will match any ipv4 packet.
+  The flow rules::
 
-        flow create 0 ingress pattern eth / vlan / ipv4 / end ...
+        flow create 0 ingress pattern eth / vlan / end ...
+        flow create 0 ingress pattern eth has_vlan is 1 / end ...
+        flow create 0 ingress pattern eth type is 0x8100 / end ...
 
-  Will match tagged packets only, with any VLAN ID value.
-  The flow rule::
+  Will match single-tagged packets only, with any VLAN ID value.
+  The flow rules::
 
-        flow create 0 ingress pattern eth / vlan vid is 3 / ipv4 / end ...
+        flow create 0 ingress pattern eth type is 0x88A8 / end ...
+        flow create 0 ingress pattern eth / vlan has_more_vlan is 1 / end ...
+
+  Will match multi-tagged packets only, with any VLAN ID value.
 
-  Will only match tagged packets with VLAN ID 3.
+- A flow pattern with 2 sequential VLAN items is not supported.
 
 - VLAN pop offload command:
 
diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst
index dd59fe8..56b3198 100644
--- a/doc/guides/rel_notes/release_20_11.rst
+++ b/doc/guides/rel_notes/release_20_11.rst
@@ -353,6 +353,9 @@  New Features
   * Updated the supported timeout for Age action to the maximal value supported
     by rte_flow API.
   * Added support of Age action query.
+  * Added support for QinQ packets matching.
+  * Added support for the new vlan fields ``has_vlan`` in the eth item and
+    ``has_more_vlan`` in the vlan item.
 
 Removed Items
 -------------
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 949b9ce..9bc1465 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -1794,6 +1794,8 @@  struct mlx5_flow_tunnel_info {
  *   Item specification.
  * @param[in] item_flags
  *   Bit-fields that holds the items detected until now.
+ * @param[in] ext_vlan_sup
+ *   Whether extended VLAN features are supported or not.
  * @param[out] error
  *   Pointer to error structure.
  *
@@ -1914,7 +1916,7 @@  struct mlx5_flow_tunnel_info {
  */
 int
 mlx5_flow_validate_item_eth(const struct rte_flow_item *item,
-			    uint64_t item_flags,
+			    uint64_t item_flags, bool ext_vlan_sup,
 			    struct rte_flow_error *error)
 {
 	const struct rte_flow_item_eth *mask = item->mask;
@@ -1922,6 +1924,7 @@  struct mlx5_flow_tunnel_info {
 		.dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
 		.src.addr_bytes = "\xff\xff\xff\xff\xff\xff",
 		.type = RTE_BE16(0xffff),
+		.has_vlan = ext_vlan_sup ? 1 : 0,
 	};
 	int ret;
 	int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 20beb96..8b5a93f 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -1306,7 +1306,7 @@  int mlx5_flow_item_acceptable(const struct rte_flow_item *item,
 			      bool range_accepted,
 			      struct rte_flow_error *error);
 int mlx5_flow_validate_item_eth(const struct rte_flow_item *item,
-				uint64_t item_flags,
+				uint64_t item_flags, bool ext_vlan_sup,
 				struct rte_flow_error *error);
 int mlx5_flow_validate_item_gre(const struct rte_flow_item *item,
 				uint64_t item_flags,
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 504d842..7bfab7d 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -1676,6 +1676,7 @@  struct field_modify_info modify_tcp[] = {
 	const struct rte_flow_item_vlan nic_mask = {
 		.tci = RTE_BE16(UINT16_MAX),
 		.inner_type = RTE_BE16(UINT16_MAX),
+		.has_more_vlan = 1,
 	};
 	const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
 	int ret;
@@ -5358,7 +5359,7 @@  struct field_modify_info modify_tcp[] = {
 			break;
 		case RTE_FLOW_ITEM_TYPE_ETH:
 			ret = mlx5_flow_validate_item_eth(items, item_flags,
-							  error);
+							  true, error);
 			if (ret < 0)
 				return ret;
 			last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L2 :
@@ -6360,9 +6361,10 @@  struct field_modify_info modify_tcp[] = {
 		.dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
 		.src.addr_bytes = "\xff\xff\xff\xff\xff\xff",
 		.type = RTE_BE16(0xffff),
+		.has_vlan = 0,
 	};
-	void *headers_m;
-	void *headers_v;
+	void *hdrs_m;
+	void *hdrs_v;
 	char *l24_v;
 	unsigned int i;
 
@@ -6371,38 +6373,26 @@  struct field_modify_info modify_tcp[] = {
 	if (!eth_m)
 		eth_m = &nic_mask;
 	if (inner) {
-		headers_m = MLX5_ADDR_OF(fte_match_param, matcher,
+		hdrs_m = MLX5_ADDR_OF(fte_match_param, matcher,
 					 inner_headers);
-		headers_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers);
+		hdrs_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers);
 	} else {
-		headers_m = MLX5_ADDR_OF(fte_match_param, matcher,
+		hdrs_m = MLX5_ADDR_OF(fte_match_param, matcher,
 					 outer_headers);
-		headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
+		hdrs_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
 	}
-	memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_m, dmac_47_16),
+	memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_m, dmac_47_16),
 	       &eth_m->dst, sizeof(eth_m->dst));
 	/* The value must be in the range of the mask. */
-	l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, dmac_47_16);
+	l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_v, dmac_47_16);
 	for (i = 0; i < sizeof(eth_m->dst); ++i)
 		l24_v[i] = eth_m->dst.addr_bytes[i] & eth_v->dst.addr_bytes[i];
-	memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_m, smac_47_16),
+	memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_m, smac_47_16),
 	       &eth_m->src, sizeof(eth_m->src));
-	l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, smac_47_16);
+	l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_v, smac_47_16);
 	/* The value must be in the range of the mask. */
 	for (i = 0; i < sizeof(eth_m->dst); ++i)
 		l24_v[i] = eth_m->src.addr_bytes[i] & eth_v->src.addr_bytes[i];
-	if (eth_v->type) {
-		/* When ethertype is present set mask for tagged VLAN. */
-		MLX5_SET(fte_match_set_lyr_2_4, headers_m, cvlan_tag, 1);
-		/* Set value for tagged VLAN if ethertype is 802.1Q. */
-		if (eth_v->type == RTE_BE16(RTE_ETHER_TYPE_VLAN) ||
-		    eth_v->type == RTE_BE16(RTE_ETHER_TYPE_QINQ)) {
-			MLX5_SET(fte_match_set_lyr_2_4, headers_v, cvlan_tag,
-				 1);
-			/* Return here to avoid setting match on ethertype. */
-			return;
-		}
-	}
 	/*
 	 * HW supports match on one Ethertype, the Ethertype following the last
 	 * VLAN tag of the packet (see PRM).
@@ -6411,19 +6401,42 @@  struct field_modify_info modify_tcp[] = {
 	 * ethertype, and use ip_version field instead.
 	 * eCPRI over Ether layer will use type value 0xAEFE.
 	 */
-	if (eth_v->type == RTE_BE16(RTE_ETHER_TYPE_IPV4) &&
-	    eth_m->type == 0xFFFF) {
-		flow_dv_set_match_ip_version(group, headers_v, headers_m, 4);
-	} else if (eth_v->type == RTE_BE16(RTE_ETHER_TYPE_IPV6) &&
-		   eth_m->type == 0xFFFF) {
-		flow_dv_set_match_ip_version(group, headers_v, headers_m, 6);
-	} else {
-		MLX5_SET(fte_match_set_lyr_2_4, headers_m, ethertype,
-			 rte_be_to_cpu_16(eth_m->type));
-		l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
-				     ethertype);
-		*(uint16_t *)(l24_v) = eth_m->type & eth_v->type;
+	if (eth_m->type == 0xFFFF) {
+		/* Set cvlan_tag mask for any single\multi\un-tagged case. */
+		MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, cvlan_tag, 1);
+		switch (eth_v->type) {
+		case RTE_BE16(RTE_ETHER_TYPE_VLAN):
+			MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 1);
+			return;
+		case RTE_BE16(RTE_ETHER_TYPE_QINQ):
+			MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, svlan_tag, 1);
+			MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, svlan_tag, 1);
+			return;
+		case RTE_BE16(RTE_ETHER_TYPE_IPV4):
+			flow_dv_set_match_ip_version(group, hdrs_v, hdrs_m, 4);
+			return;
+		case RTE_BE16(RTE_ETHER_TYPE_IPV6):
+			flow_dv_set_match_ip_version(group, hdrs_v, hdrs_m, 6);
+			return;
+		default:
+			break;
+		}
+	}
+	if (eth_m->has_vlan) {
+		MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, cvlan_tag, 1);
+		if (eth_v->has_vlan) {
+			/*
+			 * Here, when also has_more_vlan field in VLAN item is
+			 * not set, only single-tagged packets will be matched.
+			 */
+			MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 1);
+			return;
+		}
 	}
+	MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, ethertype,
+		 rte_be_to_cpu_16(eth_m->type));
+	l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_v, ethertype);
+	*(uint16_t *)(l24_v) = eth_m->type & eth_v->type;
 }
 
 /**
@@ -6448,19 +6461,19 @@  struct field_modify_info modify_tcp[] = {
 {
 	const struct rte_flow_item_vlan *vlan_m = item->mask;
 	const struct rte_flow_item_vlan *vlan_v = item->spec;
-	void *headers_m;
-	void *headers_v;
+	void *hdrs_m;
+	void *hdrs_v;
 	uint16_t tci_m;
 	uint16_t tci_v;
 
 	if (inner) {
-		headers_m = MLX5_ADDR_OF(fte_match_param, matcher,
+		hdrs_m = MLX5_ADDR_OF(fte_match_param, matcher,
 					 inner_headers);
-		headers_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers);
+		hdrs_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers);
 	} else {
-		headers_m = MLX5_ADDR_OF(fte_match_param, matcher,
+		hdrs_m = MLX5_ADDR_OF(fte_match_param, matcher,
 					 outer_headers);
-		headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
+		hdrs_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
 		/*
 		 * This is workaround, masks are not supported,
 		 * and pre-validated.
@@ -6473,37 +6486,54 @@  struct field_modify_info modify_tcp[] = {
 	 * When VLAN item exists in flow, mark packet as tagged,
 	 * even if TCI is not specified.
 	 */
-	MLX5_SET(fte_match_set_lyr_2_4, headers_m, cvlan_tag, 1);
-	MLX5_SET(fte_match_set_lyr_2_4, headers_v, cvlan_tag, 1);
+	if (!MLX5_GET(fte_match_set_lyr_2_4, hdrs_v, svlan_tag)) {
+		MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, cvlan_tag, 1);
+		MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 1);
+	}
 	if (!vlan_v)
 		return;
 	if (!vlan_m)
 		vlan_m = &rte_flow_item_vlan_mask;
 	tci_m = rte_be_to_cpu_16(vlan_m->tci);
 	tci_v = rte_be_to_cpu_16(vlan_m->tci & vlan_v->tci);
-	MLX5_SET(fte_match_set_lyr_2_4, headers_m, first_vid, tci_m);
-	MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_vid, tci_v);
-	MLX5_SET(fte_match_set_lyr_2_4, headers_m, first_cfi, tci_m >> 12);
-	MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_cfi, tci_v >> 12);
-	MLX5_SET(fte_match_set_lyr_2_4, headers_m, first_prio, tci_m >> 13);
-	MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_prio, tci_v >> 13);
+	MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, first_vid, tci_m);
+	MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, first_vid, tci_v);
+	MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, first_cfi, tci_m >> 12);
+	MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, first_cfi, tci_v >> 12);
+	MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, first_prio, tci_m >> 13);
+	MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, first_prio, tci_v >> 13);
 	/*
 	 * HW is optimized for IPv4/IPv6. In such cases, avoid setting
 	 * ethertype, and use ip_version field instead.
 	 */
-	if (vlan_v->inner_type == RTE_BE16(RTE_ETHER_TYPE_IPV4) &&
-	    vlan_m->inner_type == 0xFFFF) {
-		flow_dv_set_match_ip_version(group, headers_v, headers_m, 4);
-	} else if (vlan_v->inner_type == RTE_BE16(RTE_ETHER_TYPE_IPV6) &&
-		   vlan_m->inner_type == 0xFFFF) {
-		flow_dv_set_match_ip_version(group, headers_v, headers_m, 6);
-	} else {
-		MLX5_SET(fte_match_set_lyr_2_4, headers_m, ethertype,
-			 rte_be_to_cpu_16(vlan_m->inner_type));
-		MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype,
-			 rte_be_to_cpu_16(vlan_m->inner_type &
-					  vlan_v->inner_type));
+	if (vlan_m->inner_type == 0xFFFF) {
+		switch (vlan_v->inner_type) {
+		case RTE_BE16(RTE_ETHER_TYPE_VLAN):
+			MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, svlan_tag, 1);
+			MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, svlan_tag, 1);
+			MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 0);
+			return;
+		case RTE_BE16(RTE_ETHER_TYPE_IPV4):
+			flow_dv_set_match_ip_version(group, hdrs_v, hdrs_m, 4);
+			return;
+		case RTE_BE16(RTE_ETHER_TYPE_IPV6):
+			flow_dv_set_match_ip_version(group, hdrs_v, hdrs_m, 6);
+			return;
+		default:
+			break;
+		}
 	}
+	if (vlan_m->has_more_vlan && vlan_v->has_more_vlan) {
+		MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, svlan_tag, 1);
+		MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, svlan_tag, 1);
+		/* Only one vlan_tag bit can be set. */
+		MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, cvlan_tag, 0);
+		return;
+	}
+	MLX5_SET(fte_match_set_lyr_2_4, hdrs_m, ethertype,
+		 rte_be_to_cpu_16(vlan_m->inner_type));
+	MLX5_SET(fte_match_set_lyr_2_4, hdrs_v, ethertype,
+		 rte_be_to_cpu_16(vlan_m->inner_type & vlan_v->inner_type));
 }
 
 /**
@@ -6515,8 +6545,6 @@  struct field_modify_info modify_tcp[] = {
  *   Flow matcher value.
  * @param[in] item
  *   Flow pattern to translate.
- * @param[in] item_flags
- *   Bit-fields that holds the items detected until now.
  * @param[in] inner
  *   Item is inner pattern.
  * @param[in] group
@@ -6525,7 +6553,6 @@  struct field_modify_info modify_tcp[] = {
 static void
 flow_dv_translate_item_ipv4(void *matcher, void *key,
 			    const struct rte_flow_item *item,
-			    const uint64_t item_flags,
 			    int inner, uint32_t group)
 {
 	const struct rte_flow_item_ipv4 *ipv4_m = item->mask;
@@ -6555,13 +6582,6 @@  struct field_modify_info modify_tcp[] = {
 		headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
 	}
 	flow_dv_set_match_ip_version(group, headers_v, headers_m, 4);
-	/*
-	 * On outer header (which must contains L2), or inner header with L2,
-	 * set cvlan_tag mask bit to mark this packet as untagged.
-	 * This should be done even if item->spec is empty.
-	 */
-	if (!inner || item_flags & MLX5_FLOW_LAYER_INNER_L2)
-		MLX5_SET(fte_match_set_lyr_2_4, headers_m, cvlan_tag, 1);
 	if (!ipv4_v)
 		return;
 	if (!ipv4_m)
@@ -6608,8 +6628,6 @@  struct field_modify_info modify_tcp[] = {
  *   Flow matcher value.
  * @param[in] item
  *   Flow pattern to translate.
- * @param[in] item_flags
- *   Bit-fields that holds the items detected until now.
  * @param[in] inner
  *   Item is inner pattern.
  * @param[in] group
@@ -6618,7 +6636,6 @@  struct field_modify_info modify_tcp[] = {
 static void
 flow_dv_translate_item_ipv6(void *matcher, void *key,
 			    const struct rte_flow_item *item,
-			    const uint64_t item_flags,
 			    int inner, uint32_t group)
 {
 	const struct rte_flow_item_ipv6 *ipv6_m = item->mask;
@@ -6657,13 +6674,6 @@  struct field_modify_info modify_tcp[] = {
 		headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
 	}
 	flow_dv_set_match_ip_version(group, headers_v, headers_m, 6);
-	/*
-	 * On outer header (which must contains L2), or inner header with L2,
-	 * set cvlan_tag mask bit to mark this packet as untagged.
-	 * This should be done even if item->spec is empty.
-	 */
-	if (!inner || item_flags & MLX5_FLOW_LAYER_INNER_L2)
-		MLX5_SET(fte_match_set_lyr_2_4, headers_m, cvlan_tag, 1);
 	if (!ipv6_v)
 		return;
 	if (!ipv6_m)
@@ -9915,7 +9925,7 @@  struct field_modify_info modify_tcp[] = {
 			mlx5_flow_tunnel_ip_check(items, next_protocol,
 						  &item_flags, &tunnel);
 			flow_dv_translate_item_ipv4(match_mask, match_value,
-						    items, item_flags, tunnel,
+						    items, tunnel,
 						    dev_flow->dv.group);
 			matcher.priority = MLX5_PRIORITY_MAP_L3;
 			last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 :
@@ -9938,7 +9948,7 @@  struct field_modify_info modify_tcp[] = {
 			mlx5_flow_tunnel_ip_check(items, next_protocol,
 						  &item_flags, &tunnel);
 			flow_dv_translate_item_ipv6(match_mask, match_value,
-						    items, item_flags, tunnel,
+						    items, tunnel,
 						    dev_flow->dv.group);
 			matcher.priority = MLX5_PRIORITY_MAP_L3;
 			last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 :
diff --git a/drivers/net/mlx5/mlx5_flow_verbs.c b/drivers/net/mlx5/mlx5_flow_verbs.c
index 9cc4410..f0e1bca 100644
--- a/drivers/net/mlx5/mlx5_flow_verbs.c
+++ b/drivers/net/mlx5/mlx5_flow_verbs.c
@@ -1263,7 +1263,7 @@ 
 			break;
 		case RTE_FLOW_ITEM_TYPE_ETH:
 			ret = mlx5_flow_validate_item_eth(items, item_flags,
-							  error);
+							  false, error);
 			if (ret < 0)
 				return ret;
 			last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L2 :