DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 01/10] ethdev: reuse header definition in flow pattern item ETH
@ 2021-03-12  9:31 Ivan Malov
  2021-03-12  9:31 ` [dpdk-dev] [PATCH 02/10] ethdev: reuse header definition in flow pattern item VLAN Ivan Malov
                   ` (10 more replies)
  0 siblings, 11 replies; 36+ messages in thread
From: Ivan Malov @ 2021-03-12  9:31 UTC (permalink / raw)
  To: dev
  Cc: Andrew Rybchenko, Andy Moreton, Ori Kam, Thomas Monjalon, Ferruh Yigit

One ought to reuse existing header structs in flow items.
This particular item contains non-header fields, so it's
important to keep the header fields in a separate struct.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 lib/librte_ethdev/rte_flow.h | 44 ++++++++++++++++++++++--------------
 1 file changed, 27 insertions(+), 17 deletions(-)

diff --git a/lib/librte_ethdev/rte_flow.h b/lib/librte_ethdev/rte_flow.h
index 669e677e9..96fd93ee1 100644
--- a/lib/librte_ethdev/rte_flow.h
+++ b/lib/librte_ethdev/rte_flow.h
@@ -728,22 +728,32 @@ static const struct rte_flow_item_raw rte_flow_item_raw_mask = {
  *
  * Matches an Ethernet header.
  *
- * The @p type field either stands for "EtherType" or "TPID" when followed
- * by so-called layer 2.5 pattern items such as RTE_FLOW_ITEM_TYPE_VLAN. In
- * the latter case, @p type refers to that of the outer header, with the
- * inner EtherType/TPID provided by the subsequent pattern item. This is the
- * same order as on the wire.
- * If the @p type field contains a TPID value, then only tagged packets with the
- * specified TPID will match the pattern.
- * The field @p has_vlan can be used to match any type of tagged packets,
- * instead of using the @p type field.
- * If the @p type and @p has_vlan fields are not specified, then both tagged
- * and untagged packets will match the pattern.
+ * Inside @p hdr field, the sub-field @p ether_type stands either for EtherType
+ * or TPID, depending on whether the item is followed by a VLAN item or not. If
+ * two VLAN items follow, the sub-field refers to the outer one, which, in turn,
+ * contains the inner TPID in the similar header field. The innermost VLAN item
+ * contains a layer-3 EtherType. All of that follows the order seen on the wire.
+ *
+ * If the field in question contains a TPID value, only tagged packets with the
+ * specified TPID will match the pattern. Alternatively, it's possible to match
+ * any type of tagged packets by means of the field @p has_vlan rather than use
+ * the EtherType/TPID field. Also, it's possible to leave the two fields unused.
+ * If this is the case, both tagged and untagged packets will match the pattern.
  */
+RTE_STD_C11
 struct rte_flow_item_eth {
-	struct rte_ether_addr dst; /**< Destination MAC. */
-	struct rte_ether_addr src; /**< Source MAC. */
-	rte_be16_t type; /**< EtherType or TPID. */
+	union {
+		struct {
+			/*
+			 * These fields are retained for compatibility.
+			 * Please switch to the new header field below.
+			 */
+			struct rte_ether_addr dst; /**< Destination MAC. */
+			struct rte_ether_addr src; /**< Source MAC. */
+			rte_be16_t type; /**< EtherType or TPID. */
+		};
+		struct rte_ether_hdr hdr;
+	};
 	uint32_t has_vlan:1; /**< Packet header contains at least one VLAN. */
 	uint32_t reserved:31; /**< Reserved, must be zero. */
 };
@@ -751,9 +761,9 @@ struct rte_flow_item_eth {
 /** Default mask for RTE_FLOW_ITEM_TYPE_ETH. */
 #ifndef __cplusplus
 static const struct rte_flow_item_eth rte_flow_item_eth_mask = {
-	.dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
-	.src.addr_bytes = "\xff\xff\xff\xff\xff\xff",
-	.type = RTE_BE16(0x0000),
+	.hdr.d_addr.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+	.hdr.s_addr.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+	.hdr.ether_type = RTE_BE16(0x0000),
 };
 #endif
 
-- 
2.20.1


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

* [dpdk-dev] [PATCH 02/10] ethdev: reuse header definition in flow pattern item VLAN
  2021-03-12  9:31 [dpdk-dev] [PATCH 01/10] ethdev: reuse header definition in flow pattern item ETH Ivan Malov
@ 2021-03-12  9:31 ` Ivan Malov
  2021-03-16 23:05   ` Ori Kam
  2021-03-12  9:31 ` [dpdk-dev] [PATCH 03/10] net: clarify endianness of 32-bit fields in VXLAN headers Ivan Malov
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 36+ messages in thread
From: Ivan Malov @ 2021-03-12  9:31 UTC (permalink / raw)
  To: dev
  Cc: Andrew Rybchenko, Andy Moreton, Ori Kam, Thomas Monjalon, Ferruh Yigit

One ought to reuse existing header structs in flow items.
This particular item contains non-header fields, so it's
important to keep the header fields in a separate struct.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 lib/librte_ethdev/rte_flow.h | 22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/lib/librte_ethdev/rte_flow.h b/lib/librte_ethdev/rte_flow.h
index 96fd93ee1..b9b349669 100644
--- a/lib/librte_ethdev/rte_flow.h
+++ b/lib/librte_ethdev/rte_flow.h
@@ -778,13 +778,23 @@ static const struct rte_flow_item_eth rte_flow_item_eth_mask = {
  * If a @p VLAN item is present in the pattern, then only tagged packets will
  * match the pattern.
  * The field @p has_more_vlan can be used to match any type of tagged packets,
- * instead of using the @p inner_type field.
- * If the @p inner_type and @p has_more_vlan fields are not specified,
+ * instead of using the @p eth_proto field of @p hdr.
+ * If the @p eth_proto of @p hdr and @p has_more_vlan fields are not specified,
  * then any tagged packets will match the pattern.
  */
+RTE_STD_C11
 struct rte_flow_item_vlan {
-	rte_be16_t tci; /**< Tag control information. */
-	rte_be16_t inner_type; /**< Inner EtherType or TPID. */
+	union {
+		struct {
+			/*
+			 * These fields are retained for compatibility.
+			 * Please switch to the new header field below.
+			 */
+			rte_be16_t tci; /**< Tag control information. */
+			rte_be16_t inner_type; /**< Inner EtherType or TPID. */
+		};
+		struct rte_vlan_hdr hdr;
+	};
 	uint32_t has_more_vlan:1;
 	/**< Packet header contains at least one more VLAN, after this VLAN. */
 	uint32_t reserved:31; /**< Reserved, must be zero. */
@@ -793,8 +803,8 @@ struct rte_flow_item_vlan {
 /** Default mask for RTE_FLOW_ITEM_TYPE_VLAN. */
 #ifndef __cplusplus
 static const struct rte_flow_item_vlan rte_flow_item_vlan_mask = {
-	.tci = RTE_BE16(0x0fff),
-	.inner_type = RTE_BE16(0x0000),
+	.hdr.vlan_tci = RTE_BE16(0x0fff),
+	.hdr.eth_proto = RTE_BE16(0x0000),
 };
 #endif
 
-- 
2.20.1


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

* [dpdk-dev] [PATCH 03/10] net: clarify endianness of 32-bit fields in VXLAN headers
  2021-03-12  9:31 [dpdk-dev] [PATCH 01/10] ethdev: reuse header definition in flow pattern item ETH Ivan Malov
  2021-03-12  9:31 ` [dpdk-dev] [PATCH 02/10] ethdev: reuse header definition in flow pattern item VLAN Ivan Malov
@ 2021-03-12  9:31 ` Ivan Malov
  2021-03-12  9:31 ` [dpdk-dev] [PATCH 04/10] ethdev: reuse header definition in flow pattern item VXLAN Ivan Malov
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 36+ messages in thread
From: Ivan Malov @ 2021-03-12  9:31 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Andy Moreton, Olivier Matz

These fields have network byte order. Highlight it using dedicated type.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 lib/librte_net/rte_vxlan.h | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/lib/librte_net/rte_vxlan.h b/lib/librte_net/rte_vxlan.h
index 2ad606165..929fa7a1d 100644
--- a/lib/librte_net/rte_vxlan.h
+++ b/lib/librte_net/rte_vxlan.h
@@ -13,6 +13,7 @@
 
 #include <stdint.h>
 
+#include <rte_byteorder.h>
 #include <rte_udp.h>
 
 
@@ -30,8 +31,8 @@ extern "C" {
  * Reserved fields (24 bits and 8 bits)
  */
 struct rte_vxlan_hdr {
-	uint32_t vx_flags; /**< flag (8) + Reserved (24). */
-	uint32_t vx_vni;   /**< VNI (24) + Reserved (8). */
+	rte_be32_t vx_flags; /**< flag (8) + Reserved (24). */
+	rte_be32_t vx_vni;   /**< VNI (24) + Reserved (8). */
 } __rte_packed;
 
 /** VXLAN tunnel header length. */
@@ -48,7 +49,7 @@ struct rte_vxlan_gpe_hdr {
 	uint8_t vx_flags;    /**< flag (8). */
 	uint8_t reserved[2]; /**< Reserved (16). */
 	uint8_t proto;       /**< next-protocol (8). */
-	uint32_t vx_vni;     /**< VNI (24) + Reserved (8). */
+	rte_be32_t vx_vni;   /**< VNI (24) + Reserved (8). */
 } __rte_packed;
 
 /** VXLAN-GPE tunnel header length. */
-- 
2.20.1


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

* [dpdk-dev] [PATCH 04/10] ethdev: reuse header definition in flow pattern item VXLAN
  2021-03-12  9:31 [dpdk-dev] [PATCH 01/10] ethdev: reuse header definition in flow pattern item ETH Ivan Malov
  2021-03-12  9:31 ` [dpdk-dev] [PATCH 02/10] ethdev: reuse header definition in flow pattern item VLAN Ivan Malov
  2021-03-12  9:31 ` [dpdk-dev] [PATCH 03/10] net: clarify endianness of 32-bit fields in VXLAN headers Ivan Malov
@ 2021-03-12  9:31 ` Ivan Malov
  2021-03-12  9:31 ` [dpdk-dev] [PATCH 05/10] common/sfc_efx/base: support encap. header provisioning Ivan Malov
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 36+ messages in thread
From: Ivan Malov @ 2021-03-12  9:31 UTC (permalink / raw)
  To: dev
  Cc: Andrew Rybchenko, Andy Moreton, Ori Kam, Thomas Monjalon, Ferruh Yigit

One ought to reuse existing header structs in flow items.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 lib/librte_ethdev/rte_flow.h | 24 +++++++++++++++++++-----
 1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/lib/librte_ethdev/rte_flow.h b/lib/librte_ethdev/rte_flow.h
index b9b349669..56c97829c 100644
--- a/lib/librte_ethdev/rte_flow.h
+++ b/lib/librte_ethdev/rte_flow.h
@@ -25,6 +25,7 @@
 #include <rte_sctp.h>
 #include <rte_tcp.h>
 #include <rte_udp.h>
+#include <rte_vxlan.h>
 #include <rte_byteorder.h>
 #include <rte_esp.h>
 #include <rte_higig.h>
@@ -954,18 +955,31 @@ static const struct rte_flow_item_sctp rte_flow_item_sctp_mask = {
  * RTE_FLOW_ITEM_TYPE_VXLAN.
  *
  * Matches a VXLAN header (RFC 7348).
+ *
+ * Fields @p flags, @p rsvd0, @p vni and @rsvd1 are left here for compatibility.
+ * Consumers of this item definition are encouraged to use field @p hdr instead.
  */
+RTE_STD_C11
 struct rte_flow_item_vxlan {
-	uint8_t flags; /**< Normally 0x08 (I flag). */
-	uint8_t rsvd0[3]; /**< Reserved, normally 0x000000. */
-	uint8_t vni[3]; /**< VXLAN identifier. */
-	uint8_t rsvd1; /**< Reserved, normally 0x00. */
+	union {
+		struct {
+			/*
+			 * These fields are retained for compatibility.
+			 * Please switch to the new header field below.
+			 */
+			uint8_t flags; /**< Normally 0x08 (I flag). */
+			uint8_t rsvd0[3]; /**< Reserved, normally 0x000000. */
+			uint8_t vni[3]; /**< VXLAN identifier. */
+			uint8_t rsvd1; /**< Reserved, normally 0x00. */
+		};
+		struct rte_vxlan_hdr hdr;
+	};
 };
 
 /** Default mask for RTE_FLOW_ITEM_TYPE_VXLAN. */
 #ifndef __cplusplus
 static const struct rte_flow_item_vxlan rte_flow_item_vxlan_mask = {
-	.vni = "\xff\xff\xff",
+	.hdr.vx_vni = RTE_BE32(__builtin_constant_p(0xffffff << 8)),
 };
 #endif
 
-- 
2.20.1


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

* [dpdk-dev] [PATCH 05/10] common/sfc_efx/base: support encap. header provisioning
  2021-03-12  9:31 [dpdk-dev] [PATCH 01/10] ethdev: reuse header definition in flow pattern item ETH Ivan Malov
                   ` (2 preceding siblings ...)
  2021-03-12  9:31 ` [dpdk-dev] [PATCH 04/10] ethdev: reuse header definition in flow pattern item VXLAN Ivan Malov
@ 2021-03-12  9:31 ` Ivan Malov
  2021-03-12  9:31 ` [dpdk-dev] [PATCH 06/10] common/sfc_efx/base: support adding action ENCAP to a set Ivan Malov
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 36+ messages in thread
From: Ivan Malov @ 2021-03-12  9:31 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Andy Moreton, Ray Kinsella, Neil Horman

Let the client allocate / free encap. headers.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h     |  21 ++++
 drivers/common/sfc_efx/base/efx_mae.c | 155 ++++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map    |   2 +
 3 files changed, 178 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index ccf9c7ab8..4a738e589 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4070,6 +4070,7 @@ typedef struct efx_mae_limits_s {
 	uint32_t			eml_max_n_action_prios;
 	uint32_t			eml_max_n_outer_prios;
 	uint32_t			eml_encap_types_supported;
+	uint32_t			eml_encap_header_size_limit;
 } efx_mae_limits_t;
 
 LIBEFX_API
@@ -4324,6 +4325,26 @@ efx_mae_match_spec_outer_rule_id_set(
 	__in				efx_mae_match_spec_t *spec,
 	__in				const efx_mae_rule_id_t *or_idp);
 
+/* Encap. header ID */
+typedef struct efx_mae_eh_id_s {
+	uint32_t id;
+} efx_mae_eh_id_t;
+
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_encap_header_alloc(
+	__in				efx_nic_t *enp,
+	__in				efx_tunnel_protocol_t encap_type,
+	__in_bcount(header_size)	uint8_t *header_data,
+	__in				size_t header_size,
+	__out				efx_mae_eh_id_t *eh_idp);
+
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_encap_header_free(
+	__in				efx_nic_t *enp,
+	__in				const efx_mae_eh_id_t *eh_idp);
+
 /* Action set ID */
 typedef struct efx_mae_aset_id_s {
 	uint32_t id;
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 338a0013f..798867963 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -353,6 +353,8 @@ efx_mae_get_limits(
 	emlp->eml_max_n_outer_prios = maep->em_max_n_outer_prios;
 	emlp->eml_max_n_action_prios = maep->em_max_n_action_prios;
 	emlp->eml_encap_types_supported = maep->em_encap_types_supported;
+	emlp->eml_encap_header_size_limit =
+	    MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_MAXNUM_MCDI2;
 
 	return (0);
 
@@ -1691,6 +1693,159 @@ efx_mae_match_spec_outer_rule_id_set(
 
 	return (0);
 
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	 __checkReturn			efx_rc_t
+efx_mae_encap_header_alloc(
+	__in				efx_nic_t *enp,
+	__in				efx_tunnel_protocol_t encap_type,
+	__in_bcount(header_size)	uint8_t *header_data,
+	__in				size_t header_size,
+	__out				efx_mae_eh_id_t *eh_idp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	efx_mcdi_req_t req;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_LENMAX_MCDI2,
+	    MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_LEN);
+	uint32_t encap_type_mcdi;
+	efx_mae_eh_id_t eh_id;
+	efx_rc_t rc;
+
+	EFX_STATIC_ASSERT(sizeof (eh_idp->id) ==
+	    MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_LEN);
+
+	EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID ==
+	    MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_NULL);
+
+	if (encp->enc_mae_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	switch (encap_type) {
+	case EFX_TUNNEL_PROTOCOL_NONE:
+		encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_NONE;
+		break;
+	case EFX_TUNNEL_PROTOCOL_VXLAN:
+		encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_VXLAN;
+		break;
+	case EFX_TUNNEL_PROTOCOL_GENEVE:
+		encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_GENEVE;
+		break;
+	case EFX_TUNNEL_PROTOCOL_NVGRE:
+		encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_NVGRE;
+		break;
+	default:
+		rc = ENOTSUP;
+		goto fail2;
+	}
+
+	if (header_size >
+	    MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_MAXNUM_MCDI2) {
+		rc = EINVAL;
+		goto fail3;
+	}
+
+	req.emr_cmd = MC_CMD_MAE_ENCAP_HEADER_ALLOC;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_LEN(header_size);
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_LEN;
+
+	MCDI_IN_SET_DWORD(req,
+	    MAE_ENCAP_HEADER_ALLOC_IN_ENCAP_TYPE, encap_type_mcdi);
+
+	memcpy(payload + MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_OFST,
+	    header_data, header_size);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail4;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_LEN) {
+		rc = EMSGSIZE;
+		goto fail5;
+	}
+
+	eh_id.id = MCDI_OUT_DWORD(req,
+	    MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID);
+
+	if (eh_id.id == EFX_MAE_RSRC_ID_INVALID) {
+		rc = ENOENT;
+		goto fail6;
+	}
+
+	eh_idp->id = eh_id.id;
+
+	return (0);
+
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_encap_header_free(
+	__in				efx_nic_t *enp,
+	__in				const efx_mae_eh_id_t *eh_idp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	efx_mcdi_req_t req;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_MAE_ENCAP_HEADER_FREE_IN_LEN(1),
+	    MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_LEN(1));
+	efx_rc_t rc;
+
+	if (encp->enc_mae_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	req.emr_cmd = MC_CMD_MAE_ENCAP_HEADER_FREE;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_MAE_ENCAP_HEADER_FREE_IN_LEN(1);
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_LEN(1);
+
+	MCDI_IN_SET_DWORD(req, MAE_ENCAP_HEADER_FREE_IN_EH_ID, eh_idp->id);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail2;
+	}
+
+	if (MCDI_OUT_DWORD(req, MAE_ENCAP_HEADER_FREE_OUT_FREED_EH_ID) !=
+	    eh_idp->id) {
+		/* Firmware failed to remove the encap. header. */
+		rc = EAGAIN;
+		goto fail3;
+	}
+
+	return (0);
+
 fail3:
 	EFSYS_PROBE(fail3);
 fail2:
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index 403feeaf1..168899d51 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -98,6 +98,8 @@ INTERNAL {
 	efx_mae_action_set_spec_fini;
 	efx_mae_action_set_spec_init;
 	efx_mae_action_set_specs_equal;
+	efx_mae_encap_header_alloc;
+	efx_mae_encap_header_free;
 	efx_mae_fini;
 	efx_mae_get_limits;
 	efx_mae_init;
-- 
2.20.1


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

* [dpdk-dev] [PATCH 06/10] common/sfc_efx/base: support adding action ENCAP to a set
  2021-03-12  9:31 [dpdk-dev] [PATCH 01/10] ethdev: reuse header definition in flow pattern item ETH Ivan Malov
                   ` (3 preceding siblings ...)
  2021-03-12  9:31 ` [dpdk-dev] [PATCH 05/10] common/sfc_efx/base: support encap. header provisioning Ivan Malov
@ 2021-03-12  9:31 ` Ivan Malov
  2021-03-12  9:31 ` [dpdk-dev] [PATCH 07/10] net/sfc: change MAE rule actions parse API Ivan Malov
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 36+ messages in thread
From: Ivan Malov @ 2021-03-12  9:31 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Andy Moreton, Ray Kinsella, Neil Horman

For convenience, there are two separate APIs provided, one for
adding the action and one for setting the encap. header ID.
This design allows the client driver to first build the action
set specification (which validates the order of the actions)
and, if everything is correct, proceed with allocation of the
resource utilised by the action set (encap. header). This
facilitates clarity of the client code and its efficiency.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h      |  16 ++++
 drivers/common/sfc_efx/base/efx_impl.h |  12 +++
 drivers/common/sfc_efx/base/efx_mae.c  | 126 ++++++++++++++++++++++++-
 drivers/common/sfc_efx/version.map     |   2 +
 4 files changed, 153 insertions(+), 3 deletions(-)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 4a738e589..052946aa3 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4252,6 +4252,15 @@ efx_mae_action_set_populate_vlan_push(
 	__in				uint16_t tpid_be,
 	__in				uint16_t tci_be);
 
+/*
+ * Use efx_mae_action_set_fill_in_eh_id() to set ID of the allocated
+ * encap. header in the specification prior to action set allocation.
+ */
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_encap(
+	__in				efx_mae_actions_t *spec);
+
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_flag(
@@ -4345,6 +4354,13 @@ efx_mae_encap_header_free(
 	__in				efx_nic_t *enp,
 	__in				const efx_mae_eh_id_t *eh_idp);
 
+/* See description before efx_mae_action_set_populate_encap(). */
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_set_fill_in_eh_id(
+	__in				efx_mae_actions_t *spec,
+	__in				const efx_mae_eh_id_t *eh_idp);
+
 /* Action set ID */
 typedef struct efx_mae_aset_id_s {
 	uint32_t id;
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 1005dd0aa..0adf43c26 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -1709,6 +1709,7 @@ typedef enum efx_mae_action_e {
 	/* These actions are strictly ordered. */
 	EFX_MAE_ACTION_VLAN_POP,
 	EFX_MAE_ACTION_VLAN_PUSH,
+	EFX_MAE_ACTION_ENCAP,
 
 	/*
 	 * These actions are not strictly ordered and can
@@ -1736,6 +1737,10 @@ typedef struct efx_mae_action_vlan_push_s {
 	uint16_t			emavp_tci_be;
 } efx_mae_action_vlan_push_t;
 
+typedef struct efx_mae_actions_rsrc_s {
+	efx_mae_eh_id_t			emar_eh_id;
+} efx_mae_actions_rsrc_t;
+
 struct efx_mae_actions_s {
 	/* Bitmap of actions in spec, indexed by action type */
 	uint32_t			ema_actions;
@@ -1746,6 +1751,13 @@ struct efx_mae_actions_s {
 	    EFX_MAE_VLAN_PUSH_MAX_NTAGS];
 	uint32_t			ema_mark_value;
 	efx_mport_sel_t			ema_deliver_mport;
+
+	/*
+	 * Always keep this at the end of the struct since
+	 * efx_mae_action_set_specs_equal() relies on that
+	 * to make sure that resource IDs are not compared.
+	 */
+	efx_mae_actions_rsrc_t		ema_rsrc;
 };
 
 #endif /* EFSYS_OPT_MAE */
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 798867963..896500de0 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -994,6 +994,8 @@ efx_mae_action_set_spec_init(
 		goto fail1;
 	}
 
+	spec->ema_rsrc.emar_eh_id.id = EFX_MAE_RSRC_ID_INVALID;
+
 	*specp = spec;
 
 	return (0);
@@ -1085,6 +1087,50 @@ efx_mae_action_set_add_vlan_push(
 	return (rc);
 }
 
+static	__checkReturn			efx_rc_t
+efx_mae_action_set_add_encap(
+	__in				efx_mae_actions_t *spec,
+	__in				size_t arg_size,
+	__in_bcount(arg_size)		const uint8_t *arg)
+{
+	efx_rc_t rc;
+
+	/*
+	 * Adding this specific action to an action set spec and setting encap.
+	 * header ID in the spec are two individual steps. This design allows
+	 * the client driver to avoid encap. header allocation when it simply
+	 * needs to check the order of actions submitted by user ("validate"),
+	 * without actually allocating an action set and inserting a rule.
+	 *
+	 * For now, mark encap. header ID as invalid; the caller will invoke
+	 * efx_mae_action_set_fill_in_eh_id() to override the field prior
+	 * to action set allocation; otherwise, the allocation will fail.
+	 */
+	spec->ema_rsrc.emar_eh_id.id = EFX_MAE_RSRC_ID_INVALID;
+
+	/*
+	 * As explained above, there are no arguments to handle here.
+	 * efx_mae_action_set_fill_in_eh_id() will take care of them.
+	 */
+	if (arg_size != 0) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if (arg != NULL) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
 static	__checkReturn			efx_rc_t
 efx_mae_action_set_add_flag(
 	__in				efx_mae_actions_t *spec,
@@ -1187,6 +1233,9 @@ static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
 	[EFX_MAE_ACTION_VLAN_PUSH] = {
 		.emad_add = efx_mae_action_set_add_vlan_push
 	},
+	[EFX_MAE_ACTION_ENCAP] = {
+		.emad_add = efx_mae_action_set_add_encap
+	},
 	[EFX_MAE_ACTION_FLAG] = {
 		.emad_add = efx_mae_action_set_add_flag
 	},
@@ -1201,6 +1250,7 @@ static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
 static const uint32_t efx_mae_action_ordered_map =
 	(1U << EFX_MAE_ACTION_VLAN_POP) |
 	(1U << EFX_MAE_ACTION_VLAN_PUSH) |
+	(1U << EFX_MAE_ACTION_ENCAP) |
 	(1U << EFX_MAE_ACTION_FLAG) |
 	(1U << EFX_MAE_ACTION_MARK) |
 	(1U << EFX_MAE_ACTION_DELIVER);
@@ -1317,6 +1367,20 @@ efx_mae_action_set_populate_vlan_push(
 	    EFX_MAE_ACTION_VLAN_PUSH, sizeof (action), arg));
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_encap(
+	__in				efx_mae_actions_t *spec)
+{
+	/*
+	 * There is no argument to pass encap. header ID, thus, one does not
+	 * need to allocate an encap. header while parsing application input.
+	 * This is useful since building an action set may be done simply to
+	 * validate a rule, whilst resource allocation usually consumes time.
+	 */
+	return (efx_mae_action_set_spec_populate(spec,
+	    EFX_MAE_ACTION_ENCAP, 0, NULL));
+}
+
 	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_flag(
 	__in				efx_mae_actions_t *spec)
@@ -1389,7 +1453,22 @@ efx_mae_action_set_specs_equal(
 	__in				const efx_mae_actions_t *left,
 	__in				const efx_mae_actions_t *right)
 {
-	return ((memcmp(left, right, sizeof (*left)) == 0) ? B_TRUE : B_FALSE);
+	size_t cmp_size = EFX_FIELD_OFFSET(efx_mae_actions_t, ema_rsrc);
+
+	/*
+	 * An action set specification consists of two parts. The first part
+	 * indicates what actions are included in the action set, as well as
+	 * extra quantitative values (in example, the number of VLAN tags to
+	 * push). The second part comprises resource IDs used by the actions.
+	 *
+	 * A resource, in example, a counter, is allocated from the hardware
+	 * by the client, and it's the client who is responsible for keeping
+	 * track of allocated resources and comparing resource IDs if needed.
+	 *
+	 * In this API, don't compare resource IDs in the two specifications.
+	 */
+
+	return ((memcmp(left, right, cmp_size) == 0) ? B_TRUE : B_FALSE);
 }
 
 	__checkReturn			efx_rc_t
@@ -1846,6 +1925,46 @@ efx_mae_encap_header_free(
 
 	return (0);
 
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_action_set_fill_in_eh_id(
+	__in				efx_mae_actions_t *spec,
+	__in				const efx_mae_eh_id_t *eh_idp)
+{
+	efx_rc_t rc;
+
+	if ((spec->ema_actions & (1U << EFX_MAE_ACTION_ENCAP)) == 0) {
+		/*
+		 * The caller has not intended to have action ENCAP originally,
+		 * hence, this attempt to indicate encap. header ID is invalid.
+		 */
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if (spec->ema_rsrc.emar_eh_id.id != EFX_MAE_RSRC_ID_INVALID) {
+		/* The caller attempts to indicate encap. header ID twice. */
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	if (eh_idp->id == EFX_MAE_RSRC_ID_INVALID) {
+		rc = EINVAL;
+		goto fail3;
+	}
+
+	spec->ema_rsrc.emar_eh_id.id = eh_idp->id;
+
+	return (0);
+
 fail3:
 	EFSYS_PROBE(fail3);
 fail2:
@@ -1889,8 +2008,6 @@ efx_mae_action_set_alloc(
 	    MAE_ACTION_SET_ALLOC_IN_COUNTER_LIST_ID, EFX_MAE_RSRC_ID_INVALID);
 	MCDI_IN_SET_DWORD(req,
 	    MAE_ACTION_SET_ALLOC_IN_COUNTER_ID, EFX_MAE_RSRC_ID_INVALID);
-	MCDI_IN_SET_DWORD(req,
-	    MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID, EFX_MAE_RSRC_ID_INVALID);
 
 	MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
 	    MAE_ACTION_SET_ALLOC_IN_VLAN_POP, spec->ema_n_vlan_tags_to_pop);
@@ -1920,6 +2037,9 @@ efx_mae_action_set_alloc(
 		    spec->ema_vlan_push_descs[outer_tag_idx].emavp_tci_be);
 	}
 
+	MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID,
+	    spec->ema_rsrc.emar_eh_id.id);
+
 	if ((spec->ema_actions & (1U << EFX_MAE_ACTION_FLAG)) != 0) {
 		MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
 		    MAE_ACTION_SET_ALLOC_IN_FLAG, 1);
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index 168899d51..f33a2a08e 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -88,9 +88,11 @@ INTERNAL {
 	efx_mae_action_rule_insert;
 	efx_mae_action_rule_remove;
 	efx_mae_action_set_alloc;
+	efx_mae_action_set_fill_in_eh_id;
 	efx_mae_action_set_free;
 	efx_mae_action_set_populate_deliver;
 	efx_mae_action_set_populate_drop;
+	efx_mae_action_set_populate_encap;
 	efx_mae_action_set_populate_flag;
 	efx_mae_action_set_populate_mark;
 	efx_mae_action_set_populate_vlan_pop;
-- 
2.20.1


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

* [dpdk-dev] [PATCH 07/10] net/sfc: change MAE rule actions parse API
  2021-03-12  9:31 [dpdk-dev] [PATCH 01/10] ethdev: reuse header definition in flow pattern item ETH Ivan Malov
                   ` (4 preceding siblings ...)
  2021-03-12  9:31 ` [dpdk-dev] [PATCH 06/10] common/sfc_efx/base: support adding action ENCAP to a set Ivan Malov
@ 2021-03-12  9:31 ` Ivan Malov
  2021-03-12  9:31 ` [dpdk-dev] [PATCH 08/10] net/sfc: support action VXLAN ENCAP in MAE backend Ivan Malov
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 36+ messages in thread
From: Ivan Malov @ 2021-03-12  9:31 UTC (permalink / raw)
  To: dev; +Cc: Igor Romanov, Andrew Rybchenko, Andy Moreton

From: Igor Romanov <igor.romanov@oktetlabs.ru>

Current API signature makes it hard to add other entities that
belong to a flow specification. Pass the flow specification
so that additional members can be accessed through the spec.

Signed-off-by: Igor Romanov <igor.romanov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
Reviewed-by: Ivan Malov <ivan.malov@oktetlabs.ru>
---
 drivers/net/sfc/sfc_flow.c | 3 +--
 drivers/net/sfc/sfc_mae.c  | 8 ++++----
 drivers/net/sfc/sfc_mae.h  | 2 +-
 3 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index ab1d2cc59..2c78473b5 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -2440,8 +2440,7 @@ sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
 	if (rc != 0)
 		return rc;
 
-	rc = sfc_mae_rule_parse_actions(sa, actions, &spec_mae->action_set,
-					error);
+	rc = sfc_mae_rule_parse_actions(sa, actions, spec_mae, error);
 	if (rc != 0)
 		return rc;
 
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 15c5c3975..50efd47ad 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -2093,7 +2093,7 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 int
 sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			   const struct rte_flow_action actions[],
-			   struct sfc_mae_action_set **action_setp,
+			   struct sfc_flow_spec_mae *spec_mae,
 			   struct rte_flow_error *error)
 {
 	struct sfc_mae_actions_bundle bundle = {0};
@@ -2127,13 +2127,13 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_rule_parse_action;
 
-	*action_setp = sfc_mae_action_set_attach(sa, spec);
-	if (*action_setp != NULL) {
+	spec_mae->action_set = sfc_mae_action_set_attach(sa, spec);
+	if (spec_mae->action_set != NULL) {
 		efx_mae_action_set_spec_fini(sa->nic, spec);
 		return 0;
 	}
 
-	rc = sfc_mae_action_set_add(sa, spec, action_setp);
+	rc = sfc_mae_action_set_add(sa, spec, &spec_mae->action_set);
 	if (rc != 0)
 		goto fail_action_set_add;
 
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index bf432638c..00987af61 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -197,7 +197,7 @@ int sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 			       struct rte_flow_error *error);
 int sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			       const struct rte_flow_action actions[],
-			       struct sfc_mae_action_set **action_setp,
+			       struct sfc_flow_spec_mae *spec_mae,
 			       struct rte_flow_error *error);
 sfc_flow_verify_cb_t sfc_mae_flow_verify;
 sfc_flow_insert_cb_t sfc_mae_flow_insert;
-- 
2.20.1


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

* [dpdk-dev] [PATCH 08/10] net/sfc: support action VXLAN ENCAP in MAE backend
  2021-03-12  9:31 [dpdk-dev] [PATCH 01/10] ethdev: reuse header definition in flow pattern item ETH Ivan Malov
                   ` (5 preceding siblings ...)
  2021-03-12  9:31 ` [dpdk-dev] [PATCH 07/10] net/sfc: change MAE rule actions parse API Ivan Malov
@ 2021-03-12  9:31 ` Ivan Malov
  2021-03-12  9:31 ` [dpdk-dev] [PATCH 09/10] common/sfc_efx/base: support adding action DECAP to a set Ivan Malov
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 36+ messages in thread
From: Ivan Malov @ 2021-03-12  9:31 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Andy Moreton

Provide necessary facilities for handling this action.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c | 550 +++++++++++++++++++++++++++++++++++++-
 drivers/net/sfc/sfc_mae.h |  29 ++
 2 files changed, 572 insertions(+), 7 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 50efd47ad..79a1bd91d 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -9,7 +9,9 @@
 
 #include <stdbool.h>
 
+#include <rte_bitops.h>
 #include <rte_common.h>
+#include <rte_vxlan.h>
 
 #include "efx.h"
 
@@ -35,6 +37,7 @@ sfc_mae_attach(struct sfc_adapter *sa)
 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
 	efx_mport_sel_t entity_mport;
 	struct sfc_mae *mae = &sa->mae;
+	struct sfc_mae_bounce_eh *bounce_eh = &mae->bounce_eh;
 	efx_mae_limits_t limits;
 	int rc;
 
@@ -80,17 +83,26 @@ sfc_mae_attach(struct sfc_adapter *sa)
 	if (rc != 0)
 		goto fail_mae_assign_switch_port;
 
+	sfc_log_init(sa, "allocate encap. header bounce buffer");
+	bounce_eh->buf_size = limits.eml_encap_header_size_limit;
+	bounce_eh->buf = rte_malloc("sfc_mae_bounce_eh",
+				    bounce_eh->buf_size, 0);
+	if (bounce_eh->buf == NULL)
+		goto fail_mae_alloc_bounce_eh;
+
 	mae->status = SFC_MAE_STATUS_SUPPORTED;
 	mae->nb_outer_rule_prios_max = limits.eml_max_n_outer_prios;
 	mae->nb_action_rule_prios_max = limits.eml_max_n_action_prios;
 	mae->encap_types_supported = limits.eml_encap_types_supported;
 	TAILQ_INIT(&mae->outer_rules);
+	TAILQ_INIT(&mae->encap_headers);
 	TAILQ_INIT(&mae->action_sets);
 
 	sfc_log_init(sa, "done");
 
 	return 0;
 
+fail_mae_alloc_bounce_eh:
 fail_mae_assign_switch_port:
 fail_mae_assign_switch_domain:
 fail_mae_assign_entity_mport:
@@ -117,6 +129,8 @@ sfc_mae_detach(struct sfc_adapter *sa)
 	if (status_prev != SFC_MAE_STATUS_SUPPORTED)
 		return;
 
+	rte_free(mae->bounce_eh.buf);
+
 	efx_mae_fini(sa->nic);
 
 	sfc_log_init(sa, "done");
@@ -254,8 +268,165 @@ sfc_mae_outer_rule_disable(struct sfc_adapter *sa,
 	return 0;
 }
 
+static struct sfc_mae_encap_header *
+sfc_mae_encap_header_attach(struct sfc_adapter *sa,
+			    const struct sfc_mae_bounce_eh *bounce_eh)
+{
+	struct sfc_mae_encap_header *encap_header;
+	struct sfc_mae *mae = &sa->mae;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	TAILQ_FOREACH(encap_header, &mae->encap_headers, entries) {
+		if (encap_header->size == bounce_eh->size &&
+		    memcmp(encap_header->buf, bounce_eh->buf,
+			   bounce_eh->size) == 0) {
+			++(encap_header->refcnt);
+			return encap_header;
+		}
+	}
+
+	return NULL;
+}
+
+static int
+sfc_mae_encap_header_add(struct sfc_adapter *sa,
+			 const struct sfc_mae_bounce_eh *bounce_eh,
+			 struct sfc_mae_encap_header **encap_headerp)
+{
+	struct sfc_mae_encap_header *encap_header;
+	struct sfc_mae *mae = &sa->mae;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	encap_header = rte_zmalloc("sfc_mae_encap_header",
+				   sizeof(*encap_header), 0);
+	if (encap_header == NULL)
+		return ENOMEM;
+
+	encap_header->size = bounce_eh->size;
+
+	encap_header->buf = rte_malloc("sfc_mae_encap_header_buf",
+				       encap_header->size, 0);
+	if (encap_header->buf == NULL) {
+		rte_free(encap_header);
+		return ENOMEM;
+	}
+
+	rte_memcpy(encap_header->buf, bounce_eh->buf, bounce_eh->size);
+
+	encap_header->refcnt = 1;
+	encap_header->type = bounce_eh->type;
+	encap_header->fw_rsrc.eh_id.id = EFX_MAE_RSRC_ID_INVALID;
+
+	TAILQ_INSERT_TAIL(&mae->encap_headers, encap_header, entries);
+
+	*encap_headerp = encap_header;
+
+	return 0;
+}
+
+static void
+sfc_mae_encap_header_del(struct sfc_adapter *sa,
+		       struct sfc_mae_encap_header *encap_header)
+{
+	struct sfc_mae *mae = &sa->mae;
+
+	if (encap_header == NULL)
+		return;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(encap_header->refcnt != 0);
+
+	--(encap_header->refcnt);
+
+	if (encap_header->refcnt != 0)
+		return;
+
+	SFC_ASSERT(encap_header->fw_rsrc.eh_id.id == EFX_MAE_RSRC_ID_INVALID);
+	SFC_ASSERT(encap_header->fw_rsrc.refcnt == 0);
+
+	TAILQ_REMOVE(&mae->encap_headers, encap_header, entries);
+	rte_free(encap_header->buf);
+	rte_free(encap_header);
+}
+
+static int
+sfc_mae_encap_header_enable(struct sfc_adapter *sa,
+			    struct sfc_mae_encap_header *encap_header,
+			    efx_mae_actions_t *action_set_spec)
+{
+	struct sfc_mae_fw_rsrc *fw_rsrc;
+	int rc;
+
+	if (encap_header == NULL)
+		return 0;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	fw_rsrc = &encap_header->fw_rsrc;
+
+	if (fw_rsrc->refcnt == 0) {
+		SFC_ASSERT(fw_rsrc->eh_id.id == EFX_MAE_RSRC_ID_INVALID);
+		SFC_ASSERT(encap_header->buf != NULL);
+		SFC_ASSERT(encap_header->size != 0);
+
+		rc = efx_mae_encap_header_alloc(sa->nic, encap_header->type,
+						encap_header->buf,
+						encap_header->size,
+						&fw_rsrc->eh_id);
+		if (rc != 0)
+			return rc;
+	}
+
+	rc = efx_mae_action_set_fill_in_eh_id(action_set_spec,
+					      &fw_rsrc->eh_id);
+	if (rc != 0) {
+		if (fw_rsrc->refcnt == 0) {
+			(void)efx_mae_encap_header_free(sa->nic,
+							&fw_rsrc->eh_id);
+		}
+		return rc;
+	}
+
+	++(fw_rsrc->refcnt);
+
+	return 0;
+}
+
+static int
+sfc_mae_encap_header_disable(struct sfc_adapter *sa,
+			     struct sfc_mae_encap_header *encap_header)
+{
+	struct sfc_mae_fw_rsrc *fw_rsrc;
+	int rc;
+
+	if (encap_header == NULL)
+		return 0;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	fw_rsrc = &encap_header->fw_rsrc;
+
+	SFC_ASSERT(fw_rsrc->eh_id.id != EFX_MAE_RSRC_ID_INVALID);
+	SFC_ASSERT(fw_rsrc->refcnt != 0);
+
+	if (fw_rsrc->refcnt == 1) {
+		rc = efx_mae_encap_header_free(sa->nic, &fw_rsrc->eh_id);
+		if (rc != 0)
+			return rc;
+
+		fw_rsrc->eh_id.id = EFX_MAE_RSRC_ID_INVALID;
+	}
+
+	--(fw_rsrc->refcnt);
+
+	return 0;
+}
+
 static struct sfc_mae_action_set *
 sfc_mae_action_set_attach(struct sfc_adapter *sa,
+			  const struct sfc_mae_encap_header *encap_header,
 			  const efx_mae_actions_t *spec)
 {
 	struct sfc_mae_action_set *action_set;
@@ -264,7 +435,8 @@ sfc_mae_action_set_attach(struct sfc_adapter *sa,
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
 	TAILQ_FOREACH(action_set, &mae->action_sets, entries) {
-		if (efx_mae_action_set_specs_equal(action_set->spec, spec)) {
+		if (action_set->encap_header == encap_header &&
+		    efx_mae_action_set_specs_equal(action_set->spec, spec)) {
 			++(action_set->refcnt);
 			return action_set;
 		}
@@ -276,6 +448,7 @@ sfc_mae_action_set_attach(struct sfc_adapter *sa,
 static int
 sfc_mae_action_set_add(struct sfc_adapter *sa,
 		       efx_mae_actions_t *spec,
+		       struct sfc_mae_encap_header *encap_header,
 		       struct sfc_mae_action_set **action_setp)
 {
 	struct sfc_mae_action_set *action_set;
@@ -289,6 +462,7 @@ sfc_mae_action_set_add(struct sfc_adapter *sa,
 
 	action_set->refcnt = 1;
 	action_set->spec = spec;
+	action_set->encap_header = encap_header;
 
 	action_set->fw_rsrc.aset_id.id = EFX_MAE_RSRC_ID_INVALID;
 
@@ -317,6 +491,7 @@ sfc_mae_action_set_del(struct sfc_adapter *sa,
 	SFC_ASSERT(action_set->fw_rsrc.refcnt == 0);
 
 	efx_mae_action_set_spec_fini(sa->nic, action_set->spec);
+	sfc_mae_encap_header_del(sa, action_set->encap_header);
 	TAILQ_REMOVE(&mae->action_sets, action_set, entries);
 	rte_free(action_set);
 }
@@ -325,6 +500,7 @@ static int
 sfc_mae_action_set_enable(struct sfc_adapter *sa,
 			  struct sfc_mae_action_set *action_set)
 {
+	struct sfc_mae_encap_header *encap_header = action_set->encap_header;
 	struct sfc_mae_fw_rsrc *fw_rsrc = &action_set->fw_rsrc;
 	int rc;
 
@@ -334,10 +510,18 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 		SFC_ASSERT(fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID);
 		SFC_ASSERT(action_set->spec != NULL);
 
+		rc = sfc_mae_encap_header_enable(sa, encap_header,
+						 action_set->spec);
+		if (rc != 0)
+			return rc;
+
 		rc = efx_mae_action_set_alloc(sa->nic, action_set->spec,
 					      &fw_rsrc->aset_id);
-		if (rc != 0)
+		if (rc != 0) {
+			(void)sfc_mae_encap_header_disable(sa, encap_header);
+
 			return rc;
+		}
 	}
 
 	++(fw_rsrc->refcnt);
@@ -362,6 +546,10 @@ sfc_mae_action_set_disable(struct sfc_adapter *sa,
 			return rc;
 
 		fw_rsrc->aset_id.id = EFX_MAE_RSRC_ID_INVALID;
+
+		rc = sfc_mae_encap_header_disable(sa, action_set->encap_header);
+		if (rc != 0)
+			return rc;
 	}
 
 	--(fw_rsrc->refcnt);
@@ -1936,6 +2124,307 @@ sfc_mae_rule_parse_action_of_set_vlan_pcp(
 	bundle->vlan_push_tci |= rte_cpu_to_be_16(vlan_tci_pcp);
 }
 
+struct sfc_mae_parsed_item {
+	const struct rte_flow_item	*item;
+	size_t				proto_header_ofst;
+	size_t				proto_header_size;
+};
+
+/*
+ * For each 16-bit word of the given header, override
+ * bits enforced by the corresponding 16-bit mask.
+ */
+static void
+sfc_mae_header_force_item_masks(uint8_t *header_buf,
+				const struct sfc_mae_parsed_item *parsed_items,
+				unsigned int nb_parsed_items)
+{
+	unsigned int item_idx;
+
+	for (item_idx = 0; item_idx < nb_parsed_items; ++item_idx) {
+		const struct sfc_mae_parsed_item *parsed_item;
+		const struct rte_flow_item *item;
+		size_t proto_header_size;
+		size_t ofst;
+
+		parsed_item = &parsed_items[item_idx];
+		proto_header_size = parsed_item->proto_header_size;
+		item = parsed_item->item;
+
+		for (ofst = 0; ofst < proto_header_size;
+		     ofst += sizeof(rte_be16_t)) {
+			rte_be16_t *wp = RTE_PTR_ADD(header_buf, ofst);
+			const rte_be16_t *w_maskp;
+			const rte_be16_t *w_specp;
+
+			w_maskp = RTE_PTR_ADD(item->mask, ofst);
+			w_specp = RTE_PTR_ADD(item->spec, ofst);
+
+			*wp &= ~(*w_maskp);
+			*wp |= (*w_specp & *w_maskp);
+		}
+
+		header_buf += proto_header_size;
+	}
+}
+
+#define SFC_IPV4_TTL_DEF	0x40
+#define SFC_IPV6_VTC_FLOW_DEF	0x60000000
+#define SFC_IPV6_HOP_LIMITS_DEF	0xff
+#define SFC_VXLAN_FLAGS_DEF	0x08000000
+
+static int
+sfc_mae_rule_parse_action_vxlan_encap(
+			    struct sfc_mae *mae,
+			    const struct rte_flow_action_vxlan_encap *conf,
+			    efx_mae_actions_t *spec,
+			    struct rte_flow_error *error)
+{
+	struct sfc_mae_bounce_eh *bounce_eh = &mae->bounce_eh;
+	struct rte_flow_item *pattern = conf->definition;
+	uint8_t *buf = bounce_eh->buf;
+
+	/* This array will keep track of non-VOID pattern items. */
+	struct sfc_mae_parsed_item parsed_items[1 /* Ethernet */ +
+						2 /* VLAN tags */ +
+						1 /* IPv4 or IPv6 */ +
+						1 /* UDP */ +
+						1 /* VXLAN */];
+	unsigned int nb_parsed_items = 0;
+
+	size_t eth_ethertype_ofst = offsetof(struct rte_ether_hdr, ether_type);
+	uint8_t dummy_buf[RTE_MAX(sizeof(struct rte_ipv4_hdr),
+				  sizeof(struct rte_ipv6_hdr))];
+	struct rte_ipv4_hdr *ipv4 = (void *)dummy_buf;
+	struct rte_ipv6_hdr *ipv6 = (void *)dummy_buf;
+	struct rte_vxlan_hdr *vxlan = NULL;
+	struct rte_udp_hdr *udp = NULL;
+	unsigned int nb_vlan_tags = 0;
+	size_t next_proto_ofst = 0;
+	size_t ethertype_ofst = 0;
+	uint64_t exp_items;
+
+	if (pattern == NULL) {
+		return rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
+				"The encap. header definition is NULL");
+	}
+
+	bounce_eh->type = EFX_TUNNEL_PROTOCOL_VXLAN;
+	bounce_eh->size = 0;
+
+	/*
+	 * Process pattern items and remember non-VOID ones.
+	 * Defer applying masks until after the complete header
+	 * has been built from the pattern items.
+	 */
+	exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_ETH);
+
+	for (; pattern->type != RTE_FLOW_ITEM_TYPE_END; ++pattern) {
+		struct sfc_mae_parsed_item *parsed_item;
+		const uint64_t exp_items_extra_vlan[] = {
+			RTE_BIT64(RTE_FLOW_ITEM_TYPE_VLAN), 0
+		};
+		size_t proto_header_size;
+		rte_be16_t *ethertypep;
+		uint8_t *next_protop;
+		uint8_t *buf_cur;
+
+		if (pattern->spec == NULL) {
+			return rte_flow_error_set(error, EINVAL,
+					RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
+					"NULL item spec in the encap. header");
+		}
+
+		if (pattern->mask == NULL) {
+			return rte_flow_error_set(error, EINVAL,
+					RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
+					"NULL item mask in the encap. header");
+		}
+
+		if (pattern->last != NULL) {
+			/* This is not a match pattern, so disallow range. */
+			return rte_flow_error_set(error, EINVAL,
+					RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
+					"Range item in the encap. header");
+		}
+
+		if (pattern->type == RTE_FLOW_ITEM_TYPE_VOID) {
+			/* Handle VOID separately, for clarity. */
+			continue;
+		}
+
+		if ((exp_items & RTE_BIT64(pattern->type)) == 0) {
+			return rte_flow_error_set(error, ENOTSUP,
+					RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
+					"Unexpected item in the encap. header");
+		}
+
+		parsed_item = &parsed_items[nb_parsed_items];
+		buf_cur = buf + bounce_eh->size;
+
+		switch (pattern->type) {
+		case RTE_FLOW_ITEM_TYPE_ETH:
+			SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_ETH,
+					       exp_items);
+			RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_eth,
+						  hdr) != 0);
+
+			proto_header_size = sizeof(struct rte_ether_hdr);
+
+			ethertype_ofst = eth_ethertype_ofst;
+
+			exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_VLAN) |
+				    RTE_BIT64(RTE_FLOW_ITEM_TYPE_IPV4) |
+				    RTE_BIT64(RTE_FLOW_ITEM_TYPE_IPV6);
+			break;
+		case RTE_FLOW_ITEM_TYPE_VLAN:
+			SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_VLAN,
+					       exp_items);
+			RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_vlan,
+						  hdr) != 0);
+
+			proto_header_size = sizeof(struct rte_vlan_hdr);
+
+			ethertypep = RTE_PTR_ADD(buf, eth_ethertype_ofst);
+			*ethertypep = RTE_BE16(RTE_ETHER_TYPE_QINQ);
+
+			ethertypep = RTE_PTR_ADD(buf, ethertype_ofst);
+			*ethertypep = RTE_BE16(RTE_ETHER_TYPE_VLAN);
+
+			ethertype_ofst =
+			    bounce_eh->size +
+			    offsetof(struct rte_vlan_hdr, eth_proto);
+
+			exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_IPV4) |
+				    RTE_BIT64(RTE_FLOW_ITEM_TYPE_IPV6);
+			exp_items |= exp_items_extra_vlan[nb_vlan_tags];
+
+			++nb_vlan_tags;
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV4:
+			SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_IPV4,
+					       exp_items);
+			RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_ipv4,
+						  hdr) != 0);
+
+			proto_header_size = sizeof(struct rte_ipv4_hdr);
+
+			ethertypep = RTE_PTR_ADD(buf, ethertype_ofst);
+			*ethertypep = RTE_BE16(RTE_ETHER_TYPE_IPV4);
+
+			next_proto_ofst =
+			    bounce_eh->size +
+			    offsetof(struct rte_ipv4_hdr, next_proto_id);
+
+			ipv4 = (struct rte_ipv4_hdr *)buf_cur;
+
+			exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_UDP);
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV6:
+			SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_IPV6,
+					       exp_items);
+			RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_ipv6,
+						  hdr) != 0);
+
+			proto_header_size = sizeof(struct rte_ipv6_hdr);
+
+			ethertypep = RTE_PTR_ADD(buf, ethertype_ofst);
+			*ethertypep = RTE_BE16(RTE_ETHER_TYPE_IPV6);
+
+			next_proto_ofst = bounce_eh->size +
+					  offsetof(struct rte_ipv6_hdr, proto);
+
+			ipv6 = (struct rte_ipv6_hdr *)buf_cur;
+
+			exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_UDP);
+			break;
+		case RTE_FLOW_ITEM_TYPE_UDP:
+			SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_UDP,
+					       exp_items);
+			RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_udp,
+						  hdr) != 0);
+
+			proto_header_size = sizeof(struct rte_udp_hdr);
+
+			next_protop = RTE_PTR_ADD(buf, next_proto_ofst);
+			*next_protop = IPPROTO_UDP;
+
+			udp = (struct rte_udp_hdr *)buf_cur;
+
+			exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_VXLAN);
+			break;
+		case RTE_FLOW_ITEM_TYPE_VXLAN:
+			SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_VXLAN,
+					       exp_items);
+			RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_vxlan,
+						  hdr) != 0);
+
+			proto_header_size = sizeof(struct rte_vxlan_hdr);
+
+			vxlan = (struct rte_vxlan_hdr *)buf_cur;
+
+			udp->dst_port = RTE_BE16(RTE_VXLAN_DEFAULT_PORT);
+			udp->dgram_len = RTE_BE16(sizeof(*udp) +
+						  sizeof(*vxlan));
+			udp->dgram_cksum = 0;
+
+			exp_items = 0;
+			break;
+		default:
+			return rte_flow_error_set(error, ENOTSUP,
+					RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
+					"Unknown item in the encap. header");
+		}
+
+		if (bounce_eh->size + proto_header_size > bounce_eh->buf_size) {
+			return rte_flow_error_set(error, E2BIG,
+					RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
+					"The encap. header is too big");
+		}
+
+		if ((proto_header_size & 1) != 0) {
+			return rte_flow_error_set(error, EINVAL,
+					RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
+					"Odd layer size in the encap. header");
+		}
+
+		rte_memcpy(buf_cur, pattern->spec, proto_header_size);
+		bounce_eh->size += proto_header_size;
+
+		parsed_item->item = pattern;
+		parsed_item->proto_header_size = proto_header_size;
+		++nb_parsed_items;
+	}
+
+	if (exp_items != 0) {
+		/* Parsing item VXLAN would have reset exp_items to 0. */
+		return rte_flow_error_set(error, ENOTSUP,
+					RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
+					"No item VXLAN in the encap. header");
+	}
+
+	/* One of the pointers (ipv4, ipv6) referes to a dummy area. */
+	ipv4->version_ihl = RTE_IPV4_VHL_DEF;
+	ipv4->time_to_live = SFC_IPV4_TTL_DEF;
+	ipv4->total_length = RTE_BE16(sizeof(*ipv4) + sizeof(*udp) +
+				      sizeof(*vxlan));
+	/* The HW cannot compute this checksum. */
+	ipv4->hdr_checksum = 0;
+	ipv4->hdr_checksum = rte_ipv4_cksum(ipv4);
+
+	ipv6->vtc_flow = RTE_BE32(SFC_IPV6_VTC_FLOW_DEF);
+	ipv6->hop_limits = SFC_IPV6_HOP_LIMITS_DEF;
+	ipv6->payload_len = udp->dgram_len;
+
+	vxlan->vx_flags = RTE_BE32(SFC_VXLAN_FLAGS_DEF);
+
+	/* Take care of the masks. */
+	sfc_mae_header_force_item_masks(buf, parsed_items, nb_parsed_items);
+
+	return (spec != NULL) ? efx_mae_action_set_populate_encap(spec) : 0;
+}
+
 static int
 sfc_mae_rule_parse_action_mark(const struct rte_flow_action_mark *conf,
 			       efx_mae_actions_t *spec)
@@ -2016,6 +2505,7 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 			  efx_mae_actions_t *spec,
 			  struct rte_flow_error *error)
 {
+	bool custom_error = B_FALSE;
 	int rc = 0;
 
 	switch (action->type) {
@@ -2039,6 +2529,14 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 				       bundle->actions_mask);
 		sfc_mae_rule_parse_action_of_set_vlan_pcp(action->conf, bundle);
 		break;
+	case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP,
+				       bundle->actions_mask);
+		rc = sfc_mae_rule_parse_action_vxlan_encap(&sa->mae,
+							   action->conf,
+							   spec, error);
+		custom_error = B_TRUE;
+		break;
 	case RTE_FLOW_ACTION_TYPE_FLAG:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_FLAG,
 				       bundle->actions_mask);
@@ -2080,24 +2578,49 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 				"Unsupported action");
 	}
 
-	if (rc != 0) {
+	if (rc == 0) {
+		bundle->actions_mask |= (1ULL << action->type);
+	} else if (!custom_error) {
 		rc = rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ACTION,
 				NULL, "Failed to request the action");
-	} else {
-		bundle->actions_mask |= (1ULL << action->type);
 	}
 
 	return rc;
 }
 
+static void
+sfc_mae_bounce_eh_invalidate(struct sfc_mae_bounce_eh *bounce_eh)
+{
+	bounce_eh->type = EFX_TUNNEL_PROTOCOL_NONE;
+}
+
+static int
+sfc_mae_process_encap_header(struct sfc_adapter *sa,
+			     const struct sfc_mae_bounce_eh *bounce_eh,
+			     struct sfc_mae_encap_header **encap_headerp)
+{
+	if (bounce_eh->type == EFX_TUNNEL_PROTOCOL_NONE) {
+		encap_headerp = NULL;
+		return 0;
+	}
+
+	*encap_headerp = sfc_mae_encap_header_attach(sa, bounce_eh);
+	if (*encap_headerp != NULL)
+		return 0;
+
+	return sfc_mae_encap_header_add(sa, bounce_eh, encap_headerp);
+}
+
 int
 sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			   const struct rte_flow_action actions[],
 			   struct sfc_flow_spec_mae *spec_mae,
 			   struct rte_flow_error *error)
 {
+	struct sfc_mae_encap_header *encap_header = NULL;
 	struct sfc_mae_actions_bundle bundle = {0};
 	const struct rte_flow_action *action;
+	struct sfc_mae *mae = &sa->mae;
 	efx_mae_actions_t *spec;
 	int rc;
 
@@ -2111,6 +2634,9 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_action_set_spec_init;
 
+	/* Cleanup after previous encap. header bounce buffer usage. */
+	sfc_mae_bounce_eh_invalidate(&mae->bounce_eh);
+
 	for (action = actions;
 	     action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
 		rc = sfc_mae_actions_bundle_sync(action, &bundle, spec, error);
@@ -2127,19 +2653,29 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_rule_parse_action;
 
-	spec_mae->action_set = sfc_mae_action_set_attach(sa, spec);
+	rc = sfc_mae_process_encap_header(sa, &mae->bounce_eh, &encap_header);
+	if (rc != 0)
+		goto fail_process_encap_header;
+
+	spec_mae->action_set = sfc_mae_action_set_attach(sa, encap_header,
+							 spec);
 	if (spec_mae->action_set != NULL) {
+		sfc_mae_encap_header_del(sa, encap_header);
 		efx_mae_action_set_spec_fini(sa->nic, spec);
 		return 0;
 	}
 
-	rc = sfc_mae_action_set_add(sa, spec, &spec_mae->action_set);
+	rc = sfc_mae_action_set_add(sa, spec, encap_header,
+				    &spec_mae->action_set);
 	if (rc != 0)
 		goto fail_action_set_add;
 
 	return 0;
 
 fail_action_set_add:
+	sfc_mae_encap_header_del(sa, encap_header);
+
+fail_process_encap_header:
 fail_rule_parse_action:
 	efx_mae_action_set_spec_fini(sa->nic, spec);
 
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 00987af61..c08fa545b 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -27,6 +27,7 @@ struct sfc_mae_fw_rsrc {
 	union {
 		efx_mae_aset_id_t	aset_id;
 		efx_mae_rule_id_t	rule_id;
+		efx_mae_eh_id_t		eh_id;
 	};
 };
 
@@ -41,11 +42,24 @@ struct sfc_mae_outer_rule {
 
 TAILQ_HEAD(sfc_mae_outer_rules, sfc_mae_outer_rule);
 
+/** Encap. header registry entry */
+struct sfc_mae_encap_header {
+	TAILQ_ENTRY(sfc_mae_encap_header)	entries;
+	unsigned int				refcnt;
+	uint8_t					*buf;
+	size_t					size;
+	efx_tunnel_protocol_t			type;
+	struct sfc_mae_fw_rsrc			fw_rsrc;
+};
+
+TAILQ_HEAD(sfc_mae_encap_headers, sfc_mae_encap_header);
+
 /** Action set registry entry */
 struct sfc_mae_action_set {
 	TAILQ_ENTRY(sfc_mae_action_set)	entries;
 	unsigned int			refcnt;
 	efx_mae_actions_t		*spec;
+	struct sfc_mae_encap_header	*encap_header;
 	struct sfc_mae_fw_rsrc		fw_rsrc;
 };
 
@@ -58,6 +72,17 @@ enum sfc_mae_status {
 	SFC_MAE_STATUS_SUPPORTED
 };
 
+/*
+ * Encap. header bounce buffer. It is used to store header data
+ * when parsing the header definition in the action VXLAN_ENCAP.
+ */
+struct sfc_mae_bounce_eh {
+	uint8_t				*buf;
+	size_t				buf_size;
+	size_t				size;
+	efx_tunnel_protocol_t		type;
+};
+
 struct sfc_mae {
 	/** Assigned switch domain identifier */
 	uint16_t			switch_domain_id;
@@ -73,8 +98,12 @@ struct sfc_mae {
 	uint32_t			encap_types_supported;
 	/** Outer rule registry */
 	struct sfc_mae_outer_rules	outer_rules;
+	/** Encap. header registry */
+	struct sfc_mae_encap_headers	encap_headers;
 	/** Action set registry */
 	struct sfc_mae_action_sets	action_sets;
+	/** Encap. header bounce buffer */
+	struct sfc_mae_bounce_eh	bounce_eh;
 };
 
 struct sfc_adapter;
-- 
2.20.1


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

* [dpdk-dev] [PATCH 09/10] common/sfc_efx/base: support adding action DECAP to a set
  2021-03-12  9:31 [dpdk-dev] [PATCH 01/10] ethdev: reuse header definition in flow pattern item ETH Ivan Malov
                   ` (6 preceding siblings ...)
  2021-03-12  9:31 ` [dpdk-dev] [PATCH 08/10] net/sfc: support action VXLAN ENCAP in MAE backend Ivan Malov
@ 2021-03-12  9:31 ` Ivan Malov
  2021-03-12  9:31 ` [dpdk-dev] [PATCH 10/10] net/sfc: support action VXLAN DECAP in transfer rules Ivan Malov
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 36+ messages in thread
From: Ivan Malov @ 2021-03-12  9:31 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Andy Moreton, Ray Kinsella, Neil Horman

The action has no arguments.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h      |  5 +++
 drivers/common/sfc_efx/base/efx_impl.h |  1 +
 drivers/common/sfc_efx/base/efx_mae.c  | 48 ++++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map     |  1 +
 4 files changed, 55 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 052946aa3..fe643de96 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4240,6 +4240,11 @@ efx_mae_action_set_spec_fini(
 	__in				efx_nic_t *enp,
 	__in				efx_mae_actions_t *spec);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_decap(
+	__in				efx_mae_actions_t *spec);
+
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_vlan_pop(
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 0adf43c26..7ee9ddec7 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -1707,6 +1707,7 @@ struct efx_mae_match_spec_s {
 
 typedef enum efx_mae_action_e {
 	/* These actions are strictly ordered. */
+	EFX_MAE_ACTION_DECAP,
 	EFX_MAE_ACTION_VLAN_POP,
 	EFX_MAE_ACTION_VLAN_PUSH,
 	EFX_MAE_ACTION_ENCAP,
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 896500de0..b384c009a 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -1013,6 +1013,37 @@ efx_mae_action_set_spec_fini(
 	EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), spec);
 }
 
+static	__checkReturn			efx_rc_t
+efx_mae_action_set_add_decap(
+	__in				efx_mae_actions_t *spec,
+	__in				size_t arg_size,
+	__in_bcount(arg_size)		const uint8_t *arg)
+{
+	efx_rc_t rc;
+
+	_NOTE(ARGUNUSED(spec))
+
+	if (arg_size != 0) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if (arg != NULL) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	/* This action does not have any arguments, so do nothing here. */
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
 static	__checkReturn			efx_rc_t
 efx_mae_action_set_add_vlan_pop(
 	__in				efx_mae_actions_t *spec,
@@ -1227,6 +1258,9 @@ typedef struct efx_mae_action_desc_s {
 } efx_mae_action_desc_t;
 
 static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
+	[EFX_MAE_ACTION_DECAP] = {
+		.emad_add = efx_mae_action_set_add_decap
+	},
 	[EFX_MAE_ACTION_VLAN_POP] = {
 		.emad_add = efx_mae_action_set_add_vlan_pop
 	},
@@ -1248,6 +1282,7 @@ static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
 };
 
 static const uint32_t efx_mae_action_ordered_map =
+	(1U << EFX_MAE_ACTION_DECAP) |
 	(1U << EFX_MAE_ACTION_VLAN_POP) |
 	(1U << EFX_MAE_ACTION_VLAN_PUSH) |
 	(1U << EFX_MAE_ACTION_ENCAP) |
@@ -1343,6 +1378,14 @@ efx_mae_action_set_spec_populate(
 	return (rc);
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_decap(
+	__in				efx_mae_actions_t *spec)
+{
+	return (efx_mae_action_set_spec_populate(spec,
+	    EFX_MAE_ACTION_DECAP, 0, NULL));
+}
+
 	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_vlan_pop(
 	__in				efx_mae_actions_t *spec)
@@ -2009,6 +2052,11 @@ efx_mae_action_set_alloc(
 	MCDI_IN_SET_DWORD(req,
 	    MAE_ACTION_SET_ALLOC_IN_COUNTER_ID, EFX_MAE_RSRC_ID_INVALID);
 
+	if ((spec->ema_actions & (1U << EFX_MAE_ACTION_DECAP)) != 0) {
+		MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
+		    MAE_ACTION_SET_ALLOC_IN_DECAP, 1);
+	}
+
 	MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
 	    MAE_ACTION_SET_ALLOC_IN_VLAN_POP, spec->ema_n_vlan_tags_to_pop);
 
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index f33a2a08e..b55e8567e 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -90,6 +90,7 @@ INTERNAL {
 	efx_mae_action_set_alloc;
 	efx_mae_action_set_fill_in_eh_id;
 	efx_mae_action_set_free;
+	efx_mae_action_set_populate_decap;
 	efx_mae_action_set_populate_deliver;
 	efx_mae_action_set_populate_drop;
 	efx_mae_action_set_populate_encap;
-- 
2.20.1


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

* [dpdk-dev] [PATCH 10/10] net/sfc: support action VXLAN DECAP in transfer rules
  2021-03-12  9:31 [dpdk-dev] [PATCH 01/10] ethdev: reuse header definition in flow pattern item ETH Ivan Malov
                   ` (7 preceding siblings ...)
  2021-03-12  9:31 ` [dpdk-dev] [PATCH 09/10] common/sfc_efx/base: support adding action DECAP to a set Ivan Malov
@ 2021-03-12  9:31 ` Ivan Malov
  2021-03-12 11:07 ` [dpdk-dev] [PATCH v2 01/10] ethdev: reuse header definition in flow pattern item ETH Ivan Malov
  2021-03-16 23:03 ` [dpdk-dev] [PATCH " Ori Kam
  10 siblings, 0 replies; 36+ messages in thread
From: Ivan Malov @ 2021-03-12  9:31 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Andy Moreton

If there is no VXLAN among pattern items, the action will be turned down.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 79a1bd91d..1d67a4be2 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -2501,6 +2501,7 @@ sfc_mae_rule_parse_action_port_id(struct sfc_adapter *sa,
 static int
 sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 			  const struct rte_flow_action *action,
+			  const struct sfc_mae_outer_rule *outer_rule,
 			  struct sfc_mae_actions_bundle *bundle,
 			  efx_mae_actions_t *spec,
 			  struct rte_flow_error *error)
@@ -2509,6 +2510,15 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 	int rc = 0;
 
 	switch (action->type) {
+	case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VXLAN_DECAP,
+				       bundle->actions_mask);
+		if (outer_rule == NULL ||
+		    outer_rule->encap_type != EFX_TUNNEL_PROTOCOL_VXLAN)
+			rc = EINVAL;
+		else
+			rc = efx_mae_action_set_populate_decap(spec);
+		break;
 	case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_POP_VLAN,
 				       bundle->actions_mask);
@@ -2643,8 +2653,8 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		if (rc != 0)
 			goto fail_rule_parse_action;
 
-		rc = sfc_mae_rule_parse_action(sa, action, &bundle, spec,
-					       error);
+		rc = sfc_mae_rule_parse_action(sa, action, spec_mae->outer_rule,
+					       &bundle, spec, error);
 		if (rc != 0)
 			goto fail_rule_parse_action;
 	}
-- 
2.20.1


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

* [dpdk-dev] [PATCH v2 01/10] ethdev: reuse header definition in flow pattern item ETH
  2021-03-12  9:31 [dpdk-dev] [PATCH 01/10] ethdev: reuse header definition in flow pattern item ETH Ivan Malov
                   ` (8 preceding siblings ...)
  2021-03-12  9:31 ` [dpdk-dev] [PATCH 10/10] net/sfc: support action VXLAN DECAP in transfer rules Ivan Malov
@ 2021-03-12 11:07 ` Ivan Malov
  2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 02/10] ethdev: reuse header definition in flow pattern item VLAN Ivan Malov
                     ` (11 more replies)
  2021-03-16 23:03 ` [dpdk-dev] [PATCH " Ori Kam
  10 siblings, 12 replies; 36+ messages in thread
From: Ivan Malov @ 2021-03-12 11:07 UTC (permalink / raw)
  To: dev
  Cc: Andrew Rybchenko, Andy Moreton, Ori Kam, Thomas Monjalon, Ferruh Yigit

One ought to reuse existing header structs in flow items.
This particular item contains non-header fields, so it's
important to keep the header fields in a separate struct.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 lib/librte_ethdev/rte_flow.h | 44 ++++++++++++++++++++++--------------
 1 file changed, 27 insertions(+), 17 deletions(-)

diff --git a/lib/librte_ethdev/rte_flow.h b/lib/librte_ethdev/rte_flow.h
index 669e677e9..96fd93ee1 100644
--- a/lib/librte_ethdev/rte_flow.h
+++ b/lib/librte_ethdev/rte_flow.h
@@ -728,22 +728,32 @@ static const struct rte_flow_item_raw rte_flow_item_raw_mask = {
  *
  * Matches an Ethernet header.
  *
- * The @p type field either stands for "EtherType" or "TPID" when followed
- * by so-called layer 2.5 pattern items such as RTE_FLOW_ITEM_TYPE_VLAN. In
- * the latter case, @p type refers to that of the outer header, with the
- * inner EtherType/TPID provided by the subsequent pattern item. This is the
- * same order as on the wire.
- * If the @p type field contains a TPID value, then only tagged packets with the
- * specified TPID will match the pattern.
- * The field @p has_vlan can be used to match any type of tagged packets,
- * instead of using the @p type field.
- * If the @p type and @p has_vlan fields are not specified, then both tagged
- * and untagged packets will match the pattern.
+ * Inside @p hdr field, the sub-field @p ether_type stands either for EtherType
+ * or TPID, depending on whether the item is followed by a VLAN item or not. If
+ * two VLAN items follow, the sub-field refers to the outer one, which, in turn,
+ * contains the inner TPID in the similar header field. The innermost VLAN item
+ * contains a layer-3 EtherType. All of that follows the order seen on the wire.
+ *
+ * If the field in question contains a TPID value, only tagged packets with the
+ * specified TPID will match the pattern. Alternatively, it's possible to match
+ * any type of tagged packets by means of the field @p has_vlan rather than use
+ * the EtherType/TPID field. Also, it's possible to leave the two fields unused.
+ * If this is the case, both tagged and untagged packets will match the pattern.
  */
+RTE_STD_C11
 struct rte_flow_item_eth {
-	struct rte_ether_addr dst; /**< Destination MAC. */
-	struct rte_ether_addr src; /**< Source MAC. */
-	rte_be16_t type; /**< EtherType or TPID. */
+	union {
+		struct {
+			/*
+			 * These fields are retained for compatibility.
+			 * Please switch to the new header field below.
+			 */
+			struct rte_ether_addr dst; /**< Destination MAC. */
+			struct rte_ether_addr src; /**< Source MAC. */
+			rte_be16_t type; /**< EtherType or TPID. */
+		};
+		struct rte_ether_hdr hdr;
+	};
 	uint32_t has_vlan:1; /**< Packet header contains at least one VLAN. */
 	uint32_t reserved:31; /**< Reserved, must be zero. */
 };
@@ -751,9 +761,9 @@ struct rte_flow_item_eth {
 /** Default mask for RTE_FLOW_ITEM_TYPE_ETH. */
 #ifndef __cplusplus
 static const struct rte_flow_item_eth rte_flow_item_eth_mask = {
-	.dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
-	.src.addr_bytes = "\xff\xff\xff\xff\xff\xff",
-	.type = RTE_BE16(0x0000),
+	.hdr.d_addr.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+	.hdr.s_addr.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+	.hdr.ether_type = RTE_BE16(0x0000),
 };
 #endif
 
-- 
2.20.1


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

* [dpdk-dev] [PATCH v2 02/10] ethdev: reuse header definition in flow pattern item VLAN
  2021-03-12 11:07 ` [dpdk-dev] [PATCH v2 01/10] ethdev: reuse header definition in flow pattern item ETH Ivan Malov
@ 2021-03-12 11:07   ` Ivan Malov
  2021-03-16 16:58     ` Ferruh Yigit
  2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 03/10] net: clarify endianness of 32-bit fields in VXLAN headers Ivan Malov
                     ` (10 subsequent siblings)
  11 siblings, 1 reply; 36+ messages in thread
From: Ivan Malov @ 2021-03-12 11:07 UTC (permalink / raw)
  To: dev
  Cc: Andrew Rybchenko, Andy Moreton, Ori Kam, Thomas Monjalon, Ferruh Yigit

One ought to reuse existing header structs in flow items.
This particular item contains non-header fields, so it's
important to keep the header fields in a separate struct.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 lib/librte_ethdev/rte_flow.h | 22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/lib/librte_ethdev/rte_flow.h b/lib/librte_ethdev/rte_flow.h
index 96fd93ee1..b9b349669 100644
--- a/lib/librte_ethdev/rte_flow.h
+++ b/lib/librte_ethdev/rte_flow.h
@@ -778,13 +778,23 @@ static const struct rte_flow_item_eth rte_flow_item_eth_mask = {
  * If a @p VLAN item is present in the pattern, then only tagged packets will
  * match the pattern.
  * The field @p has_more_vlan can be used to match any type of tagged packets,
- * instead of using the @p inner_type field.
- * If the @p inner_type and @p has_more_vlan fields are not specified,
+ * instead of using the @p eth_proto field of @p hdr.
+ * If the @p eth_proto of @p hdr and @p has_more_vlan fields are not specified,
  * then any tagged packets will match the pattern.
  */
+RTE_STD_C11
 struct rte_flow_item_vlan {
-	rte_be16_t tci; /**< Tag control information. */
-	rte_be16_t inner_type; /**< Inner EtherType or TPID. */
+	union {
+		struct {
+			/*
+			 * These fields are retained for compatibility.
+			 * Please switch to the new header field below.
+			 */
+			rte_be16_t tci; /**< Tag control information. */
+			rte_be16_t inner_type; /**< Inner EtherType or TPID. */
+		};
+		struct rte_vlan_hdr hdr;
+	};
 	uint32_t has_more_vlan:1;
 	/**< Packet header contains at least one more VLAN, after this VLAN. */
 	uint32_t reserved:31; /**< Reserved, must be zero. */
@@ -793,8 +803,8 @@ struct rte_flow_item_vlan {
 /** Default mask for RTE_FLOW_ITEM_TYPE_VLAN. */
 #ifndef __cplusplus
 static const struct rte_flow_item_vlan rte_flow_item_vlan_mask = {
-	.tci = RTE_BE16(0x0fff),
-	.inner_type = RTE_BE16(0x0000),
+	.hdr.vlan_tci = RTE_BE16(0x0fff),
+	.hdr.eth_proto = RTE_BE16(0x0000),
 };
 #endif
 
-- 
2.20.1


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

* [dpdk-dev] [PATCH v2 03/10] net: clarify endianness of 32-bit fields in VXLAN headers
  2021-03-12 11:07 ` [dpdk-dev] [PATCH v2 01/10] ethdev: reuse header definition in flow pattern item ETH Ivan Malov
  2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 02/10] ethdev: reuse header definition in flow pattern item VLAN Ivan Malov
@ 2021-03-12 11:07   ` Ivan Malov
  2021-03-16 17:34     ` Ferruh Yigit
  2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 04/10] ethdev: reuse header definition in flow pattern item VXLAN Ivan Malov
                     ` (9 subsequent siblings)
  11 siblings, 1 reply; 36+ messages in thread
From: Ivan Malov @ 2021-03-12 11:07 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Andy Moreton, Olivier Matz

These fields have network byte order. Highlight it using dedicated type.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 lib/librte_net/rte_vxlan.h | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/lib/librte_net/rte_vxlan.h b/lib/librte_net/rte_vxlan.h
index 2ad606165..929fa7a1d 100644
--- a/lib/librte_net/rte_vxlan.h
+++ b/lib/librte_net/rte_vxlan.h
@@ -13,6 +13,7 @@
 
 #include <stdint.h>
 
+#include <rte_byteorder.h>
 #include <rte_udp.h>
 
 
@@ -30,8 +31,8 @@ extern "C" {
  * Reserved fields (24 bits and 8 bits)
  */
 struct rte_vxlan_hdr {
-	uint32_t vx_flags; /**< flag (8) + Reserved (24). */
-	uint32_t vx_vni;   /**< VNI (24) + Reserved (8). */
+	rte_be32_t vx_flags; /**< flag (8) + Reserved (24). */
+	rte_be32_t vx_vni;   /**< VNI (24) + Reserved (8). */
 } __rte_packed;
 
 /** VXLAN tunnel header length. */
@@ -48,7 +49,7 @@ struct rte_vxlan_gpe_hdr {
 	uint8_t vx_flags;    /**< flag (8). */
 	uint8_t reserved[2]; /**< Reserved (16). */
 	uint8_t proto;       /**< next-protocol (8). */
-	uint32_t vx_vni;     /**< VNI (24) + Reserved (8). */
+	rte_be32_t vx_vni;   /**< VNI (24) + Reserved (8). */
 } __rte_packed;
 
 /** VXLAN-GPE tunnel header length. */
-- 
2.20.1


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

* [dpdk-dev] [PATCH v2 04/10] ethdev: reuse header definition in flow pattern item VXLAN
  2021-03-12 11:07 ` [dpdk-dev] [PATCH v2 01/10] ethdev: reuse header definition in flow pattern item ETH Ivan Malov
  2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 02/10] ethdev: reuse header definition in flow pattern item VLAN Ivan Malov
  2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 03/10] net: clarify endianness of 32-bit fields in VXLAN headers Ivan Malov
@ 2021-03-12 11:07   ` Ivan Malov
  2021-03-16 17:35     ` Ferruh Yigit
  2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 05/10] common/sfc_efx/base: support encap. header provisioning Ivan Malov
                     ` (8 subsequent siblings)
  11 siblings, 1 reply; 36+ messages in thread
From: Ivan Malov @ 2021-03-12 11:07 UTC (permalink / raw)
  To: dev
  Cc: Andrew Rybchenko, Andy Moreton, Ori Kam, Thomas Monjalon, Ferruh Yigit

One ought to reuse existing header structs in flow items.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 lib/librte_ethdev/rte_flow.h | 21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/lib/librte_ethdev/rte_flow.h b/lib/librte_ethdev/rte_flow.h
index b9b349669..6cc57136a 100644
--- a/lib/librte_ethdev/rte_flow.h
+++ b/lib/librte_ethdev/rte_flow.h
@@ -25,6 +25,7 @@
 #include <rte_sctp.h>
 #include <rte_tcp.h>
 #include <rte_udp.h>
+#include <rte_vxlan.h>
 #include <rte_byteorder.h>
 #include <rte_esp.h>
 #include <rte_higig.h>
@@ -955,17 +956,27 @@ static const struct rte_flow_item_sctp rte_flow_item_sctp_mask = {
  *
  * Matches a VXLAN header (RFC 7348).
  */
+RTE_STD_C11
 struct rte_flow_item_vxlan {
-	uint8_t flags; /**< Normally 0x08 (I flag). */
-	uint8_t rsvd0[3]; /**< Reserved, normally 0x000000. */
-	uint8_t vni[3]; /**< VXLAN identifier. */
-	uint8_t rsvd1; /**< Reserved, normally 0x00. */
+	union {
+		struct {
+			/*
+			 * These fields are retained for compatibility.
+			 * Please switch to the new header field below.
+			 */
+			uint8_t flags; /**< Normally 0x08 (I flag). */
+			uint8_t rsvd0[3]; /**< Reserved, normally 0x000000. */
+			uint8_t vni[3]; /**< VXLAN identifier. */
+			uint8_t rsvd1; /**< Reserved, normally 0x00. */
+		};
+		struct rte_vxlan_hdr hdr;
+	};
 };
 
 /** Default mask for RTE_FLOW_ITEM_TYPE_VXLAN. */
 #ifndef __cplusplus
 static const struct rte_flow_item_vxlan rte_flow_item_vxlan_mask = {
-	.vni = "\xff\xff\xff",
+	.hdr.vx_vni = RTE_BE32(__builtin_constant_p(0xffffff << 8)),
 };
 #endif
 
-- 
2.20.1


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

* [dpdk-dev] [PATCH v2 05/10] common/sfc_efx/base: support encap. header provisioning
  2021-03-12 11:07 ` [dpdk-dev] [PATCH v2 01/10] ethdev: reuse header definition in flow pattern item ETH Ivan Malov
                     ` (2 preceding siblings ...)
  2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 04/10] ethdev: reuse header definition in flow pattern item VXLAN Ivan Malov
@ 2021-03-12 11:07   ` Ivan Malov
  2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 06/10] common/sfc_efx/base: support adding action ENCAP to a set Ivan Malov
                     ` (7 subsequent siblings)
  11 siblings, 0 replies; 36+ messages in thread
From: Ivan Malov @ 2021-03-12 11:07 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Andy Moreton, Ray Kinsella, Neil Horman

Let the client allocate / free encap. headers.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h     |  21 ++++
 drivers/common/sfc_efx/base/efx_mae.c | 155 ++++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map    |   2 +
 3 files changed, 178 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index ccf9c7ab8..4a738e589 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4070,6 +4070,7 @@ typedef struct efx_mae_limits_s {
 	uint32_t			eml_max_n_action_prios;
 	uint32_t			eml_max_n_outer_prios;
 	uint32_t			eml_encap_types_supported;
+	uint32_t			eml_encap_header_size_limit;
 } efx_mae_limits_t;
 
 LIBEFX_API
@@ -4324,6 +4325,26 @@ efx_mae_match_spec_outer_rule_id_set(
 	__in				efx_mae_match_spec_t *spec,
 	__in				const efx_mae_rule_id_t *or_idp);
 
+/* Encap. header ID */
+typedef struct efx_mae_eh_id_s {
+	uint32_t id;
+} efx_mae_eh_id_t;
+
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_encap_header_alloc(
+	__in				efx_nic_t *enp,
+	__in				efx_tunnel_protocol_t encap_type,
+	__in_bcount(header_size)	uint8_t *header_data,
+	__in				size_t header_size,
+	__out				efx_mae_eh_id_t *eh_idp);
+
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_encap_header_free(
+	__in				efx_nic_t *enp,
+	__in				const efx_mae_eh_id_t *eh_idp);
+
 /* Action set ID */
 typedef struct efx_mae_aset_id_s {
 	uint32_t id;
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 338a0013f..798867963 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -353,6 +353,8 @@ efx_mae_get_limits(
 	emlp->eml_max_n_outer_prios = maep->em_max_n_outer_prios;
 	emlp->eml_max_n_action_prios = maep->em_max_n_action_prios;
 	emlp->eml_encap_types_supported = maep->em_encap_types_supported;
+	emlp->eml_encap_header_size_limit =
+	    MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_MAXNUM_MCDI2;
 
 	return (0);
 
@@ -1691,6 +1693,159 @@ efx_mae_match_spec_outer_rule_id_set(
 
 	return (0);
 
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	 __checkReturn			efx_rc_t
+efx_mae_encap_header_alloc(
+	__in				efx_nic_t *enp,
+	__in				efx_tunnel_protocol_t encap_type,
+	__in_bcount(header_size)	uint8_t *header_data,
+	__in				size_t header_size,
+	__out				efx_mae_eh_id_t *eh_idp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	efx_mcdi_req_t req;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_LENMAX_MCDI2,
+	    MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_LEN);
+	uint32_t encap_type_mcdi;
+	efx_mae_eh_id_t eh_id;
+	efx_rc_t rc;
+
+	EFX_STATIC_ASSERT(sizeof (eh_idp->id) ==
+	    MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_LEN);
+
+	EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID ==
+	    MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_NULL);
+
+	if (encp->enc_mae_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	switch (encap_type) {
+	case EFX_TUNNEL_PROTOCOL_NONE:
+		encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_NONE;
+		break;
+	case EFX_TUNNEL_PROTOCOL_VXLAN:
+		encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_VXLAN;
+		break;
+	case EFX_TUNNEL_PROTOCOL_GENEVE:
+		encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_GENEVE;
+		break;
+	case EFX_TUNNEL_PROTOCOL_NVGRE:
+		encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_NVGRE;
+		break;
+	default:
+		rc = ENOTSUP;
+		goto fail2;
+	}
+
+	if (header_size >
+	    MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_MAXNUM_MCDI2) {
+		rc = EINVAL;
+		goto fail3;
+	}
+
+	req.emr_cmd = MC_CMD_MAE_ENCAP_HEADER_ALLOC;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_LEN(header_size);
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_LEN;
+
+	MCDI_IN_SET_DWORD(req,
+	    MAE_ENCAP_HEADER_ALLOC_IN_ENCAP_TYPE, encap_type_mcdi);
+
+	memcpy(payload + MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_OFST,
+	    header_data, header_size);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail4;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_LEN) {
+		rc = EMSGSIZE;
+		goto fail5;
+	}
+
+	eh_id.id = MCDI_OUT_DWORD(req,
+	    MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID);
+
+	if (eh_id.id == EFX_MAE_RSRC_ID_INVALID) {
+		rc = ENOENT;
+		goto fail6;
+	}
+
+	eh_idp->id = eh_id.id;
+
+	return (0);
+
+fail6:
+	EFSYS_PROBE(fail6);
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_encap_header_free(
+	__in				efx_nic_t *enp,
+	__in				const efx_mae_eh_id_t *eh_idp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	efx_mcdi_req_t req;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_MAE_ENCAP_HEADER_FREE_IN_LEN(1),
+	    MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_LEN(1));
+	efx_rc_t rc;
+
+	if (encp->enc_mae_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	req.emr_cmd = MC_CMD_MAE_ENCAP_HEADER_FREE;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_MAE_ENCAP_HEADER_FREE_IN_LEN(1);
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_LEN(1);
+
+	MCDI_IN_SET_DWORD(req, MAE_ENCAP_HEADER_FREE_IN_EH_ID, eh_idp->id);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail2;
+	}
+
+	if (MCDI_OUT_DWORD(req, MAE_ENCAP_HEADER_FREE_OUT_FREED_EH_ID) !=
+	    eh_idp->id) {
+		/* Firmware failed to remove the encap. header. */
+		rc = EAGAIN;
+		goto fail3;
+	}
+
+	return (0);
+
 fail3:
 	EFSYS_PROBE(fail3);
 fail2:
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index 403feeaf1..168899d51 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -98,6 +98,8 @@ INTERNAL {
 	efx_mae_action_set_spec_fini;
 	efx_mae_action_set_spec_init;
 	efx_mae_action_set_specs_equal;
+	efx_mae_encap_header_alloc;
+	efx_mae_encap_header_free;
 	efx_mae_fini;
 	efx_mae_get_limits;
 	efx_mae_init;
-- 
2.20.1


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

* [dpdk-dev] [PATCH v2 06/10] common/sfc_efx/base: support adding action ENCAP to a set
  2021-03-12 11:07 ` [dpdk-dev] [PATCH v2 01/10] ethdev: reuse header definition in flow pattern item ETH Ivan Malov
                     ` (3 preceding siblings ...)
  2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 05/10] common/sfc_efx/base: support encap. header provisioning Ivan Malov
@ 2021-03-12 11:07   ` Ivan Malov
  2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 07/10] net/sfc: change MAE rule actions parse API Ivan Malov
                     ` (6 subsequent siblings)
  11 siblings, 0 replies; 36+ messages in thread
From: Ivan Malov @ 2021-03-12 11:07 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Andy Moreton, Ray Kinsella, Neil Horman

For convenience, there are two separate APIs provided, one for
adding the action and one for setting the encap. header ID.
This design allows the client driver to first build the action
set specification (which validates the order of the actions)
and, if everything is correct, proceed with allocation of the
resource utilised by the action set (encap. header). This
facilitates clarity of the client code and its efficiency.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h      |  16 ++++
 drivers/common/sfc_efx/base/efx_impl.h |  12 +++
 drivers/common/sfc_efx/base/efx_mae.c  | 126 ++++++++++++++++++++++++-
 drivers/common/sfc_efx/version.map     |   2 +
 4 files changed, 153 insertions(+), 3 deletions(-)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 4a738e589..052946aa3 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4252,6 +4252,15 @@ efx_mae_action_set_populate_vlan_push(
 	__in				uint16_t tpid_be,
 	__in				uint16_t tci_be);
 
+/*
+ * Use efx_mae_action_set_fill_in_eh_id() to set ID of the allocated
+ * encap. header in the specification prior to action set allocation.
+ */
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_encap(
+	__in				efx_mae_actions_t *spec);
+
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_flag(
@@ -4345,6 +4354,13 @@ efx_mae_encap_header_free(
 	__in				efx_nic_t *enp,
 	__in				const efx_mae_eh_id_t *eh_idp);
 
+/* See description before efx_mae_action_set_populate_encap(). */
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_set_fill_in_eh_id(
+	__in				efx_mae_actions_t *spec,
+	__in				const efx_mae_eh_id_t *eh_idp);
+
 /* Action set ID */
 typedef struct efx_mae_aset_id_s {
 	uint32_t id;
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 1005dd0aa..0adf43c26 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -1709,6 +1709,7 @@ typedef enum efx_mae_action_e {
 	/* These actions are strictly ordered. */
 	EFX_MAE_ACTION_VLAN_POP,
 	EFX_MAE_ACTION_VLAN_PUSH,
+	EFX_MAE_ACTION_ENCAP,
 
 	/*
 	 * These actions are not strictly ordered and can
@@ -1736,6 +1737,10 @@ typedef struct efx_mae_action_vlan_push_s {
 	uint16_t			emavp_tci_be;
 } efx_mae_action_vlan_push_t;
 
+typedef struct efx_mae_actions_rsrc_s {
+	efx_mae_eh_id_t			emar_eh_id;
+} efx_mae_actions_rsrc_t;
+
 struct efx_mae_actions_s {
 	/* Bitmap of actions in spec, indexed by action type */
 	uint32_t			ema_actions;
@@ -1746,6 +1751,13 @@ struct efx_mae_actions_s {
 	    EFX_MAE_VLAN_PUSH_MAX_NTAGS];
 	uint32_t			ema_mark_value;
 	efx_mport_sel_t			ema_deliver_mport;
+
+	/*
+	 * Always keep this at the end of the struct since
+	 * efx_mae_action_set_specs_equal() relies on that
+	 * to make sure that resource IDs are not compared.
+	 */
+	efx_mae_actions_rsrc_t		ema_rsrc;
 };
 
 #endif /* EFSYS_OPT_MAE */
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 798867963..896500de0 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -994,6 +994,8 @@ efx_mae_action_set_spec_init(
 		goto fail1;
 	}
 
+	spec->ema_rsrc.emar_eh_id.id = EFX_MAE_RSRC_ID_INVALID;
+
 	*specp = spec;
 
 	return (0);
@@ -1085,6 +1087,50 @@ efx_mae_action_set_add_vlan_push(
 	return (rc);
 }
 
+static	__checkReturn			efx_rc_t
+efx_mae_action_set_add_encap(
+	__in				efx_mae_actions_t *spec,
+	__in				size_t arg_size,
+	__in_bcount(arg_size)		const uint8_t *arg)
+{
+	efx_rc_t rc;
+
+	/*
+	 * Adding this specific action to an action set spec and setting encap.
+	 * header ID in the spec are two individual steps. This design allows
+	 * the client driver to avoid encap. header allocation when it simply
+	 * needs to check the order of actions submitted by user ("validate"),
+	 * without actually allocating an action set and inserting a rule.
+	 *
+	 * For now, mark encap. header ID as invalid; the caller will invoke
+	 * efx_mae_action_set_fill_in_eh_id() to override the field prior
+	 * to action set allocation; otherwise, the allocation will fail.
+	 */
+	spec->ema_rsrc.emar_eh_id.id = EFX_MAE_RSRC_ID_INVALID;
+
+	/*
+	 * As explained above, there are no arguments to handle here.
+	 * efx_mae_action_set_fill_in_eh_id() will take care of them.
+	 */
+	if (arg_size != 0) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if (arg != NULL) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
 static	__checkReturn			efx_rc_t
 efx_mae_action_set_add_flag(
 	__in				efx_mae_actions_t *spec,
@@ -1187,6 +1233,9 @@ static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
 	[EFX_MAE_ACTION_VLAN_PUSH] = {
 		.emad_add = efx_mae_action_set_add_vlan_push
 	},
+	[EFX_MAE_ACTION_ENCAP] = {
+		.emad_add = efx_mae_action_set_add_encap
+	},
 	[EFX_MAE_ACTION_FLAG] = {
 		.emad_add = efx_mae_action_set_add_flag
 	},
@@ -1201,6 +1250,7 @@ static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
 static const uint32_t efx_mae_action_ordered_map =
 	(1U << EFX_MAE_ACTION_VLAN_POP) |
 	(1U << EFX_MAE_ACTION_VLAN_PUSH) |
+	(1U << EFX_MAE_ACTION_ENCAP) |
 	(1U << EFX_MAE_ACTION_FLAG) |
 	(1U << EFX_MAE_ACTION_MARK) |
 	(1U << EFX_MAE_ACTION_DELIVER);
@@ -1317,6 +1367,20 @@ efx_mae_action_set_populate_vlan_push(
 	    EFX_MAE_ACTION_VLAN_PUSH, sizeof (action), arg));
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_encap(
+	__in				efx_mae_actions_t *spec)
+{
+	/*
+	 * There is no argument to pass encap. header ID, thus, one does not
+	 * need to allocate an encap. header while parsing application input.
+	 * This is useful since building an action set may be done simply to
+	 * validate a rule, whilst resource allocation usually consumes time.
+	 */
+	return (efx_mae_action_set_spec_populate(spec,
+	    EFX_MAE_ACTION_ENCAP, 0, NULL));
+}
+
 	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_flag(
 	__in				efx_mae_actions_t *spec)
@@ -1389,7 +1453,22 @@ efx_mae_action_set_specs_equal(
 	__in				const efx_mae_actions_t *left,
 	__in				const efx_mae_actions_t *right)
 {
-	return ((memcmp(left, right, sizeof (*left)) == 0) ? B_TRUE : B_FALSE);
+	size_t cmp_size = EFX_FIELD_OFFSET(efx_mae_actions_t, ema_rsrc);
+
+	/*
+	 * An action set specification consists of two parts. The first part
+	 * indicates what actions are included in the action set, as well as
+	 * extra quantitative values (in example, the number of VLAN tags to
+	 * push). The second part comprises resource IDs used by the actions.
+	 *
+	 * A resource, in example, a counter, is allocated from the hardware
+	 * by the client, and it's the client who is responsible for keeping
+	 * track of allocated resources and comparing resource IDs if needed.
+	 *
+	 * In this API, don't compare resource IDs in the two specifications.
+	 */
+
+	return ((memcmp(left, right, cmp_size) == 0) ? B_TRUE : B_FALSE);
 }
 
 	__checkReturn			efx_rc_t
@@ -1846,6 +1925,46 @@ efx_mae_encap_header_free(
 
 	return (0);
 
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_action_set_fill_in_eh_id(
+	__in				efx_mae_actions_t *spec,
+	__in				const efx_mae_eh_id_t *eh_idp)
+{
+	efx_rc_t rc;
+
+	if ((spec->ema_actions & (1U << EFX_MAE_ACTION_ENCAP)) == 0) {
+		/*
+		 * The caller has not intended to have action ENCAP originally,
+		 * hence, this attempt to indicate encap. header ID is invalid.
+		 */
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if (spec->ema_rsrc.emar_eh_id.id != EFX_MAE_RSRC_ID_INVALID) {
+		/* The caller attempts to indicate encap. header ID twice. */
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	if (eh_idp->id == EFX_MAE_RSRC_ID_INVALID) {
+		rc = EINVAL;
+		goto fail3;
+	}
+
+	spec->ema_rsrc.emar_eh_id.id = eh_idp->id;
+
+	return (0);
+
 fail3:
 	EFSYS_PROBE(fail3);
 fail2:
@@ -1889,8 +2008,6 @@ efx_mae_action_set_alloc(
 	    MAE_ACTION_SET_ALLOC_IN_COUNTER_LIST_ID, EFX_MAE_RSRC_ID_INVALID);
 	MCDI_IN_SET_DWORD(req,
 	    MAE_ACTION_SET_ALLOC_IN_COUNTER_ID, EFX_MAE_RSRC_ID_INVALID);
-	MCDI_IN_SET_DWORD(req,
-	    MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID, EFX_MAE_RSRC_ID_INVALID);
 
 	MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
 	    MAE_ACTION_SET_ALLOC_IN_VLAN_POP, spec->ema_n_vlan_tags_to_pop);
@@ -1920,6 +2037,9 @@ efx_mae_action_set_alloc(
 		    spec->ema_vlan_push_descs[outer_tag_idx].emavp_tci_be);
 	}
 
+	MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID,
+	    spec->ema_rsrc.emar_eh_id.id);
+
 	if ((spec->ema_actions & (1U << EFX_MAE_ACTION_FLAG)) != 0) {
 		MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
 		    MAE_ACTION_SET_ALLOC_IN_FLAG, 1);
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index 168899d51..f33a2a08e 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -88,9 +88,11 @@ INTERNAL {
 	efx_mae_action_rule_insert;
 	efx_mae_action_rule_remove;
 	efx_mae_action_set_alloc;
+	efx_mae_action_set_fill_in_eh_id;
 	efx_mae_action_set_free;
 	efx_mae_action_set_populate_deliver;
 	efx_mae_action_set_populate_drop;
+	efx_mae_action_set_populate_encap;
 	efx_mae_action_set_populate_flag;
 	efx_mae_action_set_populate_mark;
 	efx_mae_action_set_populate_vlan_pop;
-- 
2.20.1


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

* [dpdk-dev] [PATCH v2 07/10] net/sfc: change MAE rule actions parse API
  2021-03-12 11:07 ` [dpdk-dev] [PATCH v2 01/10] ethdev: reuse header definition in flow pattern item ETH Ivan Malov
                     ` (4 preceding siblings ...)
  2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 06/10] common/sfc_efx/base: support adding action ENCAP to a set Ivan Malov
@ 2021-03-12 11:07   ` Ivan Malov
  2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 08/10] net/sfc: support action VXLAN ENCAP in MAE backend Ivan Malov
                     ` (5 subsequent siblings)
  11 siblings, 0 replies; 36+ messages in thread
From: Ivan Malov @ 2021-03-12 11:07 UTC (permalink / raw)
  To: dev; +Cc: Igor Romanov, Andrew Rybchenko, Andy Moreton

From: Igor Romanov <igor.romanov@oktetlabs.ru>

Current API signature makes it hard to add other entities that
belong to a flow specification. Pass the flow specification
so that additional members can be accessed through the spec.

Signed-off-by: Igor Romanov <igor.romanov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
Reviewed-by: Ivan Malov <ivan.malov@oktetlabs.ru>
---
 drivers/net/sfc/sfc_flow.c | 3 +--
 drivers/net/sfc/sfc_mae.c  | 8 ++++----
 drivers/net/sfc/sfc_mae.h  | 2 +-
 3 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index ab1d2cc59..2c78473b5 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -2440,8 +2440,7 @@ sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
 	if (rc != 0)
 		return rc;
 
-	rc = sfc_mae_rule_parse_actions(sa, actions, &spec_mae->action_set,
-					error);
+	rc = sfc_mae_rule_parse_actions(sa, actions, spec_mae, error);
 	if (rc != 0)
 		return rc;
 
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 15c5c3975..50efd47ad 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -2093,7 +2093,7 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 int
 sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			   const struct rte_flow_action actions[],
-			   struct sfc_mae_action_set **action_setp,
+			   struct sfc_flow_spec_mae *spec_mae,
 			   struct rte_flow_error *error)
 {
 	struct sfc_mae_actions_bundle bundle = {0};
@@ -2127,13 +2127,13 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_rule_parse_action;
 
-	*action_setp = sfc_mae_action_set_attach(sa, spec);
-	if (*action_setp != NULL) {
+	spec_mae->action_set = sfc_mae_action_set_attach(sa, spec);
+	if (spec_mae->action_set != NULL) {
 		efx_mae_action_set_spec_fini(sa->nic, spec);
 		return 0;
 	}
 
-	rc = sfc_mae_action_set_add(sa, spec, action_setp);
+	rc = sfc_mae_action_set_add(sa, spec, &spec_mae->action_set);
 	if (rc != 0)
 		goto fail_action_set_add;
 
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index bf432638c..00987af61 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -197,7 +197,7 @@ int sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 			       struct rte_flow_error *error);
 int sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			       const struct rte_flow_action actions[],
-			       struct sfc_mae_action_set **action_setp,
+			       struct sfc_flow_spec_mae *spec_mae,
 			       struct rte_flow_error *error);
 sfc_flow_verify_cb_t sfc_mae_flow_verify;
 sfc_flow_insert_cb_t sfc_mae_flow_insert;
-- 
2.20.1


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

* [dpdk-dev] [PATCH v2 08/10] net/sfc: support action VXLAN ENCAP in MAE backend
  2021-03-12 11:07 ` [dpdk-dev] [PATCH v2 01/10] ethdev: reuse header definition in flow pattern item ETH Ivan Malov
                     ` (5 preceding siblings ...)
  2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 07/10] net/sfc: change MAE rule actions parse API Ivan Malov
@ 2021-03-12 11:07   ` Ivan Malov
  2021-03-16 17:10     ` Ivan Malov
  2021-03-31 23:21     ` Thomas Monjalon
  2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 09/10] common/sfc_efx/base: support adding action DECAP to a set Ivan Malov
                     ` (4 subsequent siblings)
  11 siblings, 2 replies; 36+ messages in thread
From: Ivan Malov @ 2021-03-12 11:07 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Andy Moreton

Provide necessary facilities for handling this action.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c | 550 +++++++++++++++++++++++++++++++++++++-
 drivers/net/sfc/sfc_mae.h |  29 ++
 2 files changed, 572 insertions(+), 7 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 50efd47ad..79a1bd91d 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -9,7 +9,9 @@
 
 #include <stdbool.h>
 
+#include <rte_bitops.h>
 #include <rte_common.h>
+#include <rte_vxlan.h>
 
 #include "efx.h"
 
@@ -35,6 +37,7 @@ sfc_mae_attach(struct sfc_adapter *sa)
 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
 	efx_mport_sel_t entity_mport;
 	struct sfc_mae *mae = &sa->mae;
+	struct sfc_mae_bounce_eh *bounce_eh = &mae->bounce_eh;
 	efx_mae_limits_t limits;
 	int rc;
 
@@ -80,17 +83,26 @@ sfc_mae_attach(struct sfc_adapter *sa)
 	if (rc != 0)
 		goto fail_mae_assign_switch_port;
 
+	sfc_log_init(sa, "allocate encap. header bounce buffer");
+	bounce_eh->buf_size = limits.eml_encap_header_size_limit;
+	bounce_eh->buf = rte_malloc("sfc_mae_bounce_eh",
+				    bounce_eh->buf_size, 0);
+	if (bounce_eh->buf == NULL)
+		goto fail_mae_alloc_bounce_eh;
+
 	mae->status = SFC_MAE_STATUS_SUPPORTED;
 	mae->nb_outer_rule_prios_max = limits.eml_max_n_outer_prios;
 	mae->nb_action_rule_prios_max = limits.eml_max_n_action_prios;
 	mae->encap_types_supported = limits.eml_encap_types_supported;
 	TAILQ_INIT(&mae->outer_rules);
+	TAILQ_INIT(&mae->encap_headers);
 	TAILQ_INIT(&mae->action_sets);
 
 	sfc_log_init(sa, "done");
 
 	return 0;
 
+fail_mae_alloc_bounce_eh:
 fail_mae_assign_switch_port:
 fail_mae_assign_switch_domain:
 fail_mae_assign_entity_mport:
@@ -117,6 +129,8 @@ sfc_mae_detach(struct sfc_adapter *sa)
 	if (status_prev != SFC_MAE_STATUS_SUPPORTED)
 		return;
 
+	rte_free(mae->bounce_eh.buf);
+
 	efx_mae_fini(sa->nic);
 
 	sfc_log_init(sa, "done");
@@ -254,8 +268,165 @@ sfc_mae_outer_rule_disable(struct sfc_adapter *sa,
 	return 0;
 }
 
+static struct sfc_mae_encap_header *
+sfc_mae_encap_header_attach(struct sfc_adapter *sa,
+			    const struct sfc_mae_bounce_eh *bounce_eh)
+{
+	struct sfc_mae_encap_header *encap_header;
+	struct sfc_mae *mae = &sa->mae;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	TAILQ_FOREACH(encap_header, &mae->encap_headers, entries) {
+		if (encap_header->size == bounce_eh->size &&
+		    memcmp(encap_header->buf, bounce_eh->buf,
+			   bounce_eh->size) == 0) {
+			++(encap_header->refcnt);
+			return encap_header;
+		}
+	}
+
+	return NULL;
+}
+
+static int
+sfc_mae_encap_header_add(struct sfc_adapter *sa,
+			 const struct sfc_mae_bounce_eh *bounce_eh,
+			 struct sfc_mae_encap_header **encap_headerp)
+{
+	struct sfc_mae_encap_header *encap_header;
+	struct sfc_mae *mae = &sa->mae;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	encap_header = rte_zmalloc("sfc_mae_encap_header",
+				   sizeof(*encap_header), 0);
+	if (encap_header == NULL)
+		return ENOMEM;
+
+	encap_header->size = bounce_eh->size;
+
+	encap_header->buf = rte_malloc("sfc_mae_encap_header_buf",
+				       encap_header->size, 0);
+	if (encap_header->buf == NULL) {
+		rte_free(encap_header);
+		return ENOMEM;
+	}
+
+	rte_memcpy(encap_header->buf, bounce_eh->buf, bounce_eh->size);
+
+	encap_header->refcnt = 1;
+	encap_header->type = bounce_eh->type;
+	encap_header->fw_rsrc.eh_id.id = EFX_MAE_RSRC_ID_INVALID;
+
+	TAILQ_INSERT_TAIL(&mae->encap_headers, encap_header, entries);
+
+	*encap_headerp = encap_header;
+
+	return 0;
+}
+
+static void
+sfc_mae_encap_header_del(struct sfc_adapter *sa,
+		       struct sfc_mae_encap_header *encap_header)
+{
+	struct sfc_mae *mae = &sa->mae;
+
+	if (encap_header == NULL)
+		return;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(encap_header->refcnt != 0);
+
+	--(encap_header->refcnt);
+
+	if (encap_header->refcnt != 0)
+		return;
+
+	SFC_ASSERT(encap_header->fw_rsrc.eh_id.id == EFX_MAE_RSRC_ID_INVALID);
+	SFC_ASSERT(encap_header->fw_rsrc.refcnt == 0);
+
+	TAILQ_REMOVE(&mae->encap_headers, encap_header, entries);
+	rte_free(encap_header->buf);
+	rte_free(encap_header);
+}
+
+static int
+sfc_mae_encap_header_enable(struct sfc_adapter *sa,
+			    struct sfc_mae_encap_header *encap_header,
+			    efx_mae_actions_t *action_set_spec)
+{
+	struct sfc_mae_fw_rsrc *fw_rsrc;
+	int rc;
+
+	if (encap_header == NULL)
+		return 0;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	fw_rsrc = &encap_header->fw_rsrc;
+
+	if (fw_rsrc->refcnt == 0) {
+		SFC_ASSERT(fw_rsrc->eh_id.id == EFX_MAE_RSRC_ID_INVALID);
+		SFC_ASSERT(encap_header->buf != NULL);
+		SFC_ASSERT(encap_header->size != 0);
+
+		rc = efx_mae_encap_header_alloc(sa->nic, encap_header->type,
+						encap_header->buf,
+						encap_header->size,
+						&fw_rsrc->eh_id);
+		if (rc != 0)
+			return rc;
+	}
+
+	rc = efx_mae_action_set_fill_in_eh_id(action_set_spec,
+					      &fw_rsrc->eh_id);
+	if (rc != 0) {
+		if (fw_rsrc->refcnt == 0) {
+			(void)efx_mae_encap_header_free(sa->nic,
+							&fw_rsrc->eh_id);
+		}
+		return rc;
+	}
+
+	++(fw_rsrc->refcnt);
+
+	return 0;
+}
+
+static int
+sfc_mae_encap_header_disable(struct sfc_adapter *sa,
+			     struct sfc_mae_encap_header *encap_header)
+{
+	struct sfc_mae_fw_rsrc *fw_rsrc;
+	int rc;
+
+	if (encap_header == NULL)
+		return 0;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	fw_rsrc = &encap_header->fw_rsrc;
+
+	SFC_ASSERT(fw_rsrc->eh_id.id != EFX_MAE_RSRC_ID_INVALID);
+	SFC_ASSERT(fw_rsrc->refcnt != 0);
+
+	if (fw_rsrc->refcnt == 1) {
+		rc = efx_mae_encap_header_free(sa->nic, &fw_rsrc->eh_id);
+		if (rc != 0)
+			return rc;
+
+		fw_rsrc->eh_id.id = EFX_MAE_RSRC_ID_INVALID;
+	}
+
+	--(fw_rsrc->refcnt);
+
+	return 0;
+}
+
 static struct sfc_mae_action_set *
 sfc_mae_action_set_attach(struct sfc_adapter *sa,
+			  const struct sfc_mae_encap_header *encap_header,
 			  const efx_mae_actions_t *spec)
 {
 	struct sfc_mae_action_set *action_set;
@@ -264,7 +435,8 @@ sfc_mae_action_set_attach(struct sfc_adapter *sa,
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
 	TAILQ_FOREACH(action_set, &mae->action_sets, entries) {
-		if (efx_mae_action_set_specs_equal(action_set->spec, spec)) {
+		if (action_set->encap_header == encap_header &&
+		    efx_mae_action_set_specs_equal(action_set->spec, spec)) {
 			++(action_set->refcnt);
 			return action_set;
 		}
@@ -276,6 +448,7 @@ sfc_mae_action_set_attach(struct sfc_adapter *sa,
 static int
 sfc_mae_action_set_add(struct sfc_adapter *sa,
 		       efx_mae_actions_t *spec,
+		       struct sfc_mae_encap_header *encap_header,
 		       struct sfc_mae_action_set **action_setp)
 {
 	struct sfc_mae_action_set *action_set;
@@ -289,6 +462,7 @@ sfc_mae_action_set_add(struct sfc_adapter *sa,
 
 	action_set->refcnt = 1;
 	action_set->spec = spec;
+	action_set->encap_header = encap_header;
 
 	action_set->fw_rsrc.aset_id.id = EFX_MAE_RSRC_ID_INVALID;
 
@@ -317,6 +491,7 @@ sfc_mae_action_set_del(struct sfc_adapter *sa,
 	SFC_ASSERT(action_set->fw_rsrc.refcnt == 0);
 
 	efx_mae_action_set_spec_fini(sa->nic, action_set->spec);
+	sfc_mae_encap_header_del(sa, action_set->encap_header);
 	TAILQ_REMOVE(&mae->action_sets, action_set, entries);
 	rte_free(action_set);
 }
@@ -325,6 +500,7 @@ static int
 sfc_mae_action_set_enable(struct sfc_adapter *sa,
 			  struct sfc_mae_action_set *action_set)
 {
+	struct sfc_mae_encap_header *encap_header = action_set->encap_header;
 	struct sfc_mae_fw_rsrc *fw_rsrc = &action_set->fw_rsrc;
 	int rc;
 
@@ -334,10 +510,18 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 		SFC_ASSERT(fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID);
 		SFC_ASSERT(action_set->spec != NULL);
 
+		rc = sfc_mae_encap_header_enable(sa, encap_header,
+						 action_set->spec);
+		if (rc != 0)
+			return rc;
+
 		rc = efx_mae_action_set_alloc(sa->nic, action_set->spec,
 					      &fw_rsrc->aset_id);
-		if (rc != 0)
+		if (rc != 0) {
+			(void)sfc_mae_encap_header_disable(sa, encap_header);
+
 			return rc;
+		}
 	}
 
 	++(fw_rsrc->refcnt);
@@ -362,6 +546,10 @@ sfc_mae_action_set_disable(struct sfc_adapter *sa,
 			return rc;
 
 		fw_rsrc->aset_id.id = EFX_MAE_RSRC_ID_INVALID;
+
+		rc = sfc_mae_encap_header_disable(sa, action_set->encap_header);
+		if (rc != 0)
+			return rc;
 	}
 
 	--(fw_rsrc->refcnt);
@@ -1936,6 +2124,307 @@ sfc_mae_rule_parse_action_of_set_vlan_pcp(
 	bundle->vlan_push_tci |= rte_cpu_to_be_16(vlan_tci_pcp);
 }
 
+struct sfc_mae_parsed_item {
+	const struct rte_flow_item	*item;
+	size_t				proto_header_ofst;
+	size_t				proto_header_size;
+};
+
+/*
+ * For each 16-bit word of the given header, override
+ * bits enforced by the corresponding 16-bit mask.
+ */
+static void
+sfc_mae_header_force_item_masks(uint8_t *header_buf,
+				const struct sfc_mae_parsed_item *parsed_items,
+				unsigned int nb_parsed_items)
+{
+	unsigned int item_idx;
+
+	for (item_idx = 0; item_idx < nb_parsed_items; ++item_idx) {
+		const struct sfc_mae_parsed_item *parsed_item;
+		const struct rte_flow_item *item;
+		size_t proto_header_size;
+		size_t ofst;
+
+		parsed_item = &parsed_items[item_idx];
+		proto_header_size = parsed_item->proto_header_size;
+		item = parsed_item->item;
+
+		for (ofst = 0; ofst < proto_header_size;
+		     ofst += sizeof(rte_be16_t)) {
+			rte_be16_t *wp = RTE_PTR_ADD(header_buf, ofst);
+			const rte_be16_t *w_maskp;
+			const rte_be16_t *w_specp;
+
+			w_maskp = RTE_PTR_ADD(item->mask, ofst);
+			w_specp = RTE_PTR_ADD(item->spec, ofst);
+
+			*wp &= ~(*w_maskp);
+			*wp |= (*w_specp & *w_maskp);
+		}
+
+		header_buf += proto_header_size;
+	}
+}
+
+#define SFC_IPV4_TTL_DEF	0x40
+#define SFC_IPV6_VTC_FLOW_DEF	0x60000000
+#define SFC_IPV6_HOP_LIMITS_DEF	0xff
+#define SFC_VXLAN_FLAGS_DEF	0x08000000
+
+static int
+sfc_mae_rule_parse_action_vxlan_encap(
+			    struct sfc_mae *mae,
+			    const struct rte_flow_action_vxlan_encap *conf,
+			    efx_mae_actions_t *spec,
+			    struct rte_flow_error *error)
+{
+	struct sfc_mae_bounce_eh *bounce_eh = &mae->bounce_eh;
+	struct rte_flow_item *pattern = conf->definition;
+	uint8_t *buf = bounce_eh->buf;
+
+	/* This array will keep track of non-VOID pattern items. */
+	struct sfc_mae_parsed_item parsed_items[1 /* Ethernet */ +
+						2 /* VLAN tags */ +
+						1 /* IPv4 or IPv6 */ +
+						1 /* UDP */ +
+						1 /* VXLAN */];
+	unsigned int nb_parsed_items = 0;
+
+	size_t eth_ethertype_ofst = offsetof(struct rte_ether_hdr, ether_type);
+	uint8_t dummy_buf[RTE_MAX(sizeof(struct rte_ipv4_hdr),
+				  sizeof(struct rte_ipv6_hdr))];
+	struct rte_ipv4_hdr *ipv4 = (void *)dummy_buf;
+	struct rte_ipv6_hdr *ipv6 = (void *)dummy_buf;
+	struct rte_vxlan_hdr *vxlan = NULL;
+	struct rte_udp_hdr *udp = NULL;
+	unsigned int nb_vlan_tags = 0;
+	size_t next_proto_ofst = 0;
+	size_t ethertype_ofst = 0;
+	uint64_t exp_items;
+
+	if (pattern == NULL) {
+		return rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
+				"The encap. header definition is NULL");
+	}
+
+	bounce_eh->type = EFX_TUNNEL_PROTOCOL_VXLAN;
+	bounce_eh->size = 0;
+
+	/*
+	 * Process pattern items and remember non-VOID ones.
+	 * Defer applying masks until after the complete header
+	 * has been built from the pattern items.
+	 */
+	exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_ETH);
+
+	for (; pattern->type != RTE_FLOW_ITEM_TYPE_END; ++pattern) {
+		struct sfc_mae_parsed_item *parsed_item;
+		const uint64_t exp_items_extra_vlan[] = {
+			RTE_BIT64(RTE_FLOW_ITEM_TYPE_VLAN), 0
+		};
+		size_t proto_header_size;
+		rte_be16_t *ethertypep;
+		uint8_t *next_protop;
+		uint8_t *buf_cur;
+
+		if (pattern->spec == NULL) {
+			return rte_flow_error_set(error, EINVAL,
+					RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
+					"NULL item spec in the encap. header");
+		}
+
+		if (pattern->mask == NULL) {
+			return rte_flow_error_set(error, EINVAL,
+					RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
+					"NULL item mask in the encap. header");
+		}
+
+		if (pattern->last != NULL) {
+			/* This is not a match pattern, so disallow range. */
+			return rte_flow_error_set(error, EINVAL,
+					RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
+					"Range item in the encap. header");
+		}
+
+		if (pattern->type == RTE_FLOW_ITEM_TYPE_VOID) {
+			/* Handle VOID separately, for clarity. */
+			continue;
+		}
+
+		if ((exp_items & RTE_BIT64(pattern->type)) == 0) {
+			return rte_flow_error_set(error, ENOTSUP,
+					RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
+					"Unexpected item in the encap. header");
+		}
+
+		parsed_item = &parsed_items[nb_parsed_items];
+		buf_cur = buf + bounce_eh->size;
+
+		switch (pattern->type) {
+		case RTE_FLOW_ITEM_TYPE_ETH:
+			SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_ETH,
+					       exp_items);
+			RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_eth,
+						  hdr) != 0);
+
+			proto_header_size = sizeof(struct rte_ether_hdr);
+
+			ethertype_ofst = eth_ethertype_ofst;
+
+			exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_VLAN) |
+				    RTE_BIT64(RTE_FLOW_ITEM_TYPE_IPV4) |
+				    RTE_BIT64(RTE_FLOW_ITEM_TYPE_IPV6);
+			break;
+		case RTE_FLOW_ITEM_TYPE_VLAN:
+			SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_VLAN,
+					       exp_items);
+			RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_vlan,
+						  hdr) != 0);
+
+			proto_header_size = sizeof(struct rte_vlan_hdr);
+
+			ethertypep = RTE_PTR_ADD(buf, eth_ethertype_ofst);
+			*ethertypep = RTE_BE16(RTE_ETHER_TYPE_QINQ);
+
+			ethertypep = RTE_PTR_ADD(buf, ethertype_ofst);
+			*ethertypep = RTE_BE16(RTE_ETHER_TYPE_VLAN);
+
+			ethertype_ofst =
+			    bounce_eh->size +
+			    offsetof(struct rte_vlan_hdr, eth_proto);
+
+			exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_IPV4) |
+				    RTE_BIT64(RTE_FLOW_ITEM_TYPE_IPV6);
+			exp_items |= exp_items_extra_vlan[nb_vlan_tags];
+
+			++nb_vlan_tags;
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV4:
+			SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_IPV4,
+					       exp_items);
+			RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_ipv4,
+						  hdr) != 0);
+
+			proto_header_size = sizeof(struct rte_ipv4_hdr);
+
+			ethertypep = RTE_PTR_ADD(buf, ethertype_ofst);
+			*ethertypep = RTE_BE16(RTE_ETHER_TYPE_IPV4);
+
+			next_proto_ofst =
+			    bounce_eh->size +
+			    offsetof(struct rte_ipv4_hdr, next_proto_id);
+
+			ipv4 = (struct rte_ipv4_hdr *)buf_cur;
+
+			exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_UDP);
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV6:
+			SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_IPV6,
+					       exp_items);
+			RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_ipv6,
+						  hdr) != 0);
+
+			proto_header_size = sizeof(struct rte_ipv6_hdr);
+
+			ethertypep = RTE_PTR_ADD(buf, ethertype_ofst);
+			*ethertypep = RTE_BE16(RTE_ETHER_TYPE_IPV6);
+
+			next_proto_ofst = bounce_eh->size +
+					  offsetof(struct rte_ipv6_hdr, proto);
+
+			ipv6 = (struct rte_ipv6_hdr *)buf_cur;
+
+			exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_UDP);
+			break;
+		case RTE_FLOW_ITEM_TYPE_UDP:
+			SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_UDP,
+					       exp_items);
+			RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_udp,
+						  hdr) != 0);
+
+			proto_header_size = sizeof(struct rte_udp_hdr);
+
+			next_protop = RTE_PTR_ADD(buf, next_proto_ofst);
+			*next_protop = IPPROTO_UDP;
+
+			udp = (struct rte_udp_hdr *)buf_cur;
+
+			exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_VXLAN);
+			break;
+		case RTE_FLOW_ITEM_TYPE_VXLAN:
+			SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_VXLAN,
+					       exp_items);
+			RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_vxlan,
+						  hdr) != 0);
+
+			proto_header_size = sizeof(struct rte_vxlan_hdr);
+
+			vxlan = (struct rte_vxlan_hdr *)buf_cur;
+
+			udp->dst_port = RTE_BE16(RTE_VXLAN_DEFAULT_PORT);
+			udp->dgram_len = RTE_BE16(sizeof(*udp) +
+						  sizeof(*vxlan));
+			udp->dgram_cksum = 0;
+
+			exp_items = 0;
+			break;
+		default:
+			return rte_flow_error_set(error, ENOTSUP,
+					RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
+					"Unknown item in the encap. header");
+		}
+
+		if (bounce_eh->size + proto_header_size > bounce_eh->buf_size) {
+			return rte_flow_error_set(error, E2BIG,
+					RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
+					"The encap. header is too big");
+		}
+
+		if ((proto_header_size & 1) != 0) {
+			return rte_flow_error_set(error, EINVAL,
+					RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
+					"Odd layer size in the encap. header");
+		}
+
+		rte_memcpy(buf_cur, pattern->spec, proto_header_size);
+		bounce_eh->size += proto_header_size;
+
+		parsed_item->item = pattern;
+		parsed_item->proto_header_size = proto_header_size;
+		++nb_parsed_items;
+	}
+
+	if (exp_items != 0) {
+		/* Parsing item VXLAN would have reset exp_items to 0. */
+		return rte_flow_error_set(error, ENOTSUP,
+					RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
+					"No item VXLAN in the encap. header");
+	}
+
+	/* One of the pointers (ipv4, ipv6) referes to a dummy area. */
+	ipv4->version_ihl = RTE_IPV4_VHL_DEF;
+	ipv4->time_to_live = SFC_IPV4_TTL_DEF;
+	ipv4->total_length = RTE_BE16(sizeof(*ipv4) + sizeof(*udp) +
+				      sizeof(*vxlan));
+	/* The HW cannot compute this checksum. */
+	ipv4->hdr_checksum = 0;
+	ipv4->hdr_checksum = rte_ipv4_cksum(ipv4);
+
+	ipv6->vtc_flow = RTE_BE32(SFC_IPV6_VTC_FLOW_DEF);
+	ipv6->hop_limits = SFC_IPV6_HOP_LIMITS_DEF;
+	ipv6->payload_len = udp->dgram_len;
+
+	vxlan->vx_flags = RTE_BE32(SFC_VXLAN_FLAGS_DEF);
+
+	/* Take care of the masks. */
+	sfc_mae_header_force_item_masks(buf, parsed_items, nb_parsed_items);
+
+	return (spec != NULL) ? efx_mae_action_set_populate_encap(spec) : 0;
+}
+
 static int
 sfc_mae_rule_parse_action_mark(const struct rte_flow_action_mark *conf,
 			       efx_mae_actions_t *spec)
@@ -2016,6 +2505,7 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 			  efx_mae_actions_t *spec,
 			  struct rte_flow_error *error)
 {
+	bool custom_error = B_FALSE;
 	int rc = 0;
 
 	switch (action->type) {
@@ -2039,6 +2529,14 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 				       bundle->actions_mask);
 		sfc_mae_rule_parse_action_of_set_vlan_pcp(action->conf, bundle);
 		break;
+	case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP,
+				       bundle->actions_mask);
+		rc = sfc_mae_rule_parse_action_vxlan_encap(&sa->mae,
+							   action->conf,
+							   spec, error);
+		custom_error = B_TRUE;
+		break;
 	case RTE_FLOW_ACTION_TYPE_FLAG:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_FLAG,
 				       bundle->actions_mask);
@@ -2080,24 +2578,49 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 				"Unsupported action");
 	}
 
-	if (rc != 0) {
+	if (rc == 0) {
+		bundle->actions_mask |= (1ULL << action->type);
+	} else if (!custom_error) {
 		rc = rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ACTION,
 				NULL, "Failed to request the action");
-	} else {
-		bundle->actions_mask |= (1ULL << action->type);
 	}
 
 	return rc;
 }
 
+static void
+sfc_mae_bounce_eh_invalidate(struct sfc_mae_bounce_eh *bounce_eh)
+{
+	bounce_eh->type = EFX_TUNNEL_PROTOCOL_NONE;
+}
+
+static int
+sfc_mae_process_encap_header(struct sfc_adapter *sa,
+			     const struct sfc_mae_bounce_eh *bounce_eh,
+			     struct sfc_mae_encap_header **encap_headerp)
+{
+	if (bounce_eh->type == EFX_TUNNEL_PROTOCOL_NONE) {
+		encap_headerp = NULL;
+		return 0;
+	}
+
+	*encap_headerp = sfc_mae_encap_header_attach(sa, bounce_eh);
+	if (*encap_headerp != NULL)
+		return 0;
+
+	return sfc_mae_encap_header_add(sa, bounce_eh, encap_headerp);
+}
+
 int
 sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			   const struct rte_flow_action actions[],
 			   struct sfc_flow_spec_mae *spec_mae,
 			   struct rte_flow_error *error)
 {
+	struct sfc_mae_encap_header *encap_header = NULL;
 	struct sfc_mae_actions_bundle bundle = {0};
 	const struct rte_flow_action *action;
+	struct sfc_mae *mae = &sa->mae;
 	efx_mae_actions_t *spec;
 	int rc;
 
@@ -2111,6 +2634,9 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_action_set_spec_init;
 
+	/* Cleanup after previous encap. header bounce buffer usage. */
+	sfc_mae_bounce_eh_invalidate(&mae->bounce_eh);
+
 	for (action = actions;
 	     action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
 		rc = sfc_mae_actions_bundle_sync(action, &bundle, spec, error);
@@ -2127,19 +2653,29 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_rule_parse_action;
 
-	spec_mae->action_set = sfc_mae_action_set_attach(sa, spec);
+	rc = sfc_mae_process_encap_header(sa, &mae->bounce_eh, &encap_header);
+	if (rc != 0)
+		goto fail_process_encap_header;
+
+	spec_mae->action_set = sfc_mae_action_set_attach(sa, encap_header,
+							 spec);
 	if (spec_mae->action_set != NULL) {
+		sfc_mae_encap_header_del(sa, encap_header);
 		efx_mae_action_set_spec_fini(sa->nic, spec);
 		return 0;
 	}
 
-	rc = sfc_mae_action_set_add(sa, spec, &spec_mae->action_set);
+	rc = sfc_mae_action_set_add(sa, spec, encap_header,
+				    &spec_mae->action_set);
 	if (rc != 0)
 		goto fail_action_set_add;
 
 	return 0;
 
 fail_action_set_add:
+	sfc_mae_encap_header_del(sa, encap_header);
+
+fail_process_encap_header:
 fail_rule_parse_action:
 	efx_mae_action_set_spec_fini(sa->nic, spec);
 
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 00987af61..c08fa545b 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -27,6 +27,7 @@ struct sfc_mae_fw_rsrc {
 	union {
 		efx_mae_aset_id_t	aset_id;
 		efx_mae_rule_id_t	rule_id;
+		efx_mae_eh_id_t		eh_id;
 	};
 };
 
@@ -41,11 +42,24 @@ struct sfc_mae_outer_rule {
 
 TAILQ_HEAD(sfc_mae_outer_rules, sfc_mae_outer_rule);
 
+/** Encap. header registry entry */
+struct sfc_mae_encap_header {
+	TAILQ_ENTRY(sfc_mae_encap_header)	entries;
+	unsigned int				refcnt;
+	uint8_t					*buf;
+	size_t					size;
+	efx_tunnel_protocol_t			type;
+	struct sfc_mae_fw_rsrc			fw_rsrc;
+};
+
+TAILQ_HEAD(sfc_mae_encap_headers, sfc_mae_encap_header);
+
 /** Action set registry entry */
 struct sfc_mae_action_set {
 	TAILQ_ENTRY(sfc_mae_action_set)	entries;
 	unsigned int			refcnt;
 	efx_mae_actions_t		*spec;
+	struct sfc_mae_encap_header	*encap_header;
 	struct sfc_mae_fw_rsrc		fw_rsrc;
 };
 
@@ -58,6 +72,17 @@ enum sfc_mae_status {
 	SFC_MAE_STATUS_SUPPORTED
 };
 
+/*
+ * Encap. header bounce buffer. It is used to store header data
+ * when parsing the header definition in the action VXLAN_ENCAP.
+ */
+struct sfc_mae_bounce_eh {
+	uint8_t				*buf;
+	size_t				buf_size;
+	size_t				size;
+	efx_tunnel_protocol_t		type;
+};
+
 struct sfc_mae {
 	/** Assigned switch domain identifier */
 	uint16_t			switch_domain_id;
@@ -73,8 +98,12 @@ struct sfc_mae {
 	uint32_t			encap_types_supported;
 	/** Outer rule registry */
 	struct sfc_mae_outer_rules	outer_rules;
+	/** Encap. header registry */
+	struct sfc_mae_encap_headers	encap_headers;
 	/** Action set registry */
 	struct sfc_mae_action_sets	action_sets;
+	/** Encap. header bounce buffer */
+	struct sfc_mae_bounce_eh	bounce_eh;
 };
 
 struct sfc_adapter;
-- 
2.20.1


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

* [dpdk-dev] [PATCH v2 09/10] common/sfc_efx/base: support adding action DECAP to a set
  2021-03-12 11:07 ` [dpdk-dev] [PATCH v2 01/10] ethdev: reuse header definition in flow pattern item ETH Ivan Malov
                     ` (6 preceding siblings ...)
  2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 08/10] net/sfc: support action VXLAN ENCAP in MAE backend Ivan Malov
@ 2021-03-12 11:07   ` Ivan Malov
  2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 10/10] net/sfc: support action VXLAN DECAP in transfer rules Ivan Malov
                     ` (3 subsequent siblings)
  11 siblings, 0 replies; 36+ messages in thread
From: Ivan Malov @ 2021-03-12 11:07 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Andy Moreton, Ray Kinsella, Neil Horman

The action has no arguments.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h      |  5 +++
 drivers/common/sfc_efx/base/efx_impl.h |  1 +
 drivers/common/sfc_efx/base/efx_mae.c  | 48 ++++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map     |  1 +
 4 files changed, 55 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 052946aa3..fe643de96 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4240,6 +4240,11 @@ efx_mae_action_set_spec_fini(
 	__in				efx_nic_t *enp,
 	__in				efx_mae_actions_t *spec);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_decap(
+	__in				efx_mae_actions_t *spec);
+
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_vlan_pop(
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 0adf43c26..7ee9ddec7 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -1707,6 +1707,7 @@ struct efx_mae_match_spec_s {
 
 typedef enum efx_mae_action_e {
 	/* These actions are strictly ordered. */
+	EFX_MAE_ACTION_DECAP,
 	EFX_MAE_ACTION_VLAN_POP,
 	EFX_MAE_ACTION_VLAN_PUSH,
 	EFX_MAE_ACTION_ENCAP,
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 896500de0..b384c009a 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -1013,6 +1013,37 @@ efx_mae_action_set_spec_fini(
 	EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), spec);
 }
 
+static	__checkReturn			efx_rc_t
+efx_mae_action_set_add_decap(
+	__in				efx_mae_actions_t *spec,
+	__in				size_t arg_size,
+	__in_bcount(arg_size)		const uint8_t *arg)
+{
+	efx_rc_t rc;
+
+	_NOTE(ARGUNUSED(spec))
+
+	if (arg_size != 0) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if (arg != NULL) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	/* This action does not have any arguments, so do nothing here. */
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
 static	__checkReturn			efx_rc_t
 efx_mae_action_set_add_vlan_pop(
 	__in				efx_mae_actions_t *spec,
@@ -1227,6 +1258,9 @@ typedef struct efx_mae_action_desc_s {
 } efx_mae_action_desc_t;
 
 static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
+	[EFX_MAE_ACTION_DECAP] = {
+		.emad_add = efx_mae_action_set_add_decap
+	},
 	[EFX_MAE_ACTION_VLAN_POP] = {
 		.emad_add = efx_mae_action_set_add_vlan_pop
 	},
@@ -1248,6 +1282,7 @@ static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
 };
 
 static const uint32_t efx_mae_action_ordered_map =
+	(1U << EFX_MAE_ACTION_DECAP) |
 	(1U << EFX_MAE_ACTION_VLAN_POP) |
 	(1U << EFX_MAE_ACTION_VLAN_PUSH) |
 	(1U << EFX_MAE_ACTION_ENCAP) |
@@ -1343,6 +1378,14 @@ efx_mae_action_set_spec_populate(
 	return (rc);
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_decap(
+	__in				efx_mae_actions_t *spec)
+{
+	return (efx_mae_action_set_spec_populate(spec,
+	    EFX_MAE_ACTION_DECAP, 0, NULL));
+}
+
 	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_vlan_pop(
 	__in				efx_mae_actions_t *spec)
@@ -2009,6 +2052,11 @@ efx_mae_action_set_alloc(
 	MCDI_IN_SET_DWORD(req,
 	    MAE_ACTION_SET_ALLOC_IN_COUNTER_ID, EFX_MAE_RSRC_ID_INVALID);
 
+	if ((spec->ema_actions & (1U << EFX_MAE_ACTION_DECAP)) != 0) {
+		MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
+		    MAE_ACTION_SET_ALLOC_IN_DECAP, 1);
+	}
+
 	MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
 	    MAE_ACTION_SET_ALLOC_IN_VLAN_POP, spec->ema_n_vlan_tags_to_pop);
 
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index f33a2a08e..b55e8567e 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -90,6 +90,7 @@ INTERNAL {
 	efx_mae_action_set_alloc;
 	efx_mae_action_set_fill_in_eh_id;
 	efx_mae_action_set_free;
+	efx_mae_action_set_populate_decap;
 	efx_mae_action_set_populate_deliver;
 	efx_mae_action_set_populate_drop;
 	efx_mae_action_set_populate_encap;
-- 
2.20.1


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

* [dpdk-dev] [PATCH v2 10/10] net/sfc: support action VXLAN DECAP in transfer rules
  2021-03-12 11:07 ` [dpdk-dev] [PATCH v2 01/10] ethdev: reuse header definition in flow pattern item ETH Ivan Malov
                     ` (7 preceding siblings ...)
  2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 09/10] common/sfc_efx/base: support adding action DECAP to a set Ivan Malov
@ 2021-03-12 11:07   ` Ivan Malov
  2021-03-16 16:58   ` [dpdk-dev] [PATCH v2 01/10] ethdev: reuse header definition in flow pattern item ETH Ferruh Yigit
                     ` (2 subsequent siblings)
  11 siblings, 0 replies; 36+ messages in thread
From: Ivan Malov @ 2021-03-12 11:07 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Andy Moreton

If there is no VXLAN among pattern items, the action will be turned down.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 79a1bd91d..1d67a4be2 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -2501,6 +2501,7 @@ sfc_mae_rule_parse_action_port_id(struct sfc_adapter *sa,
 static int
 sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 			  const struct rte_flow_action *action,
+			  const struct sfc_mae_outer_rule *outer_rule,
 			  struct sfc_mae_actions_bundle *bundle,
 			  efx_mae_actions_t *spec,
 			  struct rte_flow_error *error)
@@ -2509,6 +2510,15 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 	int rc = 0;
 
 	switch (action->type) {
+	case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VXLAN_DECAP,
+				       bundle->actions_mask);
+		if (outer_rule == NULL ||
+		    outer_rule->encap_type != EFX_TUNNEL_PROTOCOL_VXLAN)
+			rc = EINVAL;
+		else
+			rc = efx_mae_action_set_populate_decap(spec);
+		break;
 	case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_POP_VLAN,
 				       bundle->actions_mask);
@@ -2643,8 +2653,8 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		if (rc != 0)
 			goto fail_rule_parse_action;
 
-		rc = sfc_mae_rule_parse_action(sa, action, &bundle, spec,
-					       error);
+		rc = sfc_mae_rule_parse_action(sa, action, spec_mae->outer_rule,
+					       &bundle, spec, error);
 		if (rc != 0)
 			goto fail_rule_parse_action;
 	}
-- 
2.20.1


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

* Re: [dpdk-dev] [PATCH v2 01/10] ethdev: reuse header definition in flow pattern item ETH
  2021-03-12 11:07 ` [dpdk-dev] [PATCH v2 01/10] ethdev: reuse header definition in flow pattern item ETH Ivan Malov
                     ` (8 preceding siblings ...)
  2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 10/10] net/sfc: support action VXLAN DECAP in transfer rules Ivan Malov
@ 2021-03-16 16:58   ` Ferruh Yigit
  2021-03-16 17:38   ` Ferruh Yigit
  2021-03-22 16:49   ` Ferruh Yigit
  11 siblings, 0 replies; 36+ messages in thread
From: Ferruh Yigit @ 2021-03-16 16:58 UTC (permalink / raw)
  To: Ivan Malov, dev; +Cc: Andrew Rybchenko, Andy Moreton, Ori Kam, Thomas Monjalon

On 3/12/2021 11:07 AM, Ivan Malov wrote:
> One ought to reuse existing header structs in flow items.
> This particular item contains non-header fields, so it's
> important to keep the header fields in a separate struct.
> 
> Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
> Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
> Reviewed-by: Andy Moreton <amoreton@xilinx.com>
> ---
>   lib/librte_ethdev/rte_flow.h | 44 ++++++++++++++++++++++--------------
>   1 file changed, 27 insertions(+), 17 deletions(-)
> 
> diff --git a/lib/librte_ethdev/rte_flow.h b/lib/librte_ethdev/rte_flow.h
> index 669e677e9..96fd93ee1 100644
> --- a/lib/librte_ethdev/rte_flow.h
> +++ b/lib/librte_ethdev/rte_flow.h
> @@ -728,22 +728,32 @@ static const struct rte_flow_item_raw rte_flow_item_raw_mask = {
>    *
>    * Matches an Ethernet header.
>    *
> - * The @p type field either stands for "EtherType" or "TPID" when followed
> - * by so-called layer 2.5 pattern items such as RTE_FLOW_ITEM_TYPE_VLAN. In
> - * the latter case, @p type refers to that of the outer header, with the
> - * inner EtherType/TPID provided by the subsequent pattern item. This is the
> - * same order as on the wire.
> - * If the @p type field contains a TPID value, then only tagged packets with the
> - * specified TPID will match the pattern.
> - * The field @p has_vlan can be used to match any type of tagged packets,
> - * instead of using the @p type field.
> - * If the @p type and @p has_vlan fields are not specified, then both tagged
> - * and untagged packets will match the pattern.
> + * Inside @p hdr field, the sub-field @p ether_type stands either for EtherType
> + * or TPID, depending on whether the item is followed by a VLAN item or not. If
> + * two VLAN items follow, the sub-field refers to the outer one, which, in turn,
> + * contains the inner TPID in the similar header field. The innermost VLAN item
> + * contains a layer-3 EtherType. All of that follows the order seen on the wire.
> + *
> + * If the field in question contains a TPID value, only tagged packets with the
> + * specified TPID will match the pattern. Alternatively, it's possible to match
> + * any type of tagged packets by means of the field @p has_vlan rather than use
> + * the EtherType/TPID field. Also, it's possible to leave the two fields unused.
> + * If this is the case, both tagged and untagged packets will match the pattern.
>    */

It seems Ivan can do his magic with preexisting text too :)

> +RTE_STD_C11
>   struct rte_flow_item_eth {
> -	struct rte_ether_addr dst; /**< Destination MAC. */
> -	struct rte_ether_addr src; /**< Source MAC. */
> -	rte_be16_t type; /**< EtherType or TPID. */
> +	union {
> +		struct {
> +			/*
> +			 * These fields are retained for compatibility.
> +			 * Please switch to the new header field below.
> +			 */
> +			struct rte_ether_addr dst; /**< Destination MAC. */
> +			struct rte_ether_addr src; /**< Source MAC. */
> +			rte_be16_t type; /**< EtherType or TPID. */
> +		};
> +		struct rte_ether_hdr hdr;
> +	};
>   	uint32_t has_vlan:1; /**< Packet header contains at least one VLAN. */
>   	uint32_t reserved:31; /**< Reserved, must be zero. */
>   };
> @@ -751,9 +761,9 @@ struct rte_flow_item_eth {
>   /** Default mask for RTE_FLOW_ITEM_TYPE_ETH. */
>   #ifndef __cplusplus
>   static const struct rte_flow_item_eth rte_flow_item_eth_mask = {
> -	.dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> -	.src.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> -	.type = RTE_BE16(0x0000),
> +	.hdr.d_addr.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> +	.hdr.s_addr.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> +	.hdr.ether_type = RTE_BE16(0x0000),
>   };
>   #endif
>   
> 

Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>

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

* Re: [dpdk-dev] [PATCH v2 02/10] ethdev: reuse header definition in flow pattern item VLAN
  2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 02/10] ethdev: reuse header definition in flow pattern item VLAN Ivan Malov
@ 2021-03-16 16:58     ` Ferruh Yigit
  0 siblings, 0 replies; 36+ messages in thread
From: Ferruh Yigit @ 2021-03-16 16:58 UTC (permalink / raw)
  To: Ivan Malov, dev; +Cc: Andrew Rybchenko, Andy Moreton, Ori Kam, Thomas Monjalon

On 3/12/2021 11:07 AM, Ivan Malov wrote:
> One ought to reuse existing header structs in flow items.
> This particular item contains non-header fields, so it's
> important to keep the header fields in a separate struct.
> 
> Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
> Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
> Reviewed-by: Andy Moreton <amoreton@xilinx.com>

Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>


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

* Re: [dpdk-dev] [PATCH v2 08/10] net/sfc: support action VXLAN ENCAP in MAE backend
  2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 08/10] net/sfc: support action VXLAN ENCAP in MAE backend Ivan Malov
@ 2021-03-16 17:10     ` Ivan Malov
  2021-03-16 17:15       ` Ferruh Yigit
  2021-03-31 23:21     ` Thomas Monjalon
  1 sibling, 1 reply; 36+ messages in thread
From: Ivan Malov @ 2021-03-16 17:10 UTC (permalink / raw)
  To: dev, Ferruh Yigit; +Cc: Andrew Rybchenko

Hi,

 > WARNING:TYPO_SPELLING: 'referes' may be misspelled - perhaps 'refers'?
 > #652: FILE: drivers/net/sfc/sfc_mae.c:2407:
 > +	/* One of the pointers (ipv4, ipv6) referes to a dummy area. */

It looks like an oversight. What a terrible typo. Ferruh, shall I send 
v4 to fix that? I sincerely apologise for this problem.

-- 
Ivan M

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

* Re: [dpdk-dev] [PATCH v2 08/10] net/sfc: support action VXLAN ENCAP in MAE backend
  2021-03-16 17:10     ` Ivan Malov
@ 2021-03-16 17:15       ` Ferruh Yigit
  0 siblings, 0 replies; 36+ messages in thread
From: Ferruh Yigit @ 2021-03-16 17:15 UTC (permalink / raw)
  To: Ivan Malov, dev; +Cc: Andrew Rybchenko

On 3/16/2021 5:10 PM, Ivan Malov wrote:
> Hi,
> 
>  > WARNING:TYPO_SPELLING: 'referes' may be misspelled - perhaps 'refers'?
>  > #652: FILE: drivers/net/sfc/sfc_mae.c:2407:
>  > +    /* One of the pointers (ipv4, ipv6) referes to a dummy area. */
> 
> It looks like an oversight. What a terrible typo. Ferruh, shall I send v4 to fix 
> that? I sincerely apologise for this problem.
> 

Hi Ivan, no worries, I can fix the typo while merging if that is the only issue.

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

* Re: [dpdk-dev] [PATCH v2 03/10] net: clarify endianness of 32-bit fields in VXLAN headers
  2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 03/10] net: clarify endianness of 32-bit fields in VXLAN headers Ivan Malov
@ 2021-03-16 17:34     ` Ferruh Yigit
  0 siblings, 0 replies; 36+ messages in thread
From: Ferruh Yigit @ 2021-03-16 17:34 UTC (permalink / raw)
  To: Ivan Malov, dev; +Cc: Andrew Rybchenko, Andy Moreton, Olivier Matz

On 3/12/2021 11:07 AM, Ivan Malov wrote:
> These fields have network byte order. Highlight it using dedicated type.
> 
> Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
> Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
> Reviewed-by: Andy Moreton <amoreton@xilinx.com>

Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>



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

* Re: [dpdk-dev] [PATCH v2 04/10] ethdev: reuse header definition in flow pattern item VXLAN
  2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 04/10] ethdev: reuse header definition in flow pattern item VXLAN Ivan Malov
@ 2021-03-16 17:35     ` Ferruh Yigit
  0 siblings, 0 replies; 36+ messages in thread
From: Ferruh Yigit @ 2021-03-16 17:35 UTC (permalink / raw)
  To: Ivan Malov, dev; +Cc: Andrew Rybchenko, Andy Moreton, Ori Kam, Thomas Monjalon

On 3/12/2021 11:07 AM, Ivan Malov wrote:
> One ought to reuse existing header structs in flow items.
> 
> Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
> Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
> Reviewed-by: Andy Moreton <amoreton@xilinx.com>

Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>


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

* Re: [dpdk-dev] [PATCH v2 01/10] ethdev: reuse header definition in flow pattern item ETH
  2021-03-12 11:07 ` [dpdk-dev] [PATCH v2 01/10] ethdev: reuse header definition in flow pattern item ETH Ivan Malov
                     ` (9 preceding siblings ...)
  2021-03-16 16:58   ` [dpdk-dev] [PATCH v2 01/10] ethdev: reuse header definition in flow pattern item ETH Ferruh Yigit
@ 2021-03-16 17:38   ` Ferruh Yigit
  2021-03-17  6:40     ` Andrew Rybchenko
  2021-03-22 16:49   ` Ferruh Yigit
  11 siblings, 1 reply; 36+ messages in thread
From: Ferruh Yigit @ 2021-03-16 17:38 UTC (permalink / raw)
  To: Ivan Malov, dev; +Cc: Andrew Rybchenko, Andy Moreton, Ori Kam, Thomas Monjalon

On 3/12/2021 11:07 AM, Ivan Malov wrote:
> One ought to reuse existing header structs in flow items.
> This particular item contains non-header fields, so it's
> important to keep the header fields in a separate struct.
> 

Hi Ivan, Andrew, Thanks for following this up and updates.

For record, existing deprecation note is:
https://git.dpdk.org/dpdk/tree/doc/guides/rel_notes/deprecation.rst?h=v21.02#n99

Ori, Andrew,

Is there any struct left not updated after this patch?

> Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
> Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
> Reviewed-by: Andy Moreton <amoreton@xilinx.com>

<...>


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

* Re: [dpdk-dev] [PATCH 01/10] ethdev: reuse header definition in flow pattern item ETH
  2021-03-12  9:31 [dpdk-dev] [PATCH 01/10] ethdev: reuse header definition in flow pattern item ETH Ivan Malov
                   ` (9 preceding siblings ...)
  2021-03-12 11:07 ` [dpdk-dev] [PATCH v2 01/10] ethdev: reuse header definition in flow pattern item ETH Ivan Malov
@ 2021-03-16 23:03 ` Ori Kam
  10 siblings, 0 replies; 36+ messages in thread
From: Ori Kam @ 2021-03-16 23:03 UTC (permalink / raw)
  To: Ivan Malov, dev
  Cc: Andrew Rybchenko, Andy Moreton, NBU-Contact-Thomas Monjalon,
	Ferruh Yigit

Hi Ivan,

> -----Original Message-----
> From: Ivan Malov <ivan.malov@oktetlabs.ru>
> Sent: Friday, March 12, 2021 11:32 AM
> 
> One ought to reuse existing header structs in flow items.
> This particular item contains non-header fields, so it's
> important to keep the header fields in a separate struct.
> 
> Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
> Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
> Reviewed-by: Andy Moreton <amoreton@xilinx.com>
> ---
>  lib/librte_ethdev/rte_flow.h | 44 ++++++++++++++++++++++--------------
>  1 file changed, 27 insertions(+), 17 deletions(-)
> 
> diff --git a/lib/librte_ethdev/rte_flow.h b/lib/librte_ethdev/rte_flow.h
> index 669e677e9..96fd93ee1 100644
> --- a/lib/librte_ethdev/rte_flow.h
> +++ b/lib/librte_ethdev/rte_flow.h
> @@ -728,22 +728,32 @@ static const struct rte_flow_item_raw
> rte_flow_item_raw_mask = {
>   *
>   * Matches an Ethernet header.
>   *
> - * The @p type field either stands for "EtherType" or "TPID" when followed
> - * by so-called layer 2.5 pattern items such as RTE_FLOW_ITEM_TYPE_VLAN.
> In
> - * the latter case, @p type refers to that of the outer header, with the
> - * inner EtherType/TPID provided by the subsequent pattern item. This is the
> - * same order as on the wire.
> - * If the @p type field contains a TPID value, then only tagged packets with the
> - * specified TPID will match the pattern.
> - * The field @p has_vlan can be used to match any type of tagged packets,
> - * instead of using the @p type field.
> - * If the @p type and @p has_vlan fields are not specified, then both tagged
> - * and untagged packets will match the pattern.
> + * Inside @p hdr field, the sub-field @p ether_type stands either for EtherType
> + * or TPID, depending on whether the item is followed by a VLAN item or not.
> If
> + * two VLAN items follow, the sub-field refers to the outer one, which, in turn,
> + * contains the inner TPID in the similar header field. The innermost VLAN
> item
> + * contains a layer-3 EtherType. All of that follows the order seen on the wire.
> + *
> + * If the field in question contains a TPID value, only tagged packets with the
> + * specified TPID will match the pattern. Alternatively, it's possible to match
> + * any type of tagged packets by means of the field @p has_vlan rather than
> use
> + * the EtherType/TPID field. Also, it's possible to leave the two fields unused.
> + * If this is the case, both tagged and untagged packets will match the pattern.
>   */
> +RTE_STD_C11
>  struct rte_flow_item_eth {
> -	struct rte_ether_addr dst; /**< Destination MAC. */
> -	struct rte_ether_addr src; /**< Source MAC. */
> -	rte_be16_t type; /**< EtherType or TPID. */
> +	union {
> +		struct {
> +			/*
> +			 * These fields are retained for compatibility.
> +			 * Please switch to the new header field below.
> +			 */
> +			struct rte_ether_addr dst; /**< Destination MAC. */
> +			struct rte_ether_addr src; /**< Source MAC. */
> +			rte_be16_t type; /**< EtherType or TPID. */
> +		};
> +		struct rte_ether_hdr hdr;
> +	};
>  	uint32_t has_vlan:1; /**< Packet header contains at least one VLAN. */
>  	uint32_t reserved:31; /**< Reserved, must be zero. */
>  };
> @@ -751,9 +761,9 @@ struct rte_flow_item_eth {
>  /** Default mask for RTE_FLOW_ITEM_TYPE_ETH. */
>  #ifndef __cplusplus
>  static const struct rte_flow_item_eth rte_flow_item_eth_mask = {
> -	.dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> -	.src.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> -	.type = RTE_BE16(0x0000),
> +	.hdr.d_addr.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> +	.hdr.s_addr.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> +	.hdr.ether_type = RTE_BE16(0x0000),
>  };
>  #endif
> 
> --
> 2.20.1

Acked-by: Ori Kam <orika@nvidia.com>
Best,
Ori

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

* Re: [dpdk-dev] [PATCH 02/10] ethdev: reuse header definition in flow pattern item VLAN
  2021-03-12  9:31 ` [dpdk-dev] [PATCH 02/10] ethdev: reuse header definition in flow pattern item VLAN Ivan Malov
@ 2021-03-16 23:05   ` Ori Kam
  0 siblings, 0 replies; 36+ messages in thread
From: Ori Kam @ 2021-03-16 23:05 UTC (permalink / raw)
  To: Ivan Malov, dev
  Cc: Andrew Rybchenko, Andy Moreton, NBU-Contact-Thomas Monjalon,
	Ferruh Yigit

Hi Ivan,

> -----Original Message-----
> From: Ivan Malov <ivan.malov@oktetlabs.ru>
> Sent: Friday, March 12, 2021 11:32 AM
> 
> One ought to reuse existing header structs in flow items.
> This particular item contains non-header fields, so it's
> important to keep the header fields in a separate struct.
> 
> Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
> Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
> Reviewed-by: Andy Moreton <amoreton@xilinx.com>
> ---
>  lib/librte_ethdev/rte_flow.h | 22 ++++++++++++++++------
>  1 file changed, 16 insertions(+), 6 deletions(-)
> 
> diff --git a/lib/librte_ethdev/rte_flow.h b/lib/librte_ethdev/rte_flow.h
> index 96fd93ee1..b9b349669 100644
> --- a/lib/librte_ethdev/rte_flow.h
> +++ b/lib/librte_ethdev/rte_flow.h
> @@ -778,13 +778,23 @@ static const struct rte_flow_item_eth
> rte_flow_item_eth_mask = {
>   * If a @p VLAN item is present in the pattern, then only tagged packets will
>   * match the pattern.
>   * The field @p has_more_vlan can be used to match any type of tagged
> packets,
> - * instead of using the @p inner_type field.
> - * If the @p inner_type and @p has_more_vlan fields are not specified,
> + * instead of using the @p eth_proto field of @p hdr.
> + * If the @p eth_proto of @p hdr and @p has_more_vlan fields are not
> specified,
>   * then any tagged packets will match the pattern.
>   */
> +RTE_STD_C11
>  struct rte_flow_item_vlan {
> -	rte_be16_t tci; /**< Tag control information. */
> -	rte_be16_t inner_type; /**< Inner EtherType or TPID. */
> +	union {
> +		struct {
> +			/*
> +			 * These fields are retained for compatibility.
> +			 * Please switch to the new header field below.
> +			 */
> +			rte_be16_t tci; /**< Tag control information. */
> +			rte_be16_t inner_type; /**< Inner EtherType or TPID.
> */
> +		};
> +		struct rte_vlan_hdr hdr;
> +	};
>  	uint32_t has_more_vlan:1;
>  	/**< Packet header contains at least one more VLAN, after this VLAN.
> */
>  	uint32_t reserved:31; /**< Reserved, must be zero. */
> @@ -793,8 +803,8 @@ struct rte_flow_item_vlan {
>  /** Default mask for RTE_FLOW_ITEM_TYPE_VLAN. */
>  #ifndef __cplusplus
>  static const struct rte_flow_item_vlan rte_flow_item_vlan_mask = {
> -	.tci = RTE_BE16(0x0fff),
> -	.inner_type = RTE_BE16(0x0000),
> +	.hdr.vlan_tci = RTE_BE16(0x0fff),
> +	.hdr.eth_proto = RTE_BE16(0x0000),
>  };
>  #endif
> 
> --
> 2.20.1

Acked-by: Ori Kam <orika@nvidia.com>
Best,
Ori



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

* Re: [dpdk-dev] [PATCH v2 01/10] ethdev: reuse header definition in flow pattern item ETH
  2021-03-16 17:38   ` Ferruh Yigit
@ 2021-03-17  6:40     ` Andrew Rybchenko
  2021-03-22  9:01       ` Ferruh Yigit
  0 siblings, 1 reply; 36+ messages in thread
From: Andrew Rybchenko @ 2021-03-17  6:40 UTC (permalink / raw)
  To: Ferruh Yigit, Ivan Malov, dev; +Cc: Andy Moreton, Ori Kam, Thomas Monjalon

On 3/16/21 8:38 PM, Ferruh Yigit wrote:
> On 3/12/2021 11:07 AM, Ivan Malov wrote:
>> One ought to reuse existing header structs in flow items.
>> This particular item contains non-header fields, so it's
>> important to keep the header fields in a separate struct.
>>
> 
> Hi Ivan, Andrew, Thanks for following this up and updates.
> 
> For record, existing deprecation note is:
> https://git.dpdk.org/dpdk/tree/doc/guides/rel_notes/deprecation.rst?h=v21.02#n99
> 
> 
> Ori, Andrew,
> 
> Is there any struct left not updated after this patch?

As I understand the following flow items corresponding to
network protocols, but still define own fields. Sometimes
corresponding network protocols do not have definitions in
DPDK, but it is not an excuse and definitions should be
simply added:
rte_flow_item_e_tag
rte_flow_item_nvgre
rte_flow_item_mpls
rte_flow_item_gre
rte_flow_item_gtp
rte_flow_item_geneve
rte_flow_item_vxlan_gpe
rte_flow_item_arp_eth_ipv4
rte_flow_item_icmp6
rte_flow_item_icmp6_nd_ns
rte_flow_item_icmp6_nd_na
rte_flow_item_icmp6_nd_opt
rte_flow_item_icmp6_nd_opt_sla_eth
rte_flow_item_icmp6_nd_opt_tla_eth
rte_flow_item_gtp_psc
rte_flow_item_pppoe
rte_flow_item_pppoe_proto_id
rte_flow_item_l2tpv3oip
rte_flow_item_nsh
rte_flow_item_igmp
rte_flow_item_ah
rte_flow_item_pfcp
rte_flow_item_geneve_opt

The list is composed very quickly so may be I oversight
something, but it definitely answers the question - yes,
more flow items remain.

> 
>> Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
>> Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
>> Reviewed-by: Andy Moreton <amoreton@xilinx.com>
> 
> <...>


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

* Re: [dpdk-dev] [PATCH v2 01/10] ethdev: reuse header definition in flow pattern item ETH
  2021-03-17  6:40     ` Andrew Rybchenko
@ 2021-03-22  9:01       ` Ferruh Yigit
  2021-03-22 10:10         ` Andrew Rybchenko
  0 siblings, 1 reply; 36+ messages in thread
From: Ferruh Yigit @ 2021-03-22  9:01 UTC (permalink / raw)
  To: Andrew Rybchenko, Ivan Malov, dev; +Cc: Andy Moreton, Ori Kam, Thomas Monjalon

On 3/17/2021 6:40 AM, Andrew Rybchenko wrote:
> On 3/16/21 8:38 PM, Ferruh Yigit wrote:
>> On 3/12/2021 11:07 AM, Ivan Malov wrote:
>>> One ought to reuse existing header structs in flow items.
>>> This particular item contains non-header fields, so it's
>>> important to keep the header fields in a separate struct.
>>>
>>
>> Hi Ivan, Andrew, Thanks for following this up and updates.
>>
>> For record, existing deprecation note is:
>> https://git.dpdk.org/dpdk/tree/doc/guides/rel_notes/deprecation.rst?h=v21.02#n99
>>
>>
>> Ori, Andrew,
>>
>> Is there any struct left not updated after this patch?
> 
> As I understand the following flow items corresponding to
> network protocols, but still define own fields. Sometimes
> corresponding network protocols do not have definitions in
> DPDK, but it is not an excuse and definitions should be
> simply added:
> rte_flow_item_e_tag
> rte_flow_item_nvgre
> rte_flow_item_mpls
> rte_flow_item_gre
> rte_flow_item_gtp
> rte_flow_item_geneve
> rte_flow_item_vxlan_gpe
> rte_flow_item_arp_eth_ipv4
> rte_flow_item_icmp6
> rte_flow_item_icmp6_nd_ns
> rte_flow_item_icmp6_nd_na
> rte_flow_item_icmp6_nd_opt
> rte_flow_item_icmp6_nd_opt_sla_eth
> rte_flow_item_icmp6_nd_opt_tla_eth
> rte_flow_item_gtp_psc
> rte_flow_item_pppoe
> rte_flow_item_pppoe_proto_id
> rte_flow_item_l2tpv3oip
> rte_flow_item_nsh
> rte_flow_item_igmp
> rte_flow_item_ah
> rte_flow_item_pfcp
> rte_flow_item_geneve_opt
> 
> The list is composed very quickly so may be I oversight
> something, but it definitely answers the question - yes,
> more flow items remain.
> 

Ahh, I was thinking the problematic ones, the ones adding extra fields than the 
protocol header, 'rte_flow_item_eth', 'rte_flow_item_vlan' and there was one 
more I guess, but you are right, all needs be updated.

So there are more to be updated, are you planning to work on any more of them in 
this release?

btw, thanks again for addressing this issue.


>>
>>> Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
>>> Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
>>> Reviewed-by: Andy Moreton <amoreton@xilinx.com>
>>
>> <...>
> 


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

* Re: [dpdk-dev] [PATCH v2 01/10] ethdev: reuse header definition in flow pattern item ETH
  2021-03-22  9:01       ` Ferruh Yigit
@ 2021-03-22 10:10         ` Andrew Rybchenko
  0 siblings, 0 replies; 36+ messages in thread
From: Andrew Rybchenko @ 2021-03-22 10:10 UTC (permalink / raw)
  To: Ferruh Yigit, Ivan Malov, dev; +Cc: Andy Moreton, Ori Kam, Thomas Monjalon

On 3/22/21 12:01 PM, Ferruh Yigit wrote:
> On 3/17/2021 6:40 AM, Andrew Rybchenko wrote:
>> On 3/16/21 8:38 PM, Ferruh Yigit wrote:
>>> On 3/12/2021 11:07 AM, Ivan Malov wrote:
>>>> One ought to reuse existing header structs in flow items.
>>>> This particular item contains non-header fields, so it's
>>>> important to keep the header fields in a separate struct.
>>>>
>>>
>>> Hi Ivan, Andrew, Thanks for following this up and updates.
>>>
>>> For record, existing deprecation note is:
>>> https://git.dpdk.org/dpdk/tree/doc/guides/rel_notes/deprecation.rst?h=v21.02#n99
>>>
>>>
>>>
>>> Ori, Andrew,
>>>
>>> Is there any struct left not updated after this patch?
>>
>> As I understand the following flow items corresponding to
>> network protocols, but still define own fields. Sometimes
>> corresponding network protocols do not have definitions in
>> DPDK, but it is not an excuse and definitions should be
>> simply added:
>> rte_flow_item_e_tag
>> rte_flow_item_nvgre
>> rte_flow_item_mpls
>> rte_flow_item_gre
>> rte_flow_item_gtp
>> rte_flow_item_geneve
>> rte_flow_item_vxlan_gpe
>> rte_flow_item_arp_eth_ipv4
>> rte_flow_item_icmp6
>> rte_flow_item_icmp6_nd_ns
>> rte_flow_item_icmp6_nd_na
>> rte_flow_item_icmp6_nd_opt
>> rte_flow_item_icmp6_nd_opt_sla_eth
>> rte_flow_item_icmp6_nd_opt_tla_eth
>> rte_flow_item_gtp_psc
>> rte_flow_item_pppoe
>> rte_flow_item_pppoe_proto_id
>> rte_flow_item_l2tpv3oip
>> rte_flow_item_nsh
>> rte_flow_item_igmp
>> rte_flow_item_ah
>> rte_flow_item_pfcp
>> rte_flow_item_geneve_opt
>>
>> The list is composed very quickly so may be I oversight
>> something, but it definitely answers the question - yes,
>> more flow items remain.
>>
> 
> Ahh, I was thinking the problematic ones, the ones adding extra fields
> than the protocol header, 'rte_flow_item_eth', 'rte_flow_item_vlan' and
> there was one more I guess, but you are right, all needs be updated.
> 
> So there are more to be updated, are you planning to work on any more of
> them in this release?

No plans on it yet.

> btw, thanks again for addressing this issue.
> 
> 
>>>
>>>> Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
>>>> Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
>>>> Reviewed-by: Andy Moreton <amoreton@xilinx.com>
>>>
>>> <...>
>>


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

* Re: [dpdk-dev] [PATCH v2 01/10] ethdev: reuse header definition in flow pattern item ETH
  2021-03-12 11:07 ` [dpdk-dev] [PATCH v2 01/10] ethdev: reuse header definition in flow pattern item ETH Ivan Malov
                     ` (10 preceding siblings ...)
  2021-03-16 17:38   ` Ferruh Yigit
@ 2021-03-22 16:49   ` Ferruh Yigit
  11 siblings, 0 replies; 36+ messages in thread
From: Ferruh Yigit @ 2021-03-22 16:49 UTC (permalink / raw)
  To: Ivan Malov, dev; +Cc: Andrew Rybchenko, Andy Moreton, Ori Kam, Thomas Monjalon

On 3/12/2021 11:07 AM, Ivan Malov wrote:
> One ought to reuse existing header structs in flow items.
> This particular item contains non-header fields, so it's
> important to keep the header fields in a separate struct.
> 
> Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
> Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
> Reviewed-by: Andy Moreton <amoreton@xilinx.com>

Series applied to dpdk-next-net/main, thanks.


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

* Re: [dpdk-dev] [PATCH v2 08/10] net/sfc: support action VXLAN ENCAP in MAE backend
  2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 08/10] net/sfc: support action VXLAN ENCAP in MAE backend Ivan Malov
  2021-03-16 17:10     ` Ivan Malov
@ 2021-03-31 23:21     ` Thomas Monjalon
  2021-03-31 23:36       ` Ivan Malov
  1 sibling, 1 reply; 36+ messages in thread
From: Thomas Monjalon @ 2021-03-31 23:21 UTC (permalink / raw)
  To: Andrew Rybchenko, Andy Moreton, Ivan Malov; +Cc: dev, ferruh.yigit

12/03/2021 12:07, Ivan Malov:
> +static int
> +sfc_mae_encap_header_add(struct sfc_adapter *sa,
> +			 const struct sfc_mae_bounce_eh *bounce_eh,
> +			 struct sfc_mae_encap_header **encap_headerp)
> +{
> +	struct sfc_mae_encap_header *encap_header;
> +	struct sfc_mae *mae = &sa->mae;
> +
> +	SFC_ASSERT(sfc_adapter_is_locked(sa));
> +
> +	encap_header = rte_zmalloc("sfc_mae_encap_header",
> +				   sizeof(*encap_header), 0);
> +	if (encap_header == NULL)
> +		return ENOMEM;
> +
> +	encap_header->size = bounce_eh->size;
> +
> +	encap_header->buf = rte_malloc("sfc_mae_encap_header_buf",
> +				       encap_header->size, 0);
> +	if (encap_header->buf == NULL) {
> +		rte_free(encap_header);
> +		return ENOMEM;
> +	}

Are the error codes positives on purpose?
checkpatch is throwing this warning:
USE_NEGATIVE_ERRNO: return of an errno should typically be negative (ie: return -ENOMEM)

Also the base code has a lot of these warnings:
RETURN_PARENTHESES: return is not a function, parentheses are not required

I guess you cannot do anything to avoid it in base code?



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

* Re: [dpdk-dev] [PATCH v2 08/10] net/sfc: support action VXLAN ENCAP in MAE backend
  2021-03-31 23:21     ` Thomas Monjalon
@ 2021-03-31 23:36       ` Ivan Malov
  2021-04-01  6:38         ` Andrew Rybchenko
  0 siblings, 1 reply; 36+ messages in thread
From: Ivan Malov @ 2021-03-31 23:36 UTC (permalink / raw)
  To: Thomas Monjalon, Andrew Rybchenko, Andy Moreton; +Cc: dev, ferruh.yigit

Hi,

On 01/04/2021 02:21, Thomas Monjalon wrote:
> 12/03/2021 12:07, Ivan Malov:
>> +static int
>> +sfc_mae_encap_header_add(struct sfc_adapter *sa,
>> +			 const struct sfc_mae_bounce_eh *bounce_eh,
>> +			 struct sfc_mae_encap_header **encap_headerp)
>> +{
>> +	struct sfc_mae_encap_header *encap_header;
>> +	struct sfc_mae *mae = &sa->mae;
>> +
>> +	SFC_ASSERT(sfc_adapter_is_locked(sa));
>> +
>> +	encap_header = rte_zmalloc("sfc_mae_encap_header",
>> +				   sizeof(*encap_header), 0);
>> +	if (encap_header == NULL)
>> +		return ENOMEM;
>> +
>> +	encap_header->size = bounce_eh->size;
>> +
>> +	encap_header->buf = rte_malloc("sfc_mae_encap_header_buf",
>> +				       encap_header->size, 0);
>> +	if (encap_header->buf == NULL) {
>> +		rte_free(encap_header);
>> +		return ENOMEM;
>> +	}
> 
> Are the error codes positives on purpose?
> checkpatch is throwing this warning:
> USE_NEGATIVE_ERRNO: return of an errno should typically be negative (ie: return -ENOMEM)

Kind of yes, on purpose. It has been like that for a long time already; 
it's simpler to keep errors positive in all such small internal helpers 
and then negate the result in the place where rte_flow_error_set() is 
used. We understand the concern of yours; our code is tested for error 
path correctness every now and again. If there're some inconsistencies, 
we are ready to fix such in no time.

> Also the base code has a lot of these warnings:
> RETURN_PARENTHESES: return is not a function, parentheses are not required
> 
> I guess you cannot do anything to avoid it in base code?

Yes, your understanding is correct. Sorry for the inconvenience.

-- 
Ivan M

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

* Re: [dpdk-dev] [PATCH v2 08/10] net/sfc: support action VXLAN ENCAP in MAE backend
  2021-03-31 23:36       ` Ivan Malov
@ 2021-04-01  6:38         ` Andrew Rybchenko
  0 siblings, 0 replies; 36+ messages in thread
From: Andrew Rybchenko @ 2021-04-01  6:38 UTC (permalink / raw)
  To: Ivan Malov, Thomas Monjalon, Andy Moreton; +Cc: dev, ferruh.yigit

On 4/1/21 2:36 AM, Ivan Malov wrote:
> Hi,
>
> On 01/04/2021 02:21, Thomas Monjalon wrote:
>> 12/03/2021 12:07, Ivan Malov:
>>> +static int
>>> +sfc_mae_encap_header_add(struct sfc_adapter *sa,
>>> +             const struct sfc_mae_bounce_eh *bounce_eh,
>>> +             struct sfc_mae_encap_header **encap_headerp)
>>> +{
>>> +    struct sfc_mae_encap_header *encap_header;
>>> +    struct sfc_mae *mae = &sa->mae;
>>> +
>>> +    SFC_ASSERT(sfc_adapter_is_locked(sa));
>>> +
>>> +    encap_header = rte_zmalloc("sfc_mae_encap_header",
>>> +                   sizeof(*encap_header), 0);
>>> +    if (encap_header == NULL)
>>> +        return ENOMEM;
>>> +
>>> +    encap_header->size = bounce_eh->size;
>>> +
>>> +    encap_header->buf = rte_malloc("sfc_mae_encap_header_buf",
>>> +                       encap_header->size, 0);
>>> +    if (encap_header->buf == NULL) {
>>> +        rte_free(encap_header);
>>> +        return ENOMEM;
>>> +    }
>>
>> Are the error codes positives on purpose?
>> checkpatch is throwing this warning:
>> USE_NEGATIVE_ERRNO: return of an errno should typically be negative
>> (ie: return -ENOMEM)
>
> Kind of yes, on purpose. It has been like that for a long time
> already; it's simpler to keep errors positive in all such small
> internal helpers and then negate the result in the place where
> rte_flow_error_set() is used. We understand the concern of yours; our
> code is tested for error path correctness every now and again. If
> there're some inconsistencies, we are ready to fix such in no time.

Yes, unfortunately base driver uses positive error codes.

The idea here is that interface between DPDK PMD and base
driver is much wider than interface between DPDK PMD and
ethdev. That's why it is much easier to care about converting
from positive to negative on PMD-ethdev border. Also rte_errno
is positive.

>> Also the base code has a lot of these warnings:
>> RETURN_PARENTHESES: return is not a function, parentheses are not
>> required

Base driver code was initially created for FreeBSD and Solaris which require
parenthesis around return value.

>> I guess you cannot do anything to avoid it in base code?
>
> Yes, your understanding is correct. Sorry for the inconvenience.
>


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

end of thread, other threads:[~2021-04-01  6:38 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-12  9:31 [dpdk-dev] [PATCH 01/10] ethdev: reuse header definition in flow pattern item ETH Ivan Malov
2021-03-12  9:31 ` [dpdk-dev] [PATCH 02/10] ethdev: reuse header definition in flow pattern item VLAN Ivan Malov
2021-03-16 23:05   ` Ori Kam
2021-03-12  9:31 ` [dpdk-dev] [PATCH 03/10] net: clarify endianness of 32-bit fields in VXLAN headers Ivan Malov
2021-03-12  9:31 ` [dpdk-dev] [PATCH 04/10] ethdev: reuse header definition in flow pattern item VXLAN Ivan Malov
2021-03-12  9:31 ` [dpdk-dev] [PATCH 05/10] common/sfc_efx/base: support encap. header provisioning Ivan Malov
2021-03-12  9:31 ` [dpdk-dev] [PATCH 06/10] common/sfc_efx/base: support adding action ENCAP to a set Ivan Malov
2021-03-12  9:31 ` [dpdk-dev] [PATCH 07/10] net/sfc: change MAE rule actions parse API Ivan Malov
2021-03-12  9:31 ` [dpdk-dev] [PATCH 08/10] net/sfc: support action VXLAN ENCAP in MAE backend Ivan Malov
2021-03-12  9:31 ` [dpdk-dev] [PATCH 09/10] common/sfc_efx/base: support adding action DECAP to a set Ivan Malov
2021-03-12  9:31 ` [dpdk-dev] [PATCH 10/10] net/sfc: support action VXLAN DECAP in transfer rules Ivan Malov
2021-03-12 11:07 ` [dpdk-dev] [PATCH v2 01/10] ethdev: reuse header definition in flow pattern item ETH Ivan Malov
2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 02/10] ethdev: reuse header definition in flow pattern item VLAN Ivan Malov
2021-03-16 16:58     ` Ferruh Yigit
2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 03/10] net: clarify endianness of 32-bit fields in VXLAN headers Ivan Malov
2021-03-16 17:34     ` Ferruh Yigit
2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 04/10] ethdev: reuse header definition in flow pattern item VXLAN Ivan Malov
2021-03-16 17:35     ` Ferruh Yigit
2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 05/10] common/sfc_efx/base: support encap. header provisioning Ivan Malov
2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 06/10] common/sfc_efx/base: support adding action ENCAP to a set Ivan Malov
2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 07/10] net/sfc: change MAE rule actions parse API Ivan Malov
2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 08/10] net/sfc: support action VXLAN ENCAP in MAE backend Ivan Malov
2021-03-16 17:10     ` Ivan Malov
2021-03-16 17:15       ` Ferruh Yigit
2021-03-31 23:21     ` Thomas Monjalon
2021-03-31 23:36       ` Ivan Malov
2021-04-01  6:38         ` Andrew Rybchenko
2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 09/10] common/sfc_efx/base: support adding action DECAP to a set Ivan Malov
2021-03-12 11:07   ` [dpdk-dev] [PATCH v2 10/10] net/sfc: support action VXLAN DECAP in transfer rules Ivan Malov
2021-03-16 16:58   ` [dpdk-dev] [PATCH v2 01/10] ethdev: reuse header definition in flow pattern item ETH Ferruh Yigit
2021-03-16 17:38   ` Ferruh Yigit
2021-03-17  6:40     ` Andrew Rybchenko
2021-03-22  9:01       ` Ferruh Yigit
2021-03-22 10:10         ` Andrew Rybchenko
2021-03-22 16:49   ` Ferruh Yigit
2021-03-16 23:03 ` [dpdk-dev] [PATCH " Ori Kam

DPDK patches and discussions

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://inbox.dpdk.org/dev/0 dev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 dev dev/ https://inbox.dpdk.org/dev \
		dev@dpdk.org
	public-inbox-index dev

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://inbox.dpdk.org/inbox.dpdk.dev


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git