DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 0/4] support DV encap and decap actions
@ 2018-09-27 14:50 Dekel Peled
  2018-09-27 14:50 ` [dpdk-dev] [PATCH 1/4] net/mlx5: add flow action functions to glue Dekel Peled
                   ` (8 more replies)
  0 siblings, 9 replies; 94+ messages in thread
From: Dekel Peled @ 2018-09-27 14:50 UTC (permalink / raw)
  To: dev, shahafs, yskoh; +Cc: orika

This series adds support of encap and decap actions in DV format.
It is using the generic encapsulation framework from [1].
Note that encap action is relevant for egress only.
Hence this series should be merged on top of [2].

[1] "ethdev: add generic L2/L3 tunnel encapsulation actions"
    http://mails.dpdk.org/archives/dev/2018-September/113122.html
[2] "net/mlx5: allow flow rule with attribute egress"
    http://mails.dpdk.org/archives/dev/2018-September/113276.html

Dekel Peled (4):
  net/mlx5: add flow action functions to glue
  net/mlx5: add definitions for DV encap and decap
  net/mlx5: add DV encap L2 and L3 operations
  net/mlx5: add DV decap L2 and L3 operations

 drivers/net/mlx5/mlx5_flow.c    |  10 +
 drivers/net/mlx5/mlx5_flow.h    |   7 +
 drivers/net/mlx5/mlx5_flow_dv.c | 487 +++++++++++++++++++++++++++++++++++++++-
 drivers/net/mlx5/mlx5_glue.c    |  33 +++
 drivers/net/mlx5/mlx5_glue.h    |   7 +
 5 files changed, 539 insertions(+), 5 deletions(-)

-- 
1.8.3.1

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

* [dpdk-dev] [PATCH 1/4] net/mlx5: add flow action functions to glue
  2018-09-27 14:50 [dpdk-dev] [PATCH 0/4] support DV encap and decap actions Dekel Peled
@ 2018-09-27 14:50 ` Dekel Peled
  2018-10-02  1:02   ` Yongseok Koh
  2018-09-27 14:50 ` [dpdk-dev] [PATCH 2/4] net/mlx5: add definitions for DV encap and decap Dekel Peled
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 94+ messages in thread
From: Dekel Peled @ 2018-09-27 14:50 UTC (permalink / raw)
  To: dev, shahafs, yskoh; +Cc: orika

This patch adds glue functions for operations:
- Create packet reformat (encap/decap) flow action.
- Destroy flow action.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/mlx5_glue.c | 33 +++++++++++++++++++++++++++++++++
 drivers/net/mlx5/mlx5_glue.h |  7 +++++++
 2 files changed, 40 insertions(+)

diff --git a/drivers/net/mlx5/mlx5_glue.c b/drivers/net/mlx5/mlx5_glue.c
index 48590df..caa4c34 100644
--- a/drivers/net/mlx5/mlx5_glue.c
+++ b/drivers/net/mlx5/mlx5_glue.c
@@ -174,6 +174,12 @@
 	return ibv_destroy_flow(flow_id);
 }
 
+static int
+mlx5_glue_destroy_flow_action(struct ibv_flow_action *action)
+{
+	return ibv_destroy_flow_action(action);
+}
+
 static struct ibv_qp *
 mlx5_glue_create_qp(struct ibv_pd *pd, struct ibv_qp_init_attr *qp_init_attr)
 {
@@ -388,6 +394,30 @@
 #endif
 }
 
+static struct ibv_flow_action *
+mlx5_glue_dv_create_flow_action_packet_reformat
+		(struct ibv_context *ctx,
+		 size_t data_sz,
+		 void *data,
+		 enum mlx5dv_flow_action_packet_reformat_type reformat_type,
+		 enum mlx5dv_flow_table_type ft_type)
+{
+#ifdef HAVE_IBV_FLOW_DV_SUPPORT
+	return mlx5dv_create_flow_action_packet_reformat(ctx,
+							 data_sz,
+							 data,
+							 reformat_type,
+							 ft_type);
+#else
+	(void)ctx;
+	(void)data_sz;
+	(void)data;
+	(void)reformat_type;
+	(void)ft_type;
+	return NULL;
+#endif
+}
+
 alignas(RTE_CACHE_LINE_SIZE)
 const struct mlx5_glue *mlx5_glue = &(const struct mlx5_glue){
 	.version = MLX5_GLUE_VERSION,
@@ -414,6 +444,7 @@
 	.modify_wq = mlx5_glue_modify_wq,
 	.create_flow = mlx5_glue_create_flow,
 	.destroy_flow = mlx5_glue_destroy_flow,
+	.destroy_flow_action = mlx5_glue_destroy_flow_action,
 	.create_qp = mlx5_glue_create_qp,
 	.create_qp_ex = mlx5_glue_create_qp_ex,
 	.destroy_qp = mlx5_glue_destroy_qp,
@@ -437,4 +468,6 @@
 	.dv_create_flow_matcher = mlx5_glue_dv_create_flow_matcher,
 	.dv_destroy_flow_matcher = mlx5_glue_dv_destroy_flow_matcher,
 	.dv_create_flow = mlx5_glue_dv_create_flow,
+	.dv_create_flow_action_packet_reformat =
+			mlx5_glue_dv_create_flow_action_packet_reformat,
 };
diff --git a/drivers/net/mlx5/mlx5_glue.h b/drivers/net/mlx5/mlx5_glue.h
index f6e4e38..7431f58 100644
--- a/drivers/net/mlx5/mlx5_glue.h
+++ b/drivers/net/mlx5/mlx5_glue.h
@@ -85,6 +85,7 @@ struct mlx5_glue {
 	struct ibv_flow *(*create_flow)(struct ibv_qp *qp,
 					struct ibv_flow_attr *flow);
 	int (*destroy_flow)(struct ibv_flow *flow_id);
+	int (*destroy_flow_action)(struct ibv_flow_action *action);
 	struct ibv_qp *(*create_qp)(struct ibv_pd *pd,
 				    struct ibv_qp_init_attr *qp_init_attr);
 	struct ibv_qp *(*create_qp_ex)
@@ -137,6 +138,12 @@ struct mlx5_glue {
 			  struct mlx5dv_flow_match_parameters *match_value,
 			  size_t num_actions,
 			  struct mlx5dv_flow_action_attr *actions_attr);
+	struct ibv_flow_action *(*dv_create_flow_action_packet_reformat)
+		(struct ibv_context *ctx,
+		 size_t data_sz,
+		 void *data,
+		 enum mlx5dv_flow_action_packet_reformat_type reformat_type,
+		 enum mlx5dv_flow_table_type ft_type);
 };
 
 const struct mlx5_glue *mlx5_glue;
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH 2/4] net/mlx5: add definitions for DV encap and decap
  2018-09-27 14:50 [dpdk-dev] [PATCH 0/4] support DV encap and decap actions Dekel Peled
  2018-09-27 14:50 ` [dpdk-dev] [PATCH 1/4] net/mlx5: add flow action functions to glue Dekel Peled
@ 2018-09-27 14:50 ` Dekel Peled
  2018-10-03  2:58   ` Yongseok Koh
  2018-09-27 14:50 ` [dpdk-dev] [PATCH 3/4] net/mlx5: add DV encap L2 and L3 operations Dekel Peled
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 94+ messages in thread
From: Dekel Peled @ 2018-09-27 14:50 UTC (permalink / raw)
  To: dev, shahafs, yskoh; +Cc: orika

This patch add the required definitions for DV encap/decap actions.
It also adds usage of the new actions definition in validation
function of existing drop operation.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow.c | 10 ++++++++++
 drivers/net/mlx5/mlx5_flow.h |  7 +++++++
 2 files changed, 17 insertions(+)

diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 79a06df..fed0d29 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -768,6 +768,16 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't have 2 fate actions in"
 					  " same flow");
+	if (action_flags & (MLX5_ACTION_TUNNEL_DECAP |
+			    MLX5_ACTION_TUNNEL_DECAP_L3 |
+			    MLX5_ACTION_TUNNEL_ENCAP |
+			    MLX5_ACTION_TUNNEL_ENCAP_L3))
+		return rte_flow_error_set(error,
+					  ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  NULL,
+					  "can't encap or decap and drop in"
+					  " same flow");
 	if (attr->egress)
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index a353d07..4a4f923 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -90,6 +90,10 @@
 #define MLX5_ACTION_OF_PUSH_VLAN (1u << 8)
 #define MLX5_ACTION_OF_SET_VLAN_VID (1u << 9)
 #define MLX5_ACTION_OF_SET_VLAN_PCP (1u << 10)
+#define MLX5_ACTION_TUNNEL_ENCAP (1u << 11)
+#define MLX5_ACTION_TUNNEL_DECAP (1u << 12)
+#define MLX5_ACTION_TUNNEL_ENCAP_L3 (1u << 13)
+#define MLX5_ACTION_TUNNEL_DECAP_L3 (1u << 14)
 
 /* possible L3 layers protocols filtering. */
 #define MLX5_IP_PROTOCOL_TCP 6
@@ -175,6 +179,9 @@ struct mlx5_flow_dv {
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
 	struct mlx5dv_flow_action_attr actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS];
 	/**< Action list. */
+
+	struct ibv_flow_action *encap_verb; /**< Verbs object of encap. */
+	struct ibv_flow_action *decap_verb; /**< Verbs object of decap. */
 #endif
 	int actions_n; /**< number of actions. */
 };
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH 3/4] net/mlx5: add DV encap L2 and L3 operations
  2018-09-27 14:50 [dpdk-dev] [PATCH 0/4] support DV encap and decap actions Dekel Peled
  2018-09-27 14:50 ` [dpdk-dev] [PATCH 1/4] net/mlx5: add flow action functions to glue Dekel Peled
  2018-09-27 14:50 ` [dpdk-dev] [PATCH 2/4] net/mlx5: add definitions for DV encap and decap Dekel Peled
@ 2018-09-27 14:50 ` Dekel Peled
  2018-10-03  6:58   ` Yongseok Koh
  2018-09-27 14:50 ` [dpdk-dev] [PATCH 4/4] net/mlx5: add DV decap " Dekel Peled
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 94+ messages in thread
From: Dekel Peled @ 2018-09-27 14:50 UTC (permalink / raw)
  To: dev, shahafs, yskoh; +Cc: orika

This patch adds support for Direct Verbs encap operations, L2 and L3.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow_dv.c | 249 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 244 insertions(+), 5 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 1f3fcb8..50925ac 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -85,6 +85,178 @@
 }
 
 /**
+ * Validate the tunnel encap action.
+ *
+ * @param[in] action_flags
+ *   holds the actions detected until now.
+ * @param[in] action
+ *   Pointer to the encap action.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_ernno is set.
+ */
+static int
+mlx5_flow_validate_action_tunnel_encap(uint64_t action_flags,
+				       const struct rte_flow_action *action,
+				       const struct rte_flow_attr *attr,
+				       struct rte_flow_error *error)
+{
+	const struct rte_flow_action_tunnel_encap *tunnel_encap = action->conf;
+
+	if (!tunnel_encap || !(tunnel_encap->buf))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  action,
+					  "configuration cannot be null");
+	if (action_flags & MLX5_ACTION_DROP)
+		return rte_flow_error_set(error,
+					  ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  NULL,
+					  "can't drop and encap in same flow");
+	if (action_flags & (MLX5_ACTION_TUNNEL_ENCAP |
+			    MLX5_ACTION_TUNNEL_ENCAP_L3))
+		return rte_flow_error_set(error,
+					  ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  NULL,
+					  "can't have 2 encap actions in same"
+					  " flow");
+	if (attr->ingress)
+		return rte_flow_error_set(error, ENOTSUP,
+					RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
+					NULL,
+					"encap action not supported for "
+					"ingress");
+	return 0;
+}
+
+/**
+ * Validate the tunnel encap L3 action
+ *
+ * @param[in] action_flags
+ *   holds the actions detected until now.
+ * @param[in] action
+ *   Pointer to the encap action.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_ernno is set.
+ */
+static int
+mlx5_flow_validate_action_tunnel_encap_l3(uint64_t action_flags,
+					  const struct rte_flow_action *action,
+					  const struct rte_flow_attr *attr,
+					  struct rte_flow_error *error)
+{
+	const struct rte_flow_action_tunnel_encap_l3 *tunnel_encap_l3 =
+								action->conf;
+
+	if (!tunnel_encap_l3 || !(tunnel_encap_l3->buf))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  action,
+					  "configuration cannot be null");
+	if (action_flags & MLX5_ACTION_DROP)
+		return rte_flow_error_set(error,
+					  ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  NULL,
+					  "can't drop and encap in same flow");
+	if (action_flags & (MLX5_ACTION_TUNNEL_ENCAP |
+			    MLX5_ACTION_TUNNEL_ENCAP_L3))
+		return rte_flow_error_set(error,
+					  ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  NULL,
+					  "can't have 2 encap actions in same"
+					  " flow");
+	if (attr->ingress)
+		return rte_flow_error_set(error, ENOTSUP,
+					RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
+					NULL,
+					"encap action not supported for "
+					"ingress");
+	return 0;
+}
+
+/**
+ * Convert encap action to DV specification.
+ *
+ * @param[in] action
+ *   Pointer to action structure.
+ * @param[in] ctx
+ *   Verbs context.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+mlx5_flow_dv_create_encap(const struct rte_flow_action *action,
+			  struct ibv_context *ctx,
+			  struct rte_flow_error *error)
+{
+	struct ibv_flow_action *encap_verb = NULL;
+	const struct rte_flow_action_tunnel_encap *encap_data;
+
+	encap_data = (const struct rte_flow_action_tunnel_encap *)action->conf;
+	encap_verb = mlx5_glue->dv_create_flow_action_packet_reformat(ctx,
+			encap_data->size,
+			encap_data->size ? encap_data->buf :
+					   NULL,
+			MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
+			MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
+	if (!encap_verb)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create encap action");
+	return encap_verb;
+}
+
+/**
+ * Convert encap L3 action to DV specification.
+ *
+ * @param[in] action
+ *   Pointer to action structure.
+ * @param[in] ctx
+ *   Verbs context.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+mlx5_flow_dv_create_encap_l3(const struct rte_flow_action *action,
+			     struct ibv_context *ctx,
+			     struct rte_flow_error *error)
+{
+	struct ibv_flow_action *encap_l3_verb = NULL;
+	const struct rte_flow_action_tunnel_encap_l3 *encap_l3_data;
+
+	encap_l3_data =
+		(const struct rte_flow_action_tunnel_encap_l3 *)action->conf;
+	encap_l3_verb = mlx5_glue->dv_create_flow_action_packet_reformat(ctx,
+			encap_l3_data->size,
+			encap_l3_data->size ? encap_l3_data->buf :
+					      NULL,
+			MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL,
+			MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
+	if (!encap_l3_verb)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create encap L3 action");
+	return encap_l3_verb;
+}
+
+/**
  * Verify the @p attributes will be correctly understood by the NIC and store
  * them in the @p flow if everything is correct.
  *
@@ -337,6 +509,26 @@
 			action_flags |= MLX5_ACTION_COUNT;
 			++actions_n;
 			break;
+		case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP:
+			ret = mlx5_flow_validate_action_tunnel_encap
+				(action_flags,
+				 actions,
+				 attr,
+				 error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_ACTION_TUNNEL_ENCAP;
+			break;
+		case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP_L3:
+			ret = mlx5_flow_validate_action_tunnel_encap_l3
+				(action_flags,
+				 actions,
+				 attr,
+				 error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_ACTION_TUNNEL_ENCAP_L3;
+			break;
 		default:
 			return rte_flow_error_set(error, ENOTSUP,
 						  RTE_FLOW_ERROR_TYPE_ACTION,
@@ -1047,10 +1239,19 @@
  *   Flow action to translate.
  * @param[in, out] dev_flow
  *   Pointer to the mlx5_flow.
+ * @param[in] ctx
+ *   Verbs context.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_ernno is set.
  */
-static void
+static int
 flow_dv_create_action(const struct rte_flow_action *action,
-		      struct mlx5_flow *dev_flow)
+		      struct mlx5_flow *dev_flow,
+		      struct ibv_context *ctx,
+		      struct rte_flow_error *error)
 {
 	const struct rte_flow_action_queue *queue;
 	const struct rte_flow_action_rss *rss;
@@ -1095,10 +1296,35 @@
 		/* Added to array only in apply since we need the QP */
 		flow->actions |= MLX5_ACTION_RSS;
 		break;
+	case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP:
+		dev_flow->dv.actions[actions_n].type =
+			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+		dev_flow->dv.actions[actions_n].action =
+			mlx5_flow_dv_create_encap(action, ctx, error);
+		if (!(dev_flow->dv.actions[actions_n].action))
+			return -rte_errno;
+		dev_flow->dv.encap_verb =
+			dev_flow->dv.actions[actions_n].action;
+		flow->actions |= MLX5_ACTION_TUNNEL_ENCAP;
+		actions_n++;
+		break;
+	case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP_L3:
+		dev_flow->dv.actions[actions_n].type =
+			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+		dev_flow->dv.actions[actions_n].action =
+			mlx5_flow_dv_create_encap_l3(action, ctx, error);
+		if (!(dev_flow->dv.actions[actions_n].action))
+			return -rte_errno;
+		dev_flow->dv.encap_verb =
+			dev_flow->dv.actions[actions_n].action;
+		flow->actions |= MLX5_ACTION_TUNNEL_ENCAP_L3;
+		actions_n++;
+		break;
 	default:
 		break;
 	}
 	dev_flow->dv.actions_n = actions_n;
+	return 0;
 }
 
 static uint32_t matcher_zero[MLX5_ST_SZ_DW(fte_match_param)] = { 0 };
@@ -1247,6 +1473,7 @@
 	};
 	void *match_value = dev_flow->dv.value.buf;
 	uint8_t inner = 0;
+	int retval = 0;
 
 	if (priority == MLX5_FLOW_PRIO_RSVD)
 		priority = priv->config.flow_prio - 1;
@@ -1262,9 +1489,14 @@
 	matcher.egress = attr->egress;
 	if (flow_dv_matcher_register(dev, &matcher, dev_flow, error))
 		return -rte_errno;
-	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++)
-		flow_dv_create_action(actions, dev_flow);
-	return 0;
+	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
+		retval =
+		flow_dv_create_action(actions, dev_flow, priv->ctx, error);
+		if (retval)
+			break;
+	}
+
+	return retval;
 }
 
 /**
@@ -1447,6 +1679,13 @@
 		LIST_REMOVE(dev_flow, next);
 		if (dev_flow->dv.matcher)
 			flow_dv_matcher_release(dev, dev_flow->dv.matcher);
+
+		if (dev_flow->dv.encap_verb) {
+			claim_zero(mlx5_glue->destroy_flow_action
+						(dev_flow->dv.encap_verb));
+			dev_flow->dv.encap_verb = NULL;
+		}
+
 		rte_free(dev_flow);
 	}
 }
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH 4/4] net/mlx5: add DV decap L2 and L3 operations
  2018-09-27 14:50 [dpdk-dev] [PATCH 0/4] support DV encap and decap actions Dekel Peled
                   ` (2 preceding siblings ...)
  2018-09-27 14:50 ` [dpdk-dev] [PATCH 3/4] net/mlx5: add DV encap L2 and L3 operations Dekel Peled
@ 2018-09-27 14:50 ` Dekel Peled
  2018-10-03  7:07   ` Yongseok Koh
  2018-10-07 14:25 ` [dpdk-dev] [PATCH v2 0/4] add support of Direct Verbs encap and decap actions Dekel Peled
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 94+ messages in thread
From: Dekel Peled @ 2018-09-27 14:50 UTC (permalink / raw)
  To: dev, shahafs, yskoh; +Cc: orika

This patch adds support for Direct Verbs decap operations, L2 and L3.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow_dv.c | 258 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 248 insertions(+), 10 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 50925ac..ca44f13 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -126,12 +126,20 @@
 					  NULL,
 					  "can't have 2 encap actions in same"
 					  " flow");
+	if (action_flags & (MLX5_ACTION_TUNNEL_DECAP |
+			    MLX5_ACTION_TUNNEL_DECAP_L3))
+		return rte_flow_error_set(error,
+					  ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  NULL,
+					  "can't encap and decap in same"
+					  " flow");
 	if (attr->ingress)
 		return rte_flow_error_set(error, ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
-					NULL,
-					"encap action not supported for "
-					"ingress");
+					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
+					  NULL,
+					  "encap action not supported for "
+					  "ingress");
 	return 0;
 }
 
@@ -178,12 +186,130 @@
 					  NULL,
 					  "can't have 2 encap actions in same"
 					  " flow");
+	if (action_flags & (MLX5_ACTION_TUNNEL_DECAP |
+			    MLX5_ACTION_TUNNEL_DECAP_L3))
+		return rte_flow_error_set(error,
+					  ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  NULL,
+					  "can't encap and decap in same"
+					  " flow");
 	if (attr->ingress)
 		return rte_flow_error_set(error, ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
-					NULL,
-					"encap action not supported for "
-					"ingress");
+					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
+					  NULL,
+					  "encap action not supported for "
+					  "ingress");
+	return 0;
+}
+
+/**
+ * Validate the tunnel decap action
+ *
+ * @param[in] action_flags
+ *   holds the actions detected until now.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_ernno is set.
+ */
+static int
+mlx5_flow_validate_action_tunnel_decap(uint64_t action_flags,
+				       const struct rte_flow_attr *attr,
+				       struct rte_flow_error *error)
+{
+	if (action_flags & MLX5_ACTION_DROP)
+		return rte_flow_error_set(error,
+					  ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  NULL,
+					  "can't drop and decap in same flow");
+	if (action_flags & (MLX5_ACTION_TUNNEL_DECAP |
+			    MLX5_ACTION_TUNNEL_DECAP_L3))
+		return rte_flow_error_set(error,
+					  ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  NULL,
+					  "can't have 2 decap actions in same"
+					  " flow");
+	if (action_flags & (MLX5_ACTION_TUNNEL_ENCAP |
+			    MLX5_ACTION_TUNNEL_ENCAP_L3))
+		return rte_flow_error_set(error,
+					  ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  NULL,
+					  "can't encap and decap in same"
+					  " flow");
+	if (attr->egress)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
+					  NULL,
+					  "decap action not supported for "
+					  "egress");
+	return 0;
+}
+
+/**
+ * Validate the tunnel decap L3 action
+ *
+ * @param[in] action_flags
+ *   holds the actions detected until now.
+ * @param[in] action
+ *   Pointer to the decap action.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_ernno is set.
+ */
+static int
+mlx5_flow_validate_action_tunnel_decap_l3(uint64_t action_flags,
+					  const struct rte_flow_action *action,
+					  const struct rte_flow_attr *attr,
+					  struct rte_flow_error *error)
+{
+	const struct rte_flow_action_tunnel_decap_l3 *tunnel_decap_l3 =
+								action->conf;
+
+	if (!tunnel_decap_l3 || !(tunnel_decap_l3->buf))
+
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  action,
+					  "configuration cannot be null");
+	if (action_flags & MLX5_ACTION_DROP)
+		return rte_flow_error_set(error,
+					  ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  NULL,
+					  "can't drop and decap in same flow");
+	if (action_flags & (MLX5_ACTION_TUNNEL_DECAP |
+			    MLX5_ACTION_TUNNEL_DECAP_L3))
+		return rte_flow_error_set(error,
+					  ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  NULL,
+					  "can't have 2 decap actions in same"
+					  " flow");
+	if (action_flags & (MLX5_ACTION_TUNNEL_ENCAP |
+			    MLX5_ACTION_TUNNEL_ENCAP_L3))
+		return rte_flow_error_set(error,
+					  ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  NULL,
+					  "can't encap and decap in same"
+					  " flow");
+	if (attr->egress)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
+					  NULL,
+					  "decap action not supported for "
+					  "egress");
 	return 0;
 }
 
@@ -257,6 +383,72 @@
 }
 
 /**
+ * Convert decap action to DV specification.
+ *
+ * @param[in] action
+ *   Pointer to action structure.
+ * @param[in] ctx
+ *   Verbs context.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+mlx5_flow_dv_create_decap(const struct rte_flow_action *action __rte_unused,
+			  struct ibv_context *ctx,
+			  struct rte_flow_error *error)
+{
+	struct ibv_flow_action *decap_verb = NULL;
+
+	decap_verb = mlx5_glue->dv_create_flow_action_packet_reformat(ctx,
+			0, NULL,
+			MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2,
+			MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
+	if (!decap_verb)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create decap action");
+	return decap_verb;
+}
+
+/**
+ * Convert decap L3 action to DV specification.
+ *
+ * @param[in] action
+ *   Pointer to action structure.
+ * @param[in] ctx
+ *   Verbs context.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+mlx5_flow_dv_create_decap_l3(const struct rte_flow_action *action,
+			     struct ibv_context *ctx,
+			     struct rte_flow_error *error)
+{
+	struct ibv_flow_action *decap_l3_verb = NULL;
+	const struct rte_flow_action_tunnel_decap_l3 *decap_l3_data;
+
+	decap_l3_data =
+		(const struct rte_flow_action_tunnel_decap_l3 *)action->conf;
+	decap_l3_verb = mlx5_glue->dv_create_flow_action_packet_reformat(ctx,
+			decap_l3_data->size,
+			decap_l3_data->size ? decap_l3_data->buf :
+					      NULL,
+			MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2,
+			MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
+	if (!decap_l3_verb)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create decap L3 action");
+
+	return decap_l3_verb;
+}
+
+/**
  * Verify the @p attributes will be correctly understood by the NIC and store
  * them in the @p flow if everything is correct.
  *
@@ -529,6 +721,25 @@
 				return ret;
 			action_flags |= MLX5_ACTION_TUNNEL_ENCAP_L3;
 			break;
+		case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP:
+			ret = mlx5_flow_validate_action_tunnel_decap
+				(action_flags,
+				 attr,
+				 error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_ACTION_TUNNEL_DECAP;
+			break;
+		case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP_L3:
+			ret = mlx5_flow_validate_action_tunnel_decap_l3
+				(action_flags,
+				 actions,
+				 attr,
+				 error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_ACTION_TUNNEL_DECAP_L3;
+			break;
 		default:
 			return rte_flow_error_set(error, ENOTSUP,
 						  RTE_FLOW_ERROR_TYPE_ACTION,
@@ -1320,6 +1531,30 @@
 		flow->actions |= MLX5_ACTION_TUNNEL_ENCAP_L3;
 		actions_n++;
 		break;
+	case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP:
+		dev_flow->dv.actions[actions_n].type =
+			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+		dev_flow->dv.actions[actions_n].action =
+			mlx5_flow_dv_create_decap(action, ctx, error);
+		if (!(dev_flow->dv.actions[actions_n].action))
+			return -rte_errno;
+		dev_flow->dv.decap_verb =
+			dev_flow->dv.actions[actions_n].action;
+		flow->actions |= MLX5_ACTION_TUNNEL_DECAP;
+		actions_n++;
+		break;
+	case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP_L3:
+		dev_flow->dv.actions[actions_n].type =
+			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+		dev_flow->dv.actions[actions_n].action =
+			mlx5_flow_dv_create_decap_l3(action, ctx, error);
+		if (!(dev_flow->dv.actions[actions_n].action))
+			return -rte_errno;
+		dev_flow->dv.decap_verb =
+			dev_flow->dv.actions[actions_n].action;
+		flow->actions |= MLX5_ACTION_TUNNEL_DECAP_L3;
+		actions_n++;
+		break;
 	default:
 		break;
 	}
@@ -1679,13 +1914,16 @@
 		LIST_REMOVE(dev_flow, next);
 		if (dev_flow->dv.matcher)
 			flow_dv_matcher_release(dev, dev_flow->dv.matcher);
-
 		if (dev_flow->dv.encap_verb) {
 			claim_zero(mlx5_glue->destroy_flow_action
 						(dev_flow->dv.encap_verb));
 			dev_flow->dv.encap_verb = NULL;
 		}
-
+		if (dev_flow->dv.decap_verb) {
+			claim_zero(mlx5_glue->destroy_flow_action
+						(dev_flow->dv.decap_verb));
+			dev_flow->dv.decap_verb = NULL;
+		}
 		rte_free(dev_flow);
 	}
 }
-- 
1.8.3.1

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

* Re: [dpdk-dev] [PATCH 1/4] net/mlx5: add flow action functions to glue
  2018-09-27 14:50 ` [dpdk-dev] [PATCH 1/4] net/mlx5: add flow action functions to glue Dekel Peled
@ 2018-10-02  1:02   ` Yongseok Koh
  2018-10-03  6:59     ` Dekel Peled
  0 siblings, 1 reply; 94+ messages in thread
From: Yongseok Koh @ 2018-10-02  1:02 UTC (permalink / raw)
  To: Dekel Peled; +Cc: dev, Shahaf Shuler, Ori Kam

On Thu, Sep 27, 2018 at 05:50:42PM +0300, Dekel Peled wrote:
> This patch adds glue functions for operations:
> - Create packet reformat (encap/decap) flow action.
> - Destroy flow action.
> 
> Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> ---
>  drivers/net/mlx5/mlx5_glue.c | 33 +++++++++++++++++++++++++++++++++
>  drivers/net/mlx5/mlx5_glue.h |  7 +++++++
>  2 files changed, 40 insertions(+)
> 
> diff --git a/drivers/net/mlx5/mlx5_glue.c b/drivers/net/mlx5/mlx5_glue.c
> index 48590df..caa4c34 100644
> --- a/drivers/net/mlx5/mlx5_glue.c
> +++ b/drivers/net/mlx5/mlx5_glue.c
> @@ -174,6 +174,12 @@
>  	return ibv_destroy_flow(flow_id);
>  }
>  
> +static int
> +mlx5_glue_destroy_flow_action(struct ibv_flow_action *action)
> +{
> +	return ibv_destroy_flow_action(action);
> +}
> +
>  static struct ibv_qp *
>  mlx5_glue_create_qp(struct ibv_pd *pd, struct ibv_qp_init_attr *qp_init_attr)
>  {
> @@ -388,6 +394,30 @@
>  #endif
>  }
>  
> +static struct ibv_flow_action *
> +mlx5_glue_dv_create_flow_action_packet_reformat
> +		(struct ibv_context *ctx,
> +		 size_t data_sz,
> +		 void *data,
> +		 enum mlx5dv_flow_action_packet_reformat_type reformat_type,
> +		 enum mlx5dv_flow_table_type ft_type)

Aren't these two structs also new? If so, you might have to declare it in
mlx5_glue.h to avoid compilation error. Please refer to mlx5dv_flow_matcher as
an example.

> +{
> +#ifdef HAVE_IBV_FLOW_DV_SUPPORT
> +	return mlx5dv_create_flow_action_packet_reformat(ctx,
> +							 data_sz,
> +							 data,
> +							 reformat_type,
> +							 ft_type);
> +#else
> +	(void)ctx;
> +	(void)data_sz;
> +	(void)data;
> +	(void)reformat_type;
> +	(void)ft_type;
> +	return NULL;
> +#endif
> +}
> +
>  alignas(RTE_CACHE_LINE_SIZE)
>  const struct mlx5_glue *mlx5_glue = &(const struct mlx5_glue){
>  	.version = MLX5_GLUE_VERSION,
> @@ -414,6 +444,7 @@
>  	.modify_wq = mlx5_glue_modify_wq,
>  	.create_flow = mlx5_glue_create_flow,
>  	.destroy_flow = mlx5_glue_destroy_flow,
> +	.destroy_flow_action = mlx5_glue_destroy_flow_action,
>  	.create_qp = mlx5_glue_create_qp,
>  	.create_qp_ex = mlx5_glue_create_qp_ex,
>  	.destroy_qp = mlx5_glue_destroy_qp,
> @@ -437,4 +468,6 @@
>  	.dv_create_flow_matcher = mlx5_glue_dv_create_flow_matcher,
>  	.dv_destroy_flow_matcher = mlx5_glue_dv_destroy_flow_matcher,
>  	.dv_create_flow = mlx5_glue_dv_create_flow,
> +	.dv_create_flow_action_packet_reformat =
> +			mlx5_glue_dv_create_flow_action_packet_reformat,
>  };
> diff --git a/drivers/net/mlx5/mlx5_glue.h b/drivers/net/mlx5/mlx5_glue.h
> index f6e4e38..7431f58 100644
> --- a/drivers/net/mlx5/mlx5_glue.h
> +++ b/drivers/net/mlx5/mlx5_glue.h
> @@ -85,6 +85,7 @@ struct mlx5_glue {
>  	struct ibv_flow *(*create_flow)(struct ibv_qp *qp,
>  					struct ibv_flow_attr *flow);
>  	int (*destroy_flow)(struct ibv_flow *flow_id);
> +	int (*destroy_flow_action)(struct ibv_flow_action *action);
>  	struct ibv_qp *(*create_qp)(struct ibv_pd *pd,
>  				    struct ibv_qp_init_attr *qp_init_attr);
>  	struct ibv_qp *(*create_qp_ex)
> @@ -137,6 +138,12 @@ struct mlx5_glue {
>  			  struct mlx5dv_flow_match_parameters *match_value,
>  			  size_t num_actions,
>  			  struct mlx5dv_flow_action_attr *actions_attr);
> +	struct ibv_flow_action *(*dv_create_flow_action_packet_reformat)
> +		(struct ibv_context *ctx,
> +		 size_t data_sz,
> +		 void *data,
> +		 enum mlx5dv_flow_action_packet_reformat_type reformat_type,
> +		 enum mlx5dv_flow_table_type ft_type);
>  };
>  
>  const struct mlx5_glue *mlx5_glue;
> -- 
> 1.8.3.1
> 

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

* Re: [dpdk-dev] [PATCH 2/4] net/mlx5: add definitions for DV encap and decap
  2018-09-27 14:50 ` [dpdk-dev] [PATCH 2/4] net/mlx5: add definitions for DV encap and decap Dekel Peled
@ 2018-10-03  2:58   ` Yongseok Koh
  2018-10-03  7:27     ` Dekel Peled
  0 siblings, 1 reply; 94+ messages in thread
From: Yongseok Koh @ 2018-10-03  2:58 UTC (permalink / raw)
  To: Dekel Peled; +Cc: dev, Shahaf Shuler, Ori Kam

On Thu, Sep 27, 2018 at 05:50:43PM +0300, Dekel Peled wrote:
> This patch add the required definitions for DV encap/decap actions.
> It also adds usage of the new actions definition in validation
> function of existing drop operation.
> 
> Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> ---
>  drivers/net/mlx5/mlx5_flow.c | 10 ++++++++++
>  drivers/net/mlx5/mlx5_flow.h |  7 +++++++
>  2 files changed, 17 insertions(+)
> 
> diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
> index 79a06df..fed0d29 100644
> --- a/drivers/net/mlx5/mlx5_flow.c
> +++ b/drivers/net/mlx5/mlx5_flow.c
> @@ -768,6 +768,16 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
>  					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
>  					  "can't have 2 fate actions in"
>  					  " same flow");
> +	if (action_flags & (MLX5_ACTION_TUNNEL_DECAP |
> +			    MLX5_ACTION_TUNNEL_DECAP_L3 |
> +			    MLX5_ACTION_TUNNEL_ENCAP |
> +			    MLX5_ACTION_TUNNEL_ENCAP_L3))
> +		return rte_flow_error_set(error,
> +					  ENOTSUP,

Shouldn't it be EINVAL?

> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> +					  NULL,
> +					  "can't encap or decap and drop in"
> +					  " same flow");
>  	if (attr->egress)
>  		return rte_flow_error_set(error, ENOTSUP,
>  					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
> diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
> index a353d07..4a4f923 100644
> --- a/drivers/net/mlx5/mlx5_flow.h
> +++ b/drivers/net/mlx5/mlx5_flow.h
> @@ -90,6 +90,10 @@
>  #define MLX5_ACTION_OF_PUSH_VLAN (1u << 8)
>  #define MLX5_ACTION_OF_SET_VLAN_VID (1u << 9)
>  #define MLX5_ACTION_OF_SET_VLAN_PCP (1u << 10)
> +#define MLX5_ACTION_TUNNEL_ENCAP (1u << 11)
> +#define MLX5_ACTION_TUNNEL_DECAP (1u << 12)
> +#define MLX5_ACTION_TUNNEL_ENCAP_L3 (1u << 13)
> +#define MLX5_ACTION_TUNNEL_DECAP_L3 (1u << 14)

Please rebase it on top of my multi-table patchset, which is PR #878 because it
also adds new actions.
>  
>  /* possible L3 layers protocols filtering. */
>  #define MLX5_IP_PROTOCOL_TCP 6
> @@ -175,6 +179,9 @@ struct mlx5_flow_dv {
>  #ifdef HAVE_IBV_FLOW_DV_SUPPORT
>  	struct mlx5dv_flow_action_attr actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS];
>  	/**< Action list. */
> +

No blank line.

> +	struct ibv_flow_action *encap_verb; /**< Verbs object of encap. */
> +	struct ibv_flow_action *decap_verb; /**< Verbs object of decap. */
>  #endif
>  	int actions_n; /**< number of actions. */
>  };
> -- 
> 1.8.3.1
> 

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

* Re: [dpdk-dev] [PATCH 3/4] net/mlx5: add DV encap L2 and L3 operations
  2018-09-27 14:50 ` [dpdk-dev] [PATCH 3/4] net/mlx5: add DV encap L2 and L3 operations Dekel Peled
@ 2018-10-03  6:58   ` Yongseok Koh
  2018-10-03  8:35     ` Dekel Peled
  0 siblings, 1 reply; 94+ messages in thread
From: Yongseok Koh @ 2018-10-03  6:58 UTC (permalink / raw)
  To: Dekel Peled; +Cc: dev, Shahaf Shuler, Ori Kam

On Thu, Sep 27, 2018 at 05:50:44PM +0300, Dekel Peled wrote:
> This patch adds support for Direct Verbs encap operations, L2 and L3.
> 
> Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> ---
>  drivers/net/mlx5/mlx5_flow_dv.c | 249 +++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 244 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
> index 1f3fcb8..50925ac 100644
> --- a/drivers/net/mlx5/mlx5_flow_dv.c
> +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> @@ -85,6 +85,178 @@
>  }
>  
>  /**
> + * Validate the tunnel encap action.
> + *
> + * @param[in] action_flags
> + *   holds the actions detected until now.
> + * @param[in] action
> + *   Pointer to the encap action.
> + * @param[in] attr
> + *   Pointer to flow attributes
> + * @param[out] error
> + *   Pointer to error structure.
> + *
> + * @return
> + *   0 on success, a negative errno value otherwise and rte_ernno is set.
> + */
> +static int
> +mlx5_flow_validate_action_tunnel_encap(uint64_t action_flags,

A static func in this file should start from flow_dv_. Or, you can move these to
mlx5_flow.c as general validation helpers. I prefer the latter.

> +				       const struct rte_flow_action *action,
> +				       const struct rte_flow_attr *attr,
> +				       struct rte_flow_error *error)
> +{
> +	const struct rte_flow_action_tunnel_encap *tunnel_encap = action->conf;
> +
> +	if (!tunnel_encap || !(tunnel_encap->buf))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> +					  action,

Two lines above can be merged? Please check others and merge lines as much as
possible.

> +					  "configuration cannot be null");
> +	if (action_flags & MLX5_ACTION_DROP)
> +		return rte_flow_error_set(error,
> +					  ENOTSUP,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> +					  NULL,
> +					  "can't drop and encap in same flow");
> +	if (action_flags & (MLX5_ACTION_TUNNEL_ENCAP |
> +			    MLX5_ACTION_TUNNEL_ENCAP_L3))
> +		return rte_flow_error_set(error,
> +					  ENOTSUP,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> +					  NULL,
> +					  "can't have 2 encap actions in same"
> +					  " flow");
> +	if (attr->ingress)
> +		return rte_flow_error_set(error, ENOTSUP,
> +					RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> +					NULL,
> +					"encap action not supported for "
> +					"ingress");
> +	return 0;
> +}
> +
> +/**
> + * Validate the tunnel encap L3 action
> + *
> + * @param[in] action_flags
> + *   holds the actions detected until now.
> + * @param[in] action
> + *   Pointer to the encap action.
> + * @param[in] attr
> + *   Pointer to flow attributes
> + * @param[out] error
> + *   Pointer to error structure.
> + *
> + * @return
> + *   0 on success, a negative errno value otherwise and rte_ernno is set.
> + */
> +static int
> +mlx5_flow_validate_action_tunnel_encap_l3(uint64_t action_flags,
> +					  const struct rte_flow_action *action,
> +					  const struct rte_flow_attr *attr,
> +					  struct rte_flow_error *error)
> +{
> +	const struct rte_flow_action_tunnel_encap_l3 *tunnel_encap_l3 =
> +								action->conf;

Indentation.

	const struct rte_flow_action_tunnel_encap_l3 *tunnel_encap_l3 =
		action->conf;

> +
> +	if (!tunnel_encap_l3 || !(tunnel_encap_l3->buf))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> +					  action,
> +					  "configuration cannot be null");
> +	if (action_flags & MLX5_ACTION_DROP)
> +		return rte_flow_error_set(error,
> +					  ENOTSUP,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> +					  NULL,
> +					  "can't drop and encap in same flow");
> +	if (action_flags & (MLX5_ACTION_TUNNEL_ENCAP |
> +			    MLX5_ACTION_TUNNEL_ENCAP_L3))
> +		return rte_flow_error_set(error,
> +					  ENOTSUP,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> +					  NULL,
> +					  "can't have 2 encap actions in same"
> +					  " flow");
> +	if (attr->ingress)
> +		return rte_flow_error_set(error, ENOTSUP,
> +					RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> +					NULL,
> +					"encap action not supported for "
> +					"ingress");
> +	return 0;
> +}
> +
> +/**
> + * Convert encap action to DV specification.
> + *
> + * @param[in] action
> + *   Pointer to action structure.
> + * @param[in] ctx
> + *   Verbs context.
> + * @param[out] error
> + *   Pointer to the error structure.
> + *
> + * @return
> + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> + */
> +static struct ibv_flow_action *
> +mlx5_flow_dv_create_encap(const struct rte_flow_action *action,

Change to flow_dv_create_encap()

> +			  struct ibv_context *ctx,
> +			  struct rte_flow_error *error)
> +{
> +	struct ibv_flow_action *encap_verb = NULL;
> +	const struct rte_flow_action_tunnel_encap *encap_data;
> +
> +	encap_data = (const struct rte_flow_action_tunnel_encap *)action->conf;
> +	encap_verb = mlx5_glue->dv_create_flow_action_packet_reformat(ctx,
> +			encap_data->size,
> +			encap_data->size ? encap_data->buf :
> +					   NULL,
> +			MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
> +			MLX5DV_FLOW_TABLE_TYPE_NIC_TX);

Indentation.

	encap_verb = mlx5_glue->dv_create_flow_action_packet_reformat
		(ctx, encap_data->size,
		 encap_data->size ? encap_data->buf : NULL,
		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);

Please make the same change to others.

> +	if (!encap_verb)
> +		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
> +				   NULL, "cannot create encap action");
> +	return encap_verb;
> +}
> +
> +/**
> + * Convert encap L3 action to DV specification.
> + *
> + * @param[in] action
> + *   Pointer to action structure.
> + * @param[in] ctx
> + *   Verbs context.
> + * @param[out] error
> + *   Pointer to the error structure.
> + *
> + * @return
> + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> + */
> +static struct ibv_flow_action *
> +mlx5_flow_dv_create_encap_l3(const struct rte_flow_action *action,

Change to flow_dv_create_encap_l3()

> +			     struct ibv_context *ctx,
> +			     struct rte_flow_error *error)
> +{
> +	struct ibv_flow_action *encap_l3_verb = NULL;
> +	const struct rte_flow_action_tunnel_encap_l3 *encap_l3_data;
> +
> +	encap_l3_data =
> +		(const struct rte_flow_action_tunnel_encap_l3 *)action->conf;
> +	encap_l3_verb = mlx5_glue->dv_create_flow_action_packet_reformat(ctx,
> +			encap_l3_data->size,
> +			encap_l3_data->size ? encap_l3_data->buf :
> +					      NULL,
> +			MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL,
> +			MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
> +	if (!encap_l3_verb)
> +		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
> +				   NULL, "cannot create encap L3 action");
> +	return encap_l3_verb;
> +}
> +
> +/**
>   * Verify the @p attributes will be correctly understood by the NIC and store
>   * them in the @p flow if everything is correct.
>   *
> @@ -337,6 +509,26 @@
>  			action_flags |= MLX5_ACTION_COUNT;
>  			++actions_n;
>  			break;
> +		case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP:
> +			ret = mlx5_flow_validate_action_tunnel_encap
> +				(action_flags,
> +				 actions,
> +				 attr,
> +				 error);

Can be one line.

> +			if (ret < 0)
> +				return ret;
> +			action_flags |= MLX5_ACTION_TUNNEL_ENCAP;
> +			break;
> +		case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP_L3:
> +			ret = mlx5_flow_validate_action_tunnel_encap_l3
> +				(action_flags,
> +				 actions,
> +				 attr,
> +				 error);
> +			if (ret < 0)
> +				return ret;
> +			action_flags |= MLX5_ACTION_TUNNEL_ENCAP_L3;
> +			break;
>  		default:
>  			return rte_flow_error_set(error, ENOTSUP,
>  						  RTE_FLOW_ERROR_TYPE_ACTION,
> @@ -1047,10 +1239,19 @@
>   *   Flow action to translate.
>   * @param[in, out] dev_flow
>   *   Pointer to the mlx5_flow.
> + * @param[in] ctx
> + *   Verbs context.
> + * @param[out] error
> + *   Pointer to the error structure.
> + *
> + * @return
> + *   0 on success, a negative errno value otherwise and rte_ernno is set.
>   */
> -static void
> +static int
>  flow_dv_create_action(const struct rte_flow_action *action,
> -		      struct mlx5_flow *dev_flow)
> +		      struct mlx5_flow *dev_flow,
> +		      struct ibv_context *ctx,

If it is just priv->ctx, it would be better to get dev as an arg and make
mlx5_flow_dv_create_encap*(dev, ...) gets priv->ctx from dev.

> +		      struct rte_flow_error *error)
>  {
>  	const struct rte_flow_action_queue *queue;
>  	const struct rte_flow_action_rss *rss;
> @@ -1095,10 +1296,35 @@
>  		/* Added to array only in apply since we need the QP */
>  		flow->actions |= MLX5_ACTION_RSS;
>  		break;
> +	case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP:
> +		dev_flow->dv.actions[actions_n].type =
> +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> +		dev_flow->dv.actions[actions_n].action =
> +			mlx5_flow_dv_create_encap(action, ctx, error);
> +		if (!(dev_flow->dv.actions[actions_n].action))
> +			return -rte_errno;
> +		dev_flow->dv.encap_verb =
> +			dev_flow->dv.actions[actions_n].action;
> +		flow->actions |= MLX5_ACTION_TUNNEL_ENCAP;
> +		actions_n++;
> +		break;
> +	case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP_L3:
> +		dev_flow->dv.actions[actions_n].type =
> +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> +		dev_flow->dv.actions[actions_n].action =
> +			mlx5_flow_dv_create_encap_l3(action, ctx, error);
> +		if (!(dev_flow->dv.actions[actions_n].action))
> +			return -rte_errno;
> +		dev_flow->dv.encap_verb =
> +			dev_flow->dv.actions[actions_n].action;
> +		flow->actions |= MLX5_ACTION_TUNNEL_ENCAP_L3;
> +		actions_n++;
> +		break;
>  	default:
>  		break;
>  	}
>  	dev_flow->dv.actions_n = actions_n;
> +	return 0;
>  }
>  
>  static uint32_t matcher_zero[MLX5_ST_SZ_DW(fte_match_param)] = { 0 };
> @@ -1247,6 +1473,7 @@
>  	};
>  	void *match_value = dev_flow->dv.value.buf;
>  	uint8_t inner = 0;
> +	int retval = 0;
>  
>  	if (priority == MLX5_FLOW_PRIO_RSVD)
>  		priority = priv->config.flow_prio - 1;
> @@ -1262,9 +1489,14 @@
>  	matcher.egress = attr->egress;
>  	if (flow_dv_matcher_register(dev, &matcher, dev_flow, error))
>  		return -rte_errno;
> -	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++)
> -		flow_dv_create_action(actions, dev_flow);
> -	return 0;
> +	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
> +		retval =
> +		flow_dv_create_action(actions, dev_flow, priv->ctx, error);
> +		if (retval)
> +			break;

The following looks better matched?

		if (flow_dv_create_action(dev, actions, dev_flow, error))
			return -rte_errno;

And leave 'return 0;' as is below.

BTW, flow_dv_matcher_register() allocates mlx5_flow_dv_matcher or increase the
refcnt. Then, if it fails here, doesn't it need to clean that up?

> +	}
> +

No blank line is allowed. Please fix other occurrences too.

> +	return retval;
>  }
>  
>  /**
> @@ -1447,6 +1679,13 @@
>  		LIST_REMOVE(dev_flow, next);
>  		if (dev_flow->dv.matcher)
>  			flow_dv_matcher_release(dev, dev_flow->dv.matcher);
> +
> +		if (dev_flow->dv.encap_verb) {
> +			claim_zero(mlx5_glue->destroy_flow_action
> +						(dev_flow->dv.encap_verb));
> +			dev_flow->dv.encap_verb = NULL;
> +		}
> +
>  		rte_free(dev_flow);
>  	}
>  }
> -- 
> 1.8.3.1
> 

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

* Re: [dpdk-dev] [PATCH 1/4] net/mlx5: add flow action functions to glue
  2018-10-02  1:02   ` Yongseok Koh
@ 2018-10-03  6:59     ` Dekel Peled
  0 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-03  6:59 UTC (permalink / raw)
  To: Yongseok Koh; +Cc: dev, Shahaf Shuler, Ori Kam

Thanks, PSB.

> -----Original Message-----
> From: Yongseok Koh
> Sent: Tuesday, October 2, 2018 4:03 AM
> To: Dekel Peled <dekelp@mellanox.com>
> Cc: dev@dpdk.org; Shahaf Shuler <shahafs@mellanox.com>; Ori Kam
> <orika@mellanox.com>
> Subject: Re: [PATCH 1/4] net/mlx5: add flow action functions to glue
> 
> On Thu, Sep 27, 2018 at 05:50:42PM +0300, Dekel Peled wrote:
> > This patch adds glue functions for operations:
> > - Create packet reformat (encap/decap) flow action.
> > - Destroy flow action.
> >
> > Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> > ---
> >  drivers/net/mlx5/mlx5_glue.c | 33
> +++++++++++++++++++++++++++++++++
> > drivers/net/mlx5/mlx5_glue.h |  7 +++++++
> >  2 files changed, 40 insertions(+)
> >
> > diff --git a/drivers/net/mlx5/mlx5_glue.c
> > b/drivers/net/mlx5/mlx5_glue.c index 48590df..caa4c34 100644
> > --- a/drivers/net/mlx5/mlx5_glue.c
> > +++ b/drivers/net/mlx5/mlx5_glue.c
> > @@ -174,6 +174,12 @@
> >  	return ibv_destroy_flow(flow_id);
> >  }
> >
> > +static int
> > +mlx5_glue_destroy_flow_action(struct ibv_flow_action *action) {
> > +	return ibv_destroy_flow_action(action); }
> > +
> >  static struct ibv_qp *
> >  mlx5_glue_create_qp(struct ibv_pd *pd, struct ibv_qp_init_attr
> > *qp_init_attr)  { @@ -388,6 +394,30 @@  #endif  }
> >
> > +static struct ibv_flow_action *
> > +mlx5_glue_dv_create_flow_action_packet_reformat
> > +		(struct ibv_context *ctx,
> > +		 size_t data_sz,
> > +		 void *data,
> > +		 enum mlx5dv_flow_action_packet_reformat_type
> reformat_type,
> > +		 enum mlx5dv_flow_table_type ft_type)
> 
> Aren't these two structs also new? If so, you might have to declare it in
> mlx5_glue.h to avoid compilation error. Please refer to
> mlx5dv_flow_matcher as an example.

Done.

> 
> > +{
> > +#ifdef HAVE_IBV_FLOW_DV_SUPPORT
> > +	return mlx5dv_create_flow_action_packet_reformat(ctx,
> > +							 data_sz,
> > +							 data,
> > +							 reformat_type,
> > +							 ft_type);
> > +#else
> > +	(void)ctx;
> > +	(void)data_sz;
> > +	(void)data;
> > +	(void)reformat_type;
> > +	(void)ft_type;
> > +	return NULL;
> > +#endif
> > +}
> > +
> >  alignas(RTE_CACHE_LINE_SIZE)
> >  const struct mlx5_glue *mlx5_glue = &(const struct mlx5_glue){
> >  	.version = MLX5_GLUE_VERSION,
> > @@ -414,6 +444,7 @@
> >  	.modify_wq = mlx5_glue_modify_wq,
> >  	.create_flow = mlx5_glue_create_flow,
> >  	.destroy_flow = mlx5_glue_destroy_flow,
> > +	.destroy_flow_action = mlx5_glue_destroy_flow_action,
> >  	.create_qp = mlx5_glue_create_qp,
> >  	.create_qp_ex = mlx5_glue_create_qp_ex,
> >  	.destroy_qp = mlx5_glue_destroy_qp,
> > @@ -437,4 +468,6 @@
> >  	.dv_create_flow_matcher = mlx5_glue_dv_create_flow_matcher,
> >  	.dv_destroy_flow_matcher = mlx5_glue_dv_destroy_flow_matcher,
> >  	.dv_create_flow = mlx5_glue_dv_create_flow,
> > +	.dv_create_flow_action_packet_reformat =
> > +
> 	mlx5_glue_dv_create_flow_action_packet_reformat,
> >  };
> > diff --git a/drivers/net/mlx5/mlx5_glue.h
> > b/drivers/net/mlx5/mlx5_glue.h index f6e4e38..7431f58 100644
> > --- a/drivers/net/mlx5/mlx5_glue.h
> > +++ b/drivers/net/mlx5/mlx5_glue.h
> > @@ -85,6 +85,7 @@ struct mlx5_glue {
> >  	struct ibv_flow *(*create_flow)(struct ibv_qp *qp,
> >  					struct ibv_flow_attr *flow);
> >  	int (*destroy_flow)(struct ibv_flow *flow_id);
> > +	int (*destroy_flow_action)(struct ibv_flow_action *action);
> >  	struct ibv_qp *(*create_qp)(struct ibv_pd *pd,
> >  				    struct ibv_qp_init_attr *qp_init_attr);
> >  	struct ibv_qp *(*create_qp_ex)
> > @@ -137,6 +138,12 @@ struct mlx5_glue {
> >  			  struct mlx5dv_flow_match_parameters
> *match_value,
> >  			  size_t num_actions,
> >  			  struct mlx5dv_flow_action_attr *actions_attr);
> > +	struct ibv_flow_action *(*dv_create_flow_action_packet_reformat)
> > +		(struct ibv_context *ctx,
> > +		 size_t data_sz,
> > +		 void *data,
> > +		 enum mlx5dv_flow_action_packet_reformat_type
> reformat_type,
> > +		 enum mlx5dv_flow_table_type ft_type);
> >  };
> >
> >  const struct mlx5_glue *mlx5_glue;
> > --
> > 1.8.3.1
> >

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

* Re: [dpdk-dev] [PATCH 4/4] net/mlx5: add DV decap L2 and L3 operations
  2018-09-27 14:50 ` [dpdk-dev] [PATCH 4/4] net/mlx5: add DV decap " Dekel Peled
@ 2018-10-03  7:07   ` Yongseok Koh
  2018-10-03 16:14     ` Dekel Peled
  0 siblings, 1 reply; 94+ messages in thread
From: Yongseok Koh @ 2018-10-03  7:07 UTC (permalink / raw)
  To: Dekel Peled; +Cc: dev, Shahaf Shuler, Ori Kam

On Thu, Sep 27, 2018 at 05:50:45PM +0300, Dekel Peled wrote:
> This patch adds support for Direct Verbs decap operations, L2 and L3.
> 

Almost same code as encap, so I also have the same comments. :-)
One more. In the title, we can't use vendor specific acronyms.

	net/mlx5: add DV decap L2 and L3 operations

DV -> Direct Verbs

How about something like this?
	net/mlx5: add L2/L3 encap to Direct Verbs flow

> Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> ---
>  drivers/net/mlx5/mlx5_flow_dv.c | 258 ++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 248 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
> index 50925ac..ca44f13 100644
> --- a/drivers/net/mlx5/mlx5_flow_dv.c
> +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> @@ -126,12 +126,20 @@
>  					  NULL,
>  					  "can't have 2 encap actions in same"
>  					  " flow");
> +	if (action_flags & (MLX5_ACTION_TUNNEL_DECAP |
> +			    MLX5_ACTION_TUNNEL_DECAP_L3))
> +		return rte_flow_error_set(error,
> +					  ENOTSUP,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> +					  NULL,
> +					  "can't encap and decap in same"
> +					  " flow");
>  	if (attr->ingress)
>  		return rte_flow_error_set(error, ENOTSUP,
> -					RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> -					NULL,
> -					"encap action not supported for "
> -					"ingress");
> +					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> +					  NULL,
> +					  "encap action not supported for "
> +					  "ingress");
>  	return 0;
>  }
>  
> @@ -178,12 +186,130 @@
>  					  NULL,
>  					  "can't have 2 encap actions in same"
>  					  " flow");
> +	if (action_flags & (MLX5_ACTION_TUNNEL_DECAP |
> +			    MLX5_ACTION_TUNNEL_DECAP_L3))
> +		return rte_flow_error_set(error,
> +					  ENOTSUP,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> +					  NULL,
> +					  "can't encap and decap in same"
> +					  " flow");
>  	if (attr->ingress)
>  		return rte_flow_error_set(error, ENOTSUP,
> -					RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> -					NULL,
> -					"encap action not supported for "
> -					"ingress");
> +					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> +					  NULL,
> +					  "encap action not supported for "
> +					  "ingress");
> +	return 0;
> +}
> +
> +/**
> + * Validate the tunnel decap action
> + *
> + * @param[in] action_flags
> + *   holds the actions detected until now.
> + * @param[in] attr
> + *   Pointer to flow attributes
> + * @param[out] error
> + *   Pointer to error structure.
> + *
> + * @return
> + *   0 on success, a negative errno value otherwise and rte_ernno is set.
> + */
> +static int
> +mlx5_flow_validate_action_tunnel_decap(uint64_t action_flags,
> +				       const struct rte_flow_attr *attr,
> +				       struct rte_flow_error *error)
> +{
> +	if (action_flags & MLX5_ACTION_DROP)
> +		return rte_flow_error_set(error,
> +					  ENOTSUP,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> +					  NULL,
> +					  "can't drop and decap in same flow");
> +	if (action_flags & (MLX5_ACTION_TUNNEL_DECAP |
> +			    MLX5_ACTION_TUNNEL_DECAP_L3))
> +		return rte_flow_error_set(error,
> +					  ENOTSUP,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> +					  NULL,
> +					  "can't have 2 decap actions in same"
> +					  " flow");
> +	if (action_flags & (MLX5_ACTION_TUNNEL_ENCAP |
> +			    MLX5_ACTION_TUNNEL_ENCAP_L3))
> +		return rte_flow_error_set(error,
> +					  ENOTSUP,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> +					  NULL,
> +					  "can't encap and decap in same"
> +					  " flow");
> +	if (attr->egress)
> +		return rte_flow_error_set(error, ENOTSUP,
> +					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
> +					  NULL,
> +					  "decap action not supported for "
> +					  "egress");
> +	return 0;
> +}
> +
> +/**
> + * Validate the tunnel decap L3 action
> + *
> + * @param[in] action_flags
> + *   holds the actions detected until now.
> + * @param[in] action
> + *   Pointer to the decap action.
> + * @param[in] attr
> + *   Pointer to flow attributes
> + * @param[out] error
> + *   Pointer to error structure.
> + *
> + * @return
> + *   0 on success, a negative errno value otherwise and rte_ernno is set.
> + */
> +static int
> +mlx5_flow_validate_action_tunnel_decap_l3(uint64_t action_flags,
> +					  const struct rte_flow_action *action,
> +					  const struct rte_flow_attr *attr,
> +					  struct rte_flow_error *error)
> +{
> +	const struct rte_flow_action_tunnel_decap_l3 *tunnel_decap_l3 =
> +								action->conf;
> +
> +	if (!tunnel_decap_l3 || !(tunnel_decap_l3->buf))
> +
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> +					  action,
> +					  "configuration cannot be null");
> +	if (action_flags & MLX5_ACTION_DROP)
> +		return rte_flow_error_set(error,
> +					  ENOTSUP,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> +					  NULL,
> +					  "can't drop and decap in same flow");
> +	if (action_flags & (MLX5_ACTION_TUNNEL_DECAP |
> +			    MLX5_ACTION_TUNNEL_DECAP_L3))
> +		return rte_flow_error_set(error,
> +					  ENOTSUP,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> +					  NULL,
> +					  "can't have 2 decap actions in same"
> +					  " flow");
> +	if (action_flags & (MLX5_ACTION_TUNNEL_ENCAP |
> +			    MLX5_ACTION_TUNNEL_ENCAP_L3))
> +		return rte_flow_error_set(error,
> +					  ENOTSUP,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> +					  NULL,
> +					  "can't encap and decap in same"
> +					  " flow");
> +	if (attr->egress)
> +		return rte_flow_error_set(error, ENOTSUP,
> +					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
> +					  NULL,
> +					  "decap action not supported for "
> +					  "egress");
>  	return 0;
>  }
>  
> @@ -257,6 +383,72 @@
>  }
>  
>  /**
> + * Convert decap action to DV specification.
> + *
> + * @param[in] action
> + *   Pointer to action structure.
> + * @param[in] ctx
> + *   Verbs context.
> + * @param[out] error
> + *   Pointer to the error structure.
> + *
> + * @return
> + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> + */
> +static struct ibv_flow_action *
> +mlx5_flow_dv_create_decap(const struct rte_flow_action *action __rte_unused,
> +			  struct ibv_context *ctx,
> +			  struct rte_flow_error *error)
> +{
> +	struct ibv_flow_action *decap_verb = NULL;
> +
> +	decap_verb = mlx5_glue->dv_create_flow_action_packet_reformat(ctx,
> +			0, NULL,
> +			MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2,
> +			MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
> +	if (!decap_verb)
> +		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
> +				   NULL, "cannot create decap action");
> +	return decap_verb;
> +}
> +
> +/**
> + * Convert decap L3 action to DV specification.
> + *
> + * @param[in] action
> + *   Pointer to action structure.
> + * @param[in] ctx
> + *   Verbs context.
> + * @param[out] error
> + *   Pointer to the error structure.
> + *
> + * @return
> + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> + */
> +static struct ibv_flow_action *
> +mlx5_flow_dv_create_decap_l3(const struct rte_flow_action *action,
> +			     struct ibv_context *ctx,
> +			     struct rte_flow_error *error)
> +{
> +	struct ibv_flow_action *decap_l3_verb = NULL;
> +	const struct rte_flow_action_tunnel_decap_l3 *decap_l3_data;
> +
> +	decap_l3_data =
> +		(const struct rte_flow_action_tunnel_decap_l3 *)action->conf;
> +	decap_l3_verb = mlx5_glue->dv_create_flow_action_packet_reformat(ctx,
> +			decap_l3_data->size,
> +			decap_l3_data->size ? decap_l3_data->buf :
> +					      NULL,
> +			MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2,
> +			MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
> +	if (!decap_l3_verb)
> +		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
> +				   NULL, "cannot create decap L3 action");
> +
> +	return decap_l3_verb;
> +}
> +
> +/**
>   * Verify the @p attributes will be correctly understood by the NIC and store
>   * them in the @p flow if everything is correct.
>   *
> @@ -529,6 +721,25 @@
>  				return ret;
>  			action_flags |= MLX5_ACTION_TUNNEL_ENCAP_L3;
>  			break;
> +		case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP:
> +			ret = mlx5_flow_validate_action_tunnel_decap
> +				(action_flags,
> +				 attr,
> +				 error);
> +			if (ret < 0)
> +				return ret;
> +			action_flags |= MLX5_ACTION_TUNNEL_DECAP;
> +			break;
> +		case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP_L3:
> +			ret = mlx5_flow_validate_action_tunnel_decap_l3
> +				(action_flags,
> +				 actions,
> +				 attr,
> +				 error);
> +			if (ret < 0)
> +				return ret;
> +			action_flags |= MLX5_ACTION_TUNNEL_DECAP_L3;
> +			break;
>  		default:
>  			return rte_flow_error_set(error, ENOTSUP,
>  						  RTE_FLOW_ERROR_TYPE_ACTION,
> @@ -1320,6 +1531,30 @@
>  		flow->actions |= MLX5_ACTION_TUNNEL_ENCAP_L3;
>  		actions_n++;
>  		break;
> +	case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP:
> +		dev_flow->dv.actions[actions_n].type =
> +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> +		dev_flow->dv.actions[actions_n].action =
> +			mlx5_flow_dv_create_decap(action, ctx, error);
> +		if (!(dev_flow->dv.actions[actions_n].action))
> +			return -rte_errno;
> +		dev_flow->dv.decap_verb =
> +			dev_flow->dv.actions[actions_n].action;
> +		flow->actions |= MLX5_ACTION_TUNNEL_DECAP;
> +		actions_n++;
> +		break;
> +	case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP_L3:
> +		dev_flow->dv.actions[actions_n].type =
> +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> +		dev_flow->dv.actions[actions_n].action =
> +			mlx5_flow_dv_create_decap_l3(action, ctx, error);
> +		if (!(dev_flow->dv.actions[actions_n].action))
> +			return -rte_errno;
> +		dev_flow->dv.decap_verb =
> +			dev_flow->dv.actions[actions_n].action;
> +		flow->actions |= MLX5_ACTION_TUNNEL_DECAP_L3;
> +		actions_n++;
> +		break;
>  	default:
>  		break;
>  	}
> @@ -1679,13 +1914,16 @@
>  		LIST_REMOVE(dev_flow, next);
>  		if (dev_flow->dv.matcher)
>  			flow_dv_matcher_release(dev, dev_flow->dv.matcher);
> -

Looks like it is a mistake on rebasing.

>  		if (dev_flow->dv.encap_verb) {
>  			claim_zero(mlx5_glue->destroy_flow_action
>  						(dev_flow->dv.encap_verb));
>  			dev_flow->dv.encap_verb = NULL;
>  		}
> -
> +		if (dev_flow->dv.decap_verb) {
> +			claim_zero(mlx5_glue->destroy_flow_action
> +						(dev_flow->dv.decap_verb));
> +			dev_flow->dv.decap_verb = NULL;
> +		}
>  		rte_free(dev_flow);
>  	}
>  }
> -- 
> 1.8.3.1
> 

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

* Re: [dpdk-dev] [PATCH 2/4] net/mlx5: add definitions for DV encap and decap
  2018-10-03  2:58   ` Yongseok Koh
@ 2018-10-03  7:27     ` Dekel Peled
  0 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-03  7:27 UTC (permalink / raw)
  To: Yongseok Koh; +Cc: dev, Shahaf Shuler, Ori Kam

Thanks, PSB.

> -----Original Message-----
> From: Yongseok Koh
> Sent: Wednesday, October 3, 2018 5:59 AM
> To: Dekel Peled <dekelp@mellanox.com>
> Cc: dev@dpdk.org; Shahaf Shuler <shahafs@mellanox.com>; Ori Kam
> <orika@mellanox.com>
> Subject: Re: [PATCH 2/4] net/mlx5: add definitions for DV encap and decap
> 
> On Thu, Sep 27, 2018 at 05:50:43PM +0300, Dekel Peled wrote:
> > This patch add the required definitions for DV encap/decap actions.
> > It also adds usage of the new actions definition in validation
> > function of existing drop operation.
> >
> > Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> > ---
> >  drivers/net/mlx5/mlx5_flow.c | 10 ++++++++++
> > drivers/net/mlx5/mlx5_flow.h |  7 +++++++
> >  2 files changed, 17 insertions(+)
> >
> > diff --git a/drivers/net/mlx5/mlx5_flow.c
> > b/drivers/net/mlx5/mlx5_flow.c index 79a06df..fed0d29 100644
> > --- a/drivers/net/mlx5/mlx5_flow.c
> > +++ b/drivers/net/mlx5/mlx5_flow.c
> > @@ -768,6 +768,16 @@ uint32_t mlx5_flow_adjust_priority(struct
> rte_eth_dev *dev, int32_t priority,
> >  					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
> >  					  "can't have 2 fate actions in"
> >  					  " same flow");
> > +	if (action_flags & (MLX5_ACTION_TUNNEL_DECAP |
> > +			    MLX5_ACTION_TUNNEL_DECAP_L3 |
> > +			    MLX5_ACTION_TUNNEL_ENCAP |
> > +			    MLX5_ACTION_TUNNEL_ENCAP_L3))
> > +		return rte_flow_error_set(error,
> > +					  ENOTSUP,
> 
> Shouldn't it be EINVAL?

OK.

> 
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > +					  NULL,
> > +					  "can't encap or decap and drop in"
> > +					  " same flow");
> >  	if (attr->egress)
> >  		return rte_flow_error_set(error, ENOTSUP,
> >
> RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, diff --git
> > a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h index
> > a353d07..4a4f923 100644
> > --- a/drivers/net/mlx5/mlx5_flow.h
> > +++ b/drivers/net/mlx5/mlx5_flow.h
> > @@ -90,6 +90,10 @@
> >  #define MLX5_ACTION_OF_PUSH_VLAN (1u << 8)  #define
> > MLX5_ACTION_OF_SET_VLAN_VID (1u << 9)  #define
> > MLX5_ACTION_OF_SET_VLAN_PCP (1u << 10)
> > +#define MLX5_ACTION_TUNNEL_ENCAP (1u << 11) #define
> > +MLX5_ACTION_TUNNEL_DECAP (1u << 12) #define
> > +MLX5_ACTION_TUNNEL_ENCAP_L3 (1u << 13) #define
> > +MLX5_ACTION_TUNNEL_DECAP_L3 (1u << 14)
> 
> Please rebase it on top of my multi-table patchset, which is PR #878 because
> it also adds new actions.

Will do.

> >
> >  /* possible L3 layers protocols filtering. */  #define
> > MLX5_IP_PROTOCOL_TCP 6 @@ -175,6 +179,9 @@ struct mlx5_flow_dv {
> > #ifdef HAVE_IBV_FLOW_DV_SUPPORT
> >  	struct mlx5dv_flow_action_attr
> actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS];
> >  	/**< Action list. */
> > +
> 
> No blank line.

OK.

> 
> > +	struct ibv_flow_action *encap_verb; /**< Verbs object of encap. */
> > +	struct ibv_flow_action *decap_verb; /**< Verbs object of decap. */
> >  #endif
> >  	int actions_n; /**< number of actions. */  };
> > --
> > 1.8.3.1
> >

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

* Re: [dpdk-dev] [PATCH 3/4] net/mlx5: add DV encap L2 and L3 operations
  2018-10-03  6:58   ` Yongseok Koh
@ 2018-10-03  8:35     ` Dekel Peled
  2018-10-03  9:32       ` Yongseok Koh
  2018-10-03 11:47       ` Dekel Peled
  0 siblings, 2 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-03  8:35 UTC (permalink / raw)
  To: Yongseok Koh; +Cc: dev, Shahaf Shuler, Ori Kam

Thanks, PSB.

> -----Original Message-----
> From: Yongseok Koh
> Sent: Wednesday, October 3, 2018 9:58 AM
> To: Dekel Peled <dekelp@mellanox.com>
> Cc: dev@dpdk.org; Shahaf Shuler <shahafs@mellanox.com>; Ori Kam
> <orika@mellanox.com>
> Subject: Re: [PATCH 3/4] net/mlx5: add DV encap L2 and L3 operations
> 
> On Thu, Sep 27, 2018 at 05:50:44PM +0300, Dekel Peled wrote:
> > This patch adds support for Direct Verbs encap operations, L2 and L3.
> >
> > Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> > ---
> >  drivers/net/mlx5/mlx5_flow_dv.c | 249
> > +++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 244 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/net/mlx5/mlx5_flow_dv.c
> > b/drivers/net/mlx5/mlx5_flow_dv.c index 1f3fcb8..50925ac 100644
> > --- a/drivers/net/mlx5/mlx5_flow_dv.c
> > +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> > @@ -85,6 +85,178 @@
> >  }
> >
> >  /**
> > + * Validate the tunnel encap action.
> > + *
> > + * @param[in] action_flags
> > + *   holds the actions detected until now.
> > + * @param[in] action
> > + *   Pointer to the encap action.
> > + * @param[in] attr
> > + *   Pointer to flow attributes
> > + * @param[out] error
> > + *   Pointer to error structure.
> > + *
> > + * @return
> > + *   0 on success, a negative errno value otherwise and rte_ernno is set.
> > + */
> > +static int
> > +mlx5_flow_validate_action_tunnel_encap(uint64_t action_flags,
> 
> A static func in this file should start from flow_dv_. Or, you can move these
> to mlx5_flow.c as general validation helpers. I prefer the latter.

Renamed functions to flow_dv_validate_action_tunnel_...
Left it as static in mlx5_flow_dv.c, since it is relevant for DV only.

> 
> > +				       const struct rte_flow_action *action,
> > +				       const struct rte_flow_attr *attr,
> > +				       struct rte_flow_error *error) {
> > +	const struct rte_flow_action_tunnel_encap *tunnel_encap =
> > +action->conf;
> > +
> > +	if (!tunnel_encap || !(tunnel_encap->buf))
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > +					  action,
> 
> Two lines above can be merged? Please check others and merge lines as
> much as possible.

Done.

> 
> > +					  "configuration cannot be null");
> > +	if (action_flags & MLX5_ACTION_DROP)
> > +		return rte_flow_error_set(error,
> > +					  ENOTSUP,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > +					  NULL,
> > +					  "can't drop and encap in same
> flow");
> > +	if (action_flags & (MLX5_ACTION_TUNNEL_ENCAP |
> > +			    MLX5_ACTION_TUNNEL_ENCAP_L3))
> > +		return rte_flow_error_set(error,
> > +					  ENOTSUP,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > +					  NULL,
> > +					  "can't have 2 encap actions in same"
> > +					  " flow");
> > +	if (attr->ingress)
> > +		return rte_flow_error_set(error, ENOTSUP,
> > +
> 	RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> > +					NULL,
> > +					"encap action not supported for "
> > +					"ingress");
> > +	return 0;
> > +}
> > +
> > +/**
> > + * Validate the tunnel encap L3 action
> > + *
> > + * @param[in] action_flags
> > + *   holds the actions detected until now.
> > + * @param[in] action
> > + *   Pointer to the encap action.
> > + * @param[in] attr
> > + *   Pointer to flow attributes
> > + * @param[out] error
> > + *   Pointer to error structure.
> > + *
> > + * @return
> > + *   0 on success, a negative errno value otherwise and rte_ernno is set.
> > + */
> > +static int
> > +mlx5_flow_validate_action_tunnel_encap_l3(uint64_t action_flags,
> > +					  const struct rte_flow_action *action,
> > +					  const struct rte_flow_attr *attr,
> > +					  struct rte_flow_error *error)
> > +{
> > +	const struct rte_flow_action_tunnel_encap_l3 *tunnel_encap_l3 =
> > +								action->conf;
> 
> Indentation.
> 
> 	const struct rte_flow_action_tunnel_encap_l3 *tunnel_encap_l3 =
> 		action->conf;

Done.

> 
> > +
> > +	if (!tunnel_encap_l3 || !(tunnel_encap_l3->buf))
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > +					  action,
> > +					  "configuration cannot be null");
> > +	if (action_flags & MLX5_ACTION_DROP)
> > +		return rte_flow_error_set(error,
> > +					  ENOTSUP,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > +					  NULL,
> > +					  "can't drop and encap in same
> flow");
> > +	if (action_flags & (MLX5_ACTION_TUNNEL_ENCAP |
> > +			    MLX5_ACTION_TUNNEL_ENCAP_L3))
> > +		return rte_flow_error_set(error,
> > +					  ENOTSUP,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > +					  NULL,
> > +					  "can't have 2 encap actions in same"
> > +					  " flow");
> > +	if (attr->ingress)
> > +		return rte_flow_error_set(error, ENOTSUP,
> > +
> 	RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> > +					NULL,
> > +					"encap action not supported for "
> > +					"ingress");
> > +	return 0;
> > +}
> > +
> > +/**
> > + * Convert encap action to DV specification.
> > + *
> > + * @param[in] action
> > + *   Pointer to action structure.
> > + * @param[in] ctx
> > + *   Verbs context.
> > + * @param[out] error
> > + *   Pointer to the error structure.
> > + *
> > + * @return
> > + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> > + */
> > +static struct ibv_flow_action *
> > +mlx5_flow_dv_create_encap(const struct rte_flow_action *action,
> 
> Change to flow_dv_create_encap()

Done.

> 
> > +			  struct ibv_context *ctx,
> > +			  struct rte_flow_error *error)
> > +{
> > +	struct ibv_flow_action *encap_verb = NULL;
> > +	const struct rte_flow_action_tunnel_encap *encap_data;
> > +
> > +	encap_data = (const struct rte_flow_action_tunnel_encap *)action-
> >conf;
> > +	encap_verb = mlx5_glue-
> >dv_create_flow_action_packet_reformat(ctx,
> > +			encap_data->size,
> > +			encap_data->size ? encap_data->buf :
> > +					   NULL,
> > +
> 	MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TU
> NNEL,
> > +			MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
> 
> Indentation.

I'm using very long MLX5DV_... names defined in rdma-core.
If I use the required indentation I get illegal line length.

> 
> 	encap_verb = mlx5_glue->dv_create_flow_action_packet_reformat
> 		(ctx, encap_data->size,
> 		 encap_data->size ? encap_data->buf : NULL,
> 
> MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
> 		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
> 
> Please make the same change to others.
> 
> > +	if (!encap_verb)
> > +		rte_flow_error_set(error, EINVAL,
> RTE_FLOW_ERROR_TYPE_ACTION,
> > +				   NULL, "cannot create encap action");
> > +	return encap_verb;
> > +}
> > +
> > +/**
> > + * Convert encap L3 action to DV specification.
> > + *
> > + * @param[in] action
> > + *   Pointer to action structure.
> > + * @param[in] ctx
> > + *   Verbs context.
> > + * @param[out] error
> > + *   Pointer to the error structure.
> > + *
> > + * @return
> > + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> > + */
> > +static struct ibv_flow_action *
> > +mlx5_flow_dv_create_encap_l3(const struct rte_flow_action *action,
> 
> Change to flow_dv_create_encap_l3()

Done.

> 
> > +			     struct ibv_context *ctx,
> > +			     struct rte_flow_error *error) {
> > +	struct ibv_flow_action *encap_l3_verb = NULL;
> > +	const struct rte_flow_action_tunnel_encap_l3 *encap_l3_data;
> > +
> > +	encap_l3_data =
> > +		(const struct rte_flow_action_tunnel_encap_l3 *)action-
> >conf;
> > +	encap_l3_verb = mlx5_glue-
> >dv_create_flow_action_packet_reformat(ctx,
> > +			encap_l3_data->size,
> > +			encap_l3_data->size ? encap_l3_data->buf :
> > +					      NULL,
> > +
> 	MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TU
> NNEL,
> > +			MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
> > +	if (!encap_l3_verb)
> > +		rte_flow_error_set(error, EINVAL,
> RTE_FLOW_ERROR_TYPE_ACTION,
> > +				   NULL, "cannot create encap L3 action");
> > +	return encap_l3_verb;
> > +}
> > +
> > +/**
> >   * Verify the @p attributes will be correctly understood by the NIC and
> store
> >   * them in the @p flow if everything is correct.
> >   *
> > @@ -337,6 +509,26 @@
> >  			action_flags |= MLX5_ACTION_COUNT;
> >  			++actions_n;
> >  			break;
> > +		case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP:
> > +			ret = mlx5_flow_validate_action_tunnel_encap
> > +				(action_flags,
> > +				 actions,
> > +				 attr,
> > +				 error);
> 
> Can be one line.

Done.

> 
> > +			if (ret < 0)
> > +				return ret;
> > +			action_flags |= MLX5_ACTION_TUNNEL_ENCAP;
> > +			break;
> > +		case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP_L3:
> > +			ret = mlx5_flow_validate_action_tunnel_encap_l3
> > +				(action_flags,
> > +				 actions,
> > +				 attr,
> > +				 error);
> > +			if (ret < 0)
> > +				return ret;
> > +			action_flags |= MLX5_ACTION_TUNNEL_ENCAP_L3;
> > +			break;
> >  		default:
> >  			return rte_flow_error_set(error, ENOTSUP,
> >
> RTE_FLOW_ERROR_TYPE_ACTION,
> > @@ -1047,10 +1239,19 @@
> >   *   Flow action to translate.
> >   * @param[in, out] dev_flow
> >   *   Pointer to the mlx5_flow.
> > + * @param[in] ctx
> > + *   Verbs context.
> > + * @param[out] error
> > + *   Pointer to the error structure.
> > + *
> > + * @return
> > + *   0 on success, a negative errno value otherwise and rte_ernno is set.
> >   */
> > -static void
> > +static int
> >  flow_dv_create_action(const struct rte_flow_action *action,
> > -		      struct mlx5_flow *dev_flow)
> > +		      struct mlx5_flow *dev_flow,
> > +		      struct ibv_context *ctx,
> 
> If it is just priv->ctx, it would be better to get dev as an arg and make
> mlx5_flow_dv_create_encap*(dev, ...) gets priv->ctx from dev.

I considered it during implementation, but preferred to give the functions only what they need.

> 
> > +		      struct rte_flow_error *error)
> >  {
> >  	const struct rte_flow_action_queue *queue;
> >  	const struct rte_flow_action_rss *rss; @@ -1095,10 +1296,35 @@
> >  		/* Added to array only in apply since we need the QP */
> >  		flow->actions |= MLX5_ACTION_RSS;
> >  		break;
> > +	case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP:
> > +		dev_flow->dv.actions[actions_n].type =
> > +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> > +		dev_flow->dv.actions[actions_n].action =
> > +			mlx5_flow_dv_create_encap(action, ctx, error);
> > +		if (!(dev_flow->dv.actions[actions_n].action))
> > +			return -rte_errno;
> > +		dev_flow->dv.encap_verb =
> > +			dev_flow->dv.actions[actions_n].action;
> > +		flow->actions |= MLX5_ACTION_TUNNEL_ENCAP;
> > +		actions_n++;
> > +		break;
> > +	case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP_L3:
> > +		dev_flow->dv.actions[actions_n].type =
> > +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> > +		dev_flow->dv.actions[actions_n].action =
> > +			mlx5_flow_dv_create_encap_l3(action, ctx, error);
> > +		if (!(dev_flow->dv.actions[actions_n].action))
> > +			return -rte_errno;
> > +		dev_flow->dv.encap_verb =
> > +			dev_flow->dv.actions[actions_n].action;
> > +		flow->actions |= MLX5_ACTION_TUNNEL_ENCAP_L3;
> > +		actions_n++;
> > +		break;
> >  	default:
> >  		break;
> >  	}
> >  	dev_flow->dv.actions_n = actions_n;
> > +	return 0;
> >  }
> >
> >  static uint32_t matcher_zero[MLX5_ST_SZ_DW(fte_match_param)] = { 0 };
> > @@ -1247,6 +1473,7 @@
> >  	};
> >  	void *match_value = dev_flow->dv.value.buf;
> >  	uint8_t inner = 0;
> > +	int retval = 0;
> >
> >  	if (priority == MLX5_FLOW_PRIO_RSVD)
> >  		priority = priv->config.flow_prio - 1; @@ -1262,9 +1489,14
> @@
> >  	matcher.egress = attr->egress;
> >  	if (flow_dv_matcher_register(dev, &matcher, dev_flow, error))
> >  		return -rte_errno;
> > -	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++)
> > -		flow_dv_create_action(actions, dev_flow);
> > -	return 0;
> > +	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
> > +		retval =
> > +		flow_dv_create_action(actions, dev_flow, priv->ctx, error);
> > +		if (retval)
> > +			break;
> 
> The following looks better matched?
> 
> 		if (flow_dv_create_action(dev, actions, dev_flow, error))
> 			return -rte_errno;
> 
> And leave 'return 0;' as is below.

OK.

> 
> BTW, flow_dv_matcher_register() allocates mlx5_flow_dv_matcher or
> increase the refcnt. Then, if it fails here, doesn't it need to clean that up?
> 
> > +	}
> > +
> 
> No blank line is allowed. Please fix other occurrences too.

Done.

> 
> > +	return retval;
> >  }
> >
> >  /**
> > @@ -1447,6 +1679,13 @@
> >  		LIST_REMOVE(dev_flow, next);
> >  		if (dev_flow->dv.matcher)
> >  			flow_dv_matcher_release(dev, dev_flow-
> >dv.matcher);
> > +
> > +		if (dev_flow->dv.encap_verb) {
> > +			claim_zero(mlx5_glue->destroy_flow_action
> > +						(dev_flow->dv.encap_verb));
> > +			dev_flow->dv.encap_verb = NULL;
> > +		}
> > +
> >  		rte_free(dev_flow);
> >  	}
> >  }
> > --
> > 1.8.3.1
> >

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

* Re: [dpdk-dev] [PATCH 3/4] net/mlx5: add DV encap L2 and L3 operations
  2018-10-03  8:35     ` Dekel Peled
@ 2018-10-03  9:32       ` Yongseok Koh
  2018-10-03 11:35         ` Dekel Peled
  2018-10-03 11:47       ` Dekel Peled
  1 sibling, 1 reply; 94+ messages in thread
From: Yongseok Koh @ 2018-10-03  9:32 UTC (permalink / raw)
  To: Dekel Peled; +Cc: dev, Shahaf Shuler, Ori Kam

On Wed, Oct 03, 2018 at 01:35:16AM -0700, Dekel Peled wrote:
> Thanks, PSB.
> 
> > -----Original Message-----
> > From: Yongseok Koh
> > Sent: Wednesday, October 3, 2018 9:58 AM
> > To: Dekel Peled <dekelp@mellanox.com>
> > Cc: dev@dpdk.org; Shahaf Shuler <shahafs@mellanox.com>; Ori Kam
> > <orika@mellanox.com>
> > Subject: Re: [PATCH 3/4] net/mlx5: add DV encap L2 and L3 operations
> > 
> > On Thu, Sep 27, 2018 at 05:50:44PM +0300, Dekel Peled wrote:
> > > This patch adds support for Direct Verbs encap operations, L2 and L3.
> > >
> > > Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> > > ---
> > >  drivers/net/mlx5/mlx5_flow_dv.c | 249
> > > +++++++++++++++++++++++++++++++++++++++-
> > >  1 file changed, 244 insertions(+), 5 deletions(-)
> > >
> > > diff --git a/drivers/net/mlx5/mlx5_flow_dv.c
> > > b/drivers/net/mlx5/mlx5_flow_dv.c index 1f3fcb8..50925ac 100644
> > > --- a/drivers/net/mlx5/mlx5_flow_dv.c
> > > +++ b/drivers/net/mlx5/mlx5_flow_dv.c
[...]
> > > +			  struct ibv_context *ctx,
> > > +			  struct rte_flow_error *error)
> > > +{
> > > +	struct ibv_flow_action *encap_verb = NULL;
> > > +	const struct rte_flow_action_tunnel_encap *encap_data;
> > > +
> > > +	encap_data = (const struct rte_flow_action_tunnel_encap *)action-
> > >conf;
> > > +	encap_verb = mlx5_glue-
> > >dv_create_flow_action_packet_reformat(ctx,
> > > +			encap_data->size,
> > > +			encap_data->size ? encap_data->buf :
> > > +					   NULL,
> > > +
> > 	MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TU
> > NNEL,
> > > +			MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
> > 
> > Indentation.
> 
> I'm using very long MLX5DV_... names defined in rdma-core.
> If I use the required indentation I get illegal line length.

The following was my suggestion and it is compliant.

	encap_verb = mlx5_glue->dv_create_flow_action_packet_reformat
		(ctx, encap_data->size,
		 encap_data->size ? encap_data->buf : NULL,
		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);

Please make the same change to others.

[...]
> > > @@ -1047,10 +1239,19 @@
> > >   *   Flow action to translate.
> > >   * @param[in, out] dev_flow
> > >   *   Pointer to the mlx5_flow.
> > > + * @param[in] ctx
> > > + *   Verbs context.
> > > + * @param[out] error
> > > + *   Pointer to the error structure.
> > > + *
> > > + * @return
> > > + *   0 on success, a negative errno value otherwise and rte_ernno is set.
> > >   */
> > > -static void
> > > +static int
> > >  flow_dv_create_action(const struct rte_flow_action *action,
> > > -		      struct mlx5_flow *dev_flow)
> > > +		      struct mlx5_flow *dev_flow,
> > > +		      struct ibv_context *ctx,
> > 
> > If it is just priv->ctx, it would be better to get dev as an arg and make
> > mlx5_flow_dv_create_encap*(dev, ...) gets priv->ctx from dev.
> 
> I considered it during implementation, but preferred to give the functions only what they need.

Two reasons.

1) having dev gets better matched with other existing ones. E.g.,
flow_dv_matcher_register() takes dev and it refers to priv->matchers and
priv->ctx.

2) extensibility. What if flow_dv_create_action() needs more fields of priv when
adding another new action in the future?

Thanks,
Yongseok

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

* Re: [dpdk-dev] [PATCH 3/4] net/mlx5: add DV encap L2 and L3 operations
  2018-10-03  9:32       ` Yongseok Koh
@ 2018-10-03 11:35         ` Dekel Peled
  0 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-03 11:35 UTC (permalink / raw)
  To: Yongseok Koh; +Cc: dev, Shahaf Shuler, Ori Kam

Thanks, PSB.

> -----Original Message-----
> From: Yongseok Koh
> Sent: Wednesday, October 3, 2018 12:33 PM
> To: Dekel Peled <dekelp@mellanox.com>
> Cc: dev@dpdk.org; Shahaf Shuler <shahafs@mellanox.com>; Ori Kam
> <orika@mellanox.com>
> Subject: Re: [PATCH 3/4] net/mlx5: add DV encap L2 and L3 operations
> 
> On Wed, Oct 03, 2018 at 01:35:16AM -0700, Dekel Peled wrote:
> > Thanks, PSB.
> >
> > > -----Original Message-----
> > > From: Yongseok Koh
> > > Sent: Wednesday, October 3, 2018 9:58 AM
> > > To: Dekel Peled <dekelp@mellanox.com>
> > > Cc: dev@dpdk.org; Shahaf Shuler <shahafs@mellanox.com>; Ori Kam
> > > <orika@mellanox.com>
> > > Subject: Re: [PATCH 3/4] net/mlx5: add DV encap L2 and L3 operations
> > >
> > > On Thu, Sep 27, 2018 at 05:50:44PM +0300, Dekel Peled wrote:
> > > > This patch adds support for Direct Verbs encap operations, L2 and L3.
> > > >
> > > > Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> > > > ---
> > > >  drivers/net/mlx5/mlx5_flow_dv.c | 249
> > > > +++++++++++++++++++++++++++++++++++++++-
> > > >  1 file changed, 244 insertions(+), 5 deletions(-)
> > > >
> > > > diff --git a/drivers/net/mlx5/mlx5_flow_dv.c
> > > > b/drivers/net/mlx5/mlx5_flow_dv.c index 1f3fcb8..50925ac 100644
> > > > --- a/drivers/net/mlx5/mlx5_flow_dv.c
> > > > +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> [...]
> > > > +			  struct ibv_context *ctx,
> > > > +			  struct rte_flow_error *error) {
> > > > +	struct ibv_flow_action *encap_verb = NULL;
> > > > +	const struct rte_flow_action_tunnel_encap *encap_data;
> > > > +
> > > > +	encap_data = (const struct rte_flow_action_tunnel_encap
> > > > +*)action-
> > > >conf;
> > > > +	encap_verb = mlx5_glue-
> > > >dv_create_flow_action_packet_reformat(ctx,
> > > > +			encap_data->size,
> > > > +			encap_data->size ? encap_data->buf :
> > > > +					   NULL,
> > > > +
> > > 	MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TU
> > > NNEL,
> > > > +			MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
> > >
> > > Indentation.
> >
> > I'm using very long MLX5DV_... names defined in rdma-core.
> > If I use the required indentation I get illegal line length.
> 
> The following was my suggestion and it is compliant.
> 
> 	encap_verb = mlx5_glue->dv_create_flow_action_packet_reformat
> 		(ctx, encap_data->size,
> 		 encap_data->size ? encap_data->buf : NULL,
> 
> MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
> 		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
> 
> Please make the same change to others.

Done.

> 
> [...]
> > > > @@ -1047,10 +1239,19 @@
> > > >   *   Flow action to translate.
> > > >   * @param[in, out] dev_flow
> > > >   *   Pointer to the mlx5_flow.
> > > > + * @param[in] ctx
> > > > + *   Verbs context.
> > > > + * @param[out] error
> > > > + *   Pointer to the error structure.
> > > > + *
> > > > + * @return
> > > > + *   0 on success, a negative errno value otherwise and rte_ernno is
> set.
> > > >   */
> > > > -static void
> > > > +static int
> > > >  flow_dv_create_action(const struct rte_flow_action *action,
> > > > -		      struct mlx5_flow *dev_flow)
> > > > +		      struct mlx5_flow *dev_flow,
> > > > +		      struct ibv_context *ctx,
> > >
> > > If it is just priv->ctx, it would be better to get dev as an arg and
> > > make mlx5_flow_dv_create_encap*(dev, ...) gets priv->ctx from dev.
> >
> > I considered it during implementation, but preferred to give the functions
> only what they need.
> 
> Two reasons.
> 
> 1) having dev gets better matched with other existing ones. E.g.,
> flow_dv_matcher_register() takes dev and it refers to priv->matchers and
> priv->ctx.
> 
> 2) extensibility. What if flow_dv_create_action() needs more fields of priv
> when adding another new action in the future?

Done.

> 
> Thanks,
> Yongseok

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

* Re: [dpdk-dev] [PATCH 3/4] net/mlx5: add DV encap L2 and L3 operations
  2018-10-03  8:35     ` Dekel Peled
  2018-10-03  9:32       ` Yongseok Koh
@ 2018-10-03 11:47       ` Dekel Peled
  2018-10-03 13:55         ` Dekel Peled
  1 sibling, 1 reply; 94+ messages in thread
From: Dekel Peled @ 2018-10-03 11:47 UTC (permalink / raw)
  To: Yongseok Koh; +Cc: dev, Shahaf Shuler, Ori Kam

One more issue, PSB.

> -----Original Message-----
> From: Dekel Peled
> Sent: Wednesday, October 3, 2018 11:35 AM
> To: Yongseok Koh <yskoh@mellanox.com>
> Cc: dev@dpdk.org; Shahaf Shuler <shahafs@mellanox.com>; Ori Kam
> <orika@mellanox.com>
> Subject: RE: [PATCH 3/4] net/mlx5: add DV encap L2 and L3 operations
> 
> Thanks, PSB.
> 
> > -----Original Message-----
> > From: Yongseok Koh
> > Sent: Wednesday, October 3, 2018 9:58 AM
> > To: Dekel Peled <dekelp@mellanox.com>
> > Cc: dev@dpdk.org; Shahaf Shuler <shahafs@mellanox.com>; Ori Kam
> > <orika@mellanox.com>
> > Subject: Re: [PATCH 3/4] net/mlx5: add DV encap L2 and L3 operations
> >
> > On Thu, Sep 27, 2018 at 05:50:44PM +0300, Dekel Peled wrote:
> > > This patch adds support for Direct Verbs encap operations, L2 and L3.
> > >
> > > Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> > > ---
> > >  drivers/net/mlx5/mlx5_flow_dv.c | 249
> > > +++++++++++++++++++++++++++++++++++++++-
> > >  1 file changed, 244 insertions(+), 5 deletions(-)
> > >
> > > diff --git a/drivers/net/mlx5/mlx5_flow_dv.c
> > > b/drivers/net/mlx5/mlx5_flow_dv.c index 1f3fcb8..50925ac 100644
> > > --- a/drivers/net/mlx5/mlx5_flow_dv.c
> > > +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> > > @@ -85,6 +85,178 @@
> > >  }
> > >
> > >  /**
> > > + * Validate the tunnel encap action.
> > > + *
> > > + * @param[in] action_flags
> > > + *   holds the actions detected until now.
> > > + * @param[in] action
> > > + *   Pointer to the encap action.
> > > + * @param[in] attr
> > > + *   Pointer to flow attributes
> > > + * @param[out] error
> > > + *   Pointer to error structure.
> > > + *
> > > + * @return
> > > + *   0 on success, a negative errno value otherwise and rte_ernno is set.
> > > + */
> > > +static int
> > > +mlx5_flow_validate_action_tunnel_encap(uint64_t action_flags,
> >
> > A static func in this file should start from flow_dv_. Or, you can
> > move these to mlx5_flow.c as general validation helpers. I prefer the latter.
> 
> Renamed functions to flow_dv_validate_action_tunnel_...
> Left it as static in mlx5_flow_dv.c, since it is relevant for DV only.
> 
> >
> > > +				       const struct rte_flow_action *action,
> > > +				       const struct rte_flow_attr *attr,
> > > +				       struct rte_flow_error *error) {
> > > +	const struct rte_flow_action_tunnel_encap *tunnel_encap =
> > > +action->conf;
> > > +
> > > +	if (!tunnel_encap || !(tunnel_encap->buf))
> > > +		return rte_flow_error_set(error, EINVAL,
> > > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > > +					  action,
> >
> > Two lines above can be merged? Please check others and merge lines as
> > much as possible.
> 
> Done.
> 
> >
> > > +					  "configuration cannot be null");
> > > +	if (action_flags & MLX5_ACTION_DROP)
> > > +		return rte_flow_error_set(error,
> > > +					  ENOTSUP,
> > > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > > +					  NULL,
> > > +					  "can't drop and encap in same
> > flow");
> > > +	if (action_flags & (MLX5_ACTION_TUNNEL_ENCAP |
> > > +			    MLX5_ACTION_TUNNEL_ENCAP_L3))
> > > +		return rte_flow_error_set(error,
> > > +					  ENOTSUP,
> > > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > > +					  NULL,
> > > +					  "can't have 2 encap actions in same"
> > > +					  " flow");
> > > +	if (attr->ingress)
> > > +		return rte_flow_error_set(error, ENOTSUP,
> > > +
> > 	RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> > > +					NULL,
> > > +					"encap action not supported for "
> > > +					"ingress");
> > > +	return 0;
> > > +}
> > > +
> > > +/**
> > > + * Validate the tunnel encap L3 action
> > > + *
> > > + * @param[in] action_flags
> > > + *   holds the actions detected until now.
> > > + * @param[in] action
> > > + *   Pointer to the encap action.
> > > + * @param[in] attr
> > > + *   Pointer to flow attributes
> > > + * @param[out] error
> > > + *   Pointer to error structure.
> > > + *
> > > + * @return
> > > + *   0 on success, a negative errno value otherwise and rte_ernno is set.
> > > + */
> > > +static int
> > > +mlx5_flow_validate_action_tunnel_encap_l3(uint64_t action_flags,
> > > +					  const struct rte_flow_action *action,
> > > +					  const struct rte_flow_attr *attr,
> > > +					  struct rte_flow_error *error) {
> > > +	const struct rte_flow_action_tunnel_encap_l3 *tunnel_encap_l3 =
> > > +								action->conf;
> >
> > Indentation.
> >
> > 	const struct rte_flow_action_tunnel_encap_l3 *tunnel_encap_l3 =
> > 		action->conf;
> 
> Done.
> 
> >
> > > +
> > > +	if (!tunnel_encap_l3 || !(tunnel_encap_l3->buf))
> > > +		return rte_flow_error_set(error, EINVAL,
> > > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > > +					  action,
> > > +					  "configuration cannot be null");
> > > +	if (action_flags & MLX5_ACTION_DROP)
> > > +		return rte_flow_error_set(error,
> > > +					  ENOTSUP,
> > > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > > +					  NULL,
> > > +					  "can't drop and encap in same
> > flow");
> > > +	if (action_flags & (MLX5_ACTION_TUNNEL_ENCAP |
> > > +			    MLX5_ACTION_TUNNEL_ENCAP_L3))
> > > +		return rte_flow_error_set(error,
> > > +					  ENOTSUP,
> > > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > > +					  NULL,
> > > +					  "can't have 2 encap actions in same"
> > > +					  " flow");
> > > +	if (attr->ingress)
> > > +		return rte_flow_error_set(error, ENOTSUP,
> > > +
> > 	RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> > > +					NULL,
> > > +					"encap action not supported for "
> > > +					"ingress");
> > > +	return 0;
> > > +}
> > > +
> > > +/**
> > > + * Convert encap action to DV specification.
> > > + *
> > > + * @param[in] action
> > > + *   Pointer to action structure.
> > > + * @param[in] ctx
> > > + *   Verbs context.
> > > + * @param[out] error
> > > + *   Pointer to the error structure.
> > > + *
> > > + * @return
> > > + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> > > + */
> > > +static struct ibv_flow_action *
> > > +mlx5_flow_dv_create_encap(const struct rte_flow_action *action,
> >
> > Change to flow_dv_create_encap()
> 
> Done.
> 
> >
> > > +			  struct ibv_context *ctx,
> > > +			  struct rte_flow_error *error)
> > > +{
> > > +	struct ibv_flow_action *encap_verb = NULL;
> > > +	const struct rte_flow_action_tunnel_encap *encap_data;
> > > +
> > > +	encap_data = (const struct rte_flow_action_tunnel_encap *)action-
> > >conf;
> > > +	encap_verb = mlx5_glue-
> > >dv_create_flow_action_packet_reformat(ctx,
> > > +			encap_data->size,
> > > +			encap_data->size ? encap_data->buf :
> > > +					   NULL,
> > > +
> > 	MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TU
> > NNEL,
> > > +			MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
> >
> > Indentation.
> 
> I'm using very long MLX5DV_... names defined in rdma-core.
> If I use the required indentation I get illegal line length.
> 
> >
> > 	encap_verb = mlx5_glue->dv_create_flow_action_packet_reformat
> > 		(ctx, encap_data->size,
> > 		 encap_data->size ? encap_data->buf : NULL,
> >
> > MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
> > 		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
> >
> > Please make the same change to others.
> >
> > > +	if (!encap_verb)
> > > +		rte_flow_error_set(error, EINVAL,
> > RTE_FLOW_ERROR_TYPE_ACTION,
> > > +				   NULL, "cannot create encap action");
> > > +	return encap_verb;
> > > +}
> > > +
> > > +/**
> > > + * Convert encap L3 action to DV specification.
> > > + *
> > > + * @param[in] action
> > > + *   Pointer to action structure.
> > > + * @param[in] ctx
> > > + *   Verbs context.
> > > + * @param[out] error
> > > + *   Pointer to the error structure.
> > > + *
> > > + * @return
> > > + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> > > + */
> > > +static struct ibv_flow_action *
> > > +mlx5_flow_dv_create_encap_l3(const struct rte_flow_action *action,
> >
> > Change to flow_dv_create_encap_l3()
> 
> Done.
> 
> >
> > > +			     struct ibv_context *ctx,
> > > +			     struct rte_flow_error *error) {
> > > +	struct ibv_flow_action *encap_l3_verb = NULL;
> > > +	const struct rte_flow_action_tunnel_encap_l3 *encap_l3_data;
> > > +
> > > +	encap_l3_data =
> > > +		(const struct rte_flow_action_tunnel_encap_l3 *)action-
> > >conf;
> > > +	encap_l3_verb = mlx5_glue-
> > >dv_create_flow_action_packet_reformat(ctx,
> > > +			encap_l3_data->size,
> > > +			encap_l3_data->size ? encap_l3_data->buf :
> > > +					      NULL,
> > > +
> > 	MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TU
> > NNEL,
> > > +			MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
> > > +	if (!encap_l3_verb)
> > > +		rte_flow_error_set(error, EINVAL,
> > RTE_FLOW_ERROR_TYPE_ACTION,
> > > +				   NULL, "cannot create encap L3 action");
> > > +	return encap_l3_verb;
> > > +}
> > > +
> > > +/**
> > >   * Verify the @p attributes will be correctly understood by the NIC
> > > and
> > store
> > >   * them in the @p flow if everything is correct.
> > >   *
> > > @@ -337,6 +509,26 @@
> > >  			action_flags |= MLX5_ACTION_COUNT;
> > >  			++actions_n;
> > >  			break;
> > > +		case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP:
> > > +			ret = mlx5_flow_validate_action_tunnel_encap
> > > +				(action_flags,
> > > +				 actions,
> > > +				 attr,
> > > +				 error);
> >
> > Can be one line.
> 
> Done.
> 
> >
> > > +			if (ret < 0)
> > > +				return ret;
> > > +			action_flags |= MLX5_ACTION_TUNNEL_ENCAP;
> > > +			break;
> > > +		case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP_L3:
> > > +			ret = mlx5_flow_validate_action_tunnel_encap_l3
> > > +				(action_flags,
> > > +				 actions,
> > > +				 attr,
> > > +				 error);
> > > +			if (ret < 0)
> > > +				return ret;
> > > +			action_flags |= MLX5_ACTION_TUNNEL_ENCAP_L3;
> > > +			break;
> > >  		default:
> > >  			return rte_flow_error_set(error, ENOTSUP,
> > >
> > RTE_FLOW_ERROR_TYPE_ACTION,
> > > @@ -1047,10 +1239,19 @@
> > >   *   Flow action to translate.
> > >   * @param[in, out] dev_flow
> > >   *   Pointer to the mlx5_flow.
> > > + * @param[in] ctx
> > > + *   Verbs context.
> > > + * @param[out] error
> > > + *   Pointer to the error structure.
> > > + *
> > > + * @return
> > > + *   0 on success, a negative errno value otherwise and rte_ernno is set.
> > >   */
> > > -static void
> > > +static int
> > >  flow_dv_create_action(const struct rte_flow_action *action,
> > > -		      struct mlx5_flow *dev_flow)
> > > +		      struct mlx5_flow *dev_flow,
> > > +		      struct ibv_context *ctx,
> >
> > If it is just priv->ctx, it would be better to get dev as an arg and
> > make mlx5_flow_dv_create_encap*(dev, ...) gets priv->ctx from dev.
> 
> I considered it during implementation, but preferred to give the functions
> only what they need.
> 
> >
> > > +		      struct rte_flow_error *error)
> > >  {
> > >  	const struct rte_flow_action_queue *queue;
> > >  	const struct rte_flow_action_rss *rss; @@ -1095,10 +1296,35 @@
> > >  		/* Added to array only in apply since we need the QP */
> > >  		flow->actions |= MLX5_ACTION_RSS;
> > >  		break;
> > > +	case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP:
> > > +		dev_flow->dv.actions[actions_n].type =
> > > +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> > > +		dev_flow->dv.actions[actions_n].action =
> > > +			mlx5_flow_dv_create_encap(action, ctx, error);
> > > +		if (!(dev_flow->dv.actions[actions_n].action))
> > > +			return -rte_errno;
> > > +		dev_flow->dv.encap_verb =
> > > +			dev_flow->dv.actions[actions_n].action;
> > > +		flow->actions |= MLX5_ACTION_TUNNEL_ENCAP;
> > > +		actions_n++;
> > > +		break;
> > > +	case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP_L3:
> > > +		dev_flow->dv.actions[actions_n].type =
> > > +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> > > +		dev_flow->dv.actions[actions_n].action =
> > > +			mlx5_flow_dv_create_encap_l3(action, ctx, error);
> > > +		if (!(dev_flow->dv.actions[actions_n].action))
> > > +			return -rte_errno;
> > > +		dev_flow->dv.encap_verb =
> > > +			dev_flow->dv.actions[actions_n].action;
> > > +		flow->actions |= MLX5_ACTION_TUNNEL_ENCAP_L3;
> > > +		actions_n++;
> > > +		break;
> > >  	default:
> > >  		break;
> > >  	}
> > >  	dev_flow->dv.actions_n = actions_n;
> > > +	return 0;
> > >  }
> > >
> > >  static uint32_t matcher_zero[MLX5_ST_SZ_DW(fte_match_param)] = { 0
> > > }; @@ -1247,6 +1473,7 @@
> > >  	};
> > >  	void *match_value = dev_flow->dv.value.buf;
> > >  	uint8_t inner = 0;
> > > +	int retval = 0;
> > >
> > >  	if (priority == MLX5_FLOW_PRIO_RSVD)
> > >  		priority = priv->config.flow_prio - 1; @@ -1262,9 +1489,14
> > @@
> > >  	matcher.egress = attr->egress;
> > >  	if (flow_dv_matcher_register(dev, &matcher, dev_flow, error))
> > >  		return -rte_errno;
> > > -	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++)
> > > -		flow_dv_create_action(actions, dev_flow);
> > > -	return 0;
> > > +	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
> > > +		retval =
> > > +		flow_dv_create_action(actions, dev_flow, priv->ctx, error);
> > > +		if (retval)
> > > +			break;
> >
> > The following looks better matched?
> >
> > 		if (flow_dv_create_action(dev, actions, dev_flow, error))
> > 			return -rte_errno;
> >
> > And leave 'return 0;' as is below.
> 
> OK.
> 
> >
> > BTW, flow_dv_matcher_register() allocates mlx5_flow_dv_matcher or
> > increase the refcnt. Then, if it fails here, doesn't it need to clean that up?

Missed this in the first time.
Moved the create_action loop earlier, right after the create_item loop,
and before the matcher_register call.

> >
> > > +	}
> > > +
> >
> > No blank line is allowed. Please fix other occurrences too.
> 
> Done.
> 
> >
> > > +	return retval;
> > >  }
> > >
> > >  /**
> > > @@ -1447,6 +1679,13 @@
> > >  		LIST_REMOVE(dev_flow, next);
> > >  		if (dev_flow->dv.matcher)
> > >  			flow_dv_matcher_release(dev, dev_flow-
> dv.matcher);
> > > +
> > > +		if (dev_flow->dv.encap_verb) {
> > > +			claim_zero(mlx5_glue->destroy_flow_action
> > > +						(dev_flow->dv.encap_verb));
> > > +			dev_flow->dv.encap_verb = NULL;
> > > +		}
> > > +
> > >  		rte_free(dev_flow);
> > >  	}
> > >  }
> > > --
> > > 1.8.3.1
> > >

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

* Re: [dpdk-dev] [PATCH 3/4] net/mlx5: add DV encap L2 and L3 operations
  2018-10-03 11:47       ` Dekel Peled
@ 2018-10-03 13:55         ` Dekel Peled
  0 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-03 13:55 UTC (permalink / raw)
  To: Yongseok Koh; +Cc: dev, Shahaf Shuler, Ori Kam

PSB

> -----Original Message-----
> From: Dekel Peled
> Sent: Wednesday, October 3, 2018 2:47 PM
> To: Yongseok Koh <yskoh@mellanox.com>
> Cc: dev@dpdk.org; Shahaf Shuler <shahafs@mellanox.com>; Ori Kam
> <orika@mellanox.com>
> Subject: RE: [PATCH 3/4] net/mlx5: add DV encap L2 and L3 operations
> 
> One more issue, PSB.
> 
> > -----Original Message-----
> > From: Dekel Peled
> > Sent: Wednesday, October 3, 2018 11:35 AM
> > To: Yongseok Koh <yskoh@mellanox.com>
> > Cc: dev@dpdk.org; Shahaf Shuler <shahafs@mellanox.com>; Ori Kam
> > <orika@mellanox.com>
> > Subject: RE: [PATCH 3/4] net/mlx5: add DV encap L2 and L3 operations
> >
> > Thanks, PSB.
> >
> > > -----Original Message-----
> > > From: Yongseok Koh
> > > Sent: Wednesday, October 3, 2018 9:58 AM
> > > To: Dekel Peled <dekelp@mellanox.com>
> > > Cc: dev@dpdk.org; Shahaf Shuler <shahafs@mellanox.com>; Ori Kam
> > > <orika@mellanox.com>
> > > Subject: Re: [PATCH 3/4] net/mlx5: add DV encap L2 and L3 operations
> > >
> > > On Thu, Sep 27, 2018 at 05:50:44PM +0300, Dekel Peled wrote:
> > > > This patch adds support for Direct Verbs encap operations, L2 and L3.
> > > >
> > > > Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> > > > ---
> > > >  drivers/net/mlx5/mlx5_flow_dv.c | 249
> > > > +++++++++++++++++++++++++++++++++++++++-
> > > >  1 file changed, 244 insertions(+), 5 deletions(-)
> > > >
> > > > diff --git a/drivers/net/mlx5/mlx5_flow_dv.c
> > > > b/drivers/net/mlx5/mlx5_flow_dv.c index 1f3fcb8..50925ac 100644
> > > > --- a/drivers/net/mlx5/mlx5_flow_dv.c
> > > > +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> > > > @@ -85,6 +85,178 @@
> > > >  }
> > > >
> > > >  /**
> > > > + * Validate the tunnel encap action.
> > > > + *
> > > > + * @param[in] action_flags
> > > > + *   holds the actions detected until now.
> > > > + * @param[in] action
> > > > + *   Pointer to the encap action.
> > > > + * @param[in] attr
> > > > + *   Pointer to flow attributes
> > > > + * @param[out] error
> > > > + *   Pointer to error structure.
> > > > + *
> > > > + * @return
> > > > + *   0 on success, a negative errno value otherwise and rte_ernno is
> set.
> > > > + */
> > > > +static int
> > > > +mlx5_flow_validate_action_tunnel_encap(uint64_t action_flags,
> > >
> > > A static func in this file should start from flow_dv_. Or, you can
> > > move these to mlx5_flow.c as general validation helpers. I prefer the
> latter.
> >
> > Renamed functions to flow_dv_validate_action_tunnel_...
> > Left it as static in mlx5_flow_dv.c, since it is relevant for DV only.
> >
> > >
> > > > +				       const struct rte_flow_action *action,
> > > > +				       const struct rte_flow_attr *attr,
> > > > +				       struct rte_flow_error *error) {
> > > > +	const struct rte_flow_action_tunnel_encap *tunnel_encap =
> > > > +action->conf;
> > > > +
> > > > +	if (!tunnel_encap || !(tunnel_encap->buf))
> > > > +		return rte_flow_error_set(error, EINVAL,
> > > > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > > > +					  action,
> > >
> > > Two lines above can be merged? Please check others and merge lines
> > > as much as possible.
> >
> > Done.
> >
> > >
> > > > +					  "configuration cannot be null");
> > > > +	if (action_flags & MLX5_ACTION_DROP)
> > > > +		return rte_flow_error_set(error,
> > > > +					  ENOTSUP,
> > > > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > > > +					  NULL,
> > > > +					  "can't drop and encap in same
> > > flow");
> > > > +	if (action_flags & (MLX5_ACTION_TUNNEL_ENCAP |
> > > > +			    MLX5_ACTION_TUNNEL_ENCAP_L3))
> > > > +		return rte_flow_error_set(error,
> > > > +					  ENOTSUP,
> > > > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > > > +					  NULL,
> > > > +					  "can't have 2 encap actions in same"
> > > > +					  " flow");
> > > > +	if (attr->ingress)
> > > > +		return rte_flow_error_set(error, ENOTSUP,
> > > > +
> > > 	RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> > > > +					NULL,
> > > > +					"encap action not supported for "
> > > > +					"ingress");
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +/**
> > > > + * Validate the tunnel encap L3 action
> > > > + *
> > > > + * @param[in] action_flags
> > > > + *   holds the actions detected until now.
> > > > + * @param[in] action
> > > > + *   Pointer to the encap action.
> > > > + * @param[in] attr
> > > > + *   Pointer to flow attributes
> > > > + * @param[out] error
> > > > + *   Pointer to error structure.
> > > > + *
> > > > + * @return
> > > > + *   0 on success, a negative errno value otherwise and rte_ernno is
> set.
> > > > + */
> > > > +static int
> > > > +mlx5_flow_validate_action_tunnel_encap_l3(uint64_t action_flags,
> > > > +					  const struct rte_flow_action *action,
> > > > +					  const struct rte_flow_attr *attr,
> > > > +					  struct rte_flow_error *error) {
> > > > +	const struct rte_flow_action_tunnel_encap_l3 *tunnel_encap_l3 =
> > > > +								action->conf;
> > >
> > > Indentation.
> > >
> > > 	const struct rte_flow_action_tunnel_encap_l3 *tunnel_encap_l3 =
> > > 		action->conf;
> >
> > Done.
> >
> > >
> > > > +
> > > > +	if (!tunnel_encap_l3 || !(tunnel_encap_l3->buf))
> > > > +		return rte_flow_error_set(error, EINVAL,
> > > > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > > > +					  action,
> > > > +					  "configuration cannot be null");
> > > > +	if (action_flags & MLX5_ACTION_DROP)
> > > > +		return rte_flow_error_set(error,
> > > > +					  ENOTSUP,
> > > > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > > > +					  NULL,
> > > > +					  "can't drop and encap in same
> > > flow");
> > > > +	if (action_flags & (MLX5_ACTION_TUNNEL_ENCAP |
> > > > +			    MLX5_ACTION_TUNNEL_ENCAP_L3))
> > > > +		return rte_flow_error_set(error,
> > > > +					  ENOTSUP,
> > > > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > > > +					  NULL,
> > > > +					  "can't have 2 encap actions in same"
> > > > +					  " flow");
> > > > +	if (attr->ingress)
> > > > +		return rte_flow_error_set(error, ENOTSUP,
> > > > +
> > > 	RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> > > > +					NULL,
> > > > +					"encap action not supported for "
> > > > +					"ingress");
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +/**
> > > > + * Convert encap action to DV specification.
> > > > + *
> > > > + * @param[in] action
> > > > + *   Pointer to action structure.
> > > > + * @param[in] ctx
> > > > + *   Verbs context.
> > > > + * @param[out] error
> > > > + *   Pointer to the error structure.
> > > > + *
> > > > + * @return
> > > > + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> > > > + */
> > > > +static struct ibv_flow_action *
> > > > +mlx5_flow_dv_create_encap(const struct rte_flow_action *action,
> > >
> > > Change to flow_dv_create_encap()
> >
> > Done.
> >
> > >
> > > > +			  struct ibv_context *ctx,
> > > > +			  struct rte_flow_error *error) {
> > > > +	struct ibv_flow_action *encap_verb = NULL;
> > > > +	const struct rte_flow_action_tunnel_encap *encap_data;
> > > > +
> > > > +	encap_data = (const struct rte_flow_action_tunnel_encap
> > > > +*)action-
> > > >conf;
> > > > +	encap_verb = mlx5_glue-
> > > >dv_create_flow_action_packet_reformat(ctx,
> > > > +			encap_data->size,
> > > > +			encap_data->size ? encap_data->buf :
> > > > +					   NULL,
> > > > +
> > > 	MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TU
> > > NNEL,
> > > > +			MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
> > >
> > > Indentation.
> >
> > I'm using very long MLX5DV_... names defined in rdma-core.
> > If I use the required indentation I get illegal line length.
> >
> > >
> > > 	encap_verb = mlx5_glue->dv_create_flow_action_packet_reformat
> > > 		(ctx, encap_data->size,
> > > 		 encap_data->size ? encap_data->buf : NULL,
> > >
> > >
> MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
> > > 		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
> > >
> > > Please make the same change to others.
> > >
> > > > +	if (!encap_verb)
> > > > +		rte_flow_error_set(error, EINVAL,
> > > RTE_FLOW_ERROR_TYPE_ACTION,
> > > > +				   NULL, "cannot create encap action");
> > > > +	return encap_verb;
> > > > +}
> > > > +
> > > > +/**
> > > > + * Convert encap L3 action to DV specification.
> > > > + *
> > > > + * @param[in] action
> > > > + *   Pointer to action structure.
> > > > + * @param[in] ctx
> > > > + *   Verbs context.
> > > > + * @param[out] error
> > > > + *   Pointer to the error structure.
> > > > + *
> > > > + * @return
> > > > + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> > > > + */
> > > > +static struct ibv_flow_action *
> > > > +mlx5_flow_dv_create_encap_l3(const struct rte_flow_action
> > > > +*action,
> > >
> > > Change to flow_dv_create_encap_l3()
> >
> > Done.
> >
> > >
> > > > +			     struct ibv_context *ctx,
> > > > +			     struct rte_flow_error *error) {
> > > > +	struct ibv_flow_action *encap_l3_verb = NULL;
> > > > +	const struct rte_flow_action_tunnel_encap_l3 *encap_l3_data;
> > > > +
> > > > +	encap_l3_data =
> > > > +		(const struct rte_flow_action_tunnel_encap_l3 *)action-
> > > >conf;
> > > > +	encap_l3_verb = mlx5_glue-
> > > >dv_create_flow_action_packet_reformat(ctx,
> > > > +			encap_l3_data->size,
> > > > +			encap_l3_data->size ? encap_l3_data->buf :
> > > > +					      NULL,
> > > > +
> > > 	MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TU
> > > NNEL,
> > > > +			MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
> > > > +	if (!encap_l3_verb)
> > > > +		rte_flow_error_set(error, EINVAL,
> > > RTE_FLOW_ERROR_TYPE_ACTION,
> > > > +				   NULL, "cannot create encap L3 action");
> > > > +	return encap_l3_verb;
> > > > +}
> > > > +
> > > > +/**
> > > >   * Verify the @p attributes will be correctly understood by the
> > > > NIC and
> > > store
> > > >   * them in the @p flow if everything is correct.
> > > >   *
> > > > @@ -337,6 +509,26 @@
> > > >  			action_flags |= MLX5_ACTION_COUNT;
> > > >  			++actions_n;
> > > >  			break;
> > > > +		case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP:
> > > > +			ret = mlx5_flow_validate_action_tunnel_encap
> > > > +				(action_flags,
> > > > +				 actions,
> > > > +				 attr,
> > > > +				 error);
> > >
> > > Can be one line.
> >
> > Done.
> >
> > >
> > > > +			if (ret < 0)
> > > > +				return ret;
> > > > +			action_flags |= MLX5_ACTION_TUNNEL_ENCAP;
> > > > +			break;
> > > > +		case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP_L3:
> > > > +			ret = mlx5_flow_validate_action_tunnel_encap_l3
> > > > +				(action_flags,
> > > > +				 actions,
> > > > +				 attr,
> > > > +				 error);
> > > > +			if (ret < 0)
> > > > +				return ret;
> > > > +			action_flags |= MLX5_ACTION_TUNNEL_ENCAP_L3;
> > > > +			break;
> > > >  		default:
> > > >  			return rte_flow_error_set(error, ENOTSUP,
> > > >
> > > RTE_FLOW_ERROR_TYPE_ACTION,
> > > > @@ -1047,10 +1239,19 @@
> > > >   *   Flow action to translate.
> > > >   * @param[in, out] dev_flow
> > > >   *   Pointer to the mlx5_flow.
> > > > + * @param[in] ctx
> > > > + *   Verbs context.
> > > > + * @param[out] error
> > > > + *   Pointer to the error structure.
> > > > + *
> > > > + * @return
> > > > + *   0 on success, a negative errno value otherwise and rte_ernno is
> set.
> > > >   */
> > > > -static void
> > > > +static int
> > > >  flow_dv_create_action(const struct rte_flow_action *action,
> > > > -		      struct mlx5_flow *dev_flow)
> > > > +		      struct mlx5_flow *dev_flow,
> > > > +		      struct ibv_context *ctx,
> > >
> > > If it is just priv->ctx, it would be better to get dev as an arg and
> > > make mlx5_flow_dv_create_encap*(dev, ...) gets priv->ctx from dev.
> >
> > I considered it during implementation, but preferred to give the
> > functions only what they need.
> >
> > >
> > > > +		      struct rte_flow_error *error)
> > > >  {
> > > >  	const struct rte_flow_action_queue *queue;
> > > >  	const struct rte_flow_action_rss *rss; @@ -1095,10 +1296,35 @@
> > > >  		/* Added to array only in apply since we need the QP */
> > > >  		flow->actions |= MLX5_ACTION_RSS;
> > > >  		break;
> > > > +	case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP:
> > > > +		dev_flow->dv.actions[actions_n].type =
> > > > +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> > > > +		dev_flow->dv.actions[actions_n].action =
> > > > +			mlx5_flow_dv_create_encap(action, ctx, error);
> > > > +		if (!(dev_flow->dv.actions[actions_n].action))
> > > > +			return -rte_errno;
> > > > +		dev_flow->dv.encap_verb =
> > > > +			dev_flow->dv.actions[actions_n].action;
> > > > +		flow->actions |= MLX5_ACTION_TUNNEL_ENCAP;
> > > > +		actions_n++;
> > > > +		break;
> > > > +	case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP_L3:
> > > > +		dev_flow->dv.actions[actions_n].type =
> > > > +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> > > > +		dev_flow->dv.actions[actions_n].action =
> > > > +			mlx5_flow_dv_create_encap_l3(action, ctx, error);
> > > > +		if (!(dev_flow->dv.actions[actions_n].action))
> > > > +			return -rte_errno;
> > > > +		dev_flow->dv.encap_verb =
> > > > +			dev_flow->dv.actions[actions_n].action;
> > > > +		flow->actions |= MLX5_ACTION_TUNNEL_ENCAP_L3;
> > > > +		actions_n++;
> > > > +		break;
> > > >  	default:
> > > >  		break;
> > > >  	}
> > > >  	dev_flow->dv.actions_n = actions_n;
> > > > +	return 0;
> > > >  }
> > > >
> > > >  static uint32_t matcher_zero[MLX5_ST_SZ_DW(fte_match_param)] = {
> > > > 0 }; @@ -1247,6 +1473,7 @@
> > > >  	};
> > > >  	void *match_value = dev_flow->dv.value.buf;
> > > >  	uint8_t inner = 0;
> > > > +	int retval = 0;
> > > >
> > > >  	if (priority == MLX5_FLOW_PRIO_RSVD)
> > > >  		priority = priv->config.flow_prio - 1; @@ -1262,9 +1489,14
> > > @@
> > > >  	matcher.egress = attr->egress;
> > > >  	if (flow_dv_matcher_register(dev, &matcher, dev_flow, error))
> > > >  		return -rte_errno;
> > > > -	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++)
> > > > -		flow_dv_create_action(actions, dev_flow);
> > > > -	return 0;
> > > > +	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
> > > > +		retval =
> > > > +		flow_dv_create_action(actions, dev_flow, priv->ctx, error);
> > > > +		if (retval)
> > > > +			break;
> > >
> > > The following looks better matched?
> > >
> > > 		if (flow_dv_create_action(dev, actions, dev_flow, error))
> > > 			return -rte_errno;
> > >
> > > And leave 'return 0;' as is below.
> >
> > OK.
> >
> > >
> > > BTW, flow_dv_matcher_register() allocates mlx5_flow_dv_matcher or
> > > increase the refcnt. Then, if it fails here, doesn't it need to clean that up?
> 
> Missed this in the first time.
> Moved the create_action loop earlier, right after the create_item loop, and
> before the matcher_register call.
> 

Please ignore previous comment.
If the create_action fails, the destroy function will clean up the matcher allocations as well.

> > >
> > > > +	}
> > > > +
> > >
> > > No blank line is allowed. Please fix other occurrences too.
> >
> > Done.
> >
> > >
> > > > +	return retval;
> > > >  }
> > > >
> > > >  /**
> > > > @@ -1447,6 +1679,13 @@
> > > >  		LIST_REMOVE(dev_flow, next);
> > > >  		if (dev_flow->dv.matcher)
> > > >  			flow_dv_matcher_release(dev, dev_flow-
> > dv.matcher);
> > > > +
> > > > +		if (dev_flow->dv.encap_verb) {
> > > > +			claim_zero(mlx5_glue->destroy_flow_action
> > > > +						(dev_flow->dv.encap_verb));
> > > > +			dev_flow->dv.encap_verb = NULL;
> > > > +		}
> > > > +
> > > >  		rte_free(dev_flow);
> > > >  	}
> > > >  }
> > > > --
> > > > 1.8.3.1
> > > >

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

* Re: [dpdk-dev] [PATCH 4/4] net/mlx5: add DV decap L2 and L3 operations
  2018-10-03  7:07   ` Yongseok Koh
@ 2018-10-03 16:14     ` Dekel Peled
  0 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-03 16:14 UTC (permalink / raw)
  To: Yongseok Koh; +Cc: dev, Shahaf Shuler, Ori Kam

Thanks, PSB.

> -----Original Message-----
> From: Yongseok Koh
> Sent: Wednesday, October 3, 2018 10:07 AM
> To: Dekel Peled <dekelp@mellanox.com>
> Cc: dev@dpdk.org; Shahaf Shuler <shahafs@mellanox.com>; Ori Kam
> <orika@mellanox.com>
> Subject: Re: [PATCH 4/4] net/mlx5: add DV decap L2 and L3 operations
> 
> On Thu, Sep 27, 2018 at 05:50:45PM +0300, Dekel Peled wrote:
> > This patch adds support for Direct Verbs decap operations, L2 and L3.
> >
> 
> Almost same code as encap, so I also have the same comments. :-) One
> more. In the title, we can't use vendor specific acronyms.
> 
> 	net/mlx5: add DV decap L2 and L3 operations
> 
> DV -> Direct Verbs
> 
> How about something like this?
> 	net/mlx5: add L2/L3 encap to Direct Verbs flow

Done.

> 
> > Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> > ---
> >  drivers/net/mlx5/mlx5_flow_dv.c | 258
> > ++++++++++++++++++++++++++++++++++++++--
> >  1 file changed, 248 insertions(+), 10 deletions(-)
> >
> > diff --git a/drivers/net/mlx5/mlx5_flow_dv.c
> > b/drivers/net/mlx5/mlx5_flow_dv.c index 50925ac..ca44f13 100644
> > --- a/drivers/net/mlx5/mlx5_flow_dv.c
> > +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> > @@ -126,12 +126,20 @@
> >  					  NULL,
> >  					  "can't have 2 encap actions in same"
> >  					  " flow");
> > +	if (action_flags & (MLX5_ACTION_TUNNEL_DECAP |
> > +			    MLX5_ACTION_TUNNEL_DECAP_L3))
> > +		return rte_flow_error_set(error,
> > +					  ENOTSUP,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > +					  NULL,
> > +					  "can't encap and decap in same"
> > +					  " flow");
> >  	if (attr->ingress)
> >  		return rte_flow_error_set(error, ENOTSUP,
> > -
> 	RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> > -					NULL,
> > -					"encap action not supported for "
> > -					"ingress");
> > +
> RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> > +					  NULL,
> > +					  "encap action not supported for "
> > +					  "ingress");
> >  	return 0;
> >  }
> >
> > @@ -178,12 +186,130 @@
> >  					  NULL,
> >  					  "can't have 2 encap actions in same"
> >  					  " flow");
> > +	if (action_flags & (MLX5_ACTION_TUNNEL_DECAP |
> > +			    MLX5_ACTION_TUNNEL_DECAP_L3))
> > +		return rte_flow_error_set(error,
> > +					  ENOTSUP,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > +					  NULL,
> > +					  "can't encap and decap in same"
> > +					  " flow");
> >  	if (attr->ingress)
> >  		return rte_flow_error_set(error, ENOTSUP,
> > -
> 	RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> > -					NULL,
> > -					"encap action not supported for "
> > -					"ingress");
> > +
> RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> > +					  NULL,
> > +					  "encap action not supported for "
> > +					  "ingress");
> > +	return 0;
> > +}
> > +
> > +/**
> > + * Validate the tunnel decap action
> > + *
> > + * @param[in] action_flags
> > + *   holds the actions detected until now.
> > + * @param[in] attr
> > + *   Pointer to flow attributes
> > + * @param[out] error
> > + *   Pointer to error structure.
> > + *
> > + * @return
> > + *   0 on success, a negative errno value otherwise and rte_ernno is set.
> > + */
> > +static int
> > +mlx5_flow_validate_action_tunnel_decap(uint64_t action_flags,
> > +				       const struct rte_flow_attr *attr,
> > +				       struct rte_flow_error *error) {
> > +	if (action_flags & MLX5_ACTION_DROP)
> > +		return rte_flow_error_set(error,
> > +					  ENOTSUP,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > +					  NULL,
> > +					  "can't drop and decap in same
> flow");
> > +	if (action_flags & (MLX5_ACTION_TUNNEL_DECAP |
> > +			    MLX5_ACTION_TUNNEL_DECAP_L3))
> > +		return rte_flow_error_set(error,
> > +					  ENOTSUP,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > +					  NULL,
> > +					  "can't have 2 decap actions in same"
> > +					  " flow");
> > +	if (action_flags & (MLX5_ACTION_TUNNEL_ENCAP |
> > +			    MLX5_ACTION_TUNNEL_ENCAP_L3))
> > +		return rte_flow_error_set(error,
> > +					  ENOTSUP,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > +					  NULL,
> > +					  "can't encap and decap in same"
> > +					  " flow");
> > +	if (attr->egress)
> > +		return rte_flow_error_set(error, ENOTSUP,
> > +
> RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
> > +					  NULL,
> > +					  "decap action not supported for "
> > +					  "egress");
> > +	return 0;
> > +}
> > +
> > +/**
> > + * Validate the tunnel decap L3 action
> > + *
> > + * @param[in] action_flags
> > + *   holds the actions detected until now.
> > + * @param[in] action
> > + *   Pointer to the decap action.
> > + * @param[in] attr
> > + *   Pointer to flow attributes
> > + * @param[out] error
> > + *   Pointer to error structure.
> > + *
> > + * @return
> > + *   0 on success, a negative errno value otherwise and rte_ernno is set.
> > + */
> > +static int
> > +mlx5_flow_validate_action_tunnel_decap_l3(uint64_t action_flags,
> > +					  const struct rte_flow_action *action,
> > +					  const struct rte_flow_attr *attr,
> > +					  struct rte_flow_error *error)
> > +{
> > +	const struct rte_flow_action_tunnel_decap_l3 *tunnel_decap_l3 =
> > +								action->conf;
> > +
> > +	if (!tunnel_decap_l3 || !(tunnel_decap_l3->buf))
> > +
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > +					  action,
> > +					  "configuration cannot be null");
> > +	if (action_flags & MLX5_ACTION_DROP)
> > +		return rte_flow_error_set(error,
> > +					  ENOTSUP,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > +					  NULL,
> > +					  "can't drop and decap in same
> flow");
> > +	if (action_flags & (MLX5_ACTION_TUNNEL_DECAP |
> > +			    MLX5_ACTION_TUNNEL_DECAP_L3))
> > +		return rte_flow_error_set(error,
> > +					  ENOTSUP,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > +					  NULL,
> > +					  "can't have 2 decap actions in same"
> > +					  " flow");
> > +	if (action_flags & (MLX5_ACTION_TUNNEL_ENCAP |
> > +			    MLX5_ACTION_TUNNEL_ENCAP_L3))
> > +		return rte_flow_error_set(error,
> > +					  ENOTSUP,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > +					  NULL,
> > +					  "can't encap and decap in same"
> > +					  " flow");
> > +	if (attr->egress)
> > +		return rte_flow_error_set(error, ENOTSUP,
> > +
> RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
> > +					  NULL,
> > +					  "decap action not supported for "
> > +					  "egress");
> >  	return 0;
> >  }
> >
> > @@ -257,6 +383,72 @@
> >  }
> >
> >  /**
> > + * Convert decap action to DV specification.
> > + *
> > + * @param[in] action
> > + *   Pointer to action structure.
> > + * @param[in] ctx
> > + *   Verbs context.
> > + * @param[out] error
> > + *   Pointer to the error structure.
> > + *
> > + * @return
> > + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> > + */
> > +static struct ibv_flow_action *
> > +mlx5_flow_dv_create_decap(const struct rte_flow_action *action
> __rte_unused,
> > +			  struct ibv_context *ctx,
> > +			  struct rte_flow_error *error)
> > +{
> > +	struct ibv_flow_action *decap_verb = NULL;
> > +
> > +	decap_verb = mlx5_glue-
> >dv_create_flow_action_packet_reformat(ctx,
> > +			0, NULL,
> > +
> 	MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_T
> O_L2,
> > +			MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
> > +	if (!decap_verb)
> > +		rte_flow_error_set(error, EINVAL,
> RTE_FLOW_ERROR_TYPE_ACTION,
> > +				   NULL, "cannot create decap action");
> > +	return decap_verb;
> > +}
> > +
> > +/**
> > + * Convert decap L3 action to DV specification.
> > + *
> > + * @param[in] action
> > + *   Pointer to action structure.
> > + * @param[in] ctx
> > + *   Verbs context.
> > + * @param[out] error
> > + *   Pointer to the error structure.
> > + *
> > + * @return
> > + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> > + */
> > +static struct ibv_flow_action *
> > +mlx5_flow_dv_create_decap_l3(const struct rte_flow_action *action,
> > +			     struct ibv_context *ctx,
> > +			     struct rte_flow_error *error) {
> > +	struct ibv_flow_action *decap_l3_verb = NULL;
> > +	const struct rte_flow_action_tunnel_decap_l3 *decap_l3_data;
> > +
> > +	decap_l3_data =
> > +		(const struct rte_flow_action_tunnel_decap_l3 *)action-
> >conf;
> > +	decap_l3_verb = mlx5_glue-
> >dv_create_flow_action_packet_reformat(ctx,
> > +			decap_l3_data->size,
> > +			decap_l3_data->size ? decap_l3_data->buf :
> > +					      NULL,
> > +
> 	MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_T
> O_L2,
> > +			MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
> > +	if (!decap_l3_verb)
> > +		rte_flow_error_set(error, EINVAL,
> RTE_FLOW_ERROR_TYPE_ACTION,
> > +				   NULL, "cannot create decap L3 action");
> > +
> > +	return decap_l3_verb;
> > +}
> > +
> > +/**
> >   * Verify the @p attributes will be correctly understood by the NIC and
> store
> >   * them in the @p flow if everything is correct.
> >   *
> > @@ -529,6 +721,25 @@
> >  				return ret;
> >  			action_flags |= MLX5_ACTION_TUNNEL_ENCAP_L3;
> >  			break;
> > +		case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP:
> > +			ret = mlx5_flow_validate_action_tunnel_decap
> > +				(action_flags,
> > +				 attr,
> > +				 error);
> > +			if (ret < 0)
> > +				return ret;
> > +			action_flags |= MLX5_ACTION_TUNNEL_DECAP;
> > +			break;
> > +		case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP_L3:
> > +			ret = mlx5_flow_validate_action_tunnel_decap_l3
> > +				(action_flags,
> > +				 actions,
> > +				 attr,
> > +				 error);
> > +			if (ret < 0)
> > +				return ret;
> > +			action_flags |= MLX5_ACTION_TUNNEL_DECAP_L3;
> > +			break;
> >  		default:
> >  			return rte_flow_error_set(error, ENOTSUP,
> >
> RTE_FLOW_ERROR_TYPE_ACTION,
> > @@ -1320,6 +1531,30 @@
> >  		flow->actions |= MLX5_ACTION_TUNNEL_ENCAP_L3;
> >  		actions_n++;
> >  		break;
> > +	case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP:
> > +		dev_flow->dv.actions[actions_n].type =
> > +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> > +		dev_flow->dv.actions[actions_n].action =
> > +			mlx5_flow_dv_create_decap(action, ctx, error);
> > +		if (!(dev_flow->dv.actions[actions_n].action))
> > +			return -rte_errno;
> > +		dev_flow->dv.decap_verb =
> > +			dev_flow->dv.actions[actions_n].action;
> > +		flow->actions |= MLX5_ACTION_TUNNEL_DECAP;
> > +		actions_n++;
> > +		break;
> > +	case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP_L3:
> > +		dev_flow->dv.actions[actions_n].type =
> > +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> > +		dev_flow->dv.actions[actions_n].action =
> > +			mlx5_flow_dv_create_decap_l3(action, ctx, error);
> > +		if (!(dev_flow->dv.actions[actions_n].action))
> > +			return -rte_errno;
> > +		dev_flow->dv.decap_verb =
> > +			dev_flow->dv.actions[actions_n].action;
> > +		flow->actions |= MLX5_ACTION_TUNNEL_DECAP_L3;
> > +		actions_n++;
> > +		break;
> >  	default:
> >  		break;
> >  	}
> > @@ -1679,13 +1914,16 @@
> >  		LIST_REMOVE(dev_flow, next);
> >  		if (dev_flow->dv.matcher)
> >  			flow_dv_matcher_release(dev, dev_flow-
> >dv.matcher);
> > -
> 
> Looks like it is a mistake on rebasing.

Redundant blank line removed.

> 
> >  		if (dev_flow->dv.encap_verb) {
> >  			claim_zero(mlx5_glue->destroy_flow_action
> >  						(dev_flow->dv.encap_verb));
> >  			dev_flow->dv.encap_verb = NULL;
> >  		}
> > -
> > +		if (dev_flow->dv.decap_verb) {
> > +			claim_zero(mlx5_glue->destroy_flow_action
> > +						(dev_flow->dv.decap_verb));
> > +			dev_flow->dv.decap_verb = NULL;
> > +		}
> >  		rte_free(dev_flow);
> >  	}
> >  }
> > --
> > 1.8.3.1
> >

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

* [dpdk-dev] [PATCH v2 0/4] add support of Direct Verbs encap and decap actions
  2018-09-27 14:50 [dpdk-dev] [PATCH 0/4] support DV encap and decap actions Dekel Peled
                   ` (3 preceding siblings ...)
  2018-09-27 14:50 ` [dpdk-dev] [PATCH 4/4] net/mlx5: add DV decap " Dekel Peled
@ 2018-10-07 14:25 ` Dekel Peled
  2018-10-09 19:25   ` [dpdk-dev] [PATCH v3 " Dekel Peled
                     ` (4 more replies)
  2018-10-07 14:25 ` [dpdk-dev] [PATCH v2 1/4] net/mlx5: add flow action functions to glue Dekel Peled
                   ` (3 subsequent siblings)
  8 siblings, 5 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-07 14:25 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This series adds support of encap and decap actions in DV format.
It is using the generic encapsulation framework from [1].
Note that encap action is relevant for egress only.
Hence this series should be merged on top of [2].

[1] "ethdev: add generic L2/L3 tunnel encapsulation actions"
    http://mails.dpdk.org/archives/dev/2018-October/114654.html
[2] "net/mlx5: allow flow rule with attribute egress"
    http://mails.dpdk.org/archives/dev/2018-October/114658.html

---
V2:
* Rebase on tip.
* Apply code review comments.
---

Dekel Peled (4):
  net/mlx5: add flow action functions to glue
  net/mlx5: add Direct Verbs encap and decap defs
  net/mlx5: add L2 and L3 encap to Direct Verbs flow
  net/mlx5: add L2 and L3 decap to Direct Verbs flow

 drivers/net/mlx5/mlx5_flow.c    |   8 +
 drivers/net/mlx5/mlx5_flow.h    |   6 +
 drivers/net/mlx5/mlx5_flow_dv.c | 440 +++++++++++++++++++++++++++++++++++++++-
 drivers/net/mlx5/mlx5_glue.c    |  33 +++
 drivers/net/mlx5/mlx5_glue.h    |   9 +
 5 files changed, 492 insertions(+), 4 deletions(-)

-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v2 1/4] net/mlx5: add flow action functions to glue
  2018-09-27 14:50 [dpdk-dev] [PATCH 0/4] support DV encap and decap actions Dekel Peled
                   ` (4 preceding siblings ...)
  2018-10-07 14:25 ` [dpdk-dev] [PATCH v2 0/4] add support of Direct Verbs encap and decap actions Dekel Peled
@ 2018-10-07 14:25 ` Dekel Peled
  2018-10-08 19:43   ` Yongseok Koh
  2018-10-07 14:25 ` [dpdk-dev] [PATCH v2 2/4] net/mlx5: add Direct Verbs encap and decap defs Dekel Peled
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 94+ messages in thread
From: Dekel Peled @ 2018-10-07 14:25 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch adds glue functions for operations:
- Create packet reformat (encap/decap) flow action.
- Destroy flow action.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/mlx5_glue.c | 33 +++++++++++++++++++++++++++++++++
 drivers/net/mlx5/mlx5_glue.h |  9 +++++++++
 2 files changed, 42 insertions(+)

diff --git a/drivers/net/mlx5/mlx5_glue.c b/drivers/net/mlx5/mlx5_glue.c
index 48590df..caa4c34 100644
--- a/drivers/net/mlx5/mlx5_glue.c
+++ b/drivers/net/mlx5/mlx5_glue.c
@@ -174,6 +174,12 @@
 	return ibv_destroy_flow(flow_id);
 }
 
+static int
+mlx5_glue_destroy_flow_action(struct ibv_flow_action *action)
+{
+	return ibv_destroy_flow_action(action);
+}
+
 static struct ibv_qp *
 mlx5_glue_create_qp(struct ibv_pd *pd, struct ibv_qp_init_attr *qp_init_attr)
 {
@@ -388,6 +394,30 @@
 #endif
 }
 
+static struct ibv_flow_action *
+mlx5_glue_dv_create_flow_action_packet_reformat
+		(struct ibv_context *ctx,
+		 size_t data_sz,
+		 void *data,
+		 enum mlx5dv_flow_action_packet_reformat_type reformat_type,
+		 enum mlx5dv_flow_table_type ft_type)
+{
+#ifdef HAVE_IBV_FLOW_DV_SUPPORT
+	return mlx5dv_create_flow_action_packet_reformat(ctx,
+							 data_sz,
+							 data,
+							 reformat_type,
+							 ft_type);
+#else
+	(void)ctx;
+	(void)data_sz;
+	(void)data;
+	(void)reformat_type;
+	(void)ft_type;
+	return NULL;
+#endif
+}
+
 alignas(RTE_CACHE_LINE_SIZE)
 const struct mlx5_glue *mlx5_glue = &(const struct mlx5_glue){
 	.version = MLX5_GLUE_VERSION,
@@ -414,6 +444,7 @@
 	.modify_wq = mlx5_glue_modify_wq,
 	.create_flow = mlx5_glue_create_flow,
 	.destroy_flow = mlx5_glue_destroy_flow,
+	.destroy_flow_action = mlx5_glue_destroy_flow_action,
 	.create_qp = mlx5_glue_create_qp,
 	.create_qp_ex = mlx5_glue_create_qp_ex,
 	.destroy_qp = mlx5_glue_destroy_qp,
@@ -437,4 +468,6 @@
 	.dv_create_flow_matcher = mlx5_glue_dv_create_flow_matcher,
 	.dv_destroy_flow_matcher = mlx5_glue_dv_destroy_flow_matcher,
 	.dv_create_flow = mlx5_glue_dv_create_flow,
+	.dv_create_flow_action_packet_reformat =
+			mlx5_glue_dv_create_flow_action_packet_reformat,
 };
diff --git a/drivers/net/mlx5/mlx5_glue.h b/drivers/net/mlx5/mlx5_glue.h
index f6e4e38..8ef4fcc 100644
--- a/drivers/net/mlx5/mlx5_glue.h
+++ b/drivers/net/mlx5/mlx5_glue.h
@@ -44,6 +44,8 @@
 struct mlx5dv_flow_matcher_attr;
 struct mlx5dv_flow_action_attr;
 struct mlx5dv_flow_match_parameters;
+enum mlx5dv_flow_action_packet_reformat_type;
+enum mlx5dv_flow_table_type;
 #endif
 
 /* LIB_GLUE_VERSION must be updated every time this structure is modified. */
@@ -85,6 +87,7 @@ struct mlx5_glue {
 	struct ibv_flow *(*create_flow)(struct ibv_qp *qp,
 					struct ibv_flow_attr *flow);
 	int (*destroy_flow)(struct ibv_flow *flow_id);
+	int (*destroy_flow_action)(struct ibv_flow_action *action);
 	struct ibv_qp *(*create_qp)(struct ibv_pd *pd,
 				    struct ibv_qp_init_attr *qp_init_attr);
 	struct ibv_qp *(*create_qp_ex)
@@ -137,6 +140,12 @@ struct mlx5_glue {
 			  struct mlx5dv_flow_match_parameters *match_value,
 			  size_t num_actions,
 			  struct mlx5dv_flow_action_attr *actions_attr);
+	struct ibv_flow_action *(*dv_create_flow_action_packet_reformat)
+		(struct ibv_context *ctx,
+		 size_t data_sz,
+		 void *data,
+		 enum mlx5dv_flow_action_packet_reformat_type reformat_type,
+		 enum mlx5dv_flow_table_type ft_type);
 };
 
 const struct mlx5_glue *mlx5_glue;
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v2 2/4] net/mlx5: add Direct Verbs encap and decap defs
  2018-09-27 14:50 [dpdk-dev] [PATCH 0/4] support DV encap and decap actions Dekel Peled
                   ` (5 preceding siblings ...)
  2018-10-07 14:25 ` [dpdk-dev] [PATCH v2 1/4] net/mlx5: add flow action functions to glue Dekel Peled
@ 2018-10-07 14:25 ` Dekel Peled
  2018-10-08 20:46   ` Yongseok Koh
  2018-10-07 14:25 ` [dpdk-dev] [PATCH v2 3/4] net/mlx5: add L2 and L3 encap to Direct Verbs flow Dekel Peled
  2018-10-07 14:25 ` [dpdk-dev] [PATCH v2 4/4] net/mlx5: add L2 and L3 decap " Dekel Peled
  8 siblings, 1 reply; 94+ messages in thread
From: Dekel Peled @ 2018-10-07 14:25 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch adds the required definitions for DV encap/decap actions.
It also adds usage of the new actions definition in validation
function of existing drop operation.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow.c | 8 ++++++++
 drivers/net/mlx5/mlx5_flow.h | 6 ++++++
 2 files changed, 14 insertions(+)

diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 1087f67..b452e11 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -766,6 +766,14 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't have 2 fate actions in"
 					  " same flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
+			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3 |
+			    MLX5_FLOW_ACTION_TUNNEL_ENCAP |
+			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't encap or decap and drop in"
+					  " same flow");
 	if (attr->egress)
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 690c597..01c73a2 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -82,6 +82,10 @@
 #define MLX5_FLOW_ACTION_OF_SET_VLAN_VID (1u << 9)
 #define MLX5_FLOW_ACTION_OF_SET_VLAN_PCP (1u << 10)
 #define MLX5_FLOW_ACTION_JUMP (1u << 11)
+#define MLX5_FLOW_ACTION_TUNNEL_ENCAP (1u << 12)
+#define MLX5_FLOW_ACTION_TUNNEL_DECAP (1u << 13)
+#define MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3 (1u << 14)
+#define MLX5_FLOW_ACTION_TUNNEL_DECAP_L3 (1u << 15)
 
 #define MLX5_FLOW_FATE_ACTIONS \
 	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS)
@@ -172,6 +176,8 @@ struct mlx5_flow_dv {
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
 	struct mlx5dv_flow_action_attr actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS];
 	/**< Action list. */
+	struct ibv_flow_action *encap_verb; /**< Verbs object of encap. */
+	struct ibv_flow_action *decap_verb; /**< Verbs object of decap. */
 #endif
 	int actions_n; /**< number of actions. */
 };
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v2 3/4] net/mlx5: add L2 and L3 encap to Direct Verbs flow
  2018-09-27 14:50 [dpdk-dev] [PATCH 0/4] support DV encap and decap actions Dekel Peled
                   ` (6 preceding siblings ...)
  2018-10-07 14:25 ` [dpdk-dev] [PATCH v2 2/4] net/mlx5: add Direct Verbs encap and decap defs Dekel Peled
@ 2018-10-07 14:25 ` Dekel Peled
  2018-10-08 21:04   ` Yongseok Koh
  2018-10-07 14:25 ` [dpdk-dev] [PATCH v2 4/4] net/mlx5: add L2 and L3 decap " Dekel Peled
  8 siblings, 1 reply; 94+ messages in thread
From: Dekel Peled @ 2018-10-07 14:25 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch adds support for Direct Verbs encap operations, L2 and L3.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow_dv.c | 226 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 222 insertions(+), 4 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 80e7b24..221c76a 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -84,6 +84,167 @@
 }
 
 /**
+ * Validate the tunnel encap action.
+ *
+ * @param[in] action_flags
+ *   holds the actions detected until now.
+ * @param[in] action
+ *   Pointer to the encap action.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_ernno is set.
+ */
+static int
+flow_dv_validate_action_tunnel_encap(uint64_t action_flags,
+				     const struct rte_flow_action *action,
+				     const struct rte_flow_attr *attr,
+				     struct rte_flow_error *error)
+{
+	const struct rte_flow_action_tunnel_encap *tunnel_encap = action->conf;
+
+	if (!tunnel_encap || !(tunnel_encap->buf))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, action,
+					  "configuration cannot be null");
+	if (action_flags & MLX5_FLOW_ACTION_DROP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't drop and encap in same flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP |
+			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't have 2 encap actions in same"
+					  " flow");
+	if (attr->ingress)
+		return rte_flow_error_set(error, ENOTSUP,
+					RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, NULL,
+					"encap action not supported for "
+					"ingress");
+	return 0;
+}
+
+/**
+ * Validate the tunnel encap L3 action
+ *
+ * @param[in] action_flags
+ *   holds the actions detected until now.
+ * @param[in] action
+ *   Pointer to the encap action.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_ernno is set.
+ */
+static int
+flow_dv_validate_action_tunnel_encap_l3(uint64_t action_flags,
+					const struct rte_flow_action *action,
+					const struct rte_flow_attr *attr,
+					struct rte_flow_error *error)
+{
+	const struct rte_flow_action_tunnel_encap_l3 *tunnel_encap_l3 =
+			action->conf;
+
+	if (!tunnel_encap_l3 || !(tunnel_encap_l3->buf))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, action,
+					  "configuration cannot be null");
+	if (action_flags & MLX5_FLOW_ACTION_DROP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't drop and encap in same flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP |
+			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't have 2 encap actions in same"
+					  " flow");
+	if (attr->ingress)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
+					  NULL,
+					  "encap action not supported for "
+					  "ingress");
+	return 0;
+}
+
+/**
+ * Convert encap action to DV specification.
+ *
+ * @param[in] action
+ *   Pointer to action structure.
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+flow_dv_create_encap(const struct rte_flow_action *action,
+		     struct rte_eth_dev *dev,
+		     struct rte_flow_error *error)
+{
+	struct ibv_flow_action *encap_verb = NULL;
+	const struct rte_flow_action_tunnel_encap *encap_data;
+	struct priv *priv = dev->data->dev_private;
+
+	encap_data = (const struct rte_flow_action_tunnel_encap *)action->conf;
+	encap_verb = mlx5_glue->dv_create_flow_action_packet_reformat
+		(priv->ctx, encap_data->size,
+		 encap_data->size ? encap_data->buf : NULL,
+		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
+		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
+	if (!encap_verb)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create encap action");
+	return encap_verb;
+}
+
+/**
+ * Convert encap L3 action to DV specification.
+ *
+ * @param[in] action
+ *   Pointer to action structure.
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+flow_dv_create_encap_l3(const struct rte_flow_action *action,
+			struct rte_eth_dev *dev,
+			struct rte_flow_error *error)
+{
+	struct ibv_flow_action *encap_l3_verb = NULL;
+	const struct rte_flow_action_tunnel_encap_l3 *encap_l3_data;
+	struct priv *priv = dev->data->dev_private;
+
+	encap_l3_data =
+		(const struct rte_flow_action_tunnel_encap_l3 *)action->conf;
+	encap_l3_verb = mlx5_glue->dv_create_flow_action_packet_reformat
+		(priv->ctx, encap_l3_data->size,
+		 encap_l3_data->size ? encap_l3_data->buf : NULL,
+		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL,
+		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
+	if (!encap_l3_verb)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create encap L3 action");
+	return encap_l3_verb;
+}
+
+/**
  * Verify the @p attributes will be correctly understood by the NIC and store
  * them in the @p flow if everything is correct.
  *
@@ -330,6 +491,20 @@
 			action_flags |= MLX5_FLOW_ACTION_COUNT;
 			++actions_n;
 			break;
+		case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP:
+			ret = flow_dv_validate_action_tunnel_encap
+				(action_flags, actions, attr, error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_TUNNEL_ENCAP;
+			break;
+		case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP_L3:
+			ret = flow_dv_validate_action_tunnel_encap_l3
+				(action_flags, actions, attr, error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3;
+			break;
 		default:
 			return rte_flow_error_set(error, ENOTSUP,
 						  RTE_FLOW_ERROR_TYPE_ACTION,
@@ -1042,10 +1217,19 @@
  *   Flow action to translate.
  * @param[in, out] dev_flow
  *   Pointer to the mlx5_flow.
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_ernno is set.
  */
-static void
+static int
 flow_dv_create_action(const struct rte_flow_action *action,
-		      struct mlx5_flow *dev_flow)
+		      struct mlx5_flow *dev_flow,
+		      struct rte_eth_dev *dev,
+		      struct rte_flow_error *error)
 {
 	const struct rte_flow_action_queue *queue;
 	const struct rte_flow_action_rss *rss;
@@ -1092,10 +1276,35 @@
 		/* Added to array only in apply since we need the QP */
 		flow->actions |= MLX5_FLOW_ACTION_RSS;
 		break;
+	case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP:
+		dev_flow->dv.actions[actions_n].type =
+			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+		dev_flow->dv.actions[actions_n].action =
+			flow_dv_create_encap(action, dev, error);
+		if (!(dev_flow->dv.actions[actions_n].action))
+			return -rte_errno;
+		dev_flow->dv.encap_verb =
+			dev_flow->dv.actions[actions_n].action;
+		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_ENCAP;
+		actions_n++;
+		break;
+	case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP_L3:
+		dev_flow->dv.actions[actions_n].type =
+			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+		dev_flow->dv.actions[actions_n].action =
+			flow_dv_create_encap_l3(action, dev, error);
+		if (!(dev_flow->dv.actions[actions_n].action))
+			return -rte_errno;
+		dev_flow->dv.encap_verb =
+			dev_flow->dv.actions[actions_n].action;
+		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3;
+		actions_n++;
+		break;
 	default:
 		break;
 	}
 	dev_flow->dv.actions_n = actions_n;
+	return 0;
 }
 
 static uint32_t matcher_zero[MLX5_ST_SZ_DW(fte_match_param)] = { 0 };
@@ -1259,8 +1468,10 @@
 	matcher.egress = attr->egress;
 	if (flow_dv_matcher_register(dev, &matcher, dev_flow, error))
 		return -rte_errno;
-	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++)
-		flow_dv_create_action(actions, dev_flow);
+	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
+		if (flow_dv_create_action(actions, dev_flow, dev, error))
+			return -rte_errno;
+	}
 	return 0;
 }
 
@@ -1444,6 +1655,13 @@
 		LIST_REMOVE(dev_flow, next);
 		if (dev_flow->dv.matcher)
 			flow_dv_matcher_release(dev, dev_flow->dv.matcher);
+
+		if (dev_flow->dv.encap_verb) {
+			claim_zero(mlx5_glue->destroy_flow_action
+						(dev_flow->dv.encap_verb));
+			dev_flow->dv.encap_verb = NULL;
+		}
+
 		rte_free(dev_flow);
 	}
 }
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v2 4/4] net/mlx5: add L2 and L3 decap to Direct Verbs flow
  2018-09-27 14:50 [dpdk-dev] [PATCH 0/4] support DV encap and decap actions Dekel Peled
                   ` (7 preceding siblings ...)
  2018-10-07 14:25 ` [dpdk-dev] [PATCH v2 3/4] net/mlx5: add L2 and L3 encap to Direct Verbs flow Dekel Peled
@ 2018-10-07 14:25 ` Dekel Peled
  2018-10-08 21:19   ` Yongseok Koh
  8 siblings, 1 reply; 94+ messages in thread
From: Dekel Peled @ 2018-10-07 14:25 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch adds support for Direct Verbs decap operations, L2 and L3.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>

Conflicts:
	drivers/net/mlx5/mlx5_flow_dv.c
---
 drivers/net/mlx5/mlx5_flow_dv.c | 224 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 219 insertions(+), 5 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 221c76a..5b44f5b 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -120,11 +120,18 @@
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't have 2 encap actions in same"
 					  " flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
+			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't encap and decap in same"
+					  " flow");
 	if (attr->ingress)
 		return rte_flow_error_set(error, ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, NULL,
-					"encap action not supported for "
-					"ingress");
+					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
+					  NULL,
+					  "encap action not supported for "
+					  "ingress");
 	return 0;
 }
 
@@ -166,6 +173,12 @@
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't have 2 encap actions in same"
 					  " flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
+			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't encap and decap in same"
+					  " flow");
 	if (attr->ingress)
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
@@ -176,6 +189,100 @@
 }
 
 /**
+ * Validate the tunnel decap action
+ *
+ * @param[in] action_flags
+ *   holds the actions detected until now.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_ernno is set.
+ */
+static int
+flow_dv_validate_action_tunnel_decap(uint64_t action_flags,
+				     const struct rte_flow_attr *attr,
+				     struct rte_flow_error *error)
+{
+	if (action_flags & MLX5_FLOW_ACTION_DROP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't drop and decap in same flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
+			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't have 2 decap actions in same"
+					  " flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP |
+			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't encap and decap in same"
+					  " flow");
+	if (attr->egress)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
+					  "decap action not supported for "
+					  "egress");
+	return 0;
+}
+
+/**
+ * Validate the tunnel decap L3 action
+ *
+ * @param[in] action_flags
+ *   holds the actions detected until now.
+ * @param[in] action
+ *   Pointer to the decap action.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_ernno is set.
+ */
+static int
+flow_dv_validate_action_tunnel_decap_l3(uint64_t action_flags,
+					const struct rte_flow_action *action,
+					const struct rte_flow_attr *attr,
+					struct rte_flow_error *error)
+{
+	const struct rte_flow_action_tunnel_decap_l3 *tunnel_decap_l3 =
+			action->conf;
+
+	if (!tunnel_decap_l3 || !(tunnel_decap_l3->buf))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, action,
+					  "configuration cannot be null");
+	if (action_flags & MLX5_FLOW_ACTION_DROP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't drop and decap in same flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
+			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't have 2 decap actions in same"
+					  " flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP |
+			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't encap and decap in same"
+					  " flow");
+	if (attr->egress)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
+					  "decap action not supported for "
+					  "egress");
+	return 0;
+}
+
+/**
  * Convert encap action to DV specification.
  *
  * @param[in] action
@@ -245,6 +352,72 @@
 }
 
 /**
+ * Convert decap action to DV specification.
+ *
+ * @param[in] action
+ *   Pointer to action structure.
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+flow_dv_create_decap(const struct rte_flow_action *action __rte_unused,
+		     struct rte_eth_dev *dev,
+		     struct rte_flow_error *error)
+{
+	struct ibv_flow_action *decap_verb = NULL;
+	struct priv *priv = dev->data->dev_private;
+
+	decap_verb = mlx5_glue->dv_create_flow_action_packet_reformat
+		(priv->ctx, 0, NULL,
+		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2,
+		 MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
+	if (!decap_verb)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create decap action");
+	return decap_verb;
+}
+
+/**
+ * Convert decap L3 action to DV specification.
+ *
+ * @param[in] action
+ *   Pointer to action structure.
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+flow_dv_create_decap_l3(const struct rte_flow_action *action,
+			struct rte_eth_dev *dev,
+			struct rte_flow_error *error)
+{
+	struct ibv_flow_action *decap_l3_verb = NULL;
+	const struct rte_flow_action_tunnel_decap_l3 *decap_l3_data;
+	struct priv *priv = dev->data->dev_private;
+
+	decap_l3_data =
+		(const struct rte_flow_action_tunnel_decap_l3 *)action->conf;
+	decap_l3_verb = mlx5_glue->dv_create_flow_action_packet_reformat
+		(priv->ctx, decap_l3_data->size,
+		 decap_l3_data->size ? decap_l3_data->buf : NULL,
+		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2,
+		 MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
+	if (!decap_l3_verb)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create decap L3 action");
+	return decap_l3_verb;
+}
+
+/**
  * Verify the @p attributes will be correctly understood by the NIC and store
  * them in the @p flow if everything is correct.
  *
@@ -505,6 +678,20 @@
 				return ret;
 			action_flags |= MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3;
 			break;
+		case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP:
+			ret = flow_dv_validate_action_tunnel_decap
+				(action_flags, attr, error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_TUNNEL_DECAP;
+			break;
+		case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP_L3:
+			ret = flow_dv_validate_action_tunnel_decap_l3
+				(action_flags, actions, attr, error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_TUNNEL_DECAP_L3;
+			break;
 		default:
 			return rte_flow_error_set(error, ENOTSUP,
 						  RTE_FLOW_ERROR_TYPE_ACTION,
@@ -1300,6 +1487,30 @@
 		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3;
 		actions_n++;
 		break;
+	case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP:
+		dev_flow->dv.actions[actions_n].type =
+			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+		dev_flow->dv.actions[actions_n].action =
+			flow_dv_create_decap(action, dev, error);
+		if (!(dev_flow->dv.actions[actions_n].action))
+			return -rte_errno;
+		dev_flow->dv.decap_verb =
+			dev_flow->dv.actions[actions_n].action;
+		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_DECAP;
+		actions_n++;
+		break;
+	case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP_L3:
+		dev_flow->dv.actions[actions_n].type =
+			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+		dev_flow->dv.actions[actions_n].action =
+			flow_dv_create_decap_l3(action, dev, error);
+		if (!(dev_flow->dv.actions[actions_n].action))
+			return -rte_errno;
+		dev_flow->dv.decap_verb =
+			dev_flow->dv.actions[actions_n].action;
+		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_DECAP_L3;
+		actions_n++;
+		break;
 	default:
 		break;
 	}
@@ -1655,13 +1866,16 @@
 		LIST_REMOVE(dev_flow, next);
 		if (dev_flow->dv.matcher)
 			flow_dv_matcher_release(dev, dev_flow->dv.matcher);
-
 		if (dev_flow->dv.encap_verb) {
 			claim_zero(mlx5_glue->destroy_flow_action
 						(dev_flow->dv.encap_verb));
 			dev_flow->dv.encap_verb = NULL;
 		}
-
+		if (dev_flow->dv.decap_verb) {
+			claim_zero(mlx5_glue->destroy_flow_action
+						(dev_flow->dv.decap_verb));
+			dev_flow->dv.decap_verb = NULL;
+		}
 		rte_free(dev_flow);
 	}
 }
-- 
1.8.3.1

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

* Re: [dpdk-dev] [PATCH v2 1/4] net/mlx5: add flow action functions to glue
  2018-10-07 14:25 ` [dpdk-dev] [PATCH v2 1/4] net/mlx5: add flow action functions to glue Dekel Peled
@ 2018-10-08 19:43   ` Yongseok Koh
  2018-10-09 18:49     ` Dekel Peled
  0 siblings, 1 reply; 94+ messages in thread
From: Yongseok Koh @ 2018-10-08 19:43 UTC (permalink / raw)
  To: Dekel Peled; +Cc: Shahaf Shuler, dev, Ori Kam

On Sun, Oct 07, 2018 at 05:25:05PM +0300, Dekel Peled wrote:
> This patch adds glue functions for operations:
> - Create packet reformat (encap/decap) flow action.
> - Destroy flow action.
> 
> Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> ---

I'm not still able to compile this patch on my host, which is RH7.4 with MOFED
MLNX_OFED_LINUX-4.4-2.0.4.0.

>  drivers/net/mlx5/mlx5_glue.c | 33 +++++++++++++++++++++++++++++++++
>  drivers/net/mlx5/mlx5_glue.h |  9 +++++++++
>  2 files changed, 42 insertions(+)
> 
> diff --git a/drivers/net/mlx5/mlx5_glue.c b/drivers/net/mlx5/mlx5_glue.c
> index 48590df..caa4c34 100644
> --- a/drivers/net/mlx5/mlx5_glue.c
> +++ b/drivers/net/mlx5/mlx5_glue.c
> @@ -174,6 +174,12 @@
>  	return ibv_destroy_flow(flow_id);
>  }
>  
> +static int
> +mlx5_glue_destroy_flow_action(struct ibv_flow_action *action)
> +{
> +	return ibv_destroy_flow_action(action);
> +}

Shouldn't this be under HAVE_IBV_FLOW_DV_SUPPORT? My host doesn't have it either
- ibv_destroy_flow_action() and ibv_flow_action.

> +
>  static struct ibv_qp *
>  mlx5_glue_create_qp(struct ibv_pd *pd, struct ibv_qp_init_attr *qp_init_attr)
>  {
> @@ -388,6 +394,30 @@
>  #endif
>  }
>  
> +static struct ibv_flow_action *
> +mlx5_glue_dv_create_flow_action_packet_reformat
> +		(struct ibv_context *ctx,
> +		 size_t data_sz,
> +		 void *data,
> +		 enum mlx5dv_flow_action_packet_reformat_type reformat_type,
> +		 enum mlx5dv_flow_table_type ft_type)
> +{
> +#ifdef HAVE_IBV_FLOW_DV_SUPPORT

I don't think your change can be protected by this. According to the git logs of
rdma-core, HAVE_IBV_FLOW_DV_SUPPORT is to mark the following patch of Yishai
Hadas,

	mlx5: Introduce mlx5dv_create_flow

While, the flow action has been added by another patchset of Mark Bloch later,

	mlx5: Add packet reformat flow action

So, it seems to need another macro, doesn't it?
E.g. HAVE_IBV_FLOW_ACTION_DV_SUPPORT

> +	return mlx5dv_create_flow_action_packet_reformat(ctx,
> +							 data_sz,
> +							 data,
> +							 reformat_type,
> +							 ft_type);
> +#else
> +	(void)ctx;
> +	(void)data_sz;
> +	(void)data;
> +	(void)reformat_type;
> +	(void)ft_type;
> +	return NULL;
> +#endif
> +}
> +
>  alignas(RTE_CACHE_LINE_SIZE)
>  const struct mlx5_glue *mlx5_glue = &(const struct mlx5_glue){
>  	.version = MLX5_GLUE_VERSION,
> @@ -414,6 +444,7 @@
>  	.modify_wq = mlx5_glue_modify_wq,
>  	.create_flow = mlx5_glue_create_flow,
>  	.destroy_flow = mlx5_glue_destroy_flow,
> +	.destroy_flow_action = mlx5_glue_destroy_flow_action,
>  	.create_qp = mlx5_glue_create_qp,
>  	.create_qp_ex = mlx5_glue_create_qp_ex,
>  	.destroy_qp = mlx5_glue_destroy_qp,
> @@ -437,4 +468,6 @@
>  	.dv_create_flow_matcher = mlx5_glue_dv_create_flow_matcher,
>  	.dv_destroy_flow_matcher = mlx5_glue_dv_destroy_flow_matcher,
>  	.dv_create_flow = mlx5_glue_dv_create_flow,
> +	.dv_create_flow_action_packet_reformat =
> +			mlx5_glue_dv_create_flow_action_packet_reformat,
>  };
> diff --git a/drivers/net/mlx5/mlx5_glue.h b/drivers/net/mlx5/mlx5_glue.h
> index f6e4e38..8ef4fcc 100644
> --- a/drivers/net/mlx5/mlx5_glue.h
> +++ b/drivers/net/mlx5/mlx5_glue.h
> @@ -44,6 +44,8 @@
>  struct mlx5dv_flow_matcher_attr;
>  struct mlx5dv_flow_action_attr;
>  struct mlx5dv_flow_match_parameters;
> +enum mlx5dv_flow_action_packet_reformat_type;
> +enum mlx5dv_flow_table_type;
>  #endif
>  
>  /* LIB_GLUE_VERSION must be updated every time this structure is modified. */
> @@ -85,6 +87,7 @@ struct mlx5_glue {
>  	struct ibv_flow *(*create_flow)(struct ibv_qp *qp,
>  					struct ibv_flow_attr *flow);
>  	int (*destroy_flow)(struct ibv_flow *flow_id);
> +	int (*destroy_flow_action)(struct ibv_flow_action *action);
>  	struct ibv_qp *(*create_qp)(struct ibv_pd *pd,
>  				    struct ibv_qp_init_attr *qp_init_attr);
>  	struct ibv_qp *(*create_qp_ex)
> @@ -137,6 +140,12 @@ struct mlx5_glue {
>  			  struct mlx5dv_flow_match_parameters *match_value,
>  			  size_t num_actions,
>  			  struct mlx5dv_flow_action_attr *actions_attr);
> +	struct ibv_flow_action *(*dv_create_flow_action_packet_reformat)
> +		(struct ibv_context *ctx,
> +		 size_t data_sz,
> +		 void *data,
> +		 enum mlx5dv_flow_action_packet_reformat_type reformat_type,
> +		 enum mlx5dv_flow_table_type ft_type);
>  };
>  
>  const struct mlx5_glue *mlx5_glue;
> -- 
> 1.8.3.1
> 

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

* Re: [dpdk-dev] [PATCH v2 2/4] net/mlx5: add Direct Verbs encap and decap defs
  2018-10-07 14:25 ` [dpdk-dev] [PATCH v2 2/4] net/mlx5: add Direct Verbs encap and decap defs Dekel Peled
@ 2018-10-08 20:46   ` Yongseok Koh
  0 siblings, 0 replies; 94+ messages in thread
From: Yongseok Koh @ 2018-10-08 20:46 UTC (permalink / raw)
  To: Dekel Peled; +Cc: Shahaf Shuler, dev, Ori Kam

On Sun, Oct 07, 2018 at 05:25:06PM +0300, Dekel Peled wrote:
> This patch adds the required definitions for DV encap/decap actions.
> It also adds usage of the new actions definition in validation
> function of existing drop operation.
> 
> Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> ---

You may have to rebase it again as there are more patches adding new
MLX5_FLOW_ACTION_*. Shahaf will orchestrate it.

Acked-by: Yongseok Koh <yskoh@mellanox.com>

Thanks

>  drivers/net/mlx5/mlx5_flow.c | 8 ++++++++
>  drivers/net/mlx5/mlx5_flow.h | 6 ++++++
>  2 files changed, 14 insertions(+)
> 
> diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
> index 1087f67..b452e11 100644
> --- a/drivers/net/mlx5/mlx5_flow.c
> +++ b/drivers/net/mlx5/mlx5_flow.c
> @@ -766,6 +766,14 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
>  					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
>  					  "can't have 2 fate actions in"
>  					  " same flow");
> +	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
> +			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3 |
> +			    MLX5_FLOW_ACTION_TUNNEL_ENCAP |
> +			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
> +					  "can't encap or decap and drop in"
> +					  " same flow");
>  	if (attr->egress)
>  		return rte_flow_error_set(error, ENOTSUP,
>  					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
> diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
> index 690c597..01c73a2 100644
> --- a/drivers/net/mlx5/mlx5_flow.h
> +++ b/drivers/net/mlx5/mlx5_flow.h
> @@ -82,6 +82,10 @@
>  #define MLX5_FLOW_ACTION_OF_SET_VLAN_VID (1u << 9)
>  #define MLX5_FLOW_ACTION_OF_SET_VLAN_PCP (1u << 10)
>  #define MLX5_FLOW_ACTION_JUMP (1u << 11)
> +#define MLX5_FLOW_ACTION_TUNNEL_ENCAP (1u << 12)
> +#define MLX5_FLOW_ACTION_TUNNEL_DECAP (1u << 13)
> +#define MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3 (1u << 14)
> +#define MLX5_FLOW_ACTION_TUNNEL_DECAP_L3 (1u << 15)
>  
>  #define MLX5_FLOW_FATE_ACTIONS \
>  	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS)
> @@ -172,6 +176,8 @@ struct mlx5_flow_dv {
>  #ifdef HAVE_IBV_FLOW_DV_SUPPORT
>  	struct mlx5dv_flow_action_attr actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS];
>  	/**< Action list. */
> +	struct ibv_flow_action *encap_verb; /**< Verbs object of encap. */
> +	struct ibv_flow_action *decap_verb; /**< Verbs object of decap. */
>  #endif
>  	int actions_n; /**< number of actions. */
>  };
> -- 
> 1.8.3.1
> 

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

* Re: [dpdk-dev] [PATCH v2 3/4] net/mlx5: add L2 and L3 encap to Direct Verbs flow
  2018-10-07 14:25 ` [dpdk-dev] [PATCH v2 3/4] net/mlx5: add L2 and L3 encap to Direct Verbs flow Dekel Peled
@ 2018-10-08 21:04   ` Yongseok Koh
  2018-10-09 15:55     ` Dekel Peled
  0 siblings, 1 reply; 94+ messages in thread
From: Yongseok Koh @ 2018-10-08 21:04 UTC (permalink / raw)
  To: Dekel Peled; +Cc: Shahaf Shuler, dev, Ori Kam

On Sun, Oct 07, 2018 at 05:25:07PM +0300, Dekel Peled wrote:
> This patch adds support for Direct Verbs encap operations, L2 and L3.
> 
> Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> ---

For flow_dv_create_encap(), flow_dv_create_encap_l3() and
flow_dv_create_action(), please make the 'dev' come first in the args list like
other functions.

And there are still two blank lines like I pointed out below.

With these changes, please put my acked-by tag when you submit the next version.

Thanks,
Yongseok

>  drivers/net/mlx5/mlx5_flow_dv.c | 226 +++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 222 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
> index 80e7b24..221c76a 100644
> --- a/drivers/net/mlx5/mlx5_flow_dv.c
> +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> @@ -84,6 +84,167 @@
>  }
>  
>  /**
> + * Validate the tunnel encap action.
> + *
> + * @param[in] action_flags
> + *   holds the actions detected until now.
> + * @param[in] action
> + *   Pointer to the encap action.
> + * @param[in] attr
> + *   Pointer to flow attributes
> + * @param[out] error
> + *   Pointer to error structure.
> + *
> + * @return
> + *   0 on success, a negative errno value otherwise and rte_ernno is set.
> + */
> +static int
> +flow_dv_validate_action_tunnel_encap(uint64_t action_flags,
> +				     const struct rte_flow_action *action,
> +				     const struct rte_flow_attr *attr,
> +				     struct rte_flow_error *error)
> +{
> +	const struct rte_flow_action_tunnel_encap *tunnel_encap = action->conf;
> +
> +	if (!tunnel_encap || !(tunnel_encap->buf))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, action,
> +					  "configuration cannot be null");
> +	if (action_flags & MLX5_FLOW_ACTION_DROP)
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
> +					  "can't drop and encap in same flow");
> +	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP |
> +			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
> +					  "can't have 2 encap actions in same"
> +					  " flow");
> +	if (attr->ingress)
> +		return rte_flow_error_set(error, ENOTSUP,
> +					RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, NULL,
> +					"encap action not supported for "
> +					"ingress");
> +	return 0;
> +}
> +
> +/**
> + * Validate the tunnel encap L3 action
> + *
> + * @param[in] action_flags
> + *   holds the actions detected until now.
> + * @param[in] action
> + *   Pointer to the encap action.
> + * @param[in] attr
> + *   Pointer to flow attributes
> + * @param[out] error
> + *   Pointer to error structure.
> + *
> + * @return
> + *   0 on success, a negative errno value otherwise and rte_ernno is set.
> + */
> +static int
> +flow_dv_validate_action_tunnel_encap_l3(uint64_t action_flags,
> +					const struct rte_flow_action *action,
> +					const struct rte_flow_attr *attr,
> +					struct rte_flow_error *error)
> +{
> +	const struct rte_flow_action_tunnel_encap_l3 *tunnel_encap_l3 =
> +			action->conf;
> +
> +	if (!tunnel_encap_l3 || !(tunnel_encap_l3->buf))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, action,
> +					  "configuration cannot be null");
> +	if (action_flags & MLX5_FLOW_ACTION_DROP)
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
> +					  "can't drop and encap in same flow");
> +	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP |
> +			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
> +					  "can't have 2 encap actions in same"
> +					  " flow");
> +	if (attr->ingress)
> +		return rte_flow_error_set(error, ENOTSUP,
> +					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> +					  NULL,
> +					  "encap action not supported for "
> +					  "ingress");
> +	return 0;
> +}
> +
> +/**
> + * Convert encap action to DV specification.
> + *
> + * @param[in] action
> + *   Pointer to action structure.
> + * @param[in] dev
> + *   Pointer to rte_eth_dev structure.
> + * @param[out] error
> + *   Pointer to the error structure.
> + *
> + * @return
> + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> + */
> +static struct ibv_flow_action *
> +flow_dv_create_encap(const struct rte_flow_action *action,
> +		     struct rte_eth_dev *dev,
> +		     struct rte_flow_error *error)
> +{
> +	struct ibv_flow_action *encap_verb = NULL;
> +	const struct rte_flow_action_tunnel_encap *encap_data;
> +	struct priv *priv = dev->data->dev_private;
> +
> +	encap_data = (const struct rte_flow_action_tunnel_encap *)action->conf;
> +	encap_verb = mlx5_glue->dv_create_flow_action_packet_reformat
> +		(priv->ctx, encap_data->size,
> +		 encap_data->size ? encap_data->buf : NULL,
> +		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
> +		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
> +	if (!encap_verb)
> +		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
> +				   NULL, "cannot create encap action");
> +	return encap_verb;
> +}
> +
> +/**
> + * Convert encap L3 action to DV specification.
> + *
> + * @param[in] action
> + *   Pointer to action structure.
> + * @param[in] dev
> + *   Pointer to rte_eth_dev structure.
> + * @param[out] error
> + *   Pointer to the error structure.
> + *
> + * @return
> + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> + */
> +static struct ibv_flow_action *
> +flow_dv_create_encap_l3(const struct rte_flow_action *action,
> +			struct rte_eth_dev *dev,
> +			struct rte_flow_error *error)
> +{
> +	struct ibv_flow_action *encap_l3_verb = NULL;
> +	const struct rte_flow_action_tunnel_encap_l3 *encap_l3_data;
> +	struct priv *priv = dev->data->dev_private;
> +
> +	encap_l3_data =
> +		(const struct rte_flow_action_tunnel_encap_l3 *)action->conf;
> +	encap_l3_verb = mlx5_glue->dv_create_flow_action_packet_reformat
> +		(priv->ctx, encap_l3_data->size,
> +		 encap_l3_data->size ? encap_l3_data->buf : NULL,
> +		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL,
> +		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
> +	if (!encap_l3_verb)
> +		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
> +				   NULL, "cannot create encap L3 action");
> +	return encap_l3_verb;
> +}
> +
> +/**
>   * Verify the @p attributes will be correctly understood by the NIC and store
>   * them in the @p flow if everything is correct.
>   *
> @@ -330,6 +491,20 @@
>  			action_flags |= MLX5_FLOW_ACTION_COUNT;
>  			++actions_n;
>  			break;
> +		case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP:
> +			ret = flow_dv_validate_action_tunnel_encap
> +				(action_flags, actions, attr, error);
> +			if (ret < 0)
> +				return ret;
> +			action_flags |= MLX5_FLOW_ACTION_TUNNEL_ENCAP;
> +			break;
> +		case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP_L3:
> +			ret = flow_dv_validate_action_tunnel_encap_l3
> +				(action_flags, actions, attr, error);
> +			if (ret < 0)
> +				return ret;
> +			action_flags |= MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3;
> +			break;
>  		default:
>  			return rte_flow_error_set(error, ENOTSUP,
>  						  RTE_FLOW_ERROR_TYPE_ACTION,
> @@ -1042,10 +1217,19 @@
>   *   Flow action to translate.
>   * @param[in, out] dev_flow
>   *   Pointer to the mlx5_flow.
> + * @param[in] dev
> + *   Pointer to rte_eth_dev structure.
> + * @param[out] error
> + *   Pointer to the error structure.
> + *
> + * @return
> + *   0 on success, a negative errno value otherwise and rte_ernno is set.
>   */
> -static void
> +static int
>  flow_dv_create_action(const struct rte_flow_action *action,
> -		      struct mlx5_flow *dev_flow)
> +		      struct mlx5_flow *dev_flow,
> +		      struct rte_eth_dev *dev,
> +		      struct rte_flow_error *error)
>  {
>  	const struct rte_flow_action_queue *queue;
>  	const struct rte_flow_action_rss *rss;
> @@ -1092,10 +1276,35 @@
>  		/* Added to array only in apply since we need the QP */
>  		flow->actions |= MLX5_FLOW_ACTION_RSS;
>  		break;
> +	case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP:
> +		dev_flow->dv.actions[actions_n].type =
> +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> +		dev_flow->dv.actions[actions_n].action =
> +			flow_dv_create_encap(action, dev, error);
> +		if (!(dev_flow->dv.actions[actions_n].action))
> +			return -rte_errno;
> +		dev_flow->dv.encap_verb =
> +			dev_flow->dv.actions[actions_n].action;
> +		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_ENCAP;
> +		actions_n++;
> +		break;
> +	case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP_L3:
> +		dev_flow->dv.actions[actions_n].type =
> +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> +		dev_flow->dv.actions[actions_n].action =
> +			flow_dv_create_encap_l3(action, dev, error);
> +		if (!(dev_flow->dv.actions[actions_n].action))
> +			return -rte_errno;
> +		dev_flow->dv.encap_verb =
> +			dev_flow->dv.actions[actions_n].action;
> +		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3;
> +		actions_n++;
> +		break;
>  	default:
>  		break;
>  	}
>  	dev_flow->dv.actions_n = actions_n;
> +	return 0;
>  }
>  
>  static uint32_t matcher_zero[MLX5_ST_SZ_DW(fte_match_param)] = { 0 };
> @@ -1259,8 +1468,10 @@
>  	matcher.egress = attr->egress;
>  	if (flow_dv_matcher_register(dev, &matcher, dev_flow, error))
>  		return -rte_errno;
> -	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++)
> -		flow_dv_create_action(actions, dev_flow);
> +	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
> +		if (flow_dv_create_action(actions, dev_flow, dev, error))
> +			return -rte_errno;
> +	}
>  	return 0;
>  }
>  
> @@ -1444,6 +1655,13 @@
>  		LIST_REMOVE(dev_flow, next);
>  		if (dev_flow->dv.matcher)
>  			flow_dv_matcher_release(dev, dev_flow->dv.matcher);
> +

No blank line.

> +		if (dev_flow->dv.encap_verb) {
> +			claim_zero(mlx5_glue->destroy_flow_action
> +						(dev_flow->dv.encap_verb));
> +			dev_flow->dv.encap_verb = NULL;
> +		}
> +

No blank line.

>  		rte_free(dev_flow);
>  	}
>  }
> -- 
> 1.8.3.1
> 

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

* Re: [dpdk-dev] [PATCH v2 4/4] net/mlx5: add L2 and L3 decap to Direct Verbs flow
  2018-10-07 14:25 ` [dpdk-dev] [PATCH v2 4/4] net/mlx5: add L2 and L3 decap " Dekel Peled
@ 2018-10-08 21:19   ` Yongseok Koh
  2018-10-09 16:56     ` Dekel Peled
  0 siblings, 1 reply; 94+ messages in thread
From: Yongseok Koh @ 2018-10-08 21:19 UTC (permalink / raw)
  To: Dekel Peled; +Cc: Shahaf Shuler, dev, Ori Kam

On Sun, Oct 07, 2018 at 05:25:08PM +0300, Dekel Peled wrote:
> This patch adds support for Direct Verbs decap operations, L2 and L3.
> 
> Signed-off-by: Dekel Peled <dekelp@mellanox.com>

Same comment for the order of 'dev' arg.

> Conflicts:
> 	drivers/net/mlx5/mlx5_flow_dv.c

What is this? Conflicts?

> ---
>  drivers/net/mlx5/mlx5_flow_dv.c | 224 +++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 219 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
> index 221c76a..5b44f5b 100644
> --- a/drivers/net/mlx5/mlx5_flow_dv.c
> +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> @@ -120,11 +120,18 @@
>  					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
>  					  "can't have 2 encap actions in same"
>  					  " flow");
> +	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
> +			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
> +					  "can't encap and decap in same"
> +					  " flow");
>  	if (attr->ingress)
>  		return rte_flow_error_set(error, ENOTSUP,
> -					RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, NULL,
> -					"encap action not supported for "
> -					"ingress");
> +					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> +					  NULL,
> +					  "encap action not supported for "
> +					  "ingress");

It seems to be mistakenly included in this patch when you rebase the previous
patch. Please fix it in [4/4] and [3/4].

>  	return 0;
>  }
>  
> @@ -166,6 +173,12 @@
>  					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
>  					  "can't have 2 encap actions in same"
>  					  " flow");
> +	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
> +			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
> +					  "can't encap and decap in same"
> +					  " flow");
>  	if (attr->ingress)
>  		return rte_flow_error_set(error, ENOTSUP,
>  					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> @@ -176,6 +189,100 @@
>  }
>  
>  /**
> + * Validate the tunnel decap action
> + *
> + * @param[in] action_flags
> + *   holds the actions detected until now.
> + * @param[in] attr
> + *   Pointer to flow attributes
> + * @param[out] error
> + *   Pointer to error structure.
> + *
> + * @return
> + *   0 on success, a negative errno value otherwise and rte_ernno is set.
> + */
> +static int
> +flow_dv_validate_action_tunnel_decap(uint64_t action_flags,
> +				     const struct rte_flow_attr *attr,
> +				     struct rte_flow_error *error)
> +{
> +	if (action_flags & MLX5_FLOW_ACTION_DROP)
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
> +					  "can't drop and decap in same flow");
> +	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
> +			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
> +					  "can't have 2 decap actions in same"
> +					  " flow");
> +	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP |
> +			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
> +					  "can't encap and decap in same"
> +					  " flow");
> +	if (attr->egress)
> +		return rte_flow_error_set(error, ENOTSUP,
> +					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
> +					  "decap action not supported for "
> +					  "egress");
> +	return 0;
> +}
> +
> +/**
> + * Validate the tunnel decap L3 action
> + *
> + * @param[in] action_flags
> + *   holds the actions detected until now.
> + * @param[in] action
> + *   Pointer to the decap action.
> + * @param[in] attr
> + *   Pointer to flow attributes
> + * @param[out] error
> + *   Pointer to error structure.
> + *
> + * @return
> + *   0 on success, a negative errno value otherwise and rte_ernno is set.
> + */
> +static int
> +flow_dv_validate_action_tunnel_decap_l3(uint64_t action_flags,
> +					const struct rte_flow_action *action,
> +					const struct rte_flow_attr *attr,
> +					struct rte_flow_error *error)
> +{
> +	const struct rte_flow_action_tunnel_decap_l3 *tunnel_decap_l3 =
> +			action->conf;
> +
> +	if (!tunnel_decap_l3 || !(tunnel_decap_l3->buf))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, action,
> +					  "configuration cannot be null");
> +	if (action_flags & MLX5_FLOW_ACTION_DROP)
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
> +					  "can't drop and decap in same flow");
> +	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
> +			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
> +					  "can't have 2 decap actions in same"
> +					  " flow");
> +	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP |
> +			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
> +					  "can't encap and decap in same"
> +					  " flow");
> +	if (attr->egress)
> +		return rte_flow_error_set(error, ENOTSUP,
> +					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
> +					  "decap action not supported for "
> +					  "egress");
> +	return 0;
> +}
> +
> +/**
>   * Convert encap action to DV specification.
>   *
>   * @param[in] action
> @@ -245,6 +352,72 @@
>  }
>  
>  /**
> + * Convert decap action to DV specification.
> + *
> + * @param[in] action
> + *   Pointer to action structure.
> + * @param[in] dev
> + *   Pointer to rte_eth_dev structure.
> + * @param[out] error
> + *   Pointer to the error structure.
> + *
> + * @return
> + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> + */
> +static struct ibv_flow_action *
> +flow_dv_create_decap(const struct rte_flow_action *action __rte_unused,
> +		     struct rte_eth_dev *dev,
> +		     struct rte_flow_error *error)
> +{
> +	struct ibv_flow_action *decap_verb = NULL;
> +	struct priv *priv = dev->data->dev_private;
> +
> +	decap_verb = mlx5_glue->dv_create_flow_action_packet_reformat
> +		(priv->ctx, 0, NULL,
> +		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2,
> +		 MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
> +	if (!decap_verb)
> +		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
> +				   NULL, "cannot create decap action");
> +	return decap_verb;
> +}
> +
> +/**
> + * Convert decap L3 action to DV specification.
> + *
> + * @param[in] action
> + *   Pointer to action structure.
> + * @param[in] dev
> + *   Pointer to rte_eth_dev structure.
> + * @param[out] error
> + *   Pointer to the error structure.
> + *
> + * @return
> + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> + */
> +static struct ibv_flow_action *
> +flow_dv_create_decap_l3(const struct rte_flow_action *action,
> +			struct rte_eth_dev *dev,
> +			struct rte_flow_error *error)
> +{
> +	struct ibv_flow_action *decap_l3_verb = NULL;
> +	const struct rte_flow_action_tunnel_decap_l3 *decap_l3_data;
> +	struct priv *priv = dev->data->dev_private;
> +
> +	decap_l3_data =
> +		(const struct rte_flow_action_tunnel_decap_l3 *)action->conf;
> +	decap_l3_verb = mlx5_glue->dv_create_flow_action_packet_reformat
> +		(priv->ctx, decap_l3_data->size,
> +		 decap_l3_data->size ? decap_l3_data->buf : NULL,
> +		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2,
> +		 MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
> +	if (!decap_l3_verb)
> +		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
> +				   NULL, "cannot create decap L3 action");
> +	return decap_l3_verb;
> +}
> +
> +/**
>   * Verify the @p attributes will be correctly understood by the NIC and store
>   * them in the @p flow if everything is correct.
>   *
> @@ -505,6 +678,20 @@
>  				return ret;
>  			action_flags |= MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3;
>  			break;
> +		case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP:
> +			ret = flow_dv_validate_action_tunnel_decap
> +				(action_flags, attr, error);
> +			if (ret < 0)
> +				return ret;
> +			action_flags |= MLX5_FLOW_ACTION_TUNNEL_DECAP;
> +			break;
> +		case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP_L3:
> +			ret = flow_dv_validate_action_tunnel_decap_l3
> +				(action_flags, actions, attr, error);
> +			if (ret < 0)
> +				return ret;
> +			action_flags |= MLX5_FLOW_ACTION_TUNNEL_DECAP_L3;
> +			break;
>  		default:
>  			return rte_flow_error_set(error, ENOTSUP,
>  						  RTE_FLOW_ERROR_TYPE_ACTION,
> @@ -1300,6 +1487,30 @@
>  		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3;
>  		actions_n++;
>  		break;
> +	case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP:
> +		dev_flow->dv.actions[actions_n].type =
> +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> +		dev_flow->dv.actions[actions_n].action =
> +			flow_dv_create_decap(action, dev, error);
> +		if (!(dev_flow->dv.actions[actions_n].action))
> +			return -rte_errno;
> +		dev_flow->dv.decap_verb =
> +			dev_flow->dv.actions[actions_n].action;
> +		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_DECAP;
> +		actions_n++;
> +		break;
> +	case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP_L3:
> +		dev_flow->dv.actions[actions_n].type =
> +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> +		dev_flow->dv.actions[actions_n].action =
> +			flow_dv_create_decap_l3(action, dev, error);
> +		if (!(dev_flow->dv.actions[actions_n].action))
> +			return -rte_errno;
> +		dev_flow->dv.decap_verb =
> +			dev_flow->dv.actions[actions_n].action;
> +		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_DECAP_L3;
> +		actions_n++;
> +		break;
>  	default:
>  		break;
>  	}
> @@ -1655,13 +1866,16 @@
>  		LIST_REMOVE(dev_flow, next);
>  		if (dev_flow->dv.matcher)
>  			flow_dv_matcher_release(dev, dev_flow->dv.matcher);
> -

It seems to be mistakenly included in this patch when you rebase the previous
patch. Please fix it in [4/4] and [3/4].

>  		if (dev_flow->dv.encap_verb) {
>  			claim_zero(mlx5_glue->destroy_flow_action
>  						(dev_flow->dv.encap_verb));
>  			dev_flow->dv.encap_verb = NULL;
>  		}
> -

Same here.

> +		if (dev_flow->dv.decap_verb) {
> +			claim_zero(mlx5_glue->destroy_flow_action
> +						(dev_flow->dv.decap_verb));
> +			dev_flow->dv.decap_verb = NULL;
> +		}
>  		rte_free(dev_flow);
>  	}
>  }
> -- 
> 1.8.3.1
> 

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

* Re: [dpdk-dev] [PATCH v2 3/4] net/mlx5: add L2 and L3 encap to Direct Verbs flow
  2018-10-08 21:04   ` Yongseok Koh
@ 2018-10-09 15:55     ` Dekel Peled
  0 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-09 15:55 UTC (permalink / raw)
  To: Yongseok Koh; +Cc: Shahaf Shuler, dev, Ori Kam

Thanks, PSB.

> -----Original Message-----
> From: Yongseok Koh
> Sent: Tuesday, October 9, 2018 12:05 AM
> To: Dekel Peled <dekelp@mellanox.com>
> Cc: Shahaf Shuler <shahafs@mellanox.com>; dev@dpdk.org; Ori Kam
> <orika@mellanox.com>
> Subject: Re: [PATCH v2 3/4] net/mlx5: add L2 and L3 encap to Direct Verbs
> flow
> 
> On Sun, Oct 07, 2018 at 05:25:07PM +0300, Dekel Peled wrote:
> > This patch adds support for Direct Verbs encap operations, L2 and L3.
> >
> > Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> > ---
> 
> For flow_dv_create_encap(), flow_dv_create_encap_l3() and
> flow_dv_create_action(), please make the 'dev' come first in the args list like
> other functions.

Done.

> 
> And there are still two blank lines like I pointed out below.

Fixed.

> 
> With these changes, please put my acked-by tag when you submit the next
> version.
> 
> Thanks,
> Yongseok
> 
> >  drivers/net/mlx5/mlx5_flow_dv.c | 226
> > +++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 222 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/net/mlx5/mlx5_flow_dv.c
> > b/drivers/net/mlx5/mlx5_flow_dv.c index 80e7b24..221c76a 100644
> > --- a/drivers/net/mlx5/mlx5_flow_dv.c
> > +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> > @@ -84,6 +84,167 @@
> >  }
> >
> >  /**
> > + * Validate the tunnel encap action.
> > + *
> > + * @param[in] action_flags
> > + *   holds the actions detected until now.
> > + * @param[in] action
> > + *   Pointer to the encap action.
> > + * @param[in] attr
> > + *   Pointer to flow attributes
> > + * @param[out] error
> > + *   Pointer to error structure.
> > + *
> > + * @return
> > + *   0 on success, a negative errno value otherwise and rte_ernno is set.
> > + */
> > +static int
> > +flow_dv_validate_action_tunnel_encap(uint64_t action_flags,
> > +				     const struct rte_flow_action *action,
> > +				     const struct rte_flow_attr *attr,
> > +				     struct rte_flow_error *error) {
> > +	const struct rte_flow_action_tunnel_encap *tunnel_encap =
> > +action->conf;
> > +
> > +	if (!tunnel_encap || !(tunnel_encap->buf))
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> action,
> > +					  "configuration cannot be null");
> > +	if (action_flags & MLX5_FLOW_ACTION_DROP)
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
> > +					  "can't drop and encap in same
> flow");
> > +	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP |
> > +			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
> > +					  "can't have 2 encap actions in same"
> > +					  " flow");
> > +	if (attr->ingress)
> > +		return rte_flow_error_set(error, ENOTSUP,
> > +
> 	RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, NULL,
> > +					"encap action not supported for "
> > +					"ingress");
> > +	return 0;
> > +}
> > +
> > +/**
> > + * Validate the tunnel encap L3 action
> > + *
> > + * @param[in] action_flags
> > + *   holds the actions detected until now.
> > + * @param[in] action
> > + *   Pointer to the encap action.
> > + * @param[in] attr
> > + *   Pointer to flow attributes
> > + * @param[out] error
> > + *   Pointer to error structure.
> > + *
> > + * @return
> > + *   0 on success, a negative errno value otherwise and rte_ernno is set.
> > + */
> > +static int
> > +flow_dv_validate_action_tunnel_encap_l3(uint64_t action_flags,
> > +					const struct rte_flow_action *action,
> > +					const struct rte_flow_attr *attr,
> > +					struct rte_flow_error *error)
> > +{
> > +	const struct rte_flow_action_tunnel_encap_l3 *tunnel_encap_l3 =
> > +			action->conf;
> > +
> > +	if (!tunnel_encap_l3 || !(tunnel_encap_l3->buf))
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> action,
> > +					  "configuration cannot be null");
> > +	if (action_flags & MLX5_FLOW_ACTION_DROP)
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
> > +					  "can't drop and encap in same
> flow");
> > +	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP |
> > +			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
> > +					  "can't have 2 encap actions in same"
> > +					  " flow");
> > +	if (attr->ingress)
> > +		return rte_flow_error_set(error, ENOTSUP,
> > +
> RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> > +					  NULL,
> > +					  "encap action not supported for "
> > +					  "ingress");
> > +	return 0;
> > +}
> > +
> > +/**
> > + * Convert encap action to DV specification.
> > + *
> > + * @param[in] action
> > + *   Pointer to action structure.
> > + * @param[in] dev
> > + *   Pointer to rte_eth_dev structure.
> > + * @param[out] error
> > + *   Pointer to the error structure.
> > + *
> > + * @return
> > + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> > + */
> > +static struct ibv_flow_action *
> > +flow_dv_create_encap(const struct rte_flow_action *action,
> > +		     struct rte_eth_dev *dev,
> > +		     struct rte_flow_error *error)
> > +{
> > +	struct ibv_flow_action *encap_verb = NULL;
> > +	const struct rte_flow_action_tunnel_encap *encap_data;
> > +	struct priv *priv = dev->data->dev_private;
> > +
> > +	encap_data = (const struct rte_flow_action_tunnel_encap *)action-
> >conf;
> > +	encap_verb = mlx5_glue->dv_create_flow_action_packet_reformat
> > +		(priv->ctx, encap_data->size,
> > +		 encap_data->size ? encap_data->buf : NULL,
> > +
> MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
> > +		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
> > +	if (!encap_verb)
> > +		rte_flow_error_set(error, EINVAL,
> RTE_FLOW_ERROR_TYPE_ACTION,
> > +				   NULL, "cannot create encap action");
> > +	return encap_verb;
> > +}
> > +
> > +/**
> > + * Convert encap L3 action to DV specification.
> > + *
> > + * @param[in] action
> > + *   Pointer to action structure.
> > + * @param[in] dev
> > + *   Pointer to rte_eth_dev structure.
> > + * @param[out] error
> > + *   Pointer to the error structure.
> > + *
> > + * @return
> > + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> > + */
> > +static struct ibv_flow_action *
> > +flow_dv_create_encap_l3(const struct rte_flow_action *action,
> > +			struct rte_eth_dev *dev,
> > +			struct rte_flow_error *error)
> > +{
> > +	struct ibv_flow_action *encap_l3_verb = NULL;
> > +	const struct rte_flow_action_tunnel_encap_l3 *encap_l3_data;
> > +	struct priv *priv = dev->data->dev_private;
> > +
> > +	encap_l3_data =
> > +		(const struct rte_flow_action_tunnel_encap_l3 *)action-
> >conf;
> > +	encap_l3_verb = mlx5_glue-
> >dv_create_flow_action_packet_reformat
> > +		(priv->ctx, encap_l3_data->size,
> > +		 encap_l3_data->size ? encap_l3_data->buf : NULL,
> > +
> MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL,
> > +		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
> > +	if (!encap_l3_verb)
> > +		rte_flow_error_set(error, EINVAL,
> RTE_FLOW_ERROR_TYPE_ACTION,
> > +				   NULL, "cannot create encap L3 action");
> > +	return encap_l3_verb;
> > +}
> > +
> > +/**
> >   * Verify the @p attributes will be correctly understood by the NIC and
> store
> >   * them in the @p flow if everything is correct.
> >   *
> > @@ -330,6 +491,20 @@
> >  			action_flags |= MLX5_FLOW_ACTION_COUNT;
> >  			++actions_n;
> >  			break;
> > +		case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP:
> > +			ret = flow_dv_validate_action_tunnel_encap
> > +				(action_flags, actions, attr, error);
> > +			if (ret < 0)
> > +				return ret;
> > +			action_flags |=
> MLX5_FLOW_ACTION_TUNNEL_ENCAP;
> > +			break;
> > +		case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP_L3:
> > +			ret = flow_dv_validate_action_tunnel_encap_l3
> > +				(action_flags, actions, attr, error);
> > +			if (ret < 0)
> > +				return ret;
> > +			action_flags |=
> MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3;
> > +			break;
> >  		default:
> >  			return rte_flow_error_set(error, ENOTSUP,
> >
> RTE_FLOW_ERROR_TYPE_ACTION,
> > @@ -1042,10 +1217,19 @@
> >   *   Flow action to translate.
> >   * @param[in, out] dev_flow
> >   *   Pointer to the mlx5_flow.
> > + * @param[in] dev
> > + *   Pointer to rte_eth_dev structure.
> > + * @param[out] error
> > + *   Pointer to the error structure.
> > + *
> > + * @return
> > + *   0 on success, a negative errno value otherwise and rte_ernno is set.
> >   */
> > -static void
> > +static int
> >  flow_dv_create_action(const struct rte_flow_action *action,
> > -		      struct mlx5_flow *dev_flow)
> > +		      struct mlx5_flow *dev_flow,
> > +		      struct rte_eth_dev *dev,
> > +		      struct rte_flow_error *error)
> >  {
> >  	const struct rte_flow_action_queue *queue;
> >  	const struct rte_flow_action_rss *rss; @@ -1092,10 +1276,35 @@
> >  		/* Added to array only in apply since we need the QP */
> >  		flow->actions |= MLX5_FLOW_ACTION_RSS;
> >  		break;
> > +	case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP:
> > +		dev_flow->dv.actions[actions_n].type =
> > +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> > +		dev_flow->dv.actions[actions_n].action =
> > +			flow_dv_create_encap(action, dev, error);
> > +		if (!(dev_flow->dv.actions[actions_n].action))
> > +			return -rte_errno;
> > +		dev_flow->dv.encap_verb =
> > +			dev_flow->dv.actions[actions_n].action;
> > +		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_ENCAP;
> > +		actions_n++;
> > +		break;
> > +	case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP_L3:
> > +		dev_flow->dv.actions[actions_n].type =
> > +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> > +		dev_flow->dv.actions[actions_n].action =
> > +			flow_dv_create_encap_l3(action, dev, error);
> > +		if (!(dev_flow->dv.actions[actions_n].action))
> > +			return -rte_errno;
> > +		dev_flow->dv.encap_verb =
> > +			dev_flow->dv.actions[actions_n].action;
> > +		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3;
> > +		actions_n++;
> > +		break;
> >  	default:
> >  		break;
> >  	}
> >  	dev_flow->dv.actions_n = actions_n;
> > +	return 0;
> >  }
> >
> >  static uint32_t matcher_zero[MLX5_ST_SZ_DW(fte_match_param)] = { 0 };
> > @@ -1259,8 +1468,10 @@
> >  	matcher.egress = attr->egress;
> >  	if (flow_dv_matcher_register(dev, &matcher, dev_flow, error))
> >  		return -rte_errno;
> > -	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++)
> > -		flow_dv_create_action(actions, dev_flow);
> > +	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
> > +		if (flow_dv_create_action(actions, dev_flow, dev, error))
> > +			return -rte_errno;
> > +	}
> >  	return 0;
> >  }
> >
> > @@ -1444,6 +1655,13 @@
> >  		LIST_REMOVE(dev_flow, next);
> >  		if (dev_flow->dv.matcher)
> >  			flow_dv_matcher_release(dev, dev_flow-
> >dv.matcher);
> > +
> 
> No blank line.
> 
> > +		if (dev_flow->dv.encap_verb) {
> > +			claim_zero(mlx5_glue->destroy_flow_action
> > +						(dev_flow->dv.encap_verb));
> > +			dev_flow->dv.encap_verb = NULL;
> > +		}
> > +
> 
> No blank line.
> 
> >  		rte_free(dev_flow);
> >  	}
> >  }
> > --
> > 1.8.3.1
> >

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

* Re: [dpdk-dev] [PATCH v2 4/4] net/mlx5: add L2 and L3 decap to Direct Verbs flow
  2018-10-08 21:19   ` Yongseok Koh
@ 2018-10-09 16:56     ` Dekel Peled
  0 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-09 16:56 UTC (permalink / raw)
  To: Yongseok Koh; +Cc: Shahaf Shuler, dev, Ori Kam

Thanks, PSB.

> -----Original Message-----
> From: Yongseok Koh
> Sent: Tuesday, October 9, 2018 12:19 AM
> To: Dekel Peled <dekelp@mellanox.com>
> Cc: Shahaf Shuler <shahafs@mellanox.com>; dev@dpdk.org; Ori Kam
> <orika@mellanox.com>
> Subject: Re: [PATCH v2 4/4] net/mlx5: add L2 and L3 decap to Direct Verbs
> flow
> 
> On Sun, Oct 07, 2018 at 05:25:08PM +0300, Dekel Peled wrote:
> > This patch adds support for Direct Verbs decap operations, L2 and L3.
> >
> > Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> 
> Same comment for the order of 'dev' arg.

Done.

> 
> > Conflicts:
> > 	drivers/net/mlx5/mlx5_flow_dv.c
> 
> What is this? Conflicts?

My bad, fixed.

> 
> > ---
> >  drivers/net/mlx5/mlx5_flow_dv.c | 224
> > +++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 219 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/net/mlx5/mlx5_flow_dv.c
> > b/drivers/net/mlx5/mlx5_flow_dv.c index 221c76a..5b44f5b 100644
> > --- a/drivers/net/mlx5/mlx5_flow_dv.c
> > +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> > @@ -120,11 +120,18 @@
> >  					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
> >  					  "can't have 2 encap actions in same"
> >  					  " flow");
> > +	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
> > +			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3))
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
> > +					  "can't encap and decap in same"
> > +					  " flow");
> >  	if (attr->ingress)
> >  		return rte_flow_error_set(error, ENOTSUP,
> > -
> 	RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, NULL,
> > -					"encap action not supported for "
> > -					"ingress");
> > +
> RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> > +					  NULL,
> > +					  "encap action not supported for "
> > +					  "ingress");
> 
> It seems to be mistakenly included in this patch when you rebase the
> previous patch. Please fix it in [4/4] and [3/4].

Done.

> 
> >  	return 0;
> >  }
> >
> > @@ -166,6 +173,12 @@
> >  					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
> >  					  "can't have 2 encap actions in same"
> >  					  " flow");
> > +	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
> > +			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3))
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
> > +					  "can't encap and decap in same"
> > +					  " flow");
> >  	if (attr->ingress)
> >  		return rte_flow_error_set(error, ENOTSUP,
> >
> RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, @@ -176,6 +189,100 @@  }
> >
> >  /**
> > + * Validate the tunnel decap action
> > + *
> > + * @param[in] action_flags
> > + *   holds the actions detected until now.
> > + * @param[in] attr
> > + *   Pointer to flow attributes
> > + * @param[out] error
> > + *   Pointer to error structure.
> > + *
> > + * @return
> > + *   0 on success, a negative errno value otherwise and rte_ernno is set.
> > + */
> > +static int
> > +flow_dv_validate_action_tunnel_decap(uint64_t action_flags,
> > +				     const struct rte_flow_attr *attr,
> > +				     struct rte_flow_error *error) {
> > +	if (action_flags & MLX5_FLOW_ACTION_DROP)
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
> > +					  "can't drop and decap in same
> flow");
> > +	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
> > +			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3))
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
> > +					  "can't have 2 decap actions in same"
> > +					  " flow");
> > +	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP |
> > +			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
> > +					  "can't encap and decap in same"
> > +					  " flow");
> > +	if (attr->egress)
> > +		return rte_flow_error_set(error, ENOTSUP,
> > +
> RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
> > +					  "decap action not supported for "
> > +					  "egress");
> > +	return 0;
> > +}
> > +
> > +/**
> > + * Validate the tunnel decap L3 action
> > + *
> > + * @param[in] action_flags
> > + *   holds the actions detected until now.
> > + * @param[in] action
> > + *   Pointer to the decap action.
> > + * @param[in] attr
> > + *   Pointer to flow attributes
> > + * @param[out] error
> > + *   Pointer to error structure.
> > + *
> > + * @return
> > + *   0 on success, a negative errno value otherwise and rte_ernno is set.
> > + */
> > +static int
> > +flow_dv_validate_action_tunnel_decap_l3(uint64_t action_flags,
> > +					const struct rte_flow_action *action,
> > +					const struct rte_flow_attr *attr,
> > +					struct rte_flow_error *error)
> > +{
> > +	const struct rte_flow_action_tunnel_decap_l3 *tunnel_decap_l3 =
> > +			action->conf;
> > +
> > +	if (!tunnel_decap_l3 || !(tunnel_decap_l3->buf))
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> action,
> > +					  "configuration cannot be null");
> > +	if (action_flags & MLX5_FLOW_ACTION_DROP)
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
> > +					  "can't drop and decap in same
> flow");
> > +	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
> > +			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3))
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
> > +					  "can't have 2 decap actions in same"
> > +					  " flow");
> > +	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP |
> > +			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
> > +					  "can't encap and decap in same"
> > +					  " flow");
> > +	if (attr->egress)
> > +		return rte_flow_error_set(error, ENOTSUP,
> > +
> RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
> > +					  "decap action not supported for "
> > +					  "egress");
> > +	return 0;
> > +}
> > +
> > +/**
> >   * Convert encap action to DV specification.
> >   *
> >   * @param[in] action
> > @@ -245,6 +352,72 @@
> >  }
> >
> >  /**
> > + * Convert decap action to DV specification.
> > + *
> > + * @param[in] action
> > + *   Pointer to action structure.
> > + * @param[in] dev
> > + *   Pointer to rte_eth_dev structure.
> > + * @param[out] error
> > + *   Pointer to the error structure.
> > + *
> > + * @return
> > + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> > + */
> > +static struct ibv_flow_action *
> > +flow_dv_create_decap(const struct rte_flow_action *action
> __rte_unused,
> > +		     struct rte_eth_dev *dev,
> > +		     struct rte_flow_error *error)
> > +{
> > +	struct ibv_flow_action *decap_verb = NULL;
> > +	struct priv *priv = dev->data->dev_private;
> > +
> > +	decap_verb = mlx5_glue->dv_create_flow_action_packet_reformat
> > +		(priv->ctx, 0, NULL,
> > +
> MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2,
> > +		 MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
> > +	if (!decap_verb)
> > +		rte_flow_error_set(error, EINVAL,
> RTE_FLOW_ERROR_TYPE_ACTION,
> > +				   NULL, "cannot create decap action");
> > +	return decap_verb;
> > +}
> > +
> > +/**
> > + * Convert decap L3 action to DV specification.
> > + *
> > + * @param[in] action
> > + *   Pointer to action structure.
> > + * @param[in] dev
> > + *   Pointer to rte_eth_dev structure.
> > + * @param[out] error
> > + *   Pointer to the error structure.
> > + *
> > + * @return
> > + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> > + */
> > +static struct ibv_flow_action *
> > +flow_dv_create_decap_l3(const struct rte_flow_action *action,
> > +			struct rte_eth_dev *dev,
> > +			struct rte_flow_error *error)
> > +{
> > +	struct ibv_flow_action *decap_l3_verb = NULL;
> > +	const struct rte_flow_action_tunnel_decap_l3 *decap_l3_data;
> > +	struct priv *priv = dev->data->dev_private;
> > +
> > +	decap_l3_data =
> > +		(const struct rte_flow_action_tunnel_decap_l3 *)action-
> >conf;
> > +	decap_l3_verb = mlx5_glue-
> >dv_create_flow_action_packet_reformat
> > +		(priv->ctx, decap_l3_data->size,
> > +		 decap_l3_data->size ? decap_l3_data->buf : NULL,
> > +
> MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2,
> > +		 MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
> > +	if (!decap_l3_verb)
> > +		rte_flow_error_set(error, EINVAL,
> RTE_FLOW_ERROR_TYPE_ACTION,
> > +				   NULL, "cannot create decap L3 action");
> > +	return decap_l3_verb;
> > +}
> > +
> > +/**
> >   * Verify the @p attributes will be correctly understood by the NIC and
> store
> >   * them in the @p flow if everything is correct.
> >   *
> > @@ -505,6 +678,20 @@
> >  				return ret;
> >  			action_flags |=
> MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3;
> >  			break;
> > +		case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP:
> > +			ret = flow_dv_validate_action_tunnel_decap
> > +				(action_flags, attr, error);
> > +			if (ret < 0)
> > +				return ret;
> > +			action_flags |=
> MLX5_FLOW_ACTION_TUNNEL_DECAP;
> > +			break;
> > +		case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP_L3:
> > +			ret = flow_dv_validate_action_tunnel_decap_l3
> > +				(action_flags, actions, attr, error);
> > +			if (ret < 0)
> > +				return ret;
> > +			action_flags |=
> MLX5_FLOW_ACTION_TUNNEL_DECAP_L3;
> > +			break;
> >  		default:
> >  			return rte_flow_error_set(error, ENOTSUP,
> >
> RTE_FLOW_ERROR_TYPE_ACTION,
> > @@ -1300,6 +1487,30 @@
> >  		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3;
> >  		actions_n++;
> >  		break;
> > +	case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP:
> > +		dev_flow->dv.actions[actions_n].type =
> > +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> > +		dev_flow->dv.actions[actions_n].action =
> > +			flow_dv_create_decap(action, dev, error);
> > +		if (!(dev_flow->dv.actions[actions_n].action))
> > +			return -rte_errno;
> > +		dev_flow->dv.decap_verb =
> > +			dev_flow->dv.actions[actions_n].action;
> > +		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_DECAP;
> > +		actions_n++;
> > +		break;
> > +	case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP_L3:
> > +		dev_flow->dv.actions[actions_n].type =
> > +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> > +		dev_flow->dv.actions[actions_n].action =
> > +			flow_dv_create_decap_l3(action, dev, error);
> > +		if (!(dev_flow->dv.actions[actions_n].action))
> > +			return -rte_errno;
> > +		dev_flow->dv.decap_verb =
> > +			dev_flow->dv.actions[actions_n].action;
> > +		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_DECAP_L3;
> > +		actions_n++;
> > +		break;
> >  	default:
> >  		break;
> >  	}
> > @@ -1655,13 +1866,16 @@
> >  		LIST_REMOVE(dev_flow, next);
> >  		if (dev_flow->dv.matcher)
> >  			flow_dv_matcher_release(dev, dev_flow-
> >dv.matcher);
> > -
> 
> It seems to be mistakenly included in this patch when you rebase the
> previous patch. Please fix it in [4/4] and [3/4].

Done.

> 
> >  		if (dev_flow->dv.encap_verb) {
> >  			claim_zero(mlx5_glue->destroy_flow_action
> >  						(dev_flow->dv.encap_verb));
> >  			dev_flow->dv.encap_verb = NULL;
> >  		}
> > -
> 
> Same here.

Done.

> 
> > +		if (dev_flow->dv.decap_verb) {
> > +			claim_zero(mlx5_glue->destroy_flow_action
> > +						(dev_flow->dv.decap_verb));
> > +			dev_flow->dv.decap_verb = NULL;
> > +		}
> >  		rte_free(dev_flow);
> >  	}
> >  }
> > --
> > 1.8.3.1
> >

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

* Re: [dpdk-dev] [PATCH v2 1/4] net/mlx5: add flow action functions to glue
  2018-10-08 19:43   ` Yongseok Koh
@ 2018-10-09 18:49     ` Dekel Peled
  0 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-09 18:49 UTC (permalink / raw)
  To: Yongseok Koh; +Cc: Shahaf Shuler, dev, Ori Kam

Thanks, PSB.

> -----Original Message-----
> From: Yongseok Koh
> Sent: Monday, October 8, 2018 10:43 PM
> To: Dekel Peled <dekelp@mellanox.com>
> Cc: Shahaf Shuler <shahafs@mellanox.com>; dev@dpdk.org; Ori Kam
> <orika@mellanox.com>
> Subject: Re: [PATCH v2 1/4] net/mlx5: add flow action functions to glue
> 
> On Sun, Oct 07, 2018 at 05:25:05PM +0300, Dekel Peled wrote:
> > This patch adds glue functions for operations:
> > - Create packet reformat (encap/decap) flow action.
> > - Destroy flow action.
> >
> > Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> > ---
> 
> I'm not still able to compile this patch on my host, which is RH7.4 with MOFED
> MLNX_OFED_LINUX-4.4-2.0.4.0.
> 
> >  drivers/net/mlx5/mlx5_glue.c | 33
> +++++++++++++++++++++++++++++++++
> > drivers/net/mlx5/mlx5_glue.h |  9 +++++++++
> >  2 files changed, 42 insertions(+)
> >
> > diff --git a/drivers/net/mlx5/mlx5_glue.c
> > b/drivers/net/mlx5/mlx5_glue.c index 48590df..caa4c34 100644
> > --- a/drivers/net/mlx5/mlx5_glue.c
> > +++ b/drivers/net/mlx5/mlx5_glue.c
> > @@ -174,6 +174,12 @@
> >  	return ibv_destroy_flow(flow_id);
> >  }
> >
> > +static int
> > +mlx5_glue_destroy_flow_action(struct ibv_flow_action *action) {
> > +	return ibv_destroy_flow_action(action); }
> 
> Shouldn't this be under HAVE_IBV_FLOW_DV_SUPPORT? My host doesn't
> have it either
> - ibv_destroy_flow_action() and ibv_flow_action.
> 
> > +
> >  static struct ibv_qp *
> >  mlx5_glue_create_qp(struct ibv_pd *pd, struct ibv_qp_init_attr
> > *qp_init_attr)  { @@ -388,6 +394,30 @@  #endif  }
> >
> > +static struct ibv_flow_action *
> > +mlx5_glue_dv_create_flow_action_packet_reformat
> > +		(struct ibv_context *ctx,
> > +		 size_t data_sz,
> > +		 void *data,
> > +		 enum mlx5dv_flow_action_packet_reformat_type
> reformat_type,
> > +		 enum mlx5dv_flow_table_type ft_type) { #ifdef
> > +HAVE_IBV_FLOW_DV_SUPPORT
> 
> I don't think your change can be protected by this. According to the git logs of
> rdma-core, HAVE_IBV_FLOW_DV_SUPPORT is to mark the following patch of
> Yishai Hadas,
> 
> 	mlx5: Introduce mlx5dv_create_flow
> 
> While, the flow action has been added by another patchset of Mark Bloch
> later,
> 
> 	mlx5: Add packet reformat flow action
> 
> So, it seems to need another macro, doesn't it?
> E.g. HAVE_IBV_FLOW_ACTION_DV_SUPPORT

Will add it according to your suggestion.

> 
> > +	return mlx5dv_create_flow_action_packet_reformat(ctx,
> > +							 data_sz,
> > +							 data,
> > +							 reformat_type,
> > +							 ft_type);
> > +#else
> > +	(void)ctx;
> > +	(void)data_sz;
> > +	(void)data;
> > +	(void)reformat_type;
> > +	(void)ft_type;
> > +	return NULL;
> > +#endif
> > +}
> > +
> >  alignas(RTE_CACHE_LINE_SIZE)
> >  const struct mlx5_glue *mlx5_glue = &(const struct mlx5_glue){
> >  	.version = MLX5_GLUE_VERSION,
> > @@ -414,6 +444,7 @@
> >  	.modify_wq = mlx5_glue_modify_wq,
> >  	.create_flow = mlx5_glue_create_flow,
> >  	.destroy_flow = mlx5_glue_destroy_flow,
> > +	.destroy_flow_action = mlx5_glue_destroy_flow_action,
> >  	.create_qp = mlx5_glue_create_qp,
> >  	.create_qp_ex = mlx5_glue_create_qp_ex,
> >  	.destroy_qp = mlx5_glue_destroy_qp,
> > @@ -437,4 +468,6 @@
> >  	.dv_create_flow_matcher = mlx5_glue_dv_create_flow_matcher,
> >  	.dv_destroy_flow_matcher = mlx5_glue_dv_destroy_flow_matcher,
> >  	.dv_create_flow = mlx5_glue_dv_create_flow,
> > +	.dv_create_flow_action_packet_reformat =
> > +
> 	mlx5_glue_dv_create_flow_action_packet_reformat,
> >  };
> > diff --git a/drivers/net/mlx5/mlx5_glue.h
> > b/drivers/net/mlx5/mlx5_glue.h index f6e4e38..8ef4fcc 100644
> > --- a/drivers/net/mlx5/mlx5_glue.h
> > +++ b/drivers/net/mlx5/mlx5_glue.h
> > @@ -44,6 +44,8 @@
> >  struct mlx5dv_flow_matcher_attr;
> >  struct mlx5dv_flow_action_attr;
> >  struct mlx5dv_flow_match_parameters;
> > +enum mlx5dv_flow_action_packet_reformat_type;
> > +enum mlx5dv_flow_table_type;
> >  #endif
> >
> >  /* LIB_GLUE_VERSION must be updated every time this structure is
> > modified. */ @@ -85,6 +87,7 @@ struct mlx5_glue {
> >  	struct ibv_flow *(*create_flow)(struct ibv_qp *qp,
> >  					struct ibv_flow_attr *flow);
> >  	int (*destroy_flow)(struct ibv_flow *flow_id);
> > +	int (*destroy_flow_action)(struct ibv_flow_action *action);
> >  	struct ibv_qp *(*create_qp)(struct ibv_pd *pd,
> >  				    struct ibv_qp_init_attr *qp_init_attr);
> >  	struct ibv_qp *(*create_qp_ex)
> > @@ -137,6 +140,12 @@ struct mlx5_glue {
> >  			  struct mlx5dv_flow_match_parameters
> *match_value,
> >  			  size_t num_actions,
> >  			  struct mlx5dv_flow_action_attr *actions_attr);
> > +	struct ibv_flow_action *(*dv_create_flow_action_packet_reformat)
> > +		(struct ibv_context *ctx,
> > +		 size_t data_sz,
> > +		 void *data,
> > +		 enum mlx5dv_flow_action_packet_reformat_type
> reformat_type,
> > +		 enum mlx5dv_flow_table_type ft_type);
> >  };
> >
> >  const struct mlx5_glue *mlx5_glue;
> > --
> > 1.8.3.1
> >

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

* [dpdk-dev] [PATCH v3 0/4] add support of Direct Verbs encap and decap actions
  2018-10-07 14:25 ` [dpdk-dev] [PATCH v2 0/4] add support of Direct Verbs encap and decap actions Dekel Peled
@ 2018-10-09 19:25   ` Dekel Peled
  2018-10-10  8:35     ` [dpdk-dev] [PATCH v4 " Dekel Peled
                       ` (4 more replies)
  2018-10-09 19:25   ` [dpdk-dev] [PATCH v3 1/4] net/mlx5: add flow action functions to glue Dekel Peled
                     ` (3 subsequent siblings)
  4 siblings, 5 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-09 19:25 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This series adds support of encap and decap actions in DV format.
It is using the generic encapsulation framework from [1].
Note that encap action is relevant for egress only.
Hence this series should be merged on top of [2].

[1] "ethdev: add generic L2/L3 tunnel encapsulation actions"
    http://mails.dpdk.org/archives/dev/2018-October/114654.html
[2] "net/mlx5: allow flow rule with attribute egress"
    http://mails.dpdk.org/archives/dev/2018-October/114658.html

---
V3:
* Apply additional code review comments.
---
V2:
* Rebase on tip.
* Apply code review comments.
---

Dekel Peled (4):
  net/mlx5: add flow action functions to glue
  net/mlx5: add Direct Verbs encap and decap defs
  net/mlx5: add L2 and L3 encap to Direct Verbs flow
  net/mlx5: add L2 and L3 decap to Direct Verbs flow

 drivers/net/mlx5/Makefile       |   5 +
 drivers/net/mlx5/meson.build    |   2 +
 drivers/net/mlx5/mlx5_flow.c    |   8 +
 drivers/net/mlx5/mlx5_flow.h    |   6 +
 drivers/net/mlx5/mlx5_flow_dv.c | 442 +++++++++++++++++++++++++++++++++++++++-
 drivers/net/mlx5/mlx5_glue.c    |  38 ++++
 drivers/net/mlx5/mlx5_glue.h    |  13 ++
 7 files changed, 509 insertions(+), 5 deletions(-)

-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v3 1/4] net/mlx5: add flow action functions to glue
  2018-10-07 14:25 ` [dpdk-dev] [PATCH v2 0/4] add support of Direct Verbs encap and decap actions Dekel Peled
  2018-10-09 19:25   ` [dpdk-dev] [PATCH v3 " Dekel Peled
@ 2018-10-09 19:25   ` Dekel Peled
  2018-10-10  0:36     ` Yongseok Koh
  2018-10-10  0:38     ` Yongseok Koh
  2018-10-09 19:25   ` [dpdk-dev] [PATCH v3 2/4] net/mlx5: add Direct Verbs encap and decap defs Dekel Peled
                     ` (2 subsequent siblings)
  4 siblings, 2 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-09 19:25 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch adds glue functions for operations:
- Create packet reformat (encap/decap) flow action.
- Destroy flow action.

The new operations depend on HAVE_IBV_FLOW_ACTION_DV_SUPPORT.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/Makefile    |  5 +++++
 drivers/net/mlx5/meson.build |  2 ++
 drivers/net/mlx5/mlx5_glue.c | 38 ++++++++++++++++++++++++++++++++++++++
 drivers/net/mlx5/mlx5_glue.h | 13 +++++++++++++
 4 files changed, 58 insertions(+)

diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile
index 92bae9d..474ad42 100644
--- a/drivers/net/mlx5/Makefile
+++ b/drivers/net/mlx5/Makefile
@@ -142,6 +142,11 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh
 		enum MLX5DV_FLOW_ACTION_TAG \
 		$(AUTOCONF_OUTPUT)
 	$Q sh -- '$<' '$@' \
+		HAVE_IBV_FLOW_ACTION_DV_SUPPORT \
+		infiniband/mlx5dv.h \
+		func mlx5dv_create_flow_action_packet_reformat \
+		$(AUTOCONF_OUTPUT)
+	$Q sh -- '$<' '$@' \
 		HAVE_ETHTOOL_LINK_MODE_25G \
 		/usr/include/linux/ethtool.h \
 		enum ETHTOOL_LINK_MODE_25000baseCR_Full_BIT \
diff --git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build
index 6966248..d555c3c 100644
--- a/drivers/net/mlx5/meson.build
+++ b/drivers/net/mlx5/meson.build
@@ -96,6 +96,8 @@ if build
 		'MLX5DV_CONTEXT_FLAGS_CQE_128B_COMP' ],
 		[ 'HAVE_IBV_FLOW_DV_SUPPORT', 'infiniband/mlx5dv.h',
 		'MLX5DV_FLOW_ACTION_TAG' ],
+		[ 'HAVE_IBV_FLOW_ACTION_DV_SUPPORT', 'infiniband/mlx5dv.h',
+		'mlx5dv_create_flow_action_packet_reformat' ],
 		[ 'HAVE_IBV_DEVICE_MPLS_SUPPORT', 'infiniband/verbs.h',
 		'IBV_FLOW_SPEC_MPLS' ],
 		[ 'HAVE_IBV_WQ_FLAG_RX_END_PADDING', 'infiniband/verbs.h',
diff --git a/drivers/net/mlx5/mlx5_glue.c b/drivers/net/mlx5/mlx5_glue.c
index 48590df..63fbab1 100644
--- a/drivers/net/mlx5/mlx5_glue.c
+++ b/drivers/net/mlx5/mlx5_glue.c
@@ -174,6 +174,17 @@
 	return ibv_destroy_flow(flow_id);
 }
 
+static int
+mlx5_glue_destroy_flow_action(struct ibv_flow_action *action)
+{
+#ifdef HAVE_IBV_FLOW_ACTION_DV_SUPPORT
+	return ibv_destroy_flow_action(action);
+#else
+	(void)action;
+	return NULL;
+#endif
+}
+
 static struct ibv_qp *
 mlx5_glue_create_qp(struct ibv_pd *pd, struct ibv_qp_init_attr *qp_init_attr)
 {
@@ -388,6 +399,30 @@
 #endif
 }
 
+static struct ibv_flow_action *
+mlx5_glue_dv_create_flow_action_packet_reformat
+		(struct ibv_context *ctx,
+		 size_t data_sz,
+		 void *data,
+		 enum mlx5dv_flow_action_packet_reformat_type reformat_type,
+		 enum mlx5dv_flow_table_type ft_type)
+{
+#ifdef HAVE_IBV_FLOW_ACTION_DV_SUPPORT
+	return mlx5dv_create_flow_action_packet_reformat(ctx,
+							 data_sz,
+							 data,
+							 reformat_type,
+							 ft_type);
+#else
+	(void)ctx;
+	(void)data_sz;
+	(void)data;
+	(void)reformat_type;
+	(void)ft_type;
+	return NULL;
+#endif
+}
+
 alignas(RTE_CACHE_LINE_SIZE)
 const struct mlx5_glue *mlx5_glue = &(const struct mlx5_glue){
 	.version = MLX5_GLUE_VERSION,
@@ -414,6 +449,7 @@
 	.modify_wq = mlx5_glue_modify_wq,
 	.create_flow = mlx5_glue_create_flow,
 	.destroy_flow = mlx5_glue_destroy_flow,
+	.destroy_flow_action = mlx5_glue_destroy_flow_action,
 	.create_qp = mlx5_glue_create_qp,
 	.create_qp_ex = mlx5_glue_create_qp_ex,
 	.destroy_qp = mlx5_glue_destroy_qp,
@@ -437,4 +473,6 @@
 	.dv_create_flow_matcher = mlx5_glue_dv_create_flow_matcher,
 	.dv_destroy_flow_matcher = mlx5_glue_dv_destroy_flow_matcher,
 	.dv_create_flow = mlx5_glue_dv_create_flow,
+	.dv_create_flow_action_packet_reformat =
+			mlx5_glue_dv_create_flow_action_packet_reformat,
 };
diff --git a/drivers/net/mlx5/mlx5_glue.h b/drivers/net/mlx5/mlx5_glue.h
index f6e4e38..071a650 100644
--- a/drivers/net/mlx5/mlx5_glue.h
+++ b/drivers/net/mlx5/mlx5_glue.h
@@ -46,6 +46,12 @@
 struct mlx5dv_flow_match_parameters;
 #endif
 
+#ifndef HAVE_IBV_FLOW_ACTION_DV_SUPPORT
+struct ibv_flow_action;
+enum mlx5dv_flow_action_packet_reformat_type { type = 0, };
+enum mlx5dv_flow_table_type { type = 0, };
+#endif
+
 /* LIB_GLUE_VERSION must be updated every time this structure is modified. */
 struct mlx5_glue {
 	const char *version;
@@ -85,6 +91,7 @@ struct mlx5_glue {
 	struct ibv_flow *(*create_flow)(struct ibv_qp *qp,
 					struct ibv_flow_attr *flow);
 	int (*destroy_flow)(struct ibv_flow *flow_id);
+	int (*destroy_flow_action)(struct ibv_flow_action *action);
 	struct ibv_qp *(*create_qp)(struct ibv_pd *pd,
 				    struct ibv_qp_init_attr *qp_init_attr);
 	struct ibv_qp *(*create_qp_ex)
@@ -137,6 +144,12 @@ struct mlx5_glue {
 			  struct mlx5dv_flow_match_parameters *match_value,
 			  size_t num_actions,
 			  struct mlx5dv_flow_action_attr *actions_attr);
+	struct ibv_flow_action *(*dv_create_flow_action_packet_reformat)
+		(struct ibv_context *ctx,
+		 size_t data_sz,
+		 void *data,
+		 enum mlx5dv_flow_action_packet_reformat_type reformat_type,
+		 enum mlx5dv_flow_table_type ft_type);
 };
 
 const struct mlx5_glue *mlx5_glue;
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v3 2/4] net/mlx5: add Direct Verbs encap and decap defs
  2018-10-07 14:25 ` [dpdk-dev] [PATCH v2 0/4] add support of Direct Verbs encap and decap actions Dekel Peled
  2018-10-09 19:25   ` [dpdk-dev] [PATCH v3 " Dekel Peled
  2018-10-09 19:25   ` [dpdk-dev] [PATCH v3 1/4] net/mlx5: add flow action functions to glue Dekel Peled
@ 2018-10-09 19:25   ` Dekel Peled
  2018-10-10  0:40     ` Yongseok Koh
  2018-10-09 19:25   ` [dpdk-dev] [PATCH v3 3/4] net/mlx5: add L2 and L3 encap to Direct Verbs flow Dekel Peled
  2018-10-09 19:25   ` [dpdk-dev] [PATCH v3 4/4] net/mlx5: add L2 and L3 decap " Dekel Peled
  4 siblings, 1 reply; 94+ messages in thread
From: Dekel Peled @ 2018-10-09 19:25 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch adds the required definitions for DV encap/decap actions.
It also adds usage of the new actions definition in validation
function of existing drop operation.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow.c | 8 ++++++++
 drivers/net/mlx5/mlx5_flow.h | 6 ++++++
 2 files changed, 14 insertions(+)

diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 1087f67..b452e11 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -766,6 +766,14 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't have 2 fate actions in"
 					  " same flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
+			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3 |
+			    MLX5_FLOW_ACTION_TUNNEL_ENCAP |
+			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't encap or decap and drop in"
+					  " same flow");
 	if (attr->egress)
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 690c597..01c73a2 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -82,6 +82,10 @@
 #define MLX5_FLOW_ACTION_OF_SET_VLAN_VID (1u << 9)
 #define MLX5_FLOW_ACTION_OF_SET_VLAN_PCP (1u << 10)
 #define MLX5_FLOW_ACTION_JUMP (1u << 11)
+#define MLX5_FLOW_ACTION_TUNNEL_ENCAP (1u << 12)
+#define MLX5_FLOW_ACTION_TUNNEL_DECAP (1u << 13)
+#define MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3 (1u << 14)
+#define MLX5_FLOW_ACTION_TUNNEL_DECAP_L3 (1u << 15)
 
 #define MLX5_FLOW_FATE_ACTIONS \
 	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS)
@@ -172,6 +176,8 @@ struct mlx5_flow_dv {
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
 	struct mlx5dv_flow_action_attr actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS];
 	/**< Action list. */
+	struct ibv_flow_action *encap_verb; /**< Verbs object of encap. */
+	struct ibv_flow_action *decap_verb; /**< Verbs object of decap. */
 #endif
 	int actions_n; /**< number of actions. */
 };
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v3 3/4] net/mlx5: add L2 and L3 encap to Direct Verbs flow
  2018-10-07 14:25 ` [dpdk-dev] [PATCH v2 0/4] add support of Direct Verbs encap and decap actions Dekel Peled
                     ` (2 preceding siblings ...)
  2018-10-09 19:25   ` [dpdk-dev] [PATCH v3 2/4] net/mlx5: add Direct Verbs encap and decap defs Dekel Peled
@ 2018-10-09 19:25   ` Dekel Peled
  2018-10-10  0:43     ` Yongseok Koh
  2018-10-09 19:25   ` [dpdk-dev] [PATCH v3 4/4] net/mlx5: add L2 and L3 decap " Dekel Peled
  4 siblings, 1 reply; 94+ messages in thread
From: Dekel Peled @ 2018-10-09 19:25 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch adds support for Direct Verbs encap operations, L2 and L3.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow_dv.c | 227 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 222 insertions(+), 5 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 80e7b24..73a22ba 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -84,6 +84,168 @@
 }
 
 /**
+ * Validate the tunnel encap action.
+ *
+ * @param[in] action_flags
+ *   holds the actions detected until now.
+ * @param[in] action
+ *   Pointer to the encap action.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_ernno is set.
+ */
+static int
+flow_dv_validate_action_tunnel_encap(uint64_t action_flags,
+				     const struct rte_flow_action *action,
+				     const struct rte_flow_attr *attr,
+				     struct rte_flow_error *error)
+{
+	const struct rte_flow_action_tunnel_encap *tunnel_encap = action->conf;
+
+	if (!tunnel_encap || !(tunnel_encap->buf))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, action,
+					  "configuration cannot be null");
+	if (action_flags & MLX5_FLOW_ACTION_DROP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't drop and encap in same flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP |
+			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't have 2 encap actions in same"
+					  " flow");
+	if (attr->ingress)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
+					  NULL,
+					  "encap action not supported for "
+					  "ingress");
+	return 0;
+}
+
+/**
+ * Validate the tunnel encap L3 action
+ *
+ * @param[in] action_flags
+ *   holds the actions detected until now.
+ * @param[in] action
+ *   Pointer to the encap action.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_ernno is set.
+ */
+static int
+flow_dv_validate_action_tunnel_encap_l3(uint64_t action_flags,
+					const struct rte_flow_action *action,
+					const struct rte_flow_attr *attr,
+					struct rte_flow_error *error)
+{
+	const struct rte_flow_action_tunnel_encap_l3 *tunnel_encap_l3 =
+			action->conf;
+
+	if (!tunnel_encap_l3 || !(tunnel_encap_l3->buf))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, action,
+					  "configuration cannot be null");
+	if (action_flags & MLX5_FLOW_ACTION_DROP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't drop and encap in same flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP |
+			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't have 2 encap actions in same"
+					  " flow");
+	if (attr->ingress)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
+					  NULL,
+					  "encap action not supported for "
+					  "ingress");
+	return 0;
+}
+
+/**
+ * Convert encap action to DV specification.
+ *
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[in] action
+ *   Pointer to action structure.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+flow_dv_create_encap(struct rte_eth_dev *dev,
+		     const struct rte_flow_action *action,
+		     struct rte_flow_error *error)
+{
+	struct ibv_flow_action *encap_verb = NULL;
+	const struct rte_flow_action_tunnel_encap *encap_data;
+	struct priv *priv = dev->data->dev_private;
+
+	encap_data = (const struct rte_flow_action_tunnel_encap *)action->conf;
+	encap_verb = mlx5_glue->dv_create_flow_action_packet_reformat
+		(priv->ctx, encap_data->size,
+		 encap_data->size ? encap_data->buf : NULL,
+		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
+		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
+	if (!encap_verb)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create encap action");
+	return encap_verb;
+}
+
+/**
+ * Convert encap L3 action to DV specification.
+ *
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[in] action
+ *   Pointer to action structure.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+flow_dv_create_encap_l3(struct rte_eth_dev *dev,
+			const struct rte_flow_action *action,
+			struct rte_flow_error *error)
+{
+	struct ibv_flow_action *encap_l3_verb = NULL;
+	const struct rte_flow_action_tunnel_encap_l3 *encap_l3_data;
+	struct priv *priv = dev->data->dev_private;
+
+	encap_l3_data =
+		(const struct rte_flow_action_tunnel_encap_l3 *)action->conf;
+	encap_l3_verb = mlx5_glue->dv_create_flow_action_packet_reformat
+		(priv->ctx, encap_l3_data->size,
+		 encap_l3_data->size ? encap_l3_data->buf : NULL,
+		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL,
+		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
+	if (!encap_l3_verb)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create encap L3 action");
+	return encap_l3_verb;
+}
+
+/**
  * Verify the @p attributes will be correctly understood by the NIC and store
  * them in the @p flow if everything is correct.
  *
@@ -330,6 +492,20 @@
 			action_flags |= MLX5_FLOW_ACTION_COUNT;
 			++actions_n;
 			break;
+		case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP:
+			ret = flow_dv_validate_action_tunnel_encap
+				(action_flags, actions, attr, error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_TUNNEL_ENCAP;
+			break;
+		case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP_L3:
+			ret = flow_dv_validate_action_tunnel_encap_l3
+				(action_flags, actions, attr, error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3;
+			break;
 		default:
 			return rte_flow_error_set(error, ENOTSUP,
 						  RTE_FLOW_ERROR_TYPE_ACTION,
@@ -1038,14 +1214,23 @@
 /**
  * Store the requested actions in an array.
  *
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
  * @param[in] action
  *   Flow action to translate.
  * @param[in, out] dev_flow
  *   Pointer to the mlx5_flow.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_ernno is set.
  */
-static void
-flow_dv_create_action(const struct rte_flow_action *action,
-		      struct mlx5_flow *dev_flow)
+static int
+flow_dv_create_action(struct rte_eth_dev *dev,
+		      const struct rte_flow_action *action,
+		      struct mlx5_flow *dev_flow,
+		      struct rte_flow_error *error)
 {
 	const struct rte_flow_action_queue *queue;
 	const struct rte_flow_action_rss *rss;
@@ -1092,10 +1277,35 @@
 		/* Added to array only in apply since we need the QP */
 		flow->actions |= MLX5_FLOW_ACTION_RSS;
 		break;
+	case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP:
+		dev_flow->dv.actions[actions_n].type =
+			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+		dev_flow->dv.actions[actions_n].action =
+			flow_dv_create_encap(dev, action, error);
+		if (!(dev_flow->dv.actions[actions_n].action))
+			return -rte_errno;
+		dev_flow->dv.encap_verb =
+			dev_flow->dv.actions[actions_n].action;
+		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_ENCAP;
+		actions_n++;
+		break;
+	case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP_L3:
+		dev_flow->dv.actions[actions_n].type =
+			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+		dev_flow->dv.actions[actions_n].action =
+			flow_dv_create_encap_l3(dev, action, error);
+		if (!(dev_flow->dv.actions[actions_n].action))
+			return -rte_errno;
+		dev_flow->dv.encap_verb =
+			dev_flow->dv.actions[actions_n].action;
+		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3;
+		actions_n++;
+		break;
 	default:
 		break;
 	}
 	dev_flow->dv.actions_n = actions_n;
+	return 0;
 }
 
 static uint32_t matcher_zero[MLX5_ST_SZ_DW(fte_match_param)] = { 0 };
@@ -1259,8 +1469,10 @@
 	matcher.egress = attr->egress;
 	if (flow_dv_matcher_register(dev, &matcher, dev_flow, error))
 		return -rte_errno;
-	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++)
-		flow_dv_create_action(actions, dev_flow);
+	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
+		if (flow_dv_create_action(dev, actions, dev_flow, error))
+			return -rte_errno;
+	}
 	return 0;
 }
 
@@ -1444,6 +1656,11 @@
 		LIST_REMOVE(dev_flow, next);
 		if (dev_flow->dv.matcher)
 			flow_dv_matcher_release(dev, dev_flow->dv.matcher);
+		if (dev_flow->dv.encap_verb) {
+			claim_zero(mlx5_glue->destroy_flow_action
+						(dev_flow->dv.encap_verb));
+			dev_flow->dv.encap_verb = NULL;
+		}
 		rte_free(dev_flow);
 	}
 }
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v3 4/4] net/mlx5: add L2 and L3 decap to Direct Verbs flow
  2018-10-07 14:25 ` [dpdk-dev] [PATCH v2 0/4] add support of Direct Verbs encap and decap actions Dekel Peled
                     ` (3 preceding siblings ...)
  2018-10-09 19:25   ` [dpdk-dev] [PATCH v3 3/4] net/mlx5: add L2 and L3 encap to Direct Verbs flow Dekel Peled
@ 2018-10-09 19:25   ` Dekel Peled
  2018-10-10  0:45     ` Yongseok Koh
  4 siblings, 1 reply; 94+ messages in thread
From: Dekel Peled @ 2018-10-09 19:25 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch adds support for Direct Verbs decap operations, L2 and L3.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow_dv.c | 215 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 215 insertions(+)

diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 73a22ba..d4ff812 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -120,6 +120,12 @@
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't have 2 encap actions in same"
 					  " flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
+			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't encap and decap in same"
+					  " flow");
 	if (attr->ingress)
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
@@ -167,6 +173,12 @@
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't have 2 encap actions in same"
 					  " flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
+			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't encap and decap in same"
+					  " flow");
 	if (attr->ingress)
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
@@ -177,6 +189,100 @@
 }
 
 /**
+ * Validate the tunnel decap action
+ *
+ * @param[in] action_flags
+ *   holds the actions detected until now.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_ernno is set.
+ */
+static int
+flow_dv_validate_action_tunnel_decap(uint64_t action_flags,
+				     const struct rte_flow_attr *attr,
+				     struct rte_flow_error *error)
+{
+	if (action_flags & MLX5_FLOW_ACTION_DROP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't drop and decap in same flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
+			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't have 2 decap actions in same"
+					  " flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP |
+			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't encap and decap in same"
+					  " flow");
+	if (attr->egress)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
+					  "decap action not supported for "
+					  "egress");
+	return 0;
+}
+
+/**
+ * Validate the tunnel decap L3 action
+ *
+ * @param[in] action_flags
+ *   holds the actions detected until now.
+ * @param[in] action
+ *   Pointer to the decap action.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_ernno is set.
+ */
+static int
+flow_dv_validate_action_tunnel_decap_l3(uint64_t action_flags,
+					const struct rte_flow_action *action,
+					const struct rte_flow_attr *attr,
+					struct rte_flow_error *error)
+{
+	const struct rte_flow_action_tunnel_decap_l3 *tunnel_decap_l3 =
+			action->conf;
+
+	if (!tunnel_decap_l3 || !(tunnel_decap_l3->buf))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, action,
+					  "configuration cannot be null");
+	if (action_flags & MLX5_FLOW_ACTION_DROP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't drop and decap in same flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
+			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't have 2 decap actions in same"
+					  " flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP |
+			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't encap and decap in same"
+					  " flow");
+	if (attr->egress)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
+					  "decap action not supported for "
+					  "egress");
+	return 0;
+}
+
+/**
  * Convert encap action to DV specification.
  *
  * @param[in] dev
@@ -246,6 +352,72 @@
 }
 
 /**
+ * Convert decap action to DV specification.
+ *
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[in] action
+ *   Pointer to action structure.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+flow_dv_create_decap(struct rte_eth_dev *dev,
+		     const struct rte_flow_action *action __rte_unused,
+		     struct rte_flow_error *error)
+{
+	struct ibv_flow_action *decap_verb = NULL;
+	struct priv *priv = dev->data->dev_private;
+
+	decap_verb = mlx5_glue->dv_create_flow_action_packet_reformat
+		(priv->ctx, 0, NULL,
+		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2,
+		 MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
+	if (!decap_verb)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create decap action");
+	return decap_verb;
+}
+
+/**
+ * Convert decap L3 action to DV specification.
+ *
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[in] action
+ *   Pointer to action structure.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+flow_dv_create_decap_l3(struct rte_eth_dev *dev,
+			const struct rte_flow_action *action,
+			struct rte_flow_error *error)
+{
+	struct ibv_flow_action *decap_l3_verb = NULL;
+	const struct rte_flow_action_tunnel_decap_l3 *decap_l3_data;
+	struct priv *priv = dev->data->dev_private;
+
+	decap_l3_data =
+		(const struct rte_flow_action_tunnel_decap_l3 *)action->conf;
+	decap_l3_verb = mlx5_glue->dv_create_flow_action_packet_reformat
+		(priv->ctx, decap_l3_data->size,
+		 decap_l3_data->size ? decap_l3_data->buf : NULL,
+		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2,
+		 MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
+	if (!decap_l3_verb)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create decap L3 action");
+	return decap_l3_verb;
+}
+
+/**
  * Verify the @p attributes will be correctly understood by the NIC and store
  * them in the @p flow if everything is correct.
  *
@@ -506,6 +678,20 @@
 				return ret;
 			action_flags |= MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3;
 			break;
+		case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP:
+			ret = flow_dv_validate_action_tunnel_decap
+				(action_flags, attr, error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_TUNNEL_DECAP;
+			break;
+		case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP_L3:
+			ret = flow_dv_validate_action_tunnel_decap_l3
+				(action_flags, actions, attr, error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_TUNNEL_DECAP_L3;
+			break;
 		default:
 			return rte_flow_error_set(error, ENOTSUP,
 						  RTE_FLOW_ERROR_TYPE_ACTION,
@@ -1301,6 +1487,30 @@
 		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3;
 		actions_n++;
 		break;
+	case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP:
+		dev_flow->dv.actions[actions_n].type =
+			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+		dev_flow->dv.actions[actions_n].action =
+			flow_dv_create_decap(dev, action, error);
+		if (!(dev_flow->dv.actions[actions_n].action))
+			return -rte_errno;
+		dev_flow->dv.decap_verb =
+			dev_flow->dv.actions[actions_n].action;
+		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_DECAP;
+		actions_n++;
+		break;
+	case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP_L3:
+		dev_flow->dv.actions[actions_n].type =
+			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+		dev_flow->dv.actions[actions_n].action =
+			flow_dv_create_decap_l3(dev, action, error);
+		if (!(dev_flow->dv.actions[actions_n].action))
+			return -rte_errno;
+		dev_flow->dv.decap_verb =
+			dev_flow->dv.actions[actions_n].action;
+		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_DECAP_L3;
+		actions_n++;
+		break;
 	default:
 		break;
 	}
@@ -1661,6 +1871,11 @@
 						(dev_flow->dv.encap_verb));
 			dev_flow->dv.encap_verb = NULL;
 		}
+		if (dev_flow->dv.decap_verb) {
+			claim_zero(mlx5_glue->destroy_flow_action
+						(dev_flow->dv.decap_verb));
+			dev_flow->dv.decap_verb = NULL;
+		}
 		rte_free(dev_flow);
 	}
 }
-- 
1.8.3.1

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

* Re: [dpdk-dev] [PATCH v3 1/4] net/mlx5: add flow action functions to glue
  2018-10-09 19:25   ` [dpdk-dev] [PATCH v3 1/4] net/mlx5: add flow action functions to glue Dekel Peled
@ 2018-10-10  0:36     ` Yongseok Koh
  2018-10-10  7:41       ` Dekel Peled
  2018-10-10  0:38     ` Yongseok Koh
  1 sibling, 1 reply; 94+ messages in thread
From: Yongseok Koh @ 2018-10-10  0:36 UTC (permalink / raw)
  To: Dekel Peled; +Cc: Shahaf Shuler, dev, Ori Kam

On Tue, Oct 09, 2018 at 10:25:34PM +0300, Dekel Peled wrote:
> This patch adds glue functions for operations:
> - Create packet reformat (encap/decap) flow action.
> - Destroy flow action.
> 
> The new operations depend on HAVE_IBV_FLOW_ACTION_DV_SUPPORT.
> 
> Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> ---
>  drivers/net/mlx5/Makefile    |  5 +++++
>  drivers/net/mlx5/meson.build |  2 ++
>  drivers/net/mlx5/mlx5_glue.c | 38 ++++++++++++++++++++++++++++++++++++++
>  drivers/net/mlx5/mlx5_glue.h | 13 +++++++++++++
>  4 files changed, 58 insertions(+)
> 
> diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile
> index 92bae9d..474ad42 100644
> --- a/drivers/net/mlx5/Makefile
> +++ b/drivers/net/mlx5/Makefile
> @@ -142,6 +142,11 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh
>  		enum MLX5DV_FLOW_ACTION_TAG \
>  		$(AUTOCONF_OUTPUT)
>  	$Q sh -- '$<' '$@' \
> +		HAVE_IBV_FLOW_ACTION_DV_SUPPORT \
> +		infiniband/mlx5dv.h \
> +		func mlx5dv_create_flow_action_packet_reformat \
> +		$(AUTOCONF_OUTPUT)
> +	$Q sh -- '$<' '$@' \
>  		HAVE_ETHTOOL_LINK_MODE_25G \
>  		/usr/include/linux/ethtool.h \
>  		enum ETHTOOL_LINK_MODE_25000baseCR_Full_BIT \
> diff --git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build
> index 6966248..d555c3c 100644
> --- a/drivers/net/mlx5/meson.build
> +++ b/drivers/net/mlx5/meson.build
> @@ -96,6 +96,8 @@ if build
>  		'MLX5DV_CONTEXT_FLAGS_CQE_128B_COMP' ],
>  		[ 'HAVE_IBV_FLOW_DV_SUPPORT', 'infiniband/mlx5dv.h',
>  		'MLX5DV_FLOW_ACTION_TAG' ],
> +		[ 'HAVE_IBV_FLOW_ACTION_DV_SUPPORT', 'infiniband/mlx5dv.h',
> +		'mlx5dv_create_flow_action_packet_reformat' ],
>  		[ 'HAVE_IBV_DEVICE_MPLS_SUPPORT', 'infiniband/verbs.h',
>  		'IBV_FLOW_SPEC_MPLS' ],
>  		[ 'HAVE_IBV_WQ_FLAG_RX_END_PADDING', 'infiniband/verbs.h',
> diff --git a/drivers/net/mlx5/mlx5_glue.c b/drivers/net/mlx5/mlx5_glue.c
> index 48590df..63fbab1 100644
> --- a/drivers/net/mlx5/mlx5_glue.c
> +++ b/drivers/net/mlx5/mlx5_glue.c
> @@ -174,6 +174,17 @@
>  	return ibv_destroy_flow(flow_id);
>  }
>  
> +static int
> +mlx5_glue_destroy_flow_action(struct ibv_flow_action *action)
> +{
> +#ifdef HAVE_IBV_FLOW_ACTION_DV_SUPPORT
> +	return ibv_destroy_flow_action(action);
> +#else
> +	(void)action;
> +	return NULL;
> +#endif
> +}
> +
>  static struct ibv_qp *
>  mlx5_glue_create_qp(struct ibv_pd *pd, struct ibv_qp_init_attr *qp_init_attr)
>  {
> @@ -388,6 +399,30 @@
>  #endif
>  }
>  
> +static struct ibv_flow_action *
> +mlx5_glue_dv_create_flow_action_packet_reformat
> +		(struct ibv_context *ctx,
> +		 size_t data_sz,
> +		 void *data,
> +		 enum mlx5dv_flow_action_packet_reformat_type reformat_type,
> +		 enum mlx5dv_flow_table_type ft_type)
> +{
> +#ifdef HAVE_IBV_FLOW_ACTION_DV_SUPPORT
> +	return mlx5dv_create_flow_action_packet_reformat(ctx,
> +							 data_sz,
> +							 data,
> +							 reformat_type,
> +							 ft_type);
> +#else
> +	(void)ctx;
> +	(void)data_sz;
> +	(void)data;
> +	(void)reformat_type;
> +	(void)ft_type;
> +	return NULL;
> +#endif
> +}
> +
>  alignas(RTE_CACHE_LINE_SIZE)
>  const struct mlx5_glue *mlx5_glue = &(const struct mlx5_glue){
>  	.version = MLX5_GLUE_VERSION,
> @@ -414,6 +449,7 @@
>  	.modify_wq = mlx5_glue_modify_wq,
>  	.create_flow = mlx5_glue_create_flow,
>  	.destroy_flow = mlx5_glue_destroy_flow,
> +	.destroy_flow_action = mlx5_glue_destroy_flow_action,
>  	.create_qp = mlx5_glue_create_qp,
>  	.create_qp_ex = mlx5_glue_create_qp_ex,
>  	.destroy_qp = mlx5_glue_destroy_qp,
> @@ -437,4 +473,6 @@
>  	.dv_create_flow_matcher = mlx5_glue_dv_create_flow_matcher,
>  	.dv_destroy_flow_matcher = mlx5_glue_dv_destroy_flow_matcher,
>  	.dv_create_flow = mlx5_glue_dv_create_flow,
> +	.dv_create_flow_action_packet_reformat =
> +			mlx5_glue_dv_create_flow_action_packet_reformat,
>  };
> diff --git a/drivers/net/mlx5/mlx5_glue.h b/drivers/net/mlx5/mlx5_glue.h
> index f6e4e38..071a650 100644
> --- a/drivers/net/mlx5/mlx5_glue.h
> +++ b/drivers/net/mlx5/mlx5_glue.h
> @@ -46,6 +46,12 @@
>  struct mlx5dv_flow_match_parameters;
>  #endif
>  
> +#ifndef HAVE_IBV_FLOW_ACTION_DV_SUPPORT
> +struct ibv_flow_action;
> +enum mlx5dv_flow_action_packet_reformat_type { type = 0, };
> +enum mlx5dv_flow_table_type { type = 0, };

This part still has an error.

	In file included from ../drivers/net/mlx5/mlx5_rxq.c:38:0:
	../drivers/net/mlx5/mlx5_glue.h:55:2: error: redeclaration of enumerator ‘type’
	  type = 0,
	  ^
	../drivers/net/mlx5/mlx5_glue.h:52:2: note: previous definition of ‘type’
	was here
	  type = 0,
	  ^

You should've used different names. However, I have another suggestion. Let me
speak with you offline.

Thanks,
Yongseok

> +#endif
> +
>  /* LIB_GLUE_VERSION must be updated every time this structure is modified. */
>  struct mlx5_glue {
>  	const char *version;
> @@ -85,6 +91,7 @@ struct mlx5_glue {
>  	struct ibv_flow *(*create_flow)(struct ibv_qp *qp,
>  					struct ibv_flow_attr *flow);
>  	int (*destroy_flow)(struct ibv_flow *flow_id);
> +	int (*destroy_flow_action)(struct ibv_flow_action *action);
>  	struct ibv_qp *(*create_qp)(struct ibv_pd *pd,
>  				    struct ibv_qp_init_attr *qp_init_attr);
>  	struct ibv_qp *(*create_qp_ex)
> @@ -137,6 +144,12 @@ struct mlx5_glue {
>  			  struct mlx5dv_flow_match_parameters *match_value,
>  			  size_t num_actions,
>  			  struct mlx5dv_flow_action_attr *actions_attr);
> +	struct ibv_flow_action *(*dv_create_flow_action_packet_reformat)
> +		(struct ibv_context *ctx,
> +		 size_t data_sz,
> +		 void *data,
> +		 enum mlx5dv_flow_action_packet_reformat_type reformat_type,
> +		 enum mlx5dv_flow_table_type ft_type);
>  };
>  
>  const struct mlx5_glue *mlx5_glue;
> -- 
> 1.8.3.1
> 

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

* Re: [dpdk-dev] [PATCH v3 1/4] net/mlx5: add flow action functions to glue
  2018-10-09 19:25   ` [dpdk-dev] [PATCH v3 1/4] net/mlx5: add flow action functions to glue Dekel Peled
  2018-10-10  0:36     ` Yongseok Koh
@ 2018-10-10  0:38     ` Yongseok Koh
  1 sibling, 0 replies; 94+ messages in thread
From: Yongseok Koh @ 2018-10-10  0:38 UTC (permalink / raw)
  To: Dekel Peled; +Cc: Shahaf Shuler, dev, Ori Kam

On Tue, Oct 09, 2018 at 10:25:34PM +0300, Dekel Peled wrote:
> This patch adds glue functions for operations:
> - Create packet reformat (encap/decap) flow action.
> - Destroy flow action.
> 
> The new operations depend on HAVE_IBV_FLOW_ACTION_DV_SUPPORT.
> 
> Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> ---
>  drivers/net/mlx5/Makefile    |  5 +++++
>  drivers/net/mlx5/meson.build |  2 ++
>  drivers/net/mlx5/mlx5_glue.c | 38 ++++++++++++++++++++++++++++++++++++++
>  drivers/net/mlx5/mlx5_glue.h | 13 +++++++++++++
>  4 files changed, 58 insertions(+)
> 
> diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile
> index 92bae9d..474ad42 100644
> --- a/drivers/net/mlx5/Makefile
> +++ b/drivers/net/mlx5/Makefile
> @@ -142,6 +142,11 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh
>  		enum MLX5DV_FLOW_ACTION_TAG \
>  		$(AUTOCONF_OUTPUT)
>  	$Q sh -- '$<' '$@' \
> +		HAVE_IBV_FLOW_ACTION_DV_SUPPORT \
> +		infiniband/mlx5dv.h \
> +		func mlx5dv_create_flow_action_packet_reformat \
> +		$(AUTOCONF_OUTPUT)
> +	$Q sh -- '$<' '$@' \
>  		HAVE_ETHTOOL_LINK_MODE_25G \
>  		/usr/include/linux/ethtool.h \
>  		enum ETHTOOL_LINK_MODE_25000baseCR_Full_BIT \
> diff --git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build
> index 6966248..d555c3c 100644
> --- a/drivers/net/mlx5/meson.build
> +++ b/drivers/net/mlx5/meson.build
> @@ -96,6 +96,8 @@ if build
>  		'MLX5DV_CONTEXT_FLAGS_CQE_128B_COMP' ],
>  		[ 'HAVE_IBV_FLOW_DV_SUPPORT', 'infiniband/mlx5dv.h',
>  		'MLX5DV_FLOW_ACTION_TAG' ],
> +		[ 'HAVE_IBV_FLOW_ACTION_DV_SUPPORT', 'infiniband/mlx5dv.h',
> +		'mlx5dv_create_flow_action_packet_reformat' ],
>  		[ 'HAVE_IBV_DEVICE_MPLS_SUPPORT', 'infiniband/verbs.h',
>  		'IBV_FLOW_SPEC_MPLS' ],
>  		[ 'HAVE_IBV_WQ_FLAG_RX_END_PADDING', 'infiniband/verbs.h',
> diff --git a/drivers/net/mlx5/mlx5_glue.c b/drivers/net/mlx5/mlx5_glue.c
> index 48590df..63fbab1 100644
> --- a/drivers/net/mlx5/mlx5_glue.c
> +++ b/drivers/net/mlx5/mlx5_glue.c
> @@ -174,6 +174,17 @@
>  	return ibv_destroy_flow(flow_id);
>  }
>  
> +static int
> +mlx5_glue_destroy_flow_action(struct ibv_flow_action *action)
> +{
> +#ifdef HAVE_IBV_FLOW_ACTION_DV_SUPPORT
> +	return ibv_destroy_flow_action(action);
> +#else
> +	(void)action;
> +	return NULL;

And this should be
	return ENOTSUP;
Return type mismatches, you'll see a compiler warning.

Thanks,
Yongseok

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

* Re: [dpdk-dev] [PATCH v3 2/4] net/mlx5: add Direct Verbs encap and decap defs
  2018-10-09 19:25   ` [dpdk-dev] [PATCH v3 2/4] net/mlx5: add Direct Verbs encap and decap defs Dekel Peled
@ 2018-10-10  0:40     ` Yongseok Koh
  0 siblings, 0 replies; 94+ messages in thread
From: Yongseok Koh @ 2018-10-10  0:40 UTC (permalink / raw)
  To: Dekel Peled; +Cc: Shahaf Shuler, dev, Ori Kam

On Tue, Oct 09, 2018 at 10:25:35PM +0300, Dekel Peled wrote:
> This patch adds the required definitions for DV encap/decap actions.
> It also adds usage of the new actions definition in validation
> function of existing drop operation.
> 
> Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> ---

I've acked it in v2. So, please put my acked-by tag when you submit a new
version.

Acked-by: Yongseok Koh <yskoh@mellanox.com>

Thanks

>  drivers/net/mlx5/mlx5_flow.c | 8 ++++++++
>  drivers/net/mlx5/mlx5_flow.h | 6 ++++++
>  2 files changed, 14 insertions(+)
> 
> diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
> index 1087f67..b452e11 100644
> --- a/drivers/net/mlx5/mlx5_flow.c
> +++ b/drivers/net/mlx5/mlx5_flow.c
> @@ -766,6 +766,14 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
>  					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
>  					  "can't have 2 fate actions in"
>  					  " same flow");
> +	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
> +			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3 |
> +			    MLX5_FLOW_ACTION_TUNNEL_ENCAP |
> +			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
> +					  "can't encap or decap and drop in"
> +					  " same flow");
>  	if (attr->egress)
>  		return rte_flow_error_set(error, ENOTSUP,
>  					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
> diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
> index 690c597..01c73a2 100644
> --- a/drivers/net/mlx5/mlx5_flow.h
> +++ b/drivers/net/mlx5/mlx5_flow.h
> @@ -82,6 +82,10 @@
>  #define MLX5_FLOW_ACTION_OF_SET_VLAN_VID (1u << 9)
>  #define MLX5_FLOW_ACTION_OF_SET_VLAN_PCP (1u << 10)
>  #define MLX5_FLOW_ACTION_JUMP (1u << 11)
> +#define MLX5_FLOW_ACTION_TUNNEL_ENCAP (1u << 12)
> +#define MLX5_FLOW_ACTION_TUNNEL_DECAP (1u << 13)
> +#define MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3 (1u << 14)
> +#define MLX5_FLOW_ACTION_TUNNEL_DECAP_L3 (1u << 15)
>  
>  #define MLX5_FLOW_FATE_ACTIONS \
>  	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS)
> @@ -172,6 +176,8 @@ struct mlx5_flow_dv {
>  #ifdef HAVE_IBV_FLOW_DV_SUPPORT
>  	struct mlx5dv_flow_action_attr actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS];
>  	/**< Action list. */
> +	struct ibv_flow_action *encap_verb; /**< Verbs object of encap. */
> +	struct ibv_flow_action *decap_verb; /**< Verbs object of decap. */
>  #endif
>  	int actions_n; /**< number of actions. */
>  };
> -- 
> 1.8.3.1
> 

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

* Re: [dpdk-dev] [PATCH v3 3/4] net/mlx5: add L2 and L3 encap to Direct Verbs flow
  2018-10-09 19:25   ` [dpdk-dev] [PATCH v3 3/4] net/mlx5: add L2 and L3 encap to Direct Verbs flow Dekel Peled
@ 2018-10-10  0:43     ` Yongseok Koh
  0 siblings, 0 replies; 94+ messages in thread
From: Yongseok Koh @ 2018-10-10  0:43 UTC (permalink / raw)
  To: Dekel Peled; +Cc: Shahaf Shuler, dev, Ori Kam

On Tue, Oct 09, 2018 at 10:25:36PM +0300, Dekel Peled wrote:
> This patch adds support for Direct Verbs encap operations, L2 and L3.
> 
> Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> ---

Acked-by: Yongseok Koh <yskoh@mellanox.com>

Thanks

>  drivers/net/mlx5/mlx5_flow_dv.c | 227 +++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 222 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
> index 80e7b24..73a22ba 100644
> --- a/drivers/net/mlx5/mlx5_flow_dv.c
> +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> @@ -84,6 +84,168 @@
>  }
>  
>  /**
> + * Validate the tunnel encap action.
> + *
> + * @param[in] action_flags
> + *   holds the actions detected until now.
> + * @param[in] action
> + *   Pointer to the encap action.
> + * @param[in] attr
> + *   Pointer to flow attributes
> + * @param[out] error
> + *   Pointer to error structure.
> + *
> + * @return
> + *   0 on success, a negative errno value otherwise and rte_ernno is set.
> + */
> +static int
> +flow_dv_validate_action_tunnel_encap(uint64_t action_flags,
> +				     const struct rte_flow_action *action,
> +				     const struct rte_flow_attr *attr,
> +				     struct rte_flow_error *error)
> +{
> +	const struct rte_flow_action_tunnel_encap *tunnel_encap = action->conf;
> +
> +	if (!tunnel_encap || !(tunnel_encap->buf))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, action,
> +					  "configuration cannot be null");
> +	if (action_flags & MLX5_FLOW_ACTION_DROP)
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
> +					  "can't drop and encap in same flow");
> +	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP |
> +			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
> +					  "can't have 2 encap actions in same"
> +					  " flow");
> +	if (attr->ingress)
> +		return rte_flow_error_set(error, ENOTSUP,
> +					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> +					  NULL,
> +					  "encap action not supported for "
> +					  "ingress");
> +	return 0;
> +}
> +
> +/**
> + * Validate the tunnel encap L3 action
> + *
> + * @param[in] action_flags
> + *   holds the actions detected until now.
> + * @param[in] action
> + *   Pointer to the encap action.
> + * @param[in] attr
> + *   Pointer to flow attributes
> + * @param[out] error
> + *   Pointer to error structure.
> + *
> + * @return
> + *   0 on success, a negative errno value otherwise and rte_ernno is set.
> + */
> +static int
> +flow_dv_validate_action_tunnel_encap_l3(uint64_t action_flags,
> +					const struct rte_flow_action *action,
> +					const struct rte_flow_attr *attr,
> +					struct rte_flow_error *error)
> +{
> +	const struct rte_flow_action_tunnel_encap_l3 *tunnel_encap_l3 =
> +			action->conf;
> +
> +	if (!tunnel_encap_l3 || !(tunnel_encap_l3->buf))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, action,
> +					  "configuration cannot be null");
> +	if (action_flags & MLX5_FLOW_ACTION_DROP)
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
> +					  "can't drop and encap in same flow");
> +	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP |
> +			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
> +					  "can't have 2 encap actions in same"
> +					  " flow");
> +	if (attr->ingress)
> +		return rte_flow_error_set(error, ENOTSUP,
> +					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> +					  NULL,
> +					  "encap action not supported for "
> +					  "ingress");
> +	return 0;
> +}
> +
> +/**
> + * Convert encap action to DV specification.
> + *
> + * @param[in] dev
> + *   Pointer to rte_eth_dev structure.
> + * @param[in] action
> + *   Pointer to action structure.
> + * @param[out] error
> + *   Pointer to the error structure.
> + *
> + * @return
> + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> + */
> +static struct ibv_flow_action *
> +flow_dv_create_encap(struct rte_eth_dev *dev,
> +		     const struct rte_flow_action *action,
> +		     struct rte_flow_error *error)
> +{
> +	struct ibv_flow_action *encap_verb = NULL;
> +	const struct rte_flow_action_tunnel_encap *encap_data;
> +	struct priv *priv = dev->data->dev_private;
> +
> +	encap_data = (const struct rte_flow_action_tunnel_encap *)action->conf;
> +	encap_verb = mlx5_glue->dv_create_flow_action_packet_reformat
> +		(priv->ctx, encap_data->size,
> +		 encap_data->size ? encap_data->buf : NULL,
> +		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
> +		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
> +	if (!encap_verb)
> +		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
> +				   NULL, "cannot create encap action");
> +	return encap_verb;
> +}
> +
> +/**
> + * Convert encap L3 action to DV specification.
> + *
> + * @param[in] dev
> + *   Pointer to rte_eth_dev structure.
> + * @param[in] action
> + *   Pointer to action structure.
> + * @param[out] error
> + *   Pointer to the error structure.
> + *
> + * @return
> + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> + */
> +static struct ibv_flow_action *
> +flow_dv_create_encap_l3(struct rte_eth_dev *dev,
> +			const struct rte_flow_action *action,
> +			struct rte_flow_error *error)
> +{
> +	struct ibv_flow_action *encap_l3_verb = NULL;
> +	const struct rte_flow_action_tunnel_encap_l3 *encap_l3_data;
> +	struct priv *priv = dev->data->dev_private;
> +
> +	encap_l3_data =
> +		(const struct rte_flow_action_tunnel_encap_l3 *)action->conf;
> +	encap_l3_verb = mlx5_glue->dv_create_flow_action_packet_reformat
> +		(priv->ctx, encap_l3_data->size,
> +		 encap_l3_data->size ? encap_l3_data->buf : NULL,
> +		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL,
> +		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
> +	if (!encap_l3_verb)
> +		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
> +				   NULL, "cannot create encap L3 action");
> +	return encap_l3_verb;
> +}
> +
> +/**
>   * Verify the @p attributes will be correctly understood by the NIC and store
>   * them in the @p flow if everything is correct.
>   *
> @@ -330,6 +492,20 @@
>  			action_flags |= MLX5_FLOW_ACTION_COUNT;
>  			++actions_n;
>  			break;
> +		case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP:
> +			ret = flow_dv_validate_action_tunnel_encap
> +				(action_flags, actions, attr, error);
> +			if (ret < 0)
> +				return ret;
> +			action_flags |= MLX5_FLOW_ACTION_TUNNEL_ENCAP;
> +			break;
> +		case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP_L3:
> +			ret = flow_dv_validate_action_tunnel_encap_l3
> +				(action_flags, actions, attr, error);
> +			if (ret < 0)
> +				return ret;
> +			action_flags |= MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3;
> +			break;
>  		default:
>  			return rte_flow_error_set(error, ENOTSUP,
>  						  RTE_FLOW_ERROR_TYPE_ACTION,
> @@ -1038,14 +1214,23 @@
>  /**
>   * Store the requested actions in an array.
>   *
> + * @param[in] dev
> + *   Pointer to rte_eth_dev structure.
>   * @param[in] action
>   *   Flow action to translate.
>   * @param[in, out] dev_flow
>   *   Pointer to the mlx5_flow.
> + * @param[out] error
> + *   Pointer to the error structure.
> + *
> + * @return
> + *   0 on success, a negative errno value otherwise and rte_ernno is set.
>   */
> -static void
> -flow_dv_create_action(const struct rte_flow_action *action,
> -		      struct mlx5_flow *dev_flow)
> +static int
> +flow_dv_create_action(struct rte_eth_dev *dev,
> +		      const struct rte_flow_action *action,
> +		      struct mlx5_flow *dev_flow,
> +		      struct rte_flow_error *error)
>  {
>  	const struct rte_flow_action_queue *queue;
>  	const struct rte_flow_action_rss *rss;
> @@ -1092,10 +1277,35 @@
>  		/* Added to array only in apply since we need the QP */
>  		flow->actions |= MLX5_FLOW_ACTION_RSS;
>  		break;
> +	case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP:
> +		dev_flow->dv.actions[actions_n].type =
> +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> +		dev_flow->dv.actions[actions_n].action =
> +			flow_dv_create_encap(dev, action, error);
> +		if (!(dev_flow->dv.actions[actions_n].action))
> +			return -rte_errno;
> +		dev_flow->dv.encap_verb =
> +			dev_flow->dv.actions[actions_n].action;
> +		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_ENCAP;
> +		actions_n++;
> +		break;
> +	case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP_L3:
> +		dev_flow->dv.actions[actions_n].type =
> +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> +		dev_flow->dv.actions[actions_n].action =
> +			flow_dv_create_encap_l3(dev, action, error);
> +		if (!(dev_flow->dv.actions[actions_n].action))
> +			return -rte_errno;
> +		dev_flow->dv.encap_verb =
> +			dev_flow->dv.actions[actions_n].action;
> +		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3;
> +		actions_n++;
> +		break;
>  	default:
>  		break;
>  	}
>  	dev_flow->dv.actions_n = actions_n;
> +	return 0;
>  }
>  
>  static uint32_t matcher_zero[MLX5_ST_SZ_DW(fte_match_param)] = { 0 };
> @@ -1259,8 +1469,10 @@
>  	matcher.egress = attr->egress;
>  	if (flow_dv_matcher_register(dev, &matcher, dev_flow, error))
>  		return -rte_errno;
> -	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++)
> -		flow_dv_create_action(actions, dev_flow);
> +	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
> +		if (flow_dv_create_action(dev, actions, dev_flow, error))
> +			return -rte_errno;
> +	}
>  	return 0;
>  }
>  
> @@ -1444,6 +1656,11 @@
>  		LIST_REMOVE(dev_flow, next);
>  		if (dev_flow->dv.matcher)
>  			flow_dv_matcher_release(dev, dev_flow->dv.matcher);
> +		if (dev_flow->dv.encap_verb) {
> +			claim_zero(mlx5_glue->destroy_flow_action
> +						(dev_flow->dv.encap_verb));
> +			dev_flow->dv.encap_verb = NULL;
> +		}
>  		rte_free(dev_flow);
>  	}
>  }
> -- 
> 1.8.3.1
> 

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

* Re: [dpdk-dev] [PATCH v3 4/4] net/mlx5: add L2 and L3 decap to Direct Verbs flow
  2018-10-09 19:25   ` [dpdk-dev] [PATCH v3 4/4] net/mlx5: add L2 and L3 decap " Dekel Peled
@ 2018-10-10  0:45     ` Yongseok Koh
  0 siblings, 0 replies; 94+ messages in thread
From: Yongseok Koh @ 2018-10-10  0:45 UTC (permalink / raw)
  To: Dekel Peled; +Cc: Shahaf Shuler, dev, Ori Kam

On Tue, Oct 09, 2018 at 10:25:37PM +0300, Dekel Peled wrote:
> This patch adds support for Direct Verbs decap operations, L2 and L3.
> 
> Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> ---

Acked-by: Yongseok Koh <yskoh@mellanox.com>

Thanks

>  drivers/net/mlx5/mlx5_flow_dv.c | 215 ++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 215 insertions(+)
> 
> diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
> index 73a22ba..d4ff812 100644
> --- a/drivers/net/mlx5/mlx5_flow_dv.c
> +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> @@ -120,6 +120,12 @@
>  					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
>  					  "can't have 2 encap actions in same"
>  					  " flow");
> +	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
> +			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
> +					  "can't encap and decap in same"
> +					  " flow");
>  	if (attr->ingress)
>  		return rte_flow_error_set(error, ENOTSUP,
>  					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> @@ -167,6 +173,12 @@
>  					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
>  					  "can't have 2 encap actions in same"
>  					  " flow");
> +	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
> +			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
> +					  "can't encap and decap in same"
> +					  " flow");
>  	if (attr->ingress)
>  		return rte_flow_error_set(error, ENOTSUP,
>  					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> @@ -177,6 +189,100 @@
>  }
>  
>  /**
> + * Validate the tunnel decap action
> + *
> + * @param[in] action_flags
> + *   holds the actions detected until now.
> + * @param[in] attr
> + *   Pointer to flow attributes
> + * @param[out] error
> + *   Pointer to error structure.
> + *
> + * @return
> + *   0 on success, a negative errno value otherwise and rte_ernno is set.
> + */
> +static int
> +flow_dv_validate_action_tunnel_decap(uint64_t action_flags,
> +				     const struct rte_flow_attr *attr,
> +				     struct rte_flow_error *error)
> +{
> +	if (action_flags & MLX5_FLOW_ACTION_DROP)
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
> +					  "can't drop and decap in same flow");
> +	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
> +			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
> +					  "can't have 2 decap actions in same"
> +					  " flow");
> +	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP |
> +			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
> +					  "can't encap and decap in same"
> +					  " flow");
> +	if (attr->egress)
> +		return rte_flow_error_set(error, ENOTSUP,
> +					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
> +					  "decap action not supported for "
> +					  "egress");
> +	return 0;
> +}
> +
> +/**
> + * Validate the tunnel decap L3 action
> + *
> + * @param[in] action_flags
> + *   holds the actions detected until now.
> + * @param[in] action
> + *   Pointer to the decap action.
> + * @param[in] attr
> + *   Pointer to flow attributes
> + * @param[out] error
> + *   Pointer to error structure.
> + *
> + * @return
> + *   0 on success, a negative errno value otherwise and rte_ernno is set.
> + */
> +static int
> +flow_dv_validate_action_tunnel_decap_l3(uint64_t action_flags,
> +					const struct rte_flow_action *action,
> +					const struct rte_flow_attr *attr,
> +					struct rte_flow_error *error)
> +{
> +	const struct rte_flow_action_tunnel_decap_l3 *tunnel_decap_l3 =
> +			action->conf;
> +
> +	if (!tunnel_decap_l3 || !(tunnel_decap_l3->buf))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, action,
> +					  "configuration cannot be null");
> +	if (action_flags & MLX5_FLOW_ACTION_DROP)
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
> +					  "can't drop and decap in same flow");
> +	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
> +			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
> +					  "can't have 2 decap actions in same"
> +					  " flow");
> +	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP |
> +			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
> +					  "can't encap and decap in same"
> +					  " flow");
> +	if (attr->egress)
> +		return rte_flow_error_set(error, ENOTSUP,
> +					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
> +					  "decap action not supported for "
> +					  "egress");
> +	return 0;
> +}
> +
> +/**
>   * Convert encap action to DV specification.
>   *
>   * @param[in] dev
> @@ -246,6 +352,72 @@
>  }
>  
>  /**
> + * Convert decap action to DV specification.
> + *
> + * @param[in] dev
> + *   Pointer to rte_eth_dev structure.
> + * @param[in] action
> + *   Pointer to action structure.
> + * @param[out] error
> + *   Pointer to the error structure.
> + *
> + * @return
> + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> + */
> +static struct ibv_flow_action *
> +flow_dv_create_decap(struct rte_eth_dev *dev,
> +		     const struct rte_flow_action *action __rte_unused,
> +		     struct rte_flow_error *error)
> +{
> +	struct ibv_flow_action *decap_verb = NULL;
> +	struct priv *priv = dev->data->dev_private;
> +
> +	decap_verb = mlx5_glue->dv_create_flow_action_packet_reformat
> +		(priv->ctx, 0, NULL,
> +		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2,
> +		 MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
> +	if (!decap_verb)
> +		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
> +				   NULL, "cannot create decap action");
> +	return decap_verb;
> +}
> +
> +/**
> + * Convert decap L3 action to DV specification.
> + *
> + * @param[in] dev
> + *   Pointer to rte_eth_dev structure.
> + * @param[in] action
> + *   Pointer to action structure.
> + * @param[out] error
> + *   Pointer to the error structure.
> + *
> + * @return
> + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> + */
> +static struct ibv_flow_action *
> +flow_dv_create_decap_l3(struct rte_eth_dev *dev,
> +			const struct rte_flow_action *action,
> +			struct rte_flow_error *error)
> +{
> +	struct ibv_flow_action *decap_l3_verb = NULL;
> +	const struct rte_flow_action_tunnel_decap_l3 *decap_l3_data;
> +	struct priv *priv = dev->data->dev_private;
> +
> +	decap_l3_data =
> +		(const struct rte_flow_action_tunnel_decap_l3 *)action->conf;
> +	decap_l3_verb = mlx5_glue->dv_create_flow_action_packet_reformat
> +		(priv->ctx, decap_l3_data->size,
> +		 decap_l3_data->size ? decap_l3_data->buf : NULL,
> +		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2,
> +		 MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
> +	if (!decap_l3_verb)
> +		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
> +				   NULL, "cannot create decap L3 action");
> +	return decap_l3_verb;
> +}
> +
> +/**
>   * Verify the @p attributes will be correctly understood by the NIC and store
>   * them in the @p flow if everything is correct.
>   *
> @@ -506,6 +678,20 @@
>  				return ret;
>  			action_flags |= MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3;
>  			break;
> +		case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP:
> +			ret = flow_dv_validate_action_tunnel_decap
> +				(action_flags, attr, error);
> +			if (ret < 0)
> +				return ret;
> +			action_flags |= MLX5_FLOW_ACTION_TUNNEL_DECAP;
> +			break;
> +		case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP_L3:
> +			ret = flow_dv_validate_action_tunnel_decap_l3
> +				(action_flags, actions, attr, error);
> +			if (ret < 0)
> +				return ret;
> +			action_flags |= MLX5_FLOW_ACTION_TUNNEL_DECAP_L3;
> +			break;
>  		default:
>  			return rte_flow_error_set(error, ENOTSUP,
>  						  RTE_FLOW_ERROR_TYPE_ACTION,
> @@ -1301,6 +1487,30 @@
>  		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3;
>  		actions_n++;
>  		break;
> +	case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP:
> +		dev_flow->dv.actions[actions_n].type =
> +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> +		dev_flow->dv.actions[actions_n].action =
> +			flow_dv_create_decap(dev, action, error);
> +		if (!(dev_flow->dv.actions[actions_n].action))
> +			return -rte_errno;
> +		dev_flow->dv.decap_verb =
> +			dev_flow->dv.actions[actions_n].action;
> +		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_DECAP;
> +		actions_n++;
> +		break;
> +	case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP_L3:
> +		dev_flow->dv.actions[actions_n].type =
> +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> +		dev_flow->dv.actions[actions_n].action =
> +			flow_dv_create_decap_l3(dev, action, error);
> +		if (!(dev_flow->dv.actions[actions_n].action))
> +			return -rte_errno;
> +		dev_flow->dv.decap_verb =
> +			dev_flow->dv.actions[actions_n].action;
> +		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_DECAP_L3;
> +		actions_n++;
> +		break;
>  	default:
>  		break;
>  	}
> @@ -1661,6 +1871,11 @@
>  						(dev_flow->dv.encap_verb));
>  			dev_flow->dv.encap_verb = NULL;
>  		}
> +		if (dev_flow->dv.decap_verb) {
> +			claim_zero(mlx5_glue->destroy_flow_action
> +						(dev_flow->dv.decap_verb));
> +			dev_flow->dv.decap_verb = NULL;
> +		}
>  		rte_free(dev_flow);
>  	}
>  }
> -- 
> 1.8.3.1
> 

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

* Re: [dpdk-dev] [PATCH v3 1/4] net/mlx5: add flow action functions to glue
  2018-10-10  0:36     ` Yongseok Koh
@ 2018-10-10  7:41       ` Dekel Peled
  0 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-10  7:41 UTC (permalink / raw)
  To: Yongseok Koh; +Cc: Shahaf Shuler, dev, Ori Kam

Thanks, PSB.
Note I'm replying here to comments from both emails you sent.

> -----Original Message-----
> From: Yongseok Koh
> Sent: Wednesday, October 10, 2018 3:36 AM
> To: Dekel Peled <dekelp@mellanox.com>
> Cc: Shahaf Shuler <shahafs@mellanox.com>; dev@dpdk.org; Ori Kam
> <orika@mellanox.com>
> Subject: Re: [PATCH v3 1/4] net/mlx5: add flow action functions to glue
> 
> On Tue, Oct 09, 2018 at 10:25:34PM +0300, Dekel Peled wrote:
> > This patch adds glue functions for operations:
> > - Create packet reformat (encap/decap) flow action.
> > - Destroy flow action.
> >
> > The new operations depend on HAVE_IBV_FLOW_ACTION_DV_SUPPORT.
> >
> > Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> > ---
> >  drivers/net/mlx5/Makefile    |  5 +++++
> >  drivers/net/mlx5/meson.build |  2 ++
> >  drivers/net/mlx5/mlx5_glue.c | 38
> > ++++++++++++++++++++++++++++++++++++++
> >  drivers/net/mlx5/mlx5_glue.h | 13 +++++++++++++
> >  4 files changed, 58 insertions(+)
> >
> > diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile
> > index 92bae9d..474ad42 100644
> > --- a/drivers/net/mlx5/Makefile
> > +++ b/drivers/net/mlx5/Makefile
> > @@ -142,6 +142,11 @@ mlx5_autoconf.h.new:
> $(RTE_SDK)/buildtools/auto-config-h.sh
> >  		enum MLX5DV_FLOW_ACTION_TAG \
> >  		$(AUTOCONF_OUTPUT)
> >  	$Q sh -- '$<' '$@' \
> > +		HAVE_IBV_FLOW_ACTION_DV_SUPPORT \
> > +		infiniband/mlx5dv.h \
> > +		func mlx5dv_create_flow_action_packet_reformat \
> > +		$(AUTOCONF_OUTPUT)
> > +	$Q sh -- '$<' '$@' \
> >  		HAVE_ETHTOOL_LINK_MODE_25G \
> >  		/usr/include/linux/ethtool.h \
> >  		enum ETHTOOL_LINK_MODE_25000baseCR_Full_BIT \ diff --
> git
> > a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build index
> > 6966248..d555c3c 100644
> > --- a/drivers/net/mlx5/meson.build
> > +++ b/drivers/net/mlx5/meson.build
> > @@ -96,6 +96,8 @@ if build
> >  		'MLX5DV_CONTEXT_FLAGS_CQE_128B_COMP' ],
> >  		[ 'HAVE_IBV_FLOW_DV_SUPPORT', 'infiniband/mlx5dv.h',
> >  		'MLX5DV_FLOW_ACTION_TAG' ],
> > +		[ 'HAVE_IBV_FLOW_ACTION_DV_SUPPORT',
> 'infiniband/mlx5dv.h',
> > +		'mlx5dv_create_flow_action_packet_reformat' ],
> >  		[ 'HAVE_IBV_DEVICE_MPLS_SUPPORT', 'infiniband/verbs.h',
> >  		'IBV_FLOW_SPEC_MPLS' ],
> >  		[ 'HAVE_IBV_WQ_FLAG_RX_END_PADDING',
> 'infiniband/verbs.h', diff
> > --git a/drivers/net/mlx5/mlx5_glue.c b/drivers/net/mlx5/mlx5_glue.c
> > index 48590df..63fbab1 100644
> > --- a/drivers/net/mlx5/mlx5_glue.c
> > +++ b/drivers/net/mlx5/mlx5_glue.c
> > @@ -174,6 +174,17 @@
> >  	return ibv_destroy_flow(flow_id);
> >  }
> >
> > +static int
> > +mlx5_glue_destroy_flow_action(struct ibv_flow_action *action) {
> > +#ifdef HAVE_IBV_FLOW_ACTION_DV_SUPPORT
> > +	return ibv_destroy_flow_action(action); #else
> > +	(void)action;
> > +	return NULL;
> 
> And this should be
> 	return ENOTSUP;
> Return type mismatches, you'll see a compiler warning.
> 
> Thanks,
> Yongseok

Fixed.

> > +#endif
> > +}
> > +
> >  static struct ibv_qp *
> >  mlx5_glue_create_qp(struct ibv_pd *pd, struct ibv_qp_init_attr
> > *qp_init_attr)  { @@ -388,6 +399,30 @@  #endif  }
> >
> > +static struct ibv_flow_action *
> > +mlx5_glue_dv_create_flow_action_packet_reformat
> > +		(struct ibv_context *ctx,
> > +		 size_t data_sz,
> > +		 void *data,
> > +		 enum mlx5dv_flow_action_packet_reformat_type
> reformat_type,
> > +		 enum mlx5dv_flow_table_type ft_type) { #ifdef
> > +HAVE_IBV_FLOW_ACTION_DV_SUPPORT
> > +	return mlx5dv_create_flow_action_packet_reformat(ctx,
> > +							 data_sz,
> > +							 data,
> > +							 reformat_type,
> > +							 ft_type);
> > +#else
> > +	(void)ctx;
> > +	(void)data_sz;
> > +	(void)data;
> > +	(void)reformat_type;
> > +	(void)ft_type;
> > +	return NULL;
> > +#endif
> > +}
> > +
> >  alignas(RTE_CACHE_LINE_SIZE)
> >  const struct mlx5_glue *mlx5_glue = &(const struct mlx5_glue){
> >  	.version = MLX5_GLUE_VERSION,
> > @@ -414,6 +449,7 @@
> >  	.modify_wq = mlx5_glue_modify_wq,
> >  	.create_flow = mlx5_glue_create_flow,
> >  	.destroy_flow = mlx5_glue_destroy_flow,
> > +	.destroy_flow_action = mlx5_glue_destroy_flow_action,
> >  	.create_qp = mlx5_glue_create_qp,
> >  	.create_qp_ex = mlx5_glue_create_qp_ex,
> >  	.destroy_qp = mlx5_glue_destroy_qp,
> > @@ -437,4 +473,6 @@
> >  	.dv_create_flow_matcher = mlx5_glue_dv_create_flow_matcher,
> >  	.dv_destroy_flow_matcher = mlx5_glue_dv_destroy_flow_matcher,
> >  	.dv_create_flow = mlx5_glue_dv_create_flow,
> > +	.dv_create_flow_action_packet_reformat =
> > +
> 	mlx5_glue_dv_create_flow_action_packet_reformat,
> >  };
> > diff --git a/drivers/net/mlx5/mlx5_glue.h
> > b/drivers/net/mlx5/mlx5_glue.h index f6e4e38..071a650 100644
> > --- a/drivers/net/mlx5/mlx5_glue.h
> > +++ b/drivers/net/mlx5/mlx5_glue.h
> > @@ -46,6 +46,12 @@
> >  struct mlx5dv_flow_match_parameters;
> >  #endif
> >
> > +#ifndef HAVE_IBV_FLOW_ACTION_DV_SUPPORT struct ibv_flow_action;
> enum
> > +mlx5dv_flow_action_packet_reformat_type { type = 0, }; enum
> > +mlx5dv_flow_table_type { type = 0, };
> 
> This part still has an error.
> 
> 	In file included from ../drivers/net/mlx5/mlx5_rxq.c:38:0:
> 	../drivers/net/mlx5/mlx5_glue.h:55:2: error: redeclaration of
> enumerator ‘type’
> 	  type = 0,
> 	  ^
> 	../drivers/net/mlx5/mlx5_glue.h:52:2: note: previous definition of
> ‘type’
> 	was here
> 	  type = 0,
> 	  ^
> 

Fixed.

> You should've used different names. However, I have another suggestion.
> Let me speak with you offline.
> 
> Thanks,
> Yongseok
> 
> > +#endif
> > +
> >  /* LIB_GLUE_VERSION must be updated every time this structure is
> > modified. */  struct mlx5_glue {
> >  	const char *version;
> > @@ -85,6 +91,7 @@ struct mlx5_glue {
> >  	struct ibv_flow *(*create_flow)(struct ibv_qp *qp,
> >  					struct ibv_flow_attr *flow);
> >  	int (*destroy_flow)(struct ibv_flow *flow_id);
> > +	int (*destroy_flow_action)(struct ibv_flow_action *action);
> >  	struct ibv_qp *(*create_qp)(struct ibv_pd *pd,
> >  				    struct ibv_qp_init_attr *qp_init_attr);
> >  	struct ibv_qp *(*create_qp_ex)
> > @@ -137,6 +144,12 @@ struct mlx5_glue {
> >  			  struct mlx5dv_flow_match_parameters
> *match_value,
> >  			  size_t num_actions,
> >  			  struct mlx5dv_flow_action_attr *actions_attr);
> > +	struct ibv_flow_action *(*dv_create_flow_action_packet_reformat)
> > +		(struct ibv_context *ctx,
> > +		 size_t data_sz,
> > +		 void *data,
> > +		 enum mlx5dv_flow_action_packet_reformat_type
> reformat_type,
> > +		 enum mlx5dv_flow_table_type ft_type);
> >  };
> >
> >  const struct mlx5_glue *mlx5_glue;
> > --
> > 1.8.3.1
> >

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

* [dpdk-dev] [PATCH v4 0/4] add support of Direct Verbs encap and decap actions
  2018-10-09 19:25   ` [dpdk-dev] [PATCH v3 " Dekel Peled
@ 2018-10-10  8:35     ` Dekel Peled
  2018-10-11 12:12       ` [dpdk-dev] [PATCH v5 " Dekel Peled
                         ` (4 more replies)
  2018-10-10  8:35     ` [dpdk-dev] [PATCH v4 1/4] net/mlx5: add flow action functions to glue Dekel Peled
                       ` (3 subsequent siblings)
  4 siblings, 5 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-10  8:35 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This series adds support of encap and decap actions in DV format.
It is using the generic encapsulation framework from [1].
Note that encap action is relevant for egress only.
Hence this series should be merged on top of [2].

[1] "ethdev: add generic L2/L3 tunnel encapsulation actions"
    http://mails.dpdk.org/archives/dev/2018-October/114654.html
[2] "net/mlx5: allow flow rule with attribute egress"
    http://mails.dpdk.org/archives/dev/2018-October/114658.html

---
v4:
* Update in glue functions.
---
v3:
* Apply additional code review comments.
---
v2:
* Rebase on tip.
* Apply code review comments.
---

Dekel Peled (4):
  net/mlx5: add flow action functions to glue
  net/mlx5: add Direct Verbs encap and decap defs
  net/mlx5: add L2 and L3 encap to Direct Verbs flow
  net/mlx5: add L2 and L3 decap to Direct Verbs flow

 drivers/net/mlx5/Makefile       |   5 +
 drivers/net/mlx5/meson.build    |   2 +
 drivers/net/mlx5/mlx5_flow.c    |   8 +
 drivers/net/mlx5/mlx5_flow.h    |   6 +
 drivers/net/mlx5/mlx5_flow_dv.c | 442 +++++++++++++++++++++++++++++++++++++++-
 drivers/net/mlx5/mlx5_glue.c    |  38 ++++
 drivers/net/mlx5/mlx5_glue.h    |  13 ++
 7 files changed, 509 insertions(+), 5 deletions(-)

-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v4 1/4] net/mlx5: add flow action functions to glue
  2018-10-09 19:25   ` [dpdk-dev] [PATCH v3 " Dekel Peled
  2018-10-10  8:35     ` [dpdk-dev] [PATCH v4 " Dekel Peled
@ 2018-10-10  8:35     ` Dekel Peled
  2018-10-10 21:22       ` Yongseok Koh
  2018-10-10  8:35     ` [dpdk-dev] [PATCH v4 2/4] net/mlx5: add Direct Verbs encap and decap defs Dekel Peled
                       ` (2 subsequent siblings)
  4 siblings, 1 reply; 94+ messages in thread
From: Dekel Peled @ 2018-10-10  8:35 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch adds glue functions for operations:
- Create packet reformat (encap/decap) flow action.
- Destroy flow action.

The new operations depend on HAVE_IBV_FLOW_ACTION_DV_SUPPORT.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/Makefile    |  5 +++++
 drivers/net/mlx5/meson.build |  2 ++
 drivers/net/mlx5/mlx5_glue.c | 38 ++++++++++++++++++++++++++++++++++++++
 drivers/net/mlx5/mlx5_glue.h | 13 +++++++++++++
 4 files changed, 58 insertions(+)

diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile
index 92bae9d..474ad42 100644
--- a/drivers/net/mlx5/Makefile
+++ b/drivers/net/mlx5/Makefile
@@ -142,6 +142,11 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh
 		enum MLX5DV_FLOW_ACTION_TAG \
 		$(AUTOCONF_OUTPUT)
 	$Q sh -- '$<' '$@' \
+		HAVE_IBV_FLOW_ACTION_DV_SUPPORT \
+		infiniband/mlx5dv.h \
+		func mlx5dv_create_flow_action_packet_reformat \
+		$(AUTOCONF_OUTPUT)
+	$Q sh -- '$<' '$@' \
 		HAVE_ETHTOOL_LINK_MODE_25G \
 		/usr/include/linux/ethtool.h \
 		enum ETHTOOL_LINK_MODE_25000baseCR_Full_BIT \
diff --git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build
index 6966248..d555c3c 100644
--- a/drivers/net/mlx5/meson.build
+++ b/drivers/net/mlx5/meson.build
@@ -96,6 +96,8 @@ if build
 		'MLX5DV_CONTEXT_FLAGS_CQE_128B_COMP' ],
 		[ 'HAVE_IBV_FLOW_DV_SUPPORT', 'infiniband/mlx5dv.h',
 		'MLX5DV_FLOW_ACTION_TAG' ],
+		[ 'HAVE_IBV_FLOW_ACTION_DV_SUPPORT', 'infiniband/mlx5dv.h',
+		'mlx5dv_create_flow_action_packet_reformat' ],
 		[ 'HAVE_IBV_DEVICE_MPLS_SUPPORT', 'infiniband/verbs.h',
 		'IBV_FLOW_SPEC_MPLS' ],
 		[ 'HAVE_IBV_WQ_FLAG_RX_END_PADDING', 'infiniband/verbs.h',
diff --git a/drivers/net/mlx5/mlx5_glue.c b/drivers/net/mlx5/mlx5_glue.c
index 48590df..c9b747e 100644
--- a/drivers/net/mlx5/mlx5_glue.c
+++ b/drivers/net/mlx5/mlx5_glue.c
@@ -174,6 +174,17 @@
 	return ibv_destroy_flow(flow_id);
 }
 
+static int
+mlx5_glue_destroy_flow_action(struct ibv_flow_action *action)
+{
+#ifdef HAVE_IBV_FLOW_ACTION_DV_SUPPORT
+	return ibv_destroy_flow_action(action);
+#else
+	(void)action;
+	return ENOTSUP;
+#endif
+}
+
 static struct ibv_qp *
 mlx5_glue_create_qp(struct ibv_pd *pd, struct ibv_qp_init_attr *qp_init_attr)
 {
@@ -388,6 +399,30 @@
 #endif
 }
 
+static struct ibv_flow_action *
+mlx5_glue_dv_create_flow_action_packet_reformat
+		(struct ibv_context *ctx,
+		 size_t data_sz,
+		 void *data,
+		 enum mlx5dv_flow_action_packet_reformat_type reformat_type,
+		 enum mlx5dv_flow_table_type ft_type)
+{
+#ifdef HAVE_IBV_FLOW_ACTION_DV_SUPPORT
+	return mlx5dv_create_flow_action_packet_reformat(ctx,
+							 data_sz,
+							 data,
+							 reformat_type,
+							 ft_type);
+#else
+	(void)ctx;
+	(void)data_sz;
+	(void)data;
+	(void)reformat_type;
+	(void)ft_type;
+	return NULL;
+#endif
+}
+
 alignas(RTE_CACHE_LINE_SIZE)
 const struct mlx5_glue *mlx5_glue = &(const struct mlx5_glue){
 	.version = MLX5_GLUE_VERSION,
@@ -414,6 +449,7 @@
 	.modify_wq = mlx5_glue_modify_wq,
 	.create_flow = mlx5_glue_create_flow,
 	.destroy_flow = mlx5_glue_destroy_flow,
+	.destroy_flow_action = mlx5_glue_destroy_flow_action,
 	.create_qp = mlx5_glue_create_qp,
 	.create_qp_ex = mlx5_glue_create_qp_ex,
 	.destroy_qp = mlx5_glue_destroy_qp,
@@ -437,4 +473,6 @@
 	.dv_create_flow_matcher = mlx5_glue_dv_create_flow_matcher,
 	.dv_destroy_flow_matcher = mlx5_glue_dv_destroy_flow_matcher,
 	.dv_create_flow = mlx5_glue_dv_create_flow,
+	.dv_create_flow_action_packet_reformat =
+			mlx5_glue_dv_create_flow_action_packet_reformat,
 };
diff --git a/drivers/net/mlx5/mlx5_glue.h b/drivers/net/mlx5/mlx5_glue.h
index f6e4e38..dce6bb4 100644
--- a/drivers/net/mlx5/mlx5_glue.h
+++ b/drivers/net/mlx5/mlx5_glue.h
@@ -46,6 +46,12 @@
 struct mlx5dv_flow_match_parameters;
 #endif
 
+#ifndef HAVE_IBV_FLOW_ACTION_DV_SUPPORT
+struct ibv_flow_action;
+enum mlx5dv_flow_action_packet_reformat_type { packet_reformat_type = 0, };
+enum mlx5dv_flow_table_type { flow_table_type = 0, };
+#endif
+
 /* LIB_GLUE_VERSION must be updated every time this structure is modified. */
 struct mlx5_glue {
 	const char *version;
@@ -85,6 +91,7 @@ struct mlx5_glue {
 	struct ibv_flow *(*create_flow)(struct ibv_qp *qp,
 					struct ibv_flow_attr *flow);
 	int (*destroy_flow)(struct ibv_flow *flow_id);
+	int (*destroy_flow_action)(struct ibv_flow_action *action);
 	struct ibv_qp *(*create_qp)(struct ibv_pd *pd,
 				    struct ibv_qp_init_attr *qp_init_attr);
 	struct ibv_qp *(*create_qp_ex)
@@ -137,6 +144,12 @@ struct mlx5_glue {
 			  struct mlx5dv_flow_match_parameters *match_value,
 			  size_t num_actions,
 			  struct mlx5dv_flow_action_attr *actions_attr);
+	struct ibv_flow_action *(*dv_create_flow_action_packet_reformat)
+		(struct ibv_context *ctx,
+		 size_t data_sz,
+		 void *data,
+		 enum mlx5dv_flow_action_packet_reformat_type reformat_type,
+		 enum mlx5dv_flow_table_type ft_type);
 };
 
 const struct mlx5_glue *mlx5_glue;
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v4 2/4] net/mlx5: add Direct Verbs encap and decap defs
  2018-10-09 19:25   ` [dpdk-dev] [PATCH v3 " Dekel Peled
  2018-10-10  8:35     ` [dpdk-dev] [PATCH v4 " Dekel Peled
  2018-10-10  8:35     ` [dpdk-dev] [PATCH v4 1/4] net/mlx5: add flow action functions to glue Dekel Peled
@ 2018-10-10  8:35     ` Dekel Peled
  2018-10-10  8:35     ` [dpdk-dev] [PATCH v4 3/4] net/mlx5: add L2 and L3 encap to Direct Verbs flow Dekel Peled
  2018-10-10  8:35     ` [dpdk-dev] [PATCH v4 4/4] net/mlx5: add L2 and L3 decap " Dekel Peled
  4 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-10  8:35 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch adds the required definitions for DV encap/decap actions.
It also adds usage of the new actions definition in validation
function of existing drop operation.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
Acked-by: Yongseok Koh <yskoh@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow.c | 8 ++++++++
 drivers/net/mlx5/mlx5_flow.h | 6 ++++++
 2 files changed, 14 insertions(+)

diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 1087f67..b452e11 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -766,6 +766,14 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't have 2 fate actions in"
 					  " same flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
+			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3 |
+			    MLX5_FLOW_ACTION_TUNNEL_ENCAP |
+			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't encap or decap and drop in"
+					  " same flow");
 	if (attr->egress)
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 690c597..01c73a2 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -82,6 +82,10 @@
 #define MLX5_FLOW_ACTION_OF_SET_VLAN_VID (1u << 9)
 #define MLX5_FLOW_ACTION_OF_SET_VLAN_PCP (1u << 10)
 #define MLX5_FLOW_ACTION_JUMP (1u << 11)
+#define MLX5_FLOW_ACTION_TUNNEL_ENCAP (1u << 12)
+#define MLX5_FLOW_ACTION_TUNNEL_DECAP (1u << 13)
+#define MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3 (1u << 14)
+#define MLX5_FLOW_ACTION_TUNNEL_DECAP_L3 (1u << 15)
 
 #define MLX5_FLOW_FATE_ACTIONS \
 	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS)
@@ -172,6 +176,8 @@ struct mlx5_flow_dv {
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
 	struct mlx5dv_flow_action_attr actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS];
 	/**< Action list. */
+	struct ibv_flow_action *encap_verb; /**< Verbs object of encap. */
+	struct ibv_flow_action *decap_verb; /**< Verbs object of decap. */
 #endif
 	int actions_n; /**< number of actions. */
 };
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v4 3/4] net/mlx5: add L2 and L3 encap to Direct Verbs flow
  2018-10-09 19:25   ` [dpdk-dev] [PATCH v3 " Dekel Peled
                       ` (2 preceding siblings ...)
  2018-10-10  8:35     ` [dpdk-dev] [PATCH v4 2/4] net/mlx5: add Direct Verbs encap and decap defs Dekel Peled
@ 2018-10-10  8:35     ` Dekel Peled
  2018-10-10  8:35     ` [dpdk-dev] [PATCH v4 4/4] net/mlx5: add L2 and L3 decap " Dekel Peled
  4 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-10  8:35 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch adds support for Direct Verbs encap operations, L2 and L3.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
Acked-by: Yongseok Koh <yskoh@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow_dv.c | 227 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 222 insertions(+), 5 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 80e7b24..73a22ba 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -84,6 +84,168 @@
 }
 
 /**
+ * Validate the tunnel encap action.
+ *
+ * @param[in] action_flags
+ *   holds the actions detected until now.
+ * @param[in] action
+ *   Pointer to the encap action.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_ernno is set.
+ */
+static int
+flow_dv_validate_action_tunnel_encap(uint64_t action_flags,
+				     const struct rte_flow_action *action,
+				     const struct rte_flow_attr *attr,
+				     struct rte_flow_error *error)
+{
+	const struct rte_flow_action_tunnel_encap *tunnel_encap = action->conf;
+
+	if (!tunnel_encap || !(tunnel_encap->buf))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, action,
+					  "configuration cannot be null");
+	if (action_flags & MLX5_FLOW_ACTION_DROP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't drop and encap in same flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP |
+			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't have 2 encap actions in same"
+					  " flow");
+	if (attr->ingress)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
+					  NULL,
+					  "encap action not supported for "
+					  "ingress");
+	return 0;
+}
+
+/**
+ * Validate the tunnel encap L3 action
+ *
+ * @param[in] action_flags
+ *   holds the actions detected until now.
+ * @param[in] action
+ *   Pointer to the encap action.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_ernno is set.
+ */
+static int
+flow_dv_validate_action_tunnel_encap_l3(uint64_t action_flags,
+					const struct rte_flow_action *action,
+					const struct rte_flow_attr *attr,
+					struct rte_flow_error *error)
+{
+	const struct rte_flow_action_tunnel_encap_l3 *tunnel_encap_l3 =
+			action->conf;
+
+	if (!tunnel_encap_l3 || !(tunnel_encap_l3->buf))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, action,
+					  "configuration cannot be null");
+	if (action_flags & MLX5_FLOW_ACTION_DROP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't drop and encap in same flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP |
+			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't have 2 encap actions in same"
+					  " flow");
+	if (attr->ingress)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
+					  NULL,
+					  "encap action not supported for "
+					  "ingress");
+	return 0;
+}
+
+/**
+ * Convert encap action to DV specification.
+ *
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[in] action
+ *   Pointer to action structure.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+flow_dv_create_encap(struct rte_eth_dev *dev,
+		     const struct rte_flow_action *action,
+		     struct rte_flow_error *error)
+{
+	struct ibv_flow_action *encap_verb = NULL;
+	const struct rte_flow_action_tunnel_encap *encap_data;
+	struct priv *priv = dev->data->dev_private;
+
+	encap_data = (const struct rte_flow_action_tunnel_encap *)action->conf;
+	encap_verb = mlx5_glue->dv_create_flow_action_packet_reformat
+		(priv->ctx, encap_data->size,
+		 encap_data->size ? encap_data->buf : NULL,
+		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
+		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
+	if (!encap_verb)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create encap action");
+	return encap_verb;
+}
+
+/**
+ * Convert encap L3 action to DV specification.
+ *
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[in] action
+ *   Pointer to action structure.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+flow_dv_create_encap_l3(struct rte_eth_dev *dev,
+			const struct rte_flow_action *action,
+			struct rte_flow_error *error)
+{
+	struct ibv_flow_action *encap_l3_verb = NULL;
+	const struct rte_flow_action_tunnel_encap_l3 *encap_l3_data;
+	struct priv *priv = dev->data->dev_private;
+
+	encap_l3_data =
+		(const struct rte_flow_action_tunnel_encap_l3 *)action->conf;
+	encap_l3_verb = mlx5_glue->dv_create_flow_action_packet_reformat
+		(priv->ctx, encap_l3_data->size,
+		 encap_l3_data->size ? encap_l3_data->buf : NULL,
+		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL,
+		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
+	if (!encap_l3_verb)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create encap L3 action");
+	return encap_l3_verb;
+}
+
+/**
  * Verify the @p attributes will be correctly understood by the NIC and store
  * them in the @p flow if everything is correct.
  *
@@ -330,6 +492,20 @@
 			action_flags |= MLX5_FLOW_ACTION_COUNT;
 			++actions_n;
 			break;
+		case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP:
+			ret = flow_dv_validate_action_tunnel_encap
+				(action_flags, actions, attr, error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_TUNNEL_ENCAP;
+			break;
+		case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP_L3:
+			ret = flow_dv_validate_action_tunnel_encap_l3
+				(action_flags, actions, attr, error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3;
+			break;
 		default:
 			return rte_flow_error_set(error, ENOTSUP,
 						  RTE_FLOW_ERROR_TYPE_ACTION,
@@ -1038,14 +1214,23 @@
 /**
  * Store the requested actions in an array.
  *
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
  * @param[in] action
  *   Flow action to translate.
  * @param[in, out] dev_flow
  *   Pointer to the mlx5_flow.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_ernno is set.
  */
-static void
-flow_dv_create_action(const struct rte_flow_action *action,
-		      struct mlx5_flow *dev_flow)
+static int
+flow_dv_create_action(struct rte_eth_dev *dev,
+		      const struct rte_flow_action *action,
+		      struct mlx5_flow *dev_flow,
+		      struct rte_flow_error *error)
 {
 	const struct rte_flow_action_queue *queue;
 	const struct rte_flow_action_rss *rss;
@@ -1092,10 +1277,35 @@
 		/* Added to array only in apply since we need the QP */
 		flow->actions |= MLX5_FLOW_ACTION_RSS;
 		break;
+	case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP:
+		dev_flow->dv.actions[actions_n].type =
+			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+		dev_flow->dv.actions[actions_n].action =
+			flow_dv_create_encap(dev, action, error);
+		if (!(dev_flow->dv.actions[actions_n].action))
+			return -rte_errno;
+		dev_flow->dv.encap_verb =
+			dev_flow->dv.actions[actions_n].action;
+		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_ENCAP;
+		actions_n++;
+		break;
+	case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP_L3:
+		dev_flow->dv.actions[actions_n].type =
+			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+		dev_flow->dv.actions[actions_n].action =
+			flow_dv_create_encap_l3(dev, action, error);
+		if (!(dev_flow->dv.actions[actions_n].action))
+			return -rte_errno;
+		dev_flow->dv.encap_verb =
+			dev_flow->dv.actions[actions_n].action;
+		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3;
+		actions_n++;
+		break;
 	default:
 		break;
 	}
 	dev_flow->dv.actions_n = actions_n;
+	return 0;
 }
 
 static uint32_t matcher_zero[MLX5_ST_SZ_DW(fte_match_param)] = { 0 };
@@ -1259,8 +1469,10 @@
 	matcher.egress = attr->egress;
 	if (flow_dv_matcher_register(dev, &matcher, dev_flow, error))
 		return -rte_errno;
-	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++)
-		flow_dv_create_action(actions, dev_flow);
+	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
+		if (flow_dv_create_action(dev, actions, dev_flow, error))
+			return -rte_errno;
+	}
 	return 0;
 }
 
@@ -1444,6 +1656,11 @@
 		LIST_REMOVE(dev_flow, next);
 		if (dev_flow->dv.matcher)
 			flow_dv_matcher_release(dev, dev_flow->dv.matcher);
+		if (dev_flow->dv.encap_verb) {
+			claim_zero(mlx5_glue->destroy_flow_action
+						(dev_flow->dv.encap_verb));
+			dev_flow->dv.encap_verb = NULL;
+		}
 		rte_free(dev_flow);
 	}
 }
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v4 4/4] net/mlx5: add L2 and L3 decap to Direct Verbs flow
  2018-10-09 19:25   ` [dpdk-dev] [PATCH v3 " Dekel Peled
                       ` (3 preceding siblings ...)
  2018-10-10  8:35     ` [dpdk-dev] [PATCH v4 3/4] net/mlx5: add L2 and L3 encap to Direct Verbs flow Dekel Peled
@ 2018-10-10  8:35     ` Dekel Peled
  4 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-10  8:35 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch adds support for Direct Verbs decap operations, L2 and L3.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
Acked-by: Yongseok Koh <yskoh@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow_dv.c | 215 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 215 insertions(+)

diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 73a22ba..d4ff812 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -120,6 +120,12 @@
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't have 2 encap actions in same"
 					  " flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
+			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't encap and decap in same"
+					  " flow");
 	if (attr->ingress)
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
@@ -167,6 +173,12 @@
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't have 2 encap actions in same"
 					  " flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
+			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't encap and decap in same"
+					  " flow");
 	if (attr->ingress)
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
@@ -177,6 +189,100 @@
 }
 
 /**
+ * Validate the tunnel decap action
+ *
+ * @param[in] action_flags
+ *   holds the actions detected until now.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_ernno is set.
+ */
+static int
+flow_dv_validate_action_tunnel_decap(uint64_t action_flags,
+				     const struct rte_flow_attr *attr,
+				     struct rte_flow_error *error)
+{
+	if (action_flags & MLX5_FLOW_ACTION_DROP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't drop and decap in same flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
+			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't have 2 decap actions in same"
+					  " flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP |
+			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't encap and decap in same"
+					  " flow");
+	if (attr->egress)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
+					  "decap action not supported for "
+					  "egress");
+	return 0;
+}
+
+/**
+ * Validate the tunnel decap L3 action
+ *
+ * @param[in] action_flags
+ *   holds the actions detected until now.
+ * @param[in] action
+ *   Pointer to the decap action.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_ernno is set.
+ */
+static int
+flow_dv_validate_action_tunnel_decap_l3(uint64_t action_flags,
+					const struct rte_flow_action *action,
+					const struct rte_flow_attr *attr,
+					struct rte_flow_error *error)
+{
+	const struct rte_flow_action_tunnel_decap_l3 *tunnel_decap_l3 =
+			action->conf;
+
+	if (!tunnel_decap_l3 || !(tunnel_decap_l3->buf))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, action,
+					  "configuration cannot be null");
+	if (action_flags & MLX5_FLOW_ACTION_DROP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't drop and decap in same flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
+			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't have 2 decap actions in same"
+					  " flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP |
+			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't encap and decap in same"
+					  " flow");
+	if (attr->egress)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
+					  "decap action not supported for "
+					  "egress");
+	return 0;
+}
+
+/**
  * Convert encap action to DV specification.
  *
  * @param[in] dev
@@ -246,6 +352,72 @@
 }
 
 /**
+ * Convert decap action to DV specification.
+ *
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[in] action
+ *   Pointer to action structure.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+flow_dv_create_decap(struct rte_eth_dev *dev,
+		     const struct rte_flow_action *action __rte_unused,
+		     struct rte_flow_error *error)
+{
+	struct ibv_flow_action *decap_verb = NULL;
+	struct priv *priv = dev->data->dev_private;
+
+	decap_verb = mlx5_glue->dv_create_flow_action_packet_reformat
+		(priv->ctx, 0, NULL,
+		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2,
+		 MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
+	if (!decap_verb)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create decap action");
+	return decap_verb;
+}
+
+/**
+ * Convert decap L3 action to DV specification.
+ *
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[in] action
+ *   Pointer to action structure.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+flow_dv_create_decap_l3(struct rte_eth_dev *dev,
+			const struct rte_flow_action *action,
+			struct rte_flow_error *error)
+{
+	struct ibv_flow_action *decap_l3_verb = NULL;
+	const struct rte_flow_action_tunnel_decap_l3 *decap_l3_data;
+	struct priv *priv = dev->data->dev_private;
+
+	decap_l3_data =
+		(const struct rte_flow_action_tunnel_decap_l3 *)action->conf;
+	decap_l3_verb = mlx5_glue->dv_create_flow_action_packet_reformat
+		(priv->ctx, decap_l3_data->size,
+		 decap_l3_data->size ? decap_l3_data->buf : NULL,
+		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2,
+		 MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
+	if (!decap_l3_verb)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create decap L3 action");
+	return decap_l3_verb;
+}
+
+/**
  * Verify the @p attributes will be correctly understood by the NIC and store
  * them in the @p flow if everything is correct.
  *
@@ -506,6 +678,20 @@
 				return ret;
 			action_flags |= MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3;
 			break;
+		case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP:
+			ret = flow_dv_validate_action_tunnel_decap
+				(action_flags, attr, error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_TUNNEL_DECAP;
+			break;
+		case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP_L3:
+			ret = flow_dv_validate_action_tunnel_decap_l3
+				(action_flags, actions, attr, error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_TUNNEL_DECAP_L3;
+			break;
 		default:
 			return rte_flow_error_set(error, ENOTSUP,
 						  RTE_FLOW_ERROR_TYPE_ACTION,
@@ -1301,6 +1487,30 @@
 		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3;
 		actions_n++;
 		break;
+	case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP:
+		dev_flow->dv.actions[actions_n].type =
+			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+		dev_flow->dv.actions[actions_n].action =
+			flow_dv_create_decap(dev, action, error);
+		if (!(dev_flow->dv.actions[actions_n].action))
+			return -rte_errno;
+		dev_flow->dv.decap_verb =
+			dev_flow->dv.actions[actions_n].action;
+		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_DECAP;
+		actions_n++;
+		break;
+	case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP_L3:
+		dev_flow->dv.actions[actions_n].type =
+			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+		dev_flow->dv.actions[actions_n].action =
+			flow_dv_create_decap_l3(dev, action, error);
+		if (!(dev_flow->dv.actions[actions_n].action))
+			return -rte_errno;
+		dev_flow->dv.decap_verb =
+			dev_flow->dv.actions[actions_n].action;
+		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_DECAP_L3;
+		actions_n++;
+		break;
 	default:
 		break;
 	}
@@ -1661,6 +1871,11 @@
 						(dev_flow->dv.encap_verb));
 			dev_flow->dv.encap_verb = NULL;
 		}
+		if (dev_flow->dv.decap_verb) {
+			claim_zero(mlx5_glue->destroy_flow_action
+						(dev_flow->dv.decap_verb));
+			dev_flow->dv.decap_verb = NULL;
+		}
 		rte_free(dev_flow);
 	}
 }
-- 
1.8.3.1

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

* Re: [dpdk-dev] [PATCH v4 1/4] net/mlx5: add flow action functions to glue
  2018-10-10  8:35     ` [dpdk-dev] [PATCH v4 1/4] net/mlx5: add flow action functions to glue Dekel Peled
@ 2018-10-10 21:22       ` Yongseok Koh
  0 siblings, 0 replies; 94+ messages in thread
From: Yongseok Koh @ 2018-10-10 21:22 UTC (permalink / raw)
  To: Dekel Peled; +Cc: Shahaf Shuler, dev, Ori Kam

On Wed, Oct 10, 2018 at 11:35:28AM +0300, Dekel Peled wrote:
> This patch adds glue functions for operations:
> - Create packet reformat (encap/decap) flow action.
> - Destroy flow action.
> 
> The new operations depend on HAVE_IBV_FLOW_ACTION_DV_SUPPORT.
> 
> Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> ---
>  drivers/net/mlx5/Makefile    |  5 +++++
>  drivers/net/mlx5/meson.build |  2 ++
>  drivers/net/mlx5/mlx5_glue.c | 38 ++++++++++++++++++++++++++++++++++++++
>  drivers/net/mlx5/mlx5_glue.h | 13 +++++++++++++
>  4 files changed, 58 insertions(+)
> 
> diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile
> index 92bae9d..474ad42 100644
> --- a/drivers/net/mlx5/Makefile
> +++ b/drivers/net/mlx5/Makefile
> @@ -142,6 +142,11 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh
>  		enum MLX5DV_FLOW_ACTION_TAG \
>  		$(AUTOCONF_OUTPUT)
>  	$Q sh -- '$<' '$@' \
> +		HAVE_IBV_FLOW_ACTION_DV_SUPPORT \
> +		infiniband/mlx5dv.h \
> +		func mlx5dv_create_flow_action_packet_reformat \
> +		$(AUTOCONF_OUTPUT)

I thought you also added this macro to the code in mlx5_flow_dv.c but you
didn't. My original concern was about a case where DV is supported
(HAVE_IBV_FLOW_DV_SUPPORT) but the new flow action
(HAVE_IBV_FLOW_ACTION_DV_SUPPORT) isn't supported. Your code won't be compiled
in such a chase.

There's one more option to consider, which is much simpler. You can change the
HAVE_IBV_FLOW_DV_SUPPORT to check the new function.

	$Q sh -- '$<' '$@' \
		HAVE_IBV_FLOW_DV_SUPPORT \
		infiniband/mlx5dv.h \
		func mlx5dv_create_flow_action_packet_reformat \
		$(AUTOCONF_OUTPUT)

If we don't need to support two different versions of library, (or there could
be only one version supporting both), it isn't necessary to have two separate
macros. Let's take it offline to talk to lib/ker team.


Thanks,
Yongseok

> +	$Q sh -- '$<' '$@' \
>  		HAVE_ETHTOOL_LINK_MODE_25G \
>  		/usr/include/linux/ethtool.h \
>  		enum ETHTOOL_LINK_MODE_25000baseCR_Full_BIT \
> diff --git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build
> index 6966248..d555c3c 100644
> --- a/drivers/net/mlx5/meson.build
> +++ b/drivers/net/mlx5/meson.build
> @@ -96,6 +96,8 @@ if build
>  		'MLX5DV_CONTEXT_FLAGS_CQE_128B_COMP' ],
>  		[ 'HAVE_IBV_FLOW_DV_SUPPORT', 'infiniband/mlx5dv.h',
>  		'MLX5DV_FLOW_ACTION_TAG' ],
> +		[ 'HAVE_IBV_FLOW_ACTION_DV_SUPPORT', 'infiniband/mlx5dv.h',
> +		'mlx5dv_create_flow_action_packet_reformat' ],
>  		[ 'HAVE_IBV_DEVICE_MPLS_SUPPORT', 'infiniband/verbs.h',
>  		'IBV_FLOW_SPEC_MPLS' ],
>  		[ 'HAVE_IBV_WQ_FLAG_RX_END_PADDING', 'infiniband/verbs.h',

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

* [dpdk-dev] [PATCH v5 0/4] add support of Direct Verbs encap and decap actions
  2018-10-10  8:35     ` [dpdk-dev] [PATCH v4 " Dekel Peled
@ 2018-10-11 12:12       ` Dekel Peled
  2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 0/6] add encap and decap actions to Direct Verbs flow in MLX5 PMD Dekel Peled
                           ` (6 more replies)
  2018-10-11 12:12       ` [dpdk-dev] [PATCH v5 1/4] net/mlx5: add flow action functions to glue Dekel Peled
                         ` (3 subsequent siblings)
  4 siblings, 7 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-11 12:12 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This series adds support of encap and decap actions in DV format.
It is using the generic encapsulation framework from [1].
Note that encap action is relevant for egress only.
Hence this series should be merged on top of [2].

[1] "ethdev: add generic L2/L3 tunnel encapsulation actions"
	http://mails.dpdk.org/archives/dev/2018-October/114654.html
[2] "net/mlx5: allow flow rule with attribute egress"
	http://mails.dpdk.org/archives/dev/2018-October/114658.html
	
---
v5:
* Move DV actions code under common DV flag.
v4:
* Update in glue functions.
v3:
* Apply additional code review comments.
v2:
* Rebase on tip.
* Apply code review comments.
---

Dekel Peled (4):
  net/mlx5: add flow action functions to glue
  net/mlx5: add Direct Verbs encap and decap defs
  net/mlx5: add L2 and L3 encap to Direct Verbs flow
  net/mlx5: add L2 and L3 decap to Direct Verbs flow

 drivers/net/mlx5/Makefile       |   2 +-
 drivers/net/mlx5/meson.build    |   2 +-
 drivers/net/mlx5/mlx5_flow.c    |   8 +
 drivers/net/mlx5/mlx5_flow.h    |   6 +
 drivers/net/mlx5/mlx5_flow_dv.c | 442 +++++++++++++++++++++++++++++++++++++++-
 drivers/net/mlx5/mlx5_glue.c    |  38 ++++
 drivers/net/mlx5/mlx5_glue.h    |  10 +
 7 files changed, 501 insertions(+), 7 deletions(-)

-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v5 1/4] net/mlx5: add flow action functions to glue
  2018-10-10  8:35     ` [dpdk-dev] [PATCH v4 " Dekel Peled
  2018-10-11 12:12       ` [dpdk-dev] [PATCH v5 " Dekel Peled
@ 2018-10-11 12:12       ` Dekel Peled
  2018-10-11 17:05         ` Yongseok Koh
  2018-10-11 12:12       ` [dpdk-dev] [PATCH v5 2/4] net/mlx5: add Direct Verbs encap and decap defs Dekel Peled
                         ` (2 subsequent siblings)
  4 siblings, 1 reply; 94+ messages in thread
From: Dekel Peled @ 2018-10-11 12:12 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch adds glue functions for operations:
- Create packet reformat (encap/decap) flow action.
- Destroy flow action.

The new operations depend on HAVE_IBV_FLOW_DV_SUPPORT.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/Makefile    |  2 +-
 drivers/net/mlx5/meson.build |  2 +-
 drivers/net/mlx5/mlx5_glue.c | 38 ++++++++++++++++++++++++++++++++++++++
 drivers/net/mlx5/mlx5_glue.h | 10 ++++++++++
 4 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile
index 92bae9d..bbfb686 100644
--- a/drivers/net/mlx5/Makefile
+++ b/drivers/net/mlx5/Makefile
@@ -139,7 +139,7 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh
 	$Q sh -- '$<' '$@' \
 		HAVE_IBV_FLOW_DV_SUPPORT \
 		infiniband/mlx5dv.h \
-		enum MLX5DV_FLOW_ACTION_TAG \
+		func mlx5dv_create_flow_action_packet_reformat \
 		$(AUTOCONF_OUTPUT)
 	$Q sh -- '$<' '$@' \
 		HAVE_ETHTOOL_LINK_MODE_25G \
diff --git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build
index 6966248..c93347c 100644
--- a/drivers/net/mlx5/meson.build
+++ b/drivers/net/mlx5/meson.build
@@ -95,7 +95,7 @@ if build
 		[ 'HAVE_IBV_MLX5_MOD_CQE_128B_COMP', 'infiniband/mlx5dv.h',
 		'MLX5DV_CONTEXT_FLAGS_CQE_128B_COMP' ],
 		[ 'HAVE_IBV_FLOW_DV_SUPPORT', 'infiniband/mlx5dv.h',
-		'MLX5DV_FLOW_ACTION_TAG' ],
+		'mlx5dv_create_flow_action_packet_reformat' ],
 		[ 'HAVE_IBV_DEVICE_MPLS_SUPPORT', 'infiniband/verbs.h',
 		'IBV_FLOW_SPEC_MPLS' ],
 		[ 'HAVE_IBV_WQ_FLAG_RX_END_PADDING', 'infiniband/verbs.h',
diff --git a/drivers/net/mlx5/mlx5_glue.c b/drivers/net/mlx5/mlx5_glue.c
index 48590df..565c2cf 100644
--- a/drivers/net/mlx5/mlx5_glue.c
+++ b/drivers/net/mlx5/mlx5_glue.c
@@ -174,6 +174,17 @@
 	return ibv_destroy_flow(flow_id);
 }
 
+static int
+mlx5_glue_destroy_flow_action(struct ibv_flow_action *action)
+{
+#ifdef HAVE_IBV_FLOW_DV_SUPPORT
+	return ibv_destroy_flow_action(action);
+#else
+	(void)action;
+	return -ENOTSUP;
+#endif
+}
+
 static struct ibv_qp *
 mlx5_glue_create_qp(struct ibv_pd *pd, struct ibv_qp_init_attr *qp_init_attr)
 {
@@ -388,6 +399,30 @@
 #endif
 }
 
+static struct ibv_flow_action *
+mlx5_glue_dv_create_flow_action_packet_reformat
+		(struct ibv_context *ctx,
+		 size_t data_sz,
+		 void *data,
+		 enum mlx5dv_flow_action_packet_reformat_type reformat_type,
+		 enum mlx5dv_flow_table_type ft_type)
+{
+#ifdef HAVE_IBV_FLOW_DV_SUPPORT
+	return mlx5dv_create_flow_action_packet_reformat(ctx,
+							 data_sz,
+							 data,
+							 reformat_type,
+							 ft_type);
+#else
+	(void)ctx;
+	(void)data_sz;
+	(void)data;
+	(void)reformat_type;
+	(void)ft_type;
+	return NULL;
+#endif
+}
+
 alignas(RTE_CACHE_LINE_SIZE)
 const struct mlx5_glue *mlx5_glue = &(const struct mlx5_glue){
 	.version = MLX5_GLUE_VERSION,
@@ -414,6 +449,7 @@
 	.modify_wq = mlx5_glue_modify_wq,
 	.create_flow = mlx5_glue_create_flow,
 	.destroy_flow = mlx5_glue_destroy_flow,
+	.destroy_flow_action = mlx5_glue_destroy_flow_action,
 	.create_qp = mlx5_glue_create_qp,
 	.create_qp_ex = mlx5_glue_create_qp_ex,
 	.destroy_qp = mlx5_glue_destroy_qp,
@@ -437,4 +473,6 @@
 	.dv_create_flow_matcher = mlx5_glue_dv_create_flow_matcher,
 	.dv_destroy_flow_matcher = mlx5_glue_dv_destroy_flow_matcher,
 	.dv_create_flow = mlx5_glue_dv_create_flow,
+	.dv_create_flow_action_packet_reformat =
+			mlx5_glue_dv_create_flow_action_packet_reformat,
 };
diff --git a/drivers/net/mlx5/mlx5_glue.h b/drivers/net/mlx5/mlx5_glue.h
index f6e4e38..161e8c3 100644
--- a/drivers/net/mlx5/mlx5_glue.h
+++ b/drivers/net/mlx5/mlx5_glue.h
@@ -44,6 +44,9 @@
 struct mlx5dv_flow_matcher_attr;
 struct mlx5dv_flow_action_attr;
 struct mlx5dv_flow_match_parameters;
+struct ibv_flow_action;
+enum mlx5dv_flow_action_packet_reformat_type { packet_reformat_type = 0, };
+enum mlx5dv_flow_table_type { flow_table_type = 0, };
 #endif
 
 /* LIB_GLUE_VERSION must be updated every time this structure is modified. */
@@ -85,6 +88,7 @@ struct mlx5_glue {
 	struct ibv_flow *(*create_flow)(struct ibv_qp *qp,
 					struct ibv_flow_attr *flow);
 	int (*destroy_flow)(struct ibv_flow *flow_id);
+	int (*destroy_flow_action)(struct ibv_flow_action *action);
 	struct ibv_qp *(*create_qp)(struct ibv_pd *pd,
 				    struct ibv_qp_init_attr *qp_init_attr);
 	struct ibv_qp *(*create_qp_ex)
@@ -137,6 +141,12 @@ struct mlx5_glue {
 			  struct mlx5dv_flow_match_parameters *match_value,
 			  size_t num_actions,
 			  struct mlx5dv_flow_action_attr *actions_attr);
+	struct ibv_flow_action *(*dv_create_flow_action_packet_reformat)
+		(struct ibv_context *ctx,
+		 size_t data_sz,
+		 void *data,
+		 enum mlx5dv_flow_action_packet_reformat_type reformat_type,
+		 enum mlx5dv_flow_table_type ft_type);
 };
 
 const struct mlx5_glue *mlx5_glue;
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v5 2/4] net/mlx5: add Direct Verbs encap and decap defs
  2018-10-10  8:35     ` [dpdk-dev] [PATCH v4 " Dekel Peled
  2018-10-11 12:12       ` [dpdk-dev] [PATCH v5 " Dekel Peled
  2018-10-11 12:12       ` [dpdk-dev] [PATCH v5 1/4] net/mlx5: add flow action functions to glue Dekel Peled
@ 2018-10-11 12:12       ` Dekel Peled
  2018-10-11 12:12       ` [dpdk-dev] [PATCH v5 3/4] net/mlx5: add L2 and L3 encap to Direct Verbs flow Dekel Peled
  2018-10-11 12:12       ` [dpdk-dev] [PATCH v5 4/4] net/mlx5: add L2 and L3 decap " Dekel Peled
  4 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-11 12:12 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch adds the required definitions for DV encap/decap actions.
It also adds usage of the new actions definition in validation
function of existing drop operation.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
Acked-by: Yongseok Koh <yskoh@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow.c | 8 ++++++++
 drivers/net/mlx5/mlx5_flow.h | 6 ++++++
 2 files changed, 14 insertions(+)

diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 1087f67..b452e11 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -766,6 +766,14 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't have 2 fate actions in"
 					  " same flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
+			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3 |
+			    MLX5_FLOW_ACTION_TUNNEL_ENCAP |
+			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't encap or decap and drop in"
+					  " same flow");
 	if (attr->egress)
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 690c597..01c73a2 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -82,6 +82,10 @@
 #define MLX5_FLOW_ACTION_OF_SET_VLAN_VID (1u << 9)
 #define MLX5_FLOW_ACTION_OF_SET_VLAN_PCP (1u << 10)
 #define MLX5_FLOW_ACTION_JUMP (1u << 11)
+#define MLX5_FLOW_ACTION_TUNNEL_ENCAP (1u << 12)
+#define MLX5_FLOW_ACTION_TUNNEL_DECAP (1u << 13)
+#define MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3 (1u << 14)
+#define MLX5_FLOW_ACTION_TUNNEL_DECAP_L3 (1u << 15)
 
 #define MLX5_FLOW_FATE_ACTIONS \
 	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS)
@@ -172,6 +176,8 @@ struct mlx5_flow_dv {
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
 	struct mlx5dv_flow_action_attr actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS];
 	/**< Action list. */
+	struct ibv_flow_action *encap_verb; /**< Verbs object of encap. */
+	struct ibv_flow_action *decap_verb; /**< Verbs object of decap. */
 #endif
 	int actions_n; /**< number of actions. */
 };
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v5 3/4] net/mlx5: add L2 and L3 encap to Direct Verbs flow
  2018-10-10  8:35     ` [dpdk-dev] [PATCH v4 " Dekel Peled
                         ` (2 preceding siblings ...)
  2018-10-11 12:12       ` [dpdk-dev] [PATCH v5 2/4] net/mlx5: add Direct Verbs encap and decap defs Dekel Peled
@ 2018-10-11 12:12       ` Dekel Peled
  2018-10-11 12:12       ` [dpdk-dev] [PATCH v5 4/4] net/mlx5: add L2 and L3 decap " Dekel Peled
  4 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-11 12:12 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch adds support for Direct Verbs encap operations, L2 and L3.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
Acked-by: Yongseok Koh <yskoh@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow_dv.c | 227 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 222 insertions(+), 5 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index d13b716..3af5ddc 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -99,6 +99,168 @@
 }
 
 /**
+ * Validate the tunnel encap action.
+ *
+ * @param[in] action_flags
+ *   holds the actions detected until now.
+ * @param[in] action
+ *   Pointer to the encap action.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_ernno is set.
+ */
+static int
+flow_dv_validate_action_tunnel_encap(uint64_t action_flags,
+				     const struct rte_flow_action *action,
+				     const struct rte_flow_attr *attr,
+				     struct rte_flow_error *error)
+{
+	const struct rte_flow_action_tunnel_encap *tunnel_encap = action->conf;
+
+	if (!tunnel_encap || !(tunnel_encap->buf))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, action,
+					  "configuration cannot be null");
+	if (action_flags & MLX5_FLOW_ACTION_DROP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't drop and encap in same flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP |
+			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't have 2 encap actions in same"
+					  " flow");
+	if (attr->ingress)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
+					  NULL,
+					  "encap action not supported for "
+					  "ingress");
+	return 0;
+}
+
+/**
+ * Validate the tunnel encap L3 action
+ *
+ * @param[in] action_flags
+ *   holds the actions detected until now.
+ * @param[in] action
+ *   Pointer to the encap action.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_ernno is set.
+ */
+static int
+flow_dv_validate_action_tunnel_encap_l3(uint64_t action_flags,
+					const struct rte_flow_action *action,
+					const struct rte_flow_attr *attr,
+					struct rte_flow_error *error)
+{
+	const struct rte_flow_action_tunnel_encap_l3 *tunnel_encap_l3 =
+			action->conf;
+
+	if (!tunnel_encap_l3 || !(tunnel_encap_l3->buf))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, action,
+					  "configuration cannot be null");
+	if (action_flags & MLX5_FLOW_ACTION_DROP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't drop and encap in same flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP |
+			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't have 2 encap actions in same"
+					  " flow");
+	if (attr->ingress)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
+					  NULL,
+					  "encap action not supported for "
+					  "ingress");
+	return 0;
+}
+
+/**
+ * Convert encap action to DV specification.
+ *
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[in] action
+ *   Pointer to action structure.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+flow_dv_create_encap(struct rte_eth_dev *dev,
+		     const struct rte_flow_action *action,
+		     struct rte_flow_error *error)
+{
+	struct ibv_flow_action *encap_verb = NULL;
+	const struct rte_flow_action_tunnel_encap *encap_data;
+	struct priv *priv = dev->data->dev_private;
+
+	encap_data = (const struct rte_flow_action_tunnel_encap *)action->conf;
+	encap_verb = mlx5_glue->dv_create_flow_action_packet_reformat
+		(priv->ctx, encap_data->size,
+		 encap_data->size ? encap_data->buf : NULL,
+		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
+		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
+	if (!encap_verb)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create encap action");
+	return encap_verb;
+}
+
+/**
+ * Convert encap L3 action to DV specification.
+ *
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[in] action
+ *   Pointer to action structure.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+flow_dv_create_encap_l3(struct rte_eth_dev *dev,
+			const struct rte_flow_action *action,
+			struct rte_flow_error *error)
+{
+	struct ibv_flow_action *encap_l3_verb = NULL;
+	const struct rte_flow_action_tunnel_encap_l3 *encap_l3_data;
+	struct priv *priv = dev->data->dev_private;
+
+	encap_l3_data =
+		(const struct rte_flow_action_tunnel_encap_l3 *)action->conf;
+	encap_l3_verb = mlx5_glue->dv_create_flow_action_packet_reformat
+		(priv->ctx, encap_l3_data->size,
+		 encap_l3_data->size ? encap_l3_data->buf : NULL,
+		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL,
+		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
+	if (!encap_l3_verb)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create encap L3 action");
+	return encap_l3_verb;
+}
+
+/**
  * Verify the @p attributes will be correctly understood by the NIC and store
  * them in the @p flow if everything is correct.
  *
@@ -346,6 +508,20 @@
 			action_flags |= MLX5_FLOW_ACTION_COUNT;
 			++actions_n;
 			break;
+		case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP:
+			ret = flow_dv_validate_action_tunnel_encap
+				(action_flags, actions, attr, error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_TUNNEL_ENCAP;
+			break;
+		case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP_L3:
+			ret = flow_dv_validate_action_tunnel_encap_l3
+				(action_flags, actions, attr, error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3;
+			break;
 		default:
 			return rte_flow_error_set(error, ENOTSUP,
 						  RTE_FLOW_ERROR_TYPE_ACTION,
@@ -1054,14 +1230,23 @@
 /**
  * Store the requested actions in an array.
  *
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
  * @param[in] action
  *   Flow action to translate.
  * @param[in, out] dev_flow
  *   Pointer to the mlx5_flow.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_ernno is set.
  */
-static void
-flow_dv_create_action(const struct rte_flow_action *action,
-		      struct mlx5_flow *dev_flow)
+static int
+flow_dv_create_action(struct rte_eth_dev *dev,
+		      const struct rte_flow_action *action,
+		      struct mlx5_flow *dev_flow,
+		      struct rte_flow_error *error)
 {
 	const struct rte_flow_action_queue *queue;
 	const struct rte_flow_action_rss *rss;
@@ -1108,10 +1293,35 @@
 		/* Added to array only in apply since we need the QP */
 		flow->actions |= MLX5_FLOW_ACTION_RSS;
 		break;
+	case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP:
+		dev_flow->dv.actions[actions_n].type =
+			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+		dev_flow->dv.actions[actions_n].action =
+			flow_dv_create_encap(dev, action, error);
+		if (!(dev_flow->dv.actions[actions_n].action))
+			return -rte_errno;
+		dev_flow->dv.encap_verb =
+			dev_flow->dv.actions[actions_n].action;
+		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_ENCAP;
+		actions_n++;
+		break;
+	case RTE_FLOW_ACTION_TYPE_TUNNEL_ENCAP_L3:
+		dev_flow->dv.actions[actions_n].type =
+			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+		dev_flow->dv.actions[actions_n].action =
+			flow_dv_create_encap_l3(dev, action, error);
+		if (!(dev_flow->dv.actions[actions_n].action))
+			return -rte_errno;
+		dev_flow->dv.encap_verb =
+			dev_flow->dv.actions[actions_n].action;
+		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3;
+		actions_n++;
+		break;
 	default:
 		break;
 	}
 	dev_flow->dv.actions_n = actions_n;
+	return 0;
 }
 
 static uint32_t matcher_zero[MLX5_ST_SZ_DW(fte_match_param)] = { 0 };
@@ -1275,8 +1485,10 @@
 	matcher.egress = attr->egress;
 	if (flow_dv_matcher_register(dev, &matcher, dev_flow, error))
 		return -rte_errno;
-	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++)
-		flow_dv_create_action(actions, dev_flow);
+	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
+		if (flow_dv_create_action(dev, actions, dev_flow, error))
+			return -rte_errno;
+	}
 	return 0;
 }
 
@@ -1460,6 +1672,11 @@
 		LIST_REMOVE(dev_flow, next);
 		if (dev_flow->dv.matcher)
 			flow_dv_matcher_release(dev, dev_flow->dv.matcher);
+		if (dev_flow->dv.encap_verb) {
+			claim_zero(mlx5_glue->destroy_flow_action
+						(dev_flow->dv.encap_verb));
+			dev_flow->dv.encap_verb = NULL;
+		}
 		rte_free(dev_flow);
 	}
 }
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v5 4/4] net/mlx5: add L2 and L3 decap to Direct Verbs flow
  2018-10-10  8:35     ` [dpdk-dev] [PATCH v4 " Dekel Peled
                         ` (3 preceding siblings ...)
  2018-10-11 12:12       ` [dpdk-dev] [PATCH v5 3/4] net/mlx5: add L2 and L3 encap to Direct Verbs flow Dekel Peled
@ 2018-10-11 12:12       ` Dekel Peled
  4 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-11 12:12 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch adds support for Direct Verbs decap operations, L2 and L3.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
Acked-by: Yongseok Koh <yskoh@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow_dv.c | 215 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 215 insertions(+)

diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 3af5ddc..610818c 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -135,6 +135,12 @@
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't have 2 encap actions in same"
 					  " flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
+			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't encap and decap in same"
+					  " flow");
 	if (attr->ingress)
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
@@ -182,6 +188,12 @@
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't have 2 encap actions in same"
 					  " flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
+			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't encap and decap in same"
+					  " flow");
 	if (attr->ingress)
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
@@ -192,6 +204,100 @@
 }
 
 /**
+ * Validate the tunnel decap action
+ *
+ * @param[in] action_flags
+ *   holds the actions detected until now.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_ernno is set.
+ */
+static int
+flow_dv_validate_action_tunnel_decap(uint64_t action_flags,
+				     const struct rte_flow_attr *attr,
+				     struct rte_flow_error *error)
+{
+	if (action_flags & MLX5_FLOW_ACTION_DROP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't drop and decap in same flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
+			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't have 2 decap actions in same"
+					  " flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP |
+			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't encap and decap in same"
+					  " flow");
+	if (attr->egress)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
+					  "decap action not supported for "
+					  "egress");
+	return 0;
+}
+
+/**
+ * Validate the tunnel decap L3 action
+ *
+ * @param[in] action_flags
+ *   holds the actions detected until now.
+ * @param[in] action
+ *   Pointer to the decap action.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_ernno is set.
+ */
+static int
+flow_dv_validate_action_tunnel_decap_l3(uint64_t action_flags,
+					const struct rte_flow_action *action,
+					const struct rte_flow_attr *attr,
+					struct rte_flow_error *error)
+{
+	const struct rte_flow_action_tunnel_decap_l3 *tunnel_decap_l3 =
+			action->conf;
+
+	if (!tunnel_decap_l3 || !(tunnel_decap_l3->buf))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, action,
+					  "configuration cannot be null");
+	if (action_flags & MLX5_FLOW_ACTION_DROP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't drop and decap in same flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_DECAP |
+			    MLX5_FLOW_ACTION_TUNNEL_DECAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't have 2 decap actions in same"
+					  " flow");
+	if (action_flags & (MLX5_FLOW_ACTION_TUNNEL_ENCAP |
+			    MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't encap and decap in same"
+					  " flow");
+	if (attr->egress)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
+					  "decap action not supported for "
+					  "egress");
+	return 0;
+}
+
+/**
  * Convert encap action to DV specification.
  *
  * @param[in] dev
@@ -261,6 +367,72 @@
 }
 
 /**
+ * Convert decap action to DV specification.
+ *
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[in] action
+ *   Pointer to action structure.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+flow_dv_create_decap(struct rte_eth_dev *dev,
+		     const struct rte_flow_action *action __rte_unused,
+		     struct rte_flow_error *error)
+{
+	struct ibv_flow_action *decap_verb = NULL;
+	struct priv *priv = dev->data->dev_private;
+
+	decap_verb = mlx5_glue->dv_create_flow_action_packet_reformat
+		(priv->ctx, 0, NULL,
+		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2,
+		 MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
+	if (!decap_verb)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create decap action");
+	return decap_verb;
+}
+
+/**
+ * Convert decap L3 action to DV specification.
+ *
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[in] action
+ *   Pointer to action structure.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+flow_dv_create_decap_l3(struct rte_eth_dev *dev,
+			const struct rte_flow_action *action,
+			struct rte_flow_error *error)
+{
+	struct ibv_flow_action *decap_l3_verb = NULL;
+	const struct rte_flow_action_tunnel_decap_l3 *decap_l3_data;
+	struct priv *priv = dev->data->dev_private;
+
+	decap_l3_data =
+		(const struct rte_flow_action_tunnel_decap_l3 *)action->conf;
+	decap_l3_verb = mlx5_glue->dv_create_flow_action_packet_reformat
+		(priv->ctx, decap_l3_data->size,
+		 decap_l3_data->size ? decap_l3_data->buf : NULL,
+		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2,
+		 MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
+	if (!decap_l3_verb)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create decap L3 action");
+	return decap_l3_verb;
+}
+
+/**
  * Verify the @p attributes will be correctly understood by the NIC and store
  * them in the @p flow if everything is correct.
  *
@@ -522,6 +694,20 @@
 				return ret;
 			action_flags |= MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3;
 			break;
+		case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP:
+			ret = flow_dv_validate_action_tunnel_decap
+				(action_flags, attr, error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_TUNNEL_DECAP;
+			break;
+		case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP_L3:
+			ret = flow_dv_validate_action_tunnel_decap_l3
+				(action_flags, actions, attr, error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_TUNNEL_DECAP_L3;
+			break;
 		default:
 			return rte_flow_error_set(error, ENOTSUP,
 						  RTE_FLOW_ERROR_TYPE_ACTION,
@@ -1317,6 +1503,30 @@
 		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_ENCAP_L3;
 		actions_n++;
 		break;
+	case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP:
+		dev_flow->dv.actions[actions_n].type =
+			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+		dev_flow->dv.actions[actions_n].action =
+			flow_dv_create_decap(dev, action, error);
+		if (!(dev_flow->dv.actions[actions_n].action))
+			return -rte_errno;
+		dev_flow->dv.decap_verb =
+			dev_flow->dv.actions[actions_n].action;
+		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_DECAP;
+		actions_n++;
+		break;
+	case RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP_L3:
+		dev_flow->dv.actions[actions_n].type =
+			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+		dev_flow->dv.actions[actions_n].action =
+			flow_dv_create_decap_l3(dev, action, error);
+		if (!(dev_flow->dv.actions[actions_n].action))
+			return -rte_errno;
+		dev_flow->dv.decap_verb =
+			dev_flow->dv.actions[actions_n].action;
+		flow->actions |= MLX5_FLOW_ACTION_TUNNEL_DECAP_L3;
+		actions_n++;
+		break;
 	default:
 		break;
 	}
@@ -1677,6 +1887,11 @@
 						(dev_flow->dv.encap_verb));
 			dev_flow->dv.encap_verb = NULL;
 		}
+		if (dev_flow->dv.decap_verb) {
+			claim_zero(mlx5_glue->destroy_flow_action
+						(dev_flow->dv.decap_verb));
+			dev_flow->dv.decap_verb = NULL;
+		}
 		rte_free(dev_flow);
 	}
 }
-- 
1.8.3.1

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

* Re: [dpdk-dev] [PATCH v5 1/4] net/mlx5: add flow action functions to glue
  2018-10-11 12:12       ` [dpdk-dev] [PATCH v5 1/4] net/mlx5: add flow action functions to glue Dekel Peled
@ 2018-10-11 17:05         ` Yongseok Koh
  0 siblings, 0 replies; 94+ messages in thread
From: Yongseok Koh @ 2018-10-11 17:05 UTC (permalink / raw)
  To: Dekel Peled; +Cc: Shahaf Shuler, dev, Ori Kam


> On Oct 11, 2018, at 5:12 AM, Dekel Peled <dekelp@mellanox.com> wrote:
> 
> This patch adds glue functions for operations:
> - Create packet reformat (encap/decap) flow action.
> - Destroy flow action.
> 
> The new operations depend on HAVE_IBV_FLOW_DV_SUPPORT.
> 
> Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> ---
> drivers/net/mlx5/Makefile    |  2 +-
> drivers/net/mlx5/meson.build |  2 +-
> drivers/net/mlx5/mlx5_glue.c | 38 ++++++++++++++++++++++++++++++++++++++
> drivers/net/mlx5/mlx5_glue.h | 10 ++++++++++
> 4 files changed, 50 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile
> index 92bae9d..bbfb686 100644
> --- a/drivers/net/mlx5/Makefile
> +++ b/drivers/net/mlx5/Makefile
> @@ -139,7 +139,7 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh
> 	$Q sh -- '$<' '$@' \
> 		HAVE_IBV_FLOW_DV_SUPPORT \
> 		infiniband/mlx5dv.h \
> -		enum MLX5DV_FLOW_ACTION_TAG \
> +		func mlx5dv_create_flow_action_packet_reformat \
> 		$(AUTOCONF_OUTPUT)
> 	$Q sh -- '$<' '$@' \
> 		HAVE_ETHTOOL_LINK_MODE_25G \
> diff --git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build
> index 6966248..c93347c 100644
> --- a/drivers/net/mlx5/meson.build
> +++ b/drivers/net/mlx5/meson.build
> @@ -95,7 +95,7 @@ if build
> 		[ 'HAVE_IBV_MLX5_MOD_CQE_128B_COMP', 'infiniband/mlx5dv.h',
> 		'MLX5DV_CONTEXT_FLAGS_CQE_128B_COMP' ],
> 		[ 'HAVE_IBV_FLOW_DV_SUPPORT', 'infiniband/mlx5dv.h',
> -		'MLX5DV_FLOW_ACTION_TAG' ],
> +		'mlx5dv_create_flow_action_packet_reformat' ],
> 		[ 'HAVE_IBV_DEVICE_MPLS_SUPPORT', 'infiniband/verbs.h',
> 		'IBV_FLOW_SPEC_MPLS' ],
> 		[ 'HAVE_IBV_WQ_FLAG_RX_END_PADDING', 'infiniband/verbs.h',
> diff --git a/drivers/net/mlx5/mlx5_glue.c b/drivers/net/mlx5/mlx5_glue.c
> index 48590df..565c2cf 100644
> --- a/drivers/net/mlx5/mlx5_glue.c
> +++ b/drivers/net/mlx5/mlx5_glue.c
> @@ -174,6 +174,17 @@
> 	return ibv_destroy_flow(flow_id);
> }
> 
> +static int
> +mlx5_glue_destroy_flow_action(struct ibv_flow_action *action)
> +{
> +#ifdef HAVE_IBV_FLOW_DV_SUPPORT
> +	return ibv_destroy_flow_action(action);
> +#else
> +	(void)action;
> +	return -ENOTSUP;

Please revert it to positive value and submit v6 with my acked-by tag. 

Thanks
Yongseok

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

* [dpdk-dev] [PATCH v6 0/6] add encap and decap actions to Direct Verbs flow in MLX5 PMD
  2018-10-11 12:12       ` [dpdk-dev] [PATCH v5 " Dekel Peled
@ 2018-10-25 20:08         ` Dekel Peled
  2018-10-29 10:03           ` Shahaf Shuler
                             ` (8 more replies)
  2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 1/6] net/mlx5: add flow action functions to glue Dekel Peled
                           ` (5 subsequent siblings)
  6 siblings, 9 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-25 20:08 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This series adds support of encap and decap actions in DV format.
L2 tunnel support for VXLAN and NVGRE, and L2/L3 tunnel support 
using raw data buffer.
It is using the generic encapsulation framework from [1].

[1] "ethdev: add generic L2/L3 tunnel encapsulation actions"
    http://mails.dpdk.org/archives/dev/2018-October/114654.html
	
---
v6:
* Adapt L2 tunnel to VXLAN and NVGRE
* Add encap/decap using raw data
v5:
* Move DV actions code under common DV flag.
v4:
* Update in glue functions.
v3:
* Apply additional code review comments.
v2:
* Rebase on tip.
* Apply code review comments.


Dekel Peled (6):
  net/mlx5: add flow action functions to glue
  net/mlx5: add VXLAN encap action to Direct Verbs
  net/mlx5: add VXLAN decap action to Direct Verbs
  net/mlx5: add NVGRE encap action to Direct Verbs
  net/mlx5: add NVGRE decap action to Direct Verbs
  net/mlx5: add raw data encap decap to Direct Verbs

 drivers/net/mlx5/Makefile       |   2 +-
 drivers/net/mlx5/meson.build    |   2 +-
 drivers/net/mlx5/mlx5_flow.h    |  15 +
 drivers/net/mlx5/mlx5_flow_dv.c | 671 +++++++++++++++++++++++++++++++++++++++-
 drivers/net/mlx5/mlx5_glue.c    |  38 +++
 drivers/net/mlx5/mlx5_glue.h    |  10 +
 6 files changed, 731 insertions(+), 7 deletions(-)

-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v6 1/6] net/mlx5: add flow action functions to glue
  2018-10-11 12:12       ` [dpdk-dev] [PATCH v5 " Dekel Peled
  2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 0/6] add encap and decap actions to Direct Verbs flow in MLX5 PMD Dekel Peled
@ 2018-10-25 20:08         ` Dekel Peled
  2018-10-29 10:03           ` Shahaf Shuler
  2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 2/6] net/mlx5: add VXLAN encap action to Direct Verbs Dekel Peled
                           ` (4 subsequent siblings)
  6 siblings, 1 reply; 94+ messages in thread
From: Dekel Peled @ 2018-10-25 20:08 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch adds glue functions for operations:
- Create packet reformat (encap/decap) flow action.
- Destroy flow action.

The new operations depend on HAVE_IBV_FLOW_DV_SUPPORT.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
Acked-by: Yongseok Koh <yskoh@mellanox.com>
---
 drivers/net/mlx5/Makefile    |  2 +-
 drivers/net/mlx5/meson.build |  2 +-
 drivers/net/mlx5/mlx5_glue.c | 38 ++++++++++++++++++++++++++++++++++++++
 drivers/net/mlx5/mlx5_glue.h | 10 ++++++++++
 4 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile
index fecb57c..073a2f4 100644
--- a/drivers/net/mlx5/Makefile
+++ b/drivers/net/mlx5/Makefile
@@ -139,7 +139,7 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh
 	$Q sh -- '$<' '$@' \
 		HAVE_IBV_FLOW_DV_SUPPORT \
 		infiniband/mlx5dv.h \
-		enum MLX5DV_FLOW_ACTION_TAG \
+		func mlx5dv_create_flow_action_packet_reformat \
 		$(AUTOCONF_OUTPUT)
 	$Q sh -- '$<' '$@' \
 		HAVE_ETHTOOL_LINK_MODE_25G \
diff --git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build
index e8cbe3e..1330a4f 100644
--- a/drivers/net/mlx5/meson.build
+++ b/drivers/net/mlx5/meson.build
@@ -97,7 +97,7 @@ if build
 		[ 'HAVE_IBV_MLX5_MOD_CQE_128B_COMP', 'infiniband/mlx5dv.h',
 		'MLX5DV_CONTEXT_FLAGS_CQE_128B_COMP' ],
 		[ 'HAVE_IBV_FLOW_DV_SUPPORT', 'infiniband/mlx5dv.h',
-		'MLX5DV_FLOW_ACTION_TAG' ],
+		'mlx5dv_create_flow_action_packet_reformat' ],
 		[ 'HAVE_IBV_DEVICE_MPLS_SUPPORT', 'infiniband/verbs.h',
 		'IBV_FLOW_SPEC_MPLS' ],
 		[ 'HAVE_IBV_WQ_FLAG_RX_END_PADDING', 'infiniband/verbs.h',
diff --git a/drivers/net/mlx5/mlx5_glue.c b/drivers/net/mlx5/mlx5_glue.c
index 1afb114..dd10ad6 100644
--- a/drivers/net/mlx5/mlx5_glue.c
+++ b/drivers/net/mlx5/mlx5_glue.c
@@ -174,6 +174,17 @@
 	return ibv_destroy_flow(flow_id);
 }
 
+static int
+mlx5_glue_destroy_flow_action(struct ibv_flow_action *action)
+{
+#ifdef HAVE_IBV_FLOW_DV_SUPPORT
+	return ibv_destroy_flow_action(action);
+#else
+	(void)action;
+	return ENOTSUP;
+#endif
+}
+
 static struct ibv_qp *
 mlx5_glue_create_qp(struct ibv_pd *pd, struct ibv_qp_init_attr *qp_init_attr)
 {
@@ -444,6 +455,30 @@
 #endif
 }
 
+static struct ibv_flow_action *
+mlx5_glue_dv_create_flow_action_packet_reformat
+		(struct ibv_context *ctx,
+		 size_t data_sz,
+		 void *data,
+		 enum mlx5dv_flow_action_packet_reformat_type reformat_type,
+		 enum mlx5dv_flow_table_type ft_type)
+{
+#ifdef HAVE_IBV_FLOW_DV_SUPPORT
+	return mlx5dv_create_flow_action_packet_reformat(ctx,
+							 data_sz,
+							 data,
+							 reformat_type,
+							 ft_type);
+#else
+	(void)ctx;
+	(void)data_sz;
+	(void)data;
+	(void)reformat_type;
+	(void)ft_type;
+	return NULL;
+#endif
+}
+
 alignas(RTE_CACHE_LINE_SIZE)
 const struct mlx5_glue *mlx5_glue = &(const struct mlx5_glue){
 	.version = MLX5_GLUE_VERSION,
@@ -470,6 +505,7 @@
 	.modify_wq = mlx5_glue_modify_wq,
 	.create_flow = mlx5_glue_create_flow,
 	.destroy_flow = mlx5_glue_destroy_flow,
+	.destroy_flow_action = mlx5_glue_destroy_flow_action,
 	.create_qp = mlx5_glue_create_qp,
 	.create_qp_ex = mlx5_glue_create_qp_ex,
 	.destroy_qp = mlx5_glue_destroy_qp,
@@ -497,4 +533,6 @@
 	.dv_create_flow_matcher = mlx5_glue_dv_create_flow_matcher,
 	.dv_destroy_flow_matcher = mlx5_glue_dv_destroy_flow_matcher,
 	.dv_create_flow = mlx5_glue_dv_create_flow,
+	.dv_create_flow_action_packet_reformat =
+			mlx5_glue_dv_create_flow_action_packet_reformat,
 };
diff --git a/drivers/net/mlx5/mlx5_glue.h b/drivers/net/mlx5/mlx5_glue.h
index 44bfefe..2d92ba8 100644
--- a/drivers/net/mlx5/mlx5_glue.h
+++ b/drivers/net/mlx5/mlx5_glue.h
@@ -50,6 +50,9 @@
 struct mlx5dv_flow_matcher_attr;
 struct mlx5dv_flow_action_attr;
 struct mlx5dv_flow_match_parameters;
+struct ibv_flow_action;
+enum mlx5dv_flow_action_packet_reformat_type { packet_reformat_type = 0, };
+enum mlx5dv_flow_table_type { flow_table_type = 0, };
 #endif
 
 /* LIB_GLUE_VERSION must be updated every time this structure is modified. */
@@ -91,6 +94,7 @@ struct mlx5_glue {
 	struct ibv_flow *(*create_flow)(struct ibv_qp *qp,
 					struct ibv_flow_attr *flow);
 	int (*destroy_flow)(struct ibv_flow *flow_id);
+	int (*destroy_flow_action)(struct ibv_flow_action *action);
 	struct ibv_qp *(*create_qp)(struct ibv_pd *pd,
 				    struct ibv_qp_init_attr *qp_init_attr);
 	struct ibv_qp *(*create_qp_ex)
@@ -154,6 +158,12 @@ struct mlx5_glue {
 			  struct mlx5dv_flow_match_parameters *match_value,
 			  size_t num_actions,
 			  struct mlx5dv_flow_action_attr *actions_attr);
+	struct ibv_flow_action *(*dv_create_flow_action_packet_reformat)
+		(struct ibv_context *ctx,
+		 size_t data_sz,
+		 void *data,
+		 enum mlx5dv_flow_action_packet_reformat_type reformat_type,
+		 enum mlx5dv_flow_table_type ft_type);
 };
 
 const struct mlx5_glue *mlx5_glue;
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v6 2/6] net/mlx5: add VXLAN encap action to Direct Verbs
  2018-10-11 12:12       ` [dpdk-dev] [PATCH v5 " Dekel Peled
  2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 0/6] add encap and decap actions to Direct Verbs flow in MLX5 PMD Dekel Peled
  2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 1/6] net/mlx5: add flow action functions to glue Dekel Peled
@ 2018-10-25 20:08         ` Dekel Peled
  2018-10-29 10:03           ` Shahaf Shuler
  2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 3/6] net/mlx5: add VXLAN decap " Dekel Peled
                           ` (3 subsequent siblings)
  6 siblings, 1 reply; 94+ messages in thread
From: Dekel Peled @ 2018-10-25 20:08 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch implements the VXLAN encap action in DV flow for MLX5 PMD.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow.h    |   2 +
 drivers/net/mlx5/mlx5_flow_dv.c | 351 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 348 insertions(+), 5 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 61299d6..6e92afe 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -92,6 +92,7 @@
 #define MLX5_FLOW_ACTION_DEC_TTL (1u << 19)
 #define MLX5_FLOW_ACTION_SET_MAC_SRC (1u << 20)
 #define MLX5_FLOW_ACTION_SET_MAC_DST (1u << 21)
+#define MLX5_FLOW_ACTION_VXLAN_ENCAP (1u << 22)
 
 #define MLX5_FLOW_FATE_ACTIONS \
 	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS)
@@ -181,6 +182,7 @@ struct mlx5_flow_dv {
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
 	struct mlx5dv_flow_action_attr actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS];
 	/**< Action list. */
+	struct ibv_flow_action *verbs_action; /**< Verbs encap/decap object. */
 #endif
 	int actions_n; /**< number of actions. */
 };
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 8f729f4..14110c5 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -34,6 +34,12 @@
 
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
 
+/*
+ * Encap buf length, max:
+ *   Eth:14/VLAN:8/IPv6:40/TCP:36/TUNNEL:20/Eth:14
+ */
+#define MLX5_ENCAP_MAX_LEN 132
+
 /**
  * Validate META item.
  *
@@ -96,6 +102,300 @@
 }
 
 /**
+ * Validate the L2 encap action.
+ * Used for VXLAN encap action.
+ *
+ * @param[in] action_flags
+ *   Holds the actions detected until now.
+ * @param[in] action
+ *   Pointer to the encap action.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_validate_action_l2_encap(uint64_t action_flags,
+				 const struct rte_flow_action *action,
+				 const struct rte_flow_attr *attr,
+				 struct rte_flow_error *error)
+{
+	if (!(action->conf))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, action,
+					  "configuration cannot be null");
+	if (action_flags & MLX5_FLOW_ACTION_DROP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't drop and encap in same flow");
+	if (action_flags & MLX5_FLOW_ACTION_VXLAN_ENCAP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can only have a single encap"
+					  " action in a flow");
+	if (attr->ingress)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
+					  NULL,
+					  "encap action not supported for "
+					  "ingress");
+	return 0;
+}
+
+/**
+ * Get the size of specific rte_flow_item_type
+ *
+ * @param[in] item_type
+ *   Tested rte_flow_item_type.
+ *
+ * @return
+ *   sizeof struct item_type, 0 if void or irrelevant.
+ */
+static size_t
+flow_dv_get_item_len(const enum rte_flow_item_type item_type)
+{
+	size_t retval;
+
+	switch (item_type) {
+	case RTE_FLOW_ITEM_TYPE_ETH:
+		retval = sizeof(struct rte_flow_item_eth);
+		break;
+	case RTE_FLOW_ITEM_TYPE_VLAN:
+		retval = sizeof(struct rte_flow_item_vlan);
+		break;
+	case RTE_FLOW_ITEM_TYPE_IPV4:
+		retval = sizeof(struct rte_flow_item_ipv4);
+		break;
+	case RTE_FLOW_ITEM_TYPE_IPV6:
+		retval = sizeof(struct rte_flow_item_ipv6);
+		break;
+	case RTE_FLOW_ITEM_TYPE_UDP:
+		retval = sizeof(struct rte_flow_item_udp);
+		break;
+	case RTE_FLOW_ITEM_TYPE_TCP:
+		retval = sizeof(struct rte_flow_item_tcp);
+		break;
+	case RTE_FLOW_ITEM_TYPE_VXLAN:
+		retval = sizeof(struct rte_flow_item_vxlan);
+		break;
+	case RTE_FLOW_ITEM_TYPE_GRE:
+		retval = sizeof(struct rte_flow_item_gre);
+		break;
+	case RTE_FLOW_ITEM_TYPE_NVGRE:
+		retval = sizeof(struct rte_flow_item_nvgre);
+		break;
+	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
+		retval = sizeof(struct rte_flow_item_vxlan_gpe);
+		break;
+	case RTE_FLOW_ITEM_TYPE_MPLS:
+		retval = sizeof(struct rte_flow_item_mpls);
+		break;
+	case RTE_FLOW_ITEM_TYPE_VOID: /* Fall through. */
+	default:
+		retval = 0;
+		break;
+	}
+	return retval;
+};
+
+/**
+ * Convert the encap action data from rte_flow_item to raw buffer
+ *
+ * @param[in] item
+ *   Pointer to rte_flow_item object.
+ * @param[out] buf
+ *   Pointer to the output buffer.
+ * @param[out] size
+ *   Pointer to the output buffer size.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_convert_encap_data(const struct rte_flow_item *item, uint8_t *buf,
+			   size_t *size, struct rte_flow_error *error)
+{
+	struct ether_hdr *eth = NULL;
+	struct vlan_hdr *vlan = NULL;
+	struct ipv4_hdr *ipv4 = NULL;
+	struct ipv6_hdr *ipv6 = NULL;
+	struct udp_hdr *udp = NULL;
+	struct vxlan_hdr *vxlan = NULL;
+	size_t len;
+	size_t temp_size = 0;
+
+	if (!item)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  NULL, "invalid empty data");
+	for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+		len = flow_dv_get_item_len(item->type);
+		if (len + temp_size > MLX5_ENCAP_MAX_LEN)
+			return rte_flow_error_set(error, EINVAL,
+						  RTE_FLOW_ERROR_TYPE_ACTION,
+						  (void *)item->type,
+						  "invalid item length");
+		rte_memcpy((void *)&buf[temp_size], item->spec, len);
+		switch (item->type) {
+		case RTE_FLOW_ITEM_TYPE_ETH:
+			eth = (struct ether_hdr *)&buf[temp_size];
+			break;
+		case RTE_FLOW_ITEM_TYPE_VLAN:
+			vlan = (struct vlan_hdr *)&buf[temp_size];
+			if (!eth)
+				return rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						(void *)item->type,
+						"eth header not found");
+			if (!eth->ether_type)
+				eth->ether_type = RTE_BE16(ETHER_TYPE_VLAN);
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV4:
+			ipv4 = (struct ipv4_hdr *)&buf[temp_size];
+			if (!vlan && !eth)
+				return rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						(void *)item->type,
+						"neither eth nor vlan"
+						" header found");
+			if (vlan && !vlan->eth_proto)
+				vlan->eth_proto = RTE_BE16(ETHER_TYPE_IPv4);
+			else if (eth && !eth->ether_type)
+				eth->ether_type = RTE_BE16(ETHER_TYPE_IPv4);
+			if (!ipv4->version_ihl)
+				ipv4->version_ihl = 0x45;
+			if (!ipv4->time_to_live)
+				ipv4->time_to_live = 0x40;
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV6:
+			ipv6 = (struct ipv6_hdr *)&buf[temp_size];
+			if (!vlan && !eth)
+				return rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						(void *)item->type,
+						"neither eth nor vlan"
+						" header found");
+			if (vlan && !vlan->eth_proto)
+				vlan->eth_proto = RTE_BE16(ETHER_TYPE_IPv6);
+			else if (eth && !eth->ether_type)
+				eth->ether_type = RTE_BE16(ETHER_TYPE_IPv6);
+			if (!ipv6->vtc_flow)
+				ipv6->vtc_flow = RTE_BE32(0x60000000);
+			if (!ipv6->hop_limits)
+				ipv6->hop_limits = 0xff;
+			break;
+		case RTE_FLOW_ITEM_TYPE_UDP:
+			udp = (struct udp_hdr *)&buf[temp_size];
+			if (!ipv4 && !ipv6)
+				return rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						(void *)item->type,
+						"ip header not found");
+			if (ipv4 && !ipv4->next_proto_id)
+				ipv4->next_proto_id = IPPROTO_UDP;
+			else if (ipv6 && !ipv6->proto)
+				ipv6->proto = IPPROTO_UDP;
+			break;
+		case RTE_FLOW_ITEM_TYPE_VXLAN:
+			vxlan = (struct vxlan_hdr *)&buf[temp_size];
+			if (!udp)
+				return rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						(void *)item->type,
+						"udp header not found");
+			if (!udp->dst_port)
+				udp->dst_port = RTE_BE16(MLX5_UDP_PORT_VXLAN);
+			if (!vxlan->vx_flags)
+				vxlan->vx_flags = RTE_BE32(0x08000000);
+			break;
+		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
+			vxlan = (struct vxlan_hdr *)&buf[temp_size];
+			if (!udp)
+				return rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						(void *)item->type,
+						"udp header not found");
+			if (!udp->dst_port)
+				udp->dst_port =
+					RTE_BE16(MLX5_UDP_PORT_VXLAN_GPE);
+			if (!vxlan->vx_flags)
+				vxlan->vx_flags = RTE_BE32(0x0c000003);
+			break;
+		case RTE_FLOW_ITEM_TYPE_GRE:
+		case RTE_FLOW_ITEM_TYPE_NVGRE:
+			if (!ipv4 && !ipv6)
+				return rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						(void *)item->type,
+						"ip header not found");
+			if (ipv4 && !ipv4->next_proto_id)
+				ipv4->next_proto_id = IPPROTO_GRE;
+			else if (ipv6 && !ipv6->proto)
+				ipv6->proto = IPPROTO_GRE;
+			break;
+		case RTE_FLOW_ITEM_TYPE_VOID:
+			break;
+		default:
+			return rte_flow_error_set(error, EINVAL,
+						  RTE_FLOW_ERROR_TYPE_ACTION,
+						  (void *)item->type,
+						  "unsupported item type");
+			break;
+		}
+		temp_size += len;
+	}
+	*size = temp_size;
+	return 0;
+}
+
+/**
+ * Convert L2 encap action to DV specification.
+ * Used for VXLAN encap action.
+ *
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[in] action
+ *   Pointer to action structure.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+flow_dv_create_action_l2_encap(struct rte_eth_dev *dev,
+			       const struct rte_flow_action *action,
+			       struct rte_flow_error *error)
+{
+	struct ibv_flow_action *verbs_action = NULL;
+	const struct rte_flow_item *encap_data;
+	struct priv *priv = dev->data->dev_private;
+	uint8_t buf[MLX5_ENCAP_MAX_LEN];
+	size_t size = 0;
+	int convert_result = 0;
+
+	encap_data = ((const struct rte_flow_action_vxlan_encap *)
+						action->conf)->definition;
+	convert_result = flow_dv_convert_encap_data(encap_data, buf,
+						    &size, error);
+	if (convert_result)
+		return NULL;
+	verbs_action = mlx5_glue->dv_create_flow_action_packet_reformat
+		(priv->ctx, size, (size ? buf : NULL),
+		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
+		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
+	if (!verbs_action)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create L2 encap action");
+	return verbs_action;
+}
+
+/**
  * Verify the @p attributes will be correctly understood by the NIC and store
  * them in the @p flow if everything is correct.
  *
@@ -339,6 +639,16 @@
 			action_flags |= MLX5_FLOW_ACTION_COUNT;
 			++actions_n;
 			break;
+		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
+			ret = flow_dv_validate_action_l2_encap(action_flags,
+							       actions, attr,
+							       error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_VXLAN_ENCAP;
+			++actions_n;
+			break;
+
 		default:
 			return rte_flow_error_set(error, ENOTSUP,
 						  RTE_FLOW_ERROR_TYPE_ACTION,
@@ -1045,14 +1355,26 @@
 /**
  * Store the requested actions in an array.
  *
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
  * @param[in] action
  *   Flow action to translate.
  * @param[in, out] dev_flow
  *   Pointer to the mlx5_flow.
+ * @param[in] attr
+ *   Pointer to the flow attributes.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
-static void
-flow_dv_create_action(const struct rte_flow_action *action,
-		      struct mlx5_flow *dev_flow)
+static int
+flow_dv_create_action(struct rte_eth_dev *dev,
+		      const struct rte_flow_action *action,
+		      struct mlx5_flow *dev_flow,
+		      const struct rte_flow_attr *attr __rte_unused,
+		      struct rte_flow_error *error)
 {
 	const struct rte_flow_action_queue *queue;
 	const struct rte_flow_action_rss *rss;
@@ -1100,10 +1422,24 @@
 		/* Added to array only in apply since we need the QP */
 		flow->actions |= MLX5_FLOW_ACTION_RSS;
 		break;
+	case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
+		dev_flow->dv.actions[actions_n].type =
+			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+		dev_flow->dv.actions[actions_n].action =
+				flow_dv_create_action_l2_encap(dev, action,
+							       error);
+		if (!(dev_flow->dv.actions[actions_n].action))
+			return -rte_errno;
+		dev_flow->dv.verbs_action =
+			dev_flow->dv.actions[actions_n].action;
+		flow->actions |= MLX5_FLOW_ACTION_VXLAN_ENCAP;
+		actions_n++;
+		break;
 	default:
 		break;
 	}
 	dev_flow->dv.actions_n = actions_n;
+	return 0;
 }
 
 static uint32_t matcher_zero[MLX5_ST_SZ_DW(fte_match_param)] = { 0 };
@@ -1217,7 +1553,6 @@
 	return 0;
 }
 
-
 /**
  * Fill the flow with DV spec.
  *
@@ -1272,7 +1607,8 @@
 	if (flow_dv_matcher_register(dev, &matcher, dev_flow, error))
 		return -rte_errno;
 	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++)
-		flow_dv_create_action(actions, dev_flow);
+		if (flow_dv_create_action(dev, actions, dev_flow, attr, error))
+			return -rte_errno;
 	return 0;
 }
 
@@ -1457,6 +1793,11 @@
 		LIST_REMOVE(dev_flow, next);
 		if (dev_flow->dv.matcher)
 			flow_dv_matcher_release(dev, dev_flow);
+		if (dev_flow->dv.verbs_action) {
+			claim_zero(mlx5_glue->destroy_flow_action
+						(dev_flow->dv.verbs_action));
+			dev_flow->dv.verbs_action = NULL;
+		}
 		rte_free(dev_flow);
 	}
 }
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v6 3/6] net/mlx5: add VXLAN decap action to Direct Verbs
  2018-10-11 12:12       ` [dpdk-dev] [PATCH v5 " Dekel Peled
                           ` (2 preceding siblings ...)
  2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 2/6] net/mlx5: add VXLAN encap action to Direct Verbs Dekel Peled
@ 2018-10-25 20:08         ` Dekel Peled
  2018-10-29 10:03           ` Shahaf Shuler
  2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 4/6] net/mlx5: add NVGRE encap " Dekel Peled
                           ` (2 subsequent siblings)
  6 siblings, 1 reply; 94+ messages in thread
From: Dekel Peled @ 2018-10-25 20:08 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch implements the VXLAN decap action in DV flow for MLX5 PMD.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow.h    |   1 +
 drivers/net/mlx5/mlx5_flow_dv.c | 103 ++++++++++++++++++++++++++++++++++++++--
 2 files changed, 100 insertions(+), 4 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 6e92afe..3795644 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -93,6 +93,7 @@
 #define MLX5_FLOW_ACTION_SET_MAC_SRC (1u << 20)
 #define MLX5_FLOW_ACTION_SET_MAC_DST (1u << 21)
 #define MLX5_FLOW_ACTION_VXLAN_ENCAP (1u << 22)
+#define MLX5_FLOW_ACTION_VXLAN_DECAP (1u << 23)
 
 #define MLX5_FLOW_FATE_ACTIONS \
 	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS)
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 14110c5..e84a2b6 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -131,11 +131,12 @@
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't drop and encap in same flow");
-	if (action_flags & MLX5_FLOW_ACTION_VXLAN_ENCAP)
+	if (action_flags & (MLX5_FLOW_ACTION_VXLAN_ENCAP |
+			    MLX5_FLOW_ACTION_VXLAN_DECAP))
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
-					  "can only have a single encap"
-					  " action in a flow");
+					  "can only have a single encap or"
+					  " decap action in a flow");
 	if (attr->ingress)
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
@@ -146,6 +147,47 @@
 }
 
 /**
+ * Validate the L2 decap action.
+ * Used for VXLAN decap action.
+ *
+ * @param[in] action_flags
+ *   Holds the actions detected until now.
+ * @param[in] action
+ *   Pointer to the decap action.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_validate_action_l2_decap(uint64_t action_flags,
+			const struct rte_flow_action *action __rte_unused,
+			const struct rte_flow_attr *attr,
+			struct rte_flow_error *error)
+{
+	if (action_flags & MLX5_FLOW_ACTION_DROP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't drop and decap in same flow");
+	if (action_flags & (MLX5_FLOW_ACTION_VXLAN_ENCAP |
+			    MLX5_FLOW_ACTION_VXLAN_DECAP))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can only have a single encap or"
+					  " decap action in a flow");
+	if (attr->egress)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
+					  NULL,
+					  "decap action not supported for "
+					  "egress");
+	return 0;
+}
+
+/**
  * Get the size of specific rte_flow_item_type
  *
  * @param[in] item_type
@@ -396,6 +438,38 @@
 }
 
 /**
+ * Convert L2 decap action to DV specification.
+ * Used for VXLAN decap action.
+ *
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[in] action
+ *   Pointer to action structure.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+flow_dv_create_action_l2_decap(struct rte_eth_dev *dev,
+			const struct rte_flow_action *action __rte_unused,
+			struct rte_flow_error *error)
+{
+	struct ibv_flow_action *verbs_action = NULL;
+	struct priv *priv = dev->data->dev_private;
+
+	verbs_action = mlx5_glue->dv_create_flow_action_packet_reformat
+		(priv->ctx, 0, NULL,
+		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2,
+		 MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
+	if (!verbs_action)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create L2 decap action");
+	return verbs_action;
+}
+
+/**
  * Verify the @p attributes will be correctly understood by the NIC and store
  * them in the @p flow if everything is correct.
  *
@@ -648,7 +722,15 @@
 			action_flags |= MLX5_FLOW_ACTION_VXLAN_ENCAP;
 			++actions_n;
 			break;
-
+		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
+			ret = flow_dv_validate_action_l2_decap(action_flags,
+							       actions, attr,
+							       error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_VXLAN_DECAP;
+			++actions_n;
+			break;
 		default:
 			return rte_flow_error_set(error, ENOTSUP,
 						  RTE_FLOW_ERROR_TYPE_ACTION,
@@ -1435,6 +1517,19 @@
 		flow->actions |= MLX5_FLOW_ACTION_VXLAN_ENCAP;
 		actions_n++;
 		break;
+	case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
+		dev_flow->dv.actions[actions_n].type =
+			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+		dev_flow->dv.actions[actions_n].action =
+				flow_dv_create_action_l2_decap(dev, action,
+							       error);
+		if (!(dev_flow->dv.actions[actions_n].action))
+			return -rte_errno;
+		dev_flow->dv.verbs_action =
+			dev_flow->dv.actions[actions_n].action;
+		flow->actions |= MLX5_FLOW_ACTION_VXLAN_DECAP;
+		actions_n++;
+		break;
 	default:
 		break;
 	}
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v6 4/6] net/mlx5: add NVGRE encap action to Direct Verbs
  2018-10-11 12:12       ` [dpdk-dev] [PATCH v5 " Dekel Peled
                           ` (3 preceding siblings ...)
  2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 3/6] net/mlx5: add VXLAN decap " Dekel Peled
@ 2018-10-25 20:08         ` Dekel Peled
  2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 5/6] net/mlx5: add NVGRE decap " Dekel Peled
  2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 6/6] net/mlx5: add raw data encap decap " Dekel Peled
  6 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-25 20:08 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch implements the nvgre encap action in DV flow for MLX5 PMD.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow.h    |  4 ++++
 drivers/net/mlx5/mlx5_flow_dv.c | 27 ++++++++++++++++++++-------
 2 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 3795644..05527eb 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -94,10 +94,14 @@
 #define MLX5_FLOW_ACTION_SET_MAC_DST (1u << 21)
 #define MLX5_FLOW_ACTION_VXLAN_ENCAP (1u << 22)
 #define MLX5_FLOW_ACTION_VXLAN_DECAP (1u << 23)
+#define MLX5_FLOW_ACTION_NVGRE_ENCAP (1u << 24)
 
 #define MLX5_FLOW_FATE_ACTIONS \
 	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS)
 
+#define MLX5_FLOW_ENCAP_ACTIONS	\
+	(MLX5_FLOW_ACTION_VXLAN_ENCAP | MLX5_FLOW_ACTION_NVGRE_ENCAP)
+
 #ifndef IPPROTO_MPLS
 #define IPPROTO_MPLS 137
 #endif
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index e84a2b6..bdaec19 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -103,7 +103,7 @@
 
 /**
  * Validate the L2 encap action.
- * Used for VXLAN encap action.
+ * Used for VXLAN and NVGRE encap actions.
  *
  * @param[in] action_flags
  *   Holds the actions detected until now.
@@ -131,7 +131,7 @@
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't drop and encap in same flow");
-	if (action_flags & (MLX5_FLOW_ACTION_VXLAN_ENCAP |
+	if (action_flags & (MLX5_FLOW_ENCAP_ACTIONS |
 			    MLX5_FLOW_ACTION_VXLAN_DECAP))
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
@@ -172,7 +172,7 @@
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't drop and decap in same flow");
-	if (action_flags & (MLX5_FLOW_ACTION_VXLAN_ENCAP |
+	if (action_flags & (MLX5_FLOW_ENCAP_ACTIONS |
 			    MLX5_FLOW_ACTION_VXLAN_DECAP))
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
@@ -397,7 +397,7 @@
 
 /**
  * Convert L2 encap action to DV specification.
- * Used for VXLAN encap action.
+ * Used for VXLAN and NVGRE encap actions.
  *
  * @param[in] dev
  *   Pointer to rte_eth_dev structure.
@@ -421,7 +421,11 @@
 	size_t size = 0;
 	int convert_result = 0;
 
-	encap_data = ((const struct rte_flow_action_vxlan_encap *)
+	if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP)
+		encap_data = ((const struct rte_flow_action_vxlan_encap *)
+						action->conf)->definition;
+	else
+		encap_data = ((const struct rte_flow_action_nvgre_encap *)
 						action->conf)->definition;
 	convert_result = flow_dv_convert_encap_data(encap_data, buf,
 						    &size, error);
@@ -714,12 +718,17 @@
 			++actions_n;
 			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
+		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
 			ret = flow_dv_validate_action_l2_encap(action_flags,
 							       actions, attr,
 							       error);
 			if (ret < 0)
 				return ret;
-			action_flags |= MLX5_FLOW_ACTION_VXLAN_ENCAP;
+			action_flags |= actions->type ==
+					RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP ?
+					MLX5_FLOW_ACTION_VXLAN_ENCAP :
+					MLX5_FLOW_ACTION_NVGRE_ENCAP;
+
 			++actions_n;
 			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
@@ -1505,6 +1514,7 @@
 		flow->actions |= MLX5_FLOW_ACTION_RSS;
 		break;
 	case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
+	case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
 		dev_flow->dv.actions[actions_n].type =
 			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
 		dev_flow->dv.actions[actions_n].action =
@@ -1514,7 +1524,10 @@
 			return -rte_errno;
 		dev_flow->dv.verbs_action =
 			dev_flow->dv.actions[actions_n].action;
-		flow->actions |= MLX5_FLOW_ACTION_VXLAN_ENCAP;
+		flow->actions |= action->type ==
+				 RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP ?
+				 MLX5_FLOW_ACTION_VXLAN_ENCAP :
+				 MLX5_FLOW_ACTION_NVGRE_ENCAP;
 		actions_n++;
 		break;
 	case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v6 5/6] net/mlx5: add NVGRE decap action to Direct Verbs
  2018-10-11 12:12       ` [dpdk-dev] [PATCH v5 " Dekel Peled
                           ` (4 preceding siblings ...)
  2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 4/6] net/mlx5: add NVGRE encap " Dekel Peled
@ 2018-10-25 20:08         ` Dekel Peled
  2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 6/6] net/mlx5: add raw data encap decap " Dekel Peled
  6 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-25 20:08 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch implements the NVGRE decap action in DV flow for MLX5 PMD.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow.h    |  4 ++++
 drivers/net/mlx5/mlx5_flow_dv.c | 23 +++++++++++++++--------
 2 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 05527eb..2d73a05 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -95,6 +95,7 @@
 #define MLX5_FLOW_ACTION_VXLAN_ENCAP (1u << 22)
 #define MLX5_FLOW_ACTION_VXLAN_DECAP (1u << 23)
 #define MLX5_FLOW_ACTION_NVGRE_ENCAP (1u << 24)
+#define MLX5_FLOW_ACTION_NVGRE_DECAP (1u << 25)
 
 #define MLX5_FLOW_FATE_ACTIONS \
 	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS)
@@ -102,6 +103,9 @@
 #define MLX5_FLOW_ENCAP_ACTIONS	\
 	(MLX5_FLOW_ACTION_VXLAN_ENCAP | MLX5_FLOW_ACTION_NVGRE_ENCAP)
 
+#define MLX5_FLOW_DECAP_ACTIONS	\
+	(MLX5_FLOW_ACTION_VXLAN_DECAP | MLX5_FLOW_ACTION_NVGRE_DECAP)
+
 #ifndef IPPROTO_MPLS
 #define IPPROTO_MPLS 137
 #endif
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index bdaec19..d7d0c6b 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -131,8 +131,7 @@
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't drop and encap in same flow");
-	if (action_flags & (MLX5_FLOW_ENCAP_ACTIONS |
-			    MLX5_FLOW_ACTION_VXLAN_DECAP))
+	if (action_flags & (MLX5_FLOW_ENCAP_ACTIONS | MLX5_FLOW_DECAP_ACTIONS))
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can only have a single encap or"
@@ -148,7 +147,7 @@
 
 /**
  * Validate the L2 decap action.
- * Used for VXLAN decap action.
+ * Used for VXLAN and NVGRE decap actions.
  *
  * @param[in] action_flags
  *   Holds the actions detected until now.
@@ -172,8 +171,7 @@
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't drop and decap in same flow");
-	if (action_flags & (MLX5_FLOW_ENCAP_ACTIONS |
-			    MLX5_FLOW_ACTION_VXLAN_DECAP))
+	if (action_flags & (MLX5_FLOW_ENCAP_ACTIONS | MLX5_FLOW_DECAP_ACTIONS))
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can only have a single encap or"
@@ -443,7 +441,7 @@
 
 /**
  * Convert L2 decap action to DV specification.
- * Used for VXLAN decap action.
+ * Used for VXLAN and NVGRE decap actions.
  *
  * @param[in] dev
  *   Pointer to rte_eth_dev structure.
@@ -732,12 +730,17 @@
 			++actions_n;
 			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
+		case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
 			ret = flow_dv_validate_action_l2_decap(action_flags,
 							       actions, attr,
 							       error);
 			if (ret < 0)
 				return ret;
-			action_flags |= MLX5_FLOW_ACTION_VXLAN_DECAP;
+			action_flags |= actions->type ==
+					RTE_FLOW_ACTION_TYPE_VXLAN_DECAP ?
+					MLX5_FLOW_ACTION_VXLAN_DECAP :
+					MLX5_FLOW_ACTION_NVGRE_DECAP;
+
 			++actions_n;
 			break;
 		default:
@@ -1531,6 +1534,7 @@
 		actions_n++;
 		break;
 	case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
+	case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
 		dev_flow->dv.actions[actions_n].type =
 			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
 		dev_flow->dv.actions[actions_n].action =
@@ -1540,7 +1544,10 @@
 			return -rte_errno;
 		dev_flow->dv.verbs_action =
 			dev_flow->dv.actions[actions_n].action;
-		flow->actions |= MLX5_FLOW_ACTION_VXLAN_DECAP;
+		flow->actions |= action->type ==
+				 RTE_FLOW_ACTION_TYPE_VXLAN_DECAP ?
+				 MLX5_FLOW_ACTION_VXLAN_DECAP :
+				 MLX5_FLOW_ACTION_NVGRE_DECAP;
 		actions_n++;
 		break;
 	default:
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v6 6/6] net/mlx5: add raw data encap decap to Direct Verbs
  2018-10-11 12:12       ` [dpdk-dev] [PATCH v5 " Dekel Peled
                           ` (5 preceding siblings ...)
  2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 5/6] net/mlx5: add NVGRE decap " Dekel Peled
@ 2018-10-25 20:08         ` Dekel Peled
  2018-10-29 10:03           ` Shahaf Shuler
  6 siblings, 1 reply; 94+ messages in thread
From: Dekel Peled @ 2018-10-25 20:08 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch implements the encap and decap actions, using raw data,
in DV flow for MLX5 PMD.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow.h    |  12 ++-
 drivers/net/mlx5/mlx5_flow_dv.c | 227 ++++++++++++++++++++++++++++++++++++++--
 2 files changed, 224 insertions(+), 15 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 2d73a05..92ba111 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -96,15 +96,19 @@
 #define MLX5_FLOW_ACTION_VXLAN_DECAP (1u << 23)
 #define MLX5_FLOW_ACTION_NVGRE_ENCAP (1u << 24)
 #define MLX5_FLOW_ACTION_NVGRE_DECAP (1u << 25)
+#define MLX5_FLOW_ACTION_RAW_ENCAP (1u << 26)
+#define MLX5_FLOW_ACTION_RAW_DECAP (1u << 27)
 
 #define MLX5_FLOW_FATE_ACTIONS \
 	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS)
 
-#define MLX5_FLOW_ENCAP_ACTIONS	\
-	(MLX5_FLOW_ACTION_VXLAN_ENCAP | MLX5_FLOW_ACTION_NVGRE_ENCAP)
+#define MLX5_FLOW_ENCAP_ACTIONS	(MLX5_FLOW_ACTION_VXLAN_ENCAP | \
+				 MLX5_FLOW_ACTION_NVGRE_ENCAP | \
+				 MLX5_FLOW_ACTION_RAW_ENCAP)
 
-#define MLX5_FLOW_DECAP_ACTIONS	\
-	(MLX5_FLOW_ACTION_VXLAN_DECAP | MLX5_FLOW_ACTION_NVGRE_DECAP)
+#define MLX5_FLOW_DECAP_ACTIONS	(MLX5_FLOW_ACTION_VXLAN_DECAP | \
+				 MLX5_FLOW_ACTION_NVGRE_DECAP | \
+				 MLX5_FLOW_ACTION_RAW_DECAP)
 
 #ifndef IPPROTO_MPLS
 #define IPPROTO_MPLS 137
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index d7d0c6b..ca75645 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -186,6 +186,82 @@
 }
 
 /**
+ * Validate the raw encap action.
+ *
+ * @param[in] action_flags
+ *   Holds the actions detected until now.
+ * @param[in] action
+ *   Pointer to the encap action.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_validate_action_raw_encap(uint64_t action_flags,
+				  const struct rte_flow_action *action,
+				  const struct rte_flow_attr *attr,
+				  struct rte_flow_error *error)
+{
+	if (!(action->conf))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, action,
+					  "configuration cannot be null");
+	if (action_flags & MLX5_FLOW_ACTION_DROP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't drop and encap in same flow");
+	if (action_flags & MLX5_FLOW_ENCAP_ACTIONS)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can only have a single encap"
+					  " action in a flow");
+	/* encap without preceding decap is not supported for ingress */
+	if (attr->ingress && !(action_flags & MLX5_FLOW_ACTION_RAW_DECAP))
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
+					  NULL,
+					  "encap action not supported for "
+					  "ingress");
+	return 0;
+}
+
+/**
+ * Validate the raw decap action.
+ *
+ * @param[in] action_flags
+ *   Holds the actions detected until now.
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_validate_action_raw_decap(uint64_t action_flags,
+				  struct rte_flow_error *error)
+{
+	if (action_flags & MLX5_FLOW_ACTION_DROP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't drop and decap in same flow");
+	if (action_flags & MLX5_FLOW_ENCAP_ACTIONS)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't have encap action before"
+					  " decap action");
+	if (action_flags & MLX5_FLOW_DECAP_ACTIONS)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can only have a single decap"
+					  " action in a flow");
+	return 0;
+}
+
+/**
  * Get the size of specific rte_flow_item_type
  *
  * @param[in] item_type
@@ -396,6 +472,7 @@
 /**
  * Convert L2 encap action to DV specification.
  * Used for VXLAN and NVGRE encap actions.
+ * Also used for raw encap action without preceding decap.
  *
  * @param[in] dev
  *   Pointer to rte_eth_dev structure.
@@ -414,23 +491,34 @@
 {
 	struct ibv_flow_action *verbs_action = NULL;
 	const struct rte_flow_item *encap_data;
+	const struct rte_flow_action_raw_encap *raw_encap_data;
 	struct priv *priv = dev->data->dev_private;
 	uint8_t buf[MLX5_ENCAP_MAX_LEN];
+	uint8_t *buf_ptr = buf;
 	size_t size = 0;
 	int convert_result = 0;
 
-	if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP)
-		encap_data = ((const struct rte_flow_action_vxlan_encap *)
+	if (action->type == RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
+		raw_encap_data =
+			(const struct rte_flow_action_raw_encap *)action->conf;
+		buf_ptr = raw_encap_data->data;
+		size = raw_encap_data->size;
+	} else {
+		if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP)
+			encap_data =
+				((const struct rte_flow_action_vxlan_encap *)
 						action->conf)->definition;
-	else
-		encap_data = ((const struct rte_flow_action_nvgre_encap *)
+		else
+			encap_data =
+				((const struct rte_flow_action_nvgre_encap *)
 						action->conf)->definition;
-	convert_result = flow_dv_convert_encap_data(encap_data, buf,
-						    &size, error);
-	if (convert_result)
-		return NULL;
+		convert_result = flow_dv_convert_encap_data(encap_data, buf,
+							    &size, error);
+		if (convert_result)
+			return NULL;
+	}
 	verbs_action = mlx5_glue->dv_create_flow_action_packet_reformat
-		(priv->ctx, size, (size ? buf : NULL),
+		(priv->ctx, size, (size ? buf_ptr : NULL),
 		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
 		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
 	if (!verbs_action)
@@ -472,6 +560,50 @@
 }
 
 /**
+ * Convert raw decap/encap (L3 tunnel) action to DV specification.
+ *
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[in] action
+ *   Pointer to action structure.
+ * @param[in] attr
+ *   Pointer to the flow attributes.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+flow_dv_create_action_raw_encap(struct rte_eth_dev *dev,
+				const struct rte_flow_action *action,
+				const struct rte_flow_attr *attr,
+				struct rte_flow_error *error)
+{
+	struct ibv_flow_action *verbs_action = NULL;
+	const struct rte_flow_action_raw_encap *encap_data;
+	struct priv *priv = dev->data->dev_private;
+	enum mlx5dv_flow_action_packet_reformat_type reformat_type;
+	enum mlx5dv_flow_table_type ft_type;
+
+	encap_data = (const struct rte_flow_action_raw_encap *)action->conf;
+	reformat_type = attr->egress ?
+		MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL :
+		MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2;
+	ft_type = attr->egress ?
+			MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
+			MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
+	verbs_action = mlx5_glue->dv_create_flow_action_packet_reformat
+				(priv->ctx, encap_data->size,
+				(encap_data->size ? encap_data->data : NULL),
+				reformat_type, ft_type);
+	if (!verbs_action)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create encap action");
+	return verbs_action;
+}
+
+/**
  * Verify the @p attributes will be correctly understood by the NIC and store
  * them in the @p flow if everything is correct.
  *
@@ -726,7 +858,6 @@
 					RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP ?
 					MLX5_FLOW_ACTION_VXLAN_ENCAP :
 					MLX5_FLOW_ACTION_NVGRE_ENCAP;
-
 			++actions_n;
 			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
@@ -740,7 +871,23 @@
 					RTE_FLOW_ACTION_TYPE_VXLAN_DECAP ?
 					MLX5_FLOW_ACTION_VXLAN_DECAP :
 					MLX5_FLOW_ACTION_NVGRE_DECAP;
-
+			++actions_n;
+			break;
+		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
+			ret = flow_dv_validate_action_raw_encap(action_flags,
+								actions, attr,
+								error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_RAW_ENCAP;
+			++actions_n;
+			break;
+		case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
+			ret = flow_dv_validate_action_raw_decap(action_flags,
+								error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_RAW_DECAP;
 			++actions_n;
 			break;
 		default:
@@ -1550,6 +1697,64 @@
 				 MLX5_FLOW_ACTION_NVGRE_DECAP;
 		actions_n++;
 		break;
+	case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
+		/* Handle encap action with preceding decap */
+		if (flow->actions & MLX5_FLOW_ACTION_RAW_DECAP) {
+			dev_flow->dv.actions[actions_n].type =
+				MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+			dev_flow->dv.actions[actions_n].action =
+					flow_dv_create_action_raw_encap
+								(dev, action,
+								 attr, error);
+			if (!(dev_flow->dv.actions[actions_n].action))
+				return -rte_errno;
+			dev_flow->dv.verbs_action =
+				dev_flow->dv.actions[actions_n].action;
+		} else {
+			/* Handle encap action without preceding decap */
+			dev_flow->dv.actions[actions_n].type =
+				MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+			dev_flow->dv.actions[actions_n].action =
+					flow_dv_create_action_l2_encap
+							(dev, action, error);
+			if (!(dev_flow->dv.actions[actions_n].action))
+				return -rte_errno;
+			dev_flow->dv.verbs_action =
+				dev_flow->dv.actions[actions_n].action;
+		}
+		flow->actions |= MLX5_FLOW_ACTION_RAW_ENCAP;
+		actions_n++;
+		break;
+	case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
+		/* Check if this decap action is followed by encap. */
+		for (; action->type != RTE_FLOW_ACTION_TYPE_END &&
+		       action->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP;
+		       action++) {
+		}
+		/* Handle decap action only if it isn't followed by encap */
+		if (action->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
+			/* on egress, decap without following encap is error. */
+			if (attr->egress)
+				return rte_flow_error_set
+					(error, ENOTSUP,
+					 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
+					 NULL,
+					 "decap action not supported for "
+					 "egress");
+			dev_flow->dv.actions[actions_n].type =
+				MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+			dev_flow->dv.actions[actions_n].action =
+					flow_dv_create_action_l2_decap
+							(dev, action, error);
+			if (!(dev_flow->dv.actions[actions_n].action))
+				return -rte_errno;
+			dev_flow->dv.verbs_action =
+				dev_flow->dv.actions[actions_n].action;
+			actions_n++;
+		}
+		/* If decap is followed by encap, handle it at encap case. */
+		flow->actions |= MLX5_FLOW_ACTION_RAW_DECAP;
+		break;
 	default:
 		break;
 	}
-- 
1.8.3.1

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

* Re: [dpdk-dev] [PATCH v6 0/6] add encap and decap actions to Direct Verbs flow in MLX5 PMD
  2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 0/6] add encap and decap actions to Direct Verbs flow in MLX5 PMD Dekel Peled
@ 2018-10-29 10:03           ` Shahaf Shuler
  2018-10-29 14:42             ` Dekel Peled
  2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 0/7] " Dekel Peled
                             ` (7 subsequent siblings)
  8 siblings, 1 reply; 94+ messages in thread
From: Shahaf Shuler @ 2018-10-29 10:03 UTC (permalink / raw)
  To: Dekel Peled, Yongseok Koh; +Cc: dev, Ori Kam

Hi Dekel,

Thursday, October 25, 2018 11:08 PM, Dekel Peled:
> Subject: [dpdk-dev] [PATCH v6 0/6] add encap and decap actions to Direct
> Verbs flow in MLX5 PMD
> 
> This series adds support of encap and decap actions in DV format.
> L2 tunnel support for VXLAN and NVGRE, and L2/L3 tunnel support using raw
> data buffer.
> It is using the generic encapsulation framework from [1].
> 
> [1] "ethdev: add generic L2/L3 tunnel encapsulation actions"
> 
> https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmail
> s.dpdk.org%2Farchives%2Fdev%2F2018-
> October%2F114654.html&amp;data=02%7C01%7Cshahafs%40mellanox.com
> %7C5c61dd00f0ea45acba0608d63ab5c0e6%7Ca652971c7d2e4d9ba6a4d14925
> 6f461b%7C0%7C0%7C636760949640981142&amp;sdata=tdOJhJfndTAP6Uotk
> MJrkgBsa7AXljXJRMPsivfveUo%3D&amp;reserved=0

In general looks good, please see some comments to address. 

> 
> ---
> v6:
> * Adapt L2 tunnel to VXLAN and NVGRE
> * Add encap/decap using raw data
> v5:
> * Move DV actions code under common DV flag.
> v4:
> * Update in glue functions.
> v3:
> * Apply additional code review comments.
> v2:
> * Rebase on tip.
> * Apply code review comments.
> 
> 
> Dekel Peled (6):
>   net/mlx5: add flow action functions to glue
>   net/mlx5: add VXLAN encap action to Direct Verbs
>   net/mlx5: add VXLAN decap action to Direct Verbs
>   net/mlx5: add NVGRE encap action to Direct Verbs
>   net/mlx5: add NVGRE decap action to Direct Verbs
>   net/mlx5: add raw data encap decap to Direct Verbs
> 
>  drivers/net/mlx5/Makefile       |   2 +-
>  drivers/net/mlx5/meson.build    |   2 +-
>  drivers/net/mlx5/mlx5_flow.h    |  15 +
>  drivers/net/mlx5/mlx5_flow_dv.c | 671
> +++++++++++++++++++++++++++++++++++++++-
>  drivers/net/mlx5/mlx5_glue.c    |  38 +++
>  drivers/net/mlx5/mlx5_glue.h    |  10 +
>  6 files changed, 731 insertions(+), 7 deletions(-)
> 
> --
> 1.8.3.1

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

* Re: [dpdk-dev] [PATCH v6 1/6] net/mlx5: add flow action functions to glue
  2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 1/6] net/mlx5: add flow action functions to glue Dekel Peled
@ 2018-10-29 10:03           ` Shahaf Shuler
  0 siblings, 0 replies; 94+ messages in thread
From: Shahaf Shuler @ 2018-10-29 10:03 UTC (permalink / raw)
  To: Dekel Peled, Yongseok Koh; +Cc: dev, Ori Kam

Thursday, October 25, 2018 11:08 PM, Dekel Peled:
> Subject: [dpdk-dev] [PATCH v6 1/6] net/mlx5: add flow action functions to
> glue
> 
> This patch adds glue functions for operations:
> - Create packet reformat (encap/decap) flow action.
> - Destroy flow action.
> 
> The new operations depend on HAVE_IBV_FLOW_DV_SUPPORT.
> 
> Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> Acked-by: Yongseok Koh <yskoh@mellanox.com>

Acked-by: Shahaf Shuler <shahafs@mellanox.com>

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

* Re: [dpdk-dev] [PATCH v6 2/6] net/mlx5: add VXLAN encap action to Direct Verbs
  2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 2/6] net/mlx5: add VXLAN encap action to Direct Verbs Dekel Peled
@ 2018-10-29 10:03           ` Shahaf Shuler
  2018-10-29 16:44             ` Dekel Peled
  0 siblings, 1 reply; 94+ messages in thread
From: Shahaf Shuler @ 2018-10-29 10:03 UTC (permalink / raw)
  To: Dekel Peled, Yongseok Koh; +Cc: dev, Ori Kam

Hi Dekel,

Thursday, October 25, 2018 11:08 PM, Dekel Peled:
> Subject: [dpdk-dev] [PATCH v6 2/6] net/mlx5: add VXLAN encap action to
> Direct Verbs
> 
> This patch implements the VXLAN encap action in DV flow for MLX5 PMD.
> 
> Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> ---
>  drivers/net/mlx5/mlx5_flow.h    |   2 +
>  drivers/net/mlx5/mlx5_flow_dv.c | 351
> +++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 348 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
> index 61299d6..6e92afe 100644
> --- a/drivers/net/mlx5/mlx5_flow.h
> +++ b/drivers/net/mlx5/mlx5_flow.h
> @@ -92,6 +92,7 @@
>  #define MLX5_FLOW_ACTION_DEC_TTL (1u << 19)  #define
> MLX5_FLOW_ACTION_SET_MAC_SRC (1u << 20)  #define
> MLX5_FLOW_ACTION_SET_MAC_DST (1u << 21)
> +#define MLX5_FLOW_ACTION_VXLAN_ENCAP (1u << 22)
> 
>  #define MLX5_FLOW_FATE_ACTIONS \
>  	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE |
> MLX5_FLOW_ACTION_RSS) @@ -181,6 +182,7 @@ struct mlx5_flow_dv {
> #ifdef HAVE_IBV_FLOW_DV_SUPPORT
>  	struct mlx5dv_flow_action_attr
> actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS];
>  	/**< Action list. */
> +	struct ibv_flow_action *verbs_action; /**< Verbs encap/decap

The ibv_flow_action is already part of a union inside mlx5dv_flow_action_attr, why you need it separately? 
I see also in the below code that you copy it from the action list to this specific field. Can you elaborate why? 

> object.
> +*/
>  #endif
>  	int actions_n; /**< number of actions. */  }; diff --git
> a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
> index 8f729f4..14110c5 100644
> --- a/drivers/net/mlx5/mlx5_flow_dv.c
> +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> @@ -34,6 +34,12 @@
> 
>  #ifdef HAVE_IBV_FLOW_DV_SUPPORT
> 
> +/*
> + * Encap buf length, max:
> + *   Eth:14/VLAN:8/IPv6:40/TCP:36/TUNNEL:20/Eth:14

VLAN is 4B not 8B. which tunnel is for 20B? 

> + */
> +#define MLX5_ENCAP_MAX_LEN 132
> +
>  /**
>   * Validate META item.
>   *
> @@ -96,6 +102,300 @@
>  }
> 
>  /**
> + * Validate the L2 encap action.
> + * Used for VXLAN encap action.

No need for that. Later on you put more supported protocols. This is a generic function for L2 encap validation. 

> + *
> + * @param[in] action_flags
> + *   Holds the actions detected until now.
> + * @param[in] action
> + *   Pointer to the encap action.
> + * @param[in] attr
> + *   Pointer to flow attributes
> + * @param[out] error
> + *   Pointer to error structure.
> + *
> + * @return
> + *   0 on success, a negative errno value otherwise and rte_errno is set.
> + */
> +static int
> +flow_dv_validate_action_l2_encap(uint64_t action_flags,
> +				 const struct rte_flow_action *action,
> +				 const struct rte_flow_attr *attr,
> +				 struct rte_flow_error *error)
> +{
> +	if (!(action->conf))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> action,
> +					  "configuration cannot be null");
> +	if (action_flags & MLX5_FLOW_ACTION_DROP)
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
> +					  "can't drop and encap in same
> flow");
> +	if (action_flags & MLX5_FLOW_ACTION_VXLAN_ENCAP)
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
> +					  "can only have a single encap"
> +					  " action in a flow");
> +	if (attr->ingress)
> +		return rte_flow_error_set(error, ENOTSUP,
> +
> RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> +					  NULL,
> +					  "encap action not supported for "
> +					  "ingress");
> +	return 0;
> +}
> +
> +/**
> + * Get the size of specific rte_flow_item_type
> + *
> + * @param[in] item_type
> + *   Tested rte_flow_item_type.
> + *
> + * @return
> + *   sizeof struct item_type, 0 if void or irrelevant.
> + */
> +static size_t
> +flow_dv_get_item_len(const enum rte_flow_item_type item_type) {

Can we have this function as a macro?

#define flow_dv_get_item_len(t) (strncpm(t, VOID, 4) ? 0 : sizeof(struct rte_flow_item_##t)

Usage: flow_dv_get_item_len(ETH)


> +	size_t retval;
> +
> +	switch (item_type) {
> +	case RTE_FLOW_ITEM_TYPE_ETH:
> +		retval = sizeof(struct rte_flow_item_eth);
> +		break;
> +	case RTE_FLOW_ITEM_TYPE_VLAN:
> +		retval = sizeof(struct rte_flow_item_vlan);
> +		break;
> +	case RTE_FLOW_ITEM_TYPE_IPV4:
> +		retval = sizeof(struct rte_flow_item_ipv4);
> +		break;
> +	case RTE_FLOW_ITEM_TYPE_IPV6:
> +		retval = sizeof(struct rte_flow_item_ipv6);
> +		break;
> +	case RTE_FLOW_ITEM_TYPE_UDP:
> +		retval = sizeof(struct rte_flow_item_udp);
> +		break;
> +	case RTE_FLOW_ITEM_TYPE_TCP:
> +		retval = sizeof(struct rte_flow_item_tcp);
> +		break;
> +	case RTE_FLOW_ITEM_TYPE_VXLAN:
> +		retval = sizeof(struct rte_flow_item_vxlan);
> +		break;
> +	case RTE_FLOW_ITEM_TYPE_GRE:
> +		retval = sizeof(struct rte_flow_item_gre);
> +		break;
> +	case RTE_FLOW_ITEM_TYPE_NVGRE:
> +		retval = sizeof(struct rte_flow_item_nvgre);
> +		break;
> +	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
> +		retval = sizeof(struct rte_flow_item_vxlan_gpe);
> +		break;
> +	case RTE_FLOW_ITEM_TYPE_MPLS:
> +		retval = sizeof(struct rte_flow_item_mpls);
> +		break;
> +	case RTE_FLOW_ITEM_TYPE_VOID: /* Fall through. */
> +	default:
> +		retval = 0;
> +		break;
> +	}
> +	return retval;
> +};
> +
> +/**
> + * Convert the encap action data from rte_flow_item to raw buffer
> + *
> + * @param[in] item
> + *   Pointer to rte_flow_item object.

Since it is an item list, "items" is preferable. 

> + * @param[out] buf
> + *   Pointer to the output buffer.
> + * @param[out] size
> + *   Pointer to the output buffer size.
> + * @param[out] error
> + *   Pointer to the error structure.
> + *
> + * @return
> + *   0 on success, a negative errno value otherwise and rte_errno is set.
> + */
> +static int
> +flow_dv_convert_encap_data(const struct rte_flow_item *item, uint8_t
> *buf,
> +			   size_t *size, struct rte_flow_error *error) {
> +	struct ether_hdr *eth = NULL;
> +	struct vlan_hdr *vlan = NULL;
> +	struct ipv4_hdr *ipv4 = NULL;
> +	struct ipv6_hdr *ipv6 = NULL;
> +	struct udp_hdr *udp = NULL;
> +	struct vxlan_hdr *vxlan = NULL;
> +	size_t len;
> +	size_t temp_size = 0;
> +
> +	if (!item)
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> +					  NULL, "invalid empty data");
> +	for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
> +		len = flow_dv_get_item_len(item->type);
> +		if (len + temp_size > MLX5_ENCAP_MAX_LEN)
> +			return rte_flow_error_set(error, EINVAL,
> +
> RTE_FLOW_ERROR_TYPE_ACTION,
> +						  (void *)item->type,
> +						  "invalid item length");

It is not invalid item length, it is items total size is too big for encap. 

> +		rte_memcpy((void *)&buf[temp_size], item->spec, len);
> +		switch (item->type) {
> +		case RTE_FLOW_ITEM_TYPE_ETH:
> +			eth = (struct ether_hdr *)&buf[temp_size];
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_VLAN:
> +			vlan = (struct vlan_hdr *)&buf[temp_size];
> +			if (!eth)
> +				return rte_flow_error_set(error, EINVAL,
> +
> 	RTE_FLOW_ERROR_TYPE_ACTION,
> +						(void *)item->type,
> +						"eth header not found");
> +			if (!eth->ether_type)
> +				eth->ether_type =
> RTE_BE16(ETHER_TYPE_VLAN);
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_IPV4:
> +			ipv4 = (struct ipv4_hdr *)&buf[temp_size];
> +			if (!vlan && !eth)
> +				return rte_flow_error_set(error, EINVAL,
> +
> 	RTE_FLOW_ERROR_TYPE_ACTION,
> +						(void *)item->type,
> +						"neither eth nor vlan"
> +						" header found");
> +			if (vlan && !vlan->eth_proto)
> +				vlan->eth_proto =
> RTE_BE16(ETHER_TYPE_IPv4);
> +			else if (eth && !eth->ether_type)
> +				eth->ether_type =
> RTE_BE16(ETHER_TYPE_IPv4);
> +			if (!ipv4->version_ihl)
> +				ipv4->version_ihl = 0x45;
> +			if (!ipv4->time_to_live)
> +				ipv4->time_to_live = 0x40;

If no existing macro have those two above defined as ones. 
There are few more places on this function related to this comment. 

> +			break;
> +		case RTE_FLOW_ITEM_TYPE_IPV6:
> +			ipv6 = (struct ipv6_hdr *)&buf[temp_size];
> +			if (!vlan && !eth)
> +				return rte_flow_error_set(error, EINVAL,
> +
> 	RTE_FLOW_ERROR_TYPE_ACTION,
> +						(void *)item->type,
> +						"neither eth nor vlan"
> +						" header found");
> +			if (vlan && !vlan->eth_proto)
> +				vlan->eth_proto =
> RTE_BE16(ETHER_TYPE_IPv6);
> +			else if (eth && !eth->ether_type)
> +				eth->ether_type =
> RTE_BE16(ETHER_TYPE_IPv6);
> +			if (!ipv6->vtc_flow)
> +				ipv6->vtc_flow = RTE_BE32(0x60000000);
> +			if (!ipv6->hop_limits)
> +				ipv6->hop_limits = 0xff;
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_UDP:
> +			udp = (struct udp_hdr *)&buf[temp_size];
> +			if (!ipv4 && !ipv6)
> +				return rte_flow_error_set(error, EINVAL,
> +
> 	RTE_FLOW_ERROR_TYPE_ACTION,
> +						(void *)item->type,
> +						"ip header not found");
> +			if (ipv4 && !ipv4->next_proto_id)
> +				ipv4->next_proto_id = IPPROTO_UDP;
> +			else if (ipv6 && !ipv6->proto)
> +				ipv6->proto = IPPROTO_UDP;
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_VXLAN:
> +			vxlan = (struct vxlan_hdr *)&buf[temp_size];
> +			if (!udp)
> +				return rte_flow_error_set(error, EINVAL,
> +
> 	RTE_FLOW_ERROR_TYPE_ACTION,
> +						(void *)item->type,
> +						"udp header not found");
> +			if (!udp->dst_port)
> +				udp->dst_port =
> RTE_BE16(MLX5_UDP_PORT_VXLAN);
> +			if (!vxlan->vx_flags)
> +				vxlan->vx_flags = RTE_BE32(0x08000000);
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
> +			vxlan = (struct vxlan_hdr *)&buf[temp_size];
> +			if (!udp)
> +				return rte_flow_error_set(error, EINVAL,
> +
> 	RTE_FLOW_ERROR_TYPE_ACTION,
> +						(void *)item->type,
> +						"udp header not found");
> +			if (!udp->dst_port)
> +				udp->dst_port =
> +
> 	RTE_BE16(MLX5_UDP_PORT_VXLAN_GPE);
> +			if (!vxlan->vx_flags)
> +				vxlan->vx_flags = RTE_BE32(0x0c000003);

I would say you cannot set internally the next protocol. Only the user know what it is. 
I think in case VXLAN_GPE is set on the item list, the next_proto field is a must, otherwise the rule should be rejected. 

> +			break;
> +		case RTE_FLOW_ITEM_TYPE_GRE:
> +		case RTE_FLOW_ITEM_TYPE_NVGRE:
> +			if (!ipv4 && !ipv6)
> +				return rte_flow_error_set(error, EINVAL,
> +
> 	RTE_FLOW_ERROR_TYPE_ACTION,
> +						(void *)item->type,
> +						"ip header not found");
> +			if (ipv4 && !ipv4->next_proto_id)
> +				ipv4->next_proto_id = IPPROTO_GRE;
> +			else if (ipv6 && !ipv6->proto)
> +				ipv6->proto = IPPROTO_GRE;

This patch is for VXLAN, yet you add a GRE/NVGRE code block. It is better to add it on the subsequent patches adding this feature. 

Also you need to check if the user put the protocol type on the GRE header. Same as the VXLAN-GPE case, this is a must. 

> +			break;
> +		case RTE_FLOW_ITEM_TYPE_VOID:
> +			break;
> +		default:
> +			return rte_flow_error_set(error, EINVAL,
> +
> RTE_FLOW_ERROR_TYPE_ACTION,
> +						  (void *)item->type,
> +						  "unsupported item type");
> +			break;
> +		}
> +		temp_size += len;
> +	}
> +	*size = temp_size;
> +	return 0;
> +}
> +
> +/**
> + * Convert L2 encap action to DV specification.
> + * Used for VXLAN encap action.

Same - no need to specific which exact protocols. 

> + *
> + * @param[in] dev
> + *   Pointer to rte_eth_dev structure.
> + * @param[in] action
> + *   Pointer to action structure.
> + * @param[out] error
> + *   Pointer to the error structure.
> + *
> + * @return
> + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> + */
> +static struct ibv_flow_action *
> +flow_dv_create_action_l2_encap(struct rte_eth_dev *dev,
> +			       const struct rte_flow_action *action,
> +			       struct rte_flow_error *error) {
> +	struct ibv_flow_action *verbs_action = NULL;
> +	const struct rte_flow_item *encap_data;
> +	struct priv *priv = dev->data->dev_private;
> +	uint8_t buf[MLX5_ENCAP_MAX_LEN];
> +	size_t size = 0;
> +	int convert_result = 0;
> +
> +	encap_data = ((const struct rte_flow_action_vxlan_encap *)
> +						action->conf)->definition;
> +	convert_result = flow_dv_convert_encap_data(encap_data, buf,
> +						    &size, error);
> +	if (convert_result)
> +		return NULL;
> +	verbs_action = mlx5_glue-
> >dv_create_flow_action_packet_reformat
> +		(priv->ctx, size, (size ? buf : NULL),

How can size be 0 and yet the encap action is valid? 

> +
> MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
> +		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
> +	if (!verbs_action)
> +		rte_flow_error_set(error, EINVAL,
> RTE_FLOW_ERROR_TYPE_ACTION,
> +				   NULL, "cannot create L2 encap action");
> +	return verbs_action;
> +}
> +
> +/**
>   * Verify the @p attributes will be correctly understood by the NIC and store
>   * them in the @p flow if everything is correct.
>   *
> @@ -339,6 +639,16 @@
>  			action_flags |= MLX5_FLOW_ACTION_COUNT;
>  			++actions_n;
>  			break;
> +		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
> +			ret =
> flow_dv_validate_action_l2_encap(action_flags,
> +							       actions, attr,
> +							       error);
> +			if (ret < 0)
> +				return ret;
> +			action_flags |=
> MLX5_FLOW_ACTION_VXLAN_ENCAP;
> +			++actions_n;
> +			break;
> +
>  		default:
>  			return rte_flow_error_set(error, ENOTSUP,
> 
> RTE_FLOW_ERROR_TYPE_ACTION,
> @@ -1045,14 +1355,26 @@
>  /**
>   * Store the requested actions in an array.
>   *
> + * @param[in] dev
> + *   Pointer to rte_eth_dev structure.
>   * @param[in] action
>   *   Flow action to translate.
>   * @param[in, out] dev_flow
>   *   Pointer to the mlx5_flow.
> + * @param[in] attr
> + *   Pointer to the flow attributes.
> + * @param[out] error
> + *   Pointer to the error structure.
> + *
> + * @return
> + *   0 on success, a negative errno value otherwise and rte_errno is set.
>   */
> -static void
> -flow_dv_create_action(const struct rte_flow_action *action,
> -		      struct mlx5_flow *dev_flow)
> +static int
> +flow_dv_create_action(struct rte_eth_dev *dev,
> +		      const struct rte_flow_action *action,
> +		      struct mlx5_flow *dev_flow,
> +		      const struct rte_flow_attr *attr __rte_unused,

It was better to add this when you add the RAW encap feature. Now they marked as unused, and you didn't changed that when you actually started to use them.
Need to choose one of the paths:
1. add them on the RAW encap/decap support (better)
2. remove the rte_unused on the RAW encap/decap support


> +		      struct rte_flow_error *error)
>  {
>  	const struct rte_flow_action_queue *queue;
>  	const struct rte_flow_action_rss *rss; @@ -1100,10 +1422,24 @@
>  		/* Added to array only in apply since we need the QP */
>  		flow->actions |= MLX5_FLOW_ACTION_RSS;
>  		break;
> +	case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
> +		dev_flow->dv.actions[actions_n].type =
> +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> +		dev_flow->dv.actions[actions_n].action =
> +				flow_dv_create_action_l2_encap(dev,
> action,
> +							       error);
> +		if (!(dev_flow->dv.actions[actions_n].action))
> +			return -rte_errno;
> +		dev_flow->dv.verbs_action =
> +			dev_flow->dv.actions[actions_n].action;
> +		flow->actions |= MLX5_FLOW_ACTION_VXLAN_ENCAP;
> +		actions_n++;
> +		break;
>  	default:
>  		break;
>  	}
>  	dev_flow->dv.actions_n = actions_n;
> +	return 0;
>  }
> 
>  static uint32_t matcher_zero[MLX5_ST_SZ_DW(fte_match_param)] = { 0 };
> @@ -1217,7 +1553,6 @@
>  	return 0;
>  }
> 
> -
>  /**
>   * Fill the flow with DV spec.
>   *
> @@ -1272,7 +1607,8 @@
>  	if (flow_dv_matcher_register(dev, &matcher, dev_flow, error))
>  		return -rte_errno;
>  	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++)
> -		flow_dv_create_action(actions, dev_flow);
> +		if (flow_dv_create_action(dev, actions, dev_flow, attr,
> error))
> +			return -rte_errno;
>  	return 0;
>  }
> 
> @@ -1457,6 +1793,11 @@
>  		LIST_REMOVE(dev_flow, next);
>  		if (dev_flow->dv.matcher)
>  			flow_dv_matcher_release(dev, dev_flow);
> +		if (dev_flow->dv.verbs_action) {

Like I said in the beginning, I don't understand why this field is separate from the mlx5dv action list. 

> +			claim_zero(mlx5_glue->destroy_flow_action
> +						(dev_flow-
> >dv.verbs_action));
> +			dev_flow->dv.verbs_action = NULL;
> +		}
>  		rte_free(dev_flow);
>  	}
>  }
> --
> 1.8.3.1

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

* Re: [dpdk-dev] [PATCH v6 3/6] net/mlx5: add VXLAN decap action to Direct Verbs
  2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 3/6] net/mlx5: add VXLAN decap " Dekel Peled
@ 2018-10-29 10:03           ` Shahaf Shuler
  2018-10-29 16:46             ` Dekel Peled
  0 siblings, 1 reply; 94+ messages in thread
From: Shahaf Shuler @ 2018-10-29 10:03 UTC (permalink / raw)
  To: Dekel Peled, Yongseok Koh; +Cc: dev, Ori Kam

Thursday, October 25, 2018 11:08 PM, Dekel Peled:
> Subject: [dpdk-dev] [PATCH v6 3/6] net/mlx5: add VXLAN decap action to
> Direct Verbs
> 
> This patch implements the VXLAN decap action in DV flow for MLX5 PMD.
> 
> Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> ---
>  drivers/net/mlx5/mlx5_flow.h    |   1 +
>  drivers/net/mlx5/mlx5_flow_dv.c | 103
> ++++++++++++++++++++++++++++++++++++++--
>  2 files changed, 100 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
> index 6e92afe..3795644 100644
> --- a/drivers/net/mlx5/mlx5_flow.h
> +++ b/drivers/net/mlx5/mlx5_flow.h
> @@ -93,6 +93,7 @@
>  #define MLX5_FLOW_ACTION_SET_MAC_SRC (1u << 20)  #define
> MLX5_FLOW_ACTION_SET_MAC_DST (1u << 21)  #define
> MLX5_FLOW_ACTION_VXLAN_ENCAP (1u << 22)
> +#define MLX5_FLOW_ACTION_VXLAN_DECAP (1u << 23)
> 
>  #define MLX5_FLOW_FATE_ACTIONS \
>  	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE |
> MLX5_FLOW_ACTION_RSS) diff --git a/drivers/net/mlx5/mlx5_flow_dv.c
> b/drivers/net/mlx5/mlx5_flow_dv.c index 14110c5..e84a2b6 100644
> --- a/drivers/net/mlx5/mlx5_flow_dv.c
> +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> @@ -131,11 +131,12 @@
>  		return rte_flow_error_set(error, EINVAL,
>  					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
>  					  "can't drop and encap in same
> flow");
> -	if (action_flags & MLX5_FLOW_ACTION_VXLAN_ENCAP)
> +	if (action_flags & (MLX5_FLOW_ACTION_VXLAN_ENCAP |
> +			    MLX5_FLOW_ACTION_VXLAN_DECAP))
>  		return rte_flow_error_set(error, EINVAL,
>  					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
> -					  "can only have a single encap"
> -					  " action in a flow");
> +					  "can only have a single encap or"
> +					  " decap action in a flow");
>  	if (attr->ingress)
>  		return rte_flow_error_set(error, ENOTSUP,
> 
> RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, @@ -146,6 +147,47 @@  }
> 
>  /**
> + * Validate the L2 decap action.
> + * Used for VXLAN decap action.

Same like before

> + *
> + * @param[in] action_flags
> + *   Holds the actions detected until now.
> + * @param[in] action
> + *   Pointer to the decap action.
> + * @param[in] attr
> + *   Pointer to flow attributes
> + * @param[out] error
> + *   Pointer to error structure.
> + *
> + * @return
> + *   0 on success, a negative errno value otherwise and rte_errno is set.
> + */
> +static int
> +flow_dv_validate_action_l2_decap(uint64_t action_flags,
> +			const struct rte_flow_action *action __rte_unused,
> +			const struct rte_flow_attr *attr,
> +			struct rte_flow_error *error)
> +{
> +	if (action_flags & MLX5_FLOW_ACTION_DROP)
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
> +					  "can't drop and decap in same
> flow");
> +	if (action_flags & (MLX5_FLOW_ACTION_VXLAN_ENCAP |
> +			    MLX5_FLOW_ACTION_VXLAN_DECAP))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
> +					  "can only have a single encap or"
> +					  " decap action in a flow");
> +	if (attr->egress)
> +		return rte_flow_error_set(error, ENOTSUP,
> +
> RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
> +					  NULL,
> +					  "decap action not supported for "
> +					  "egress");
> +	return 0;
> +}
> +
> +/**
>   * Get the size of specific rte_flow_item_type
>   *
>   * @param[in] item_type
> @@ -396,6 +438,38 @@
>  }
> 
>  /**
> + * Convert L2 decap action to DV specification.
> + * Used for VXLAN decap action.

Same 

> + *
> + * @param[in] dev
> + *   Pointer to rte_eth_dev structure.
> + * @param[in] action
> + *   Pointer to action structure.
> + * @param[out] error
> + *   Pointer to the error structure.
> + *
> + * @return
> + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> + */
> +static struct ibv_flow_action *
> +flow_dv_create_action_l2_decap(struct rte_eth_dev *dev,
> +			const struct rte_flow_action *action __rte_unused,
> +			struct rte_flow_error *error)
> +{
> +	struct ibv_flow_action *verbs_action = NULL;
> +	struct priv *priv = dev->data->dev_private;
> +
> +	verbs_action = mlx5_glue-
> >dv_create_flow_action_packet_reformat
> +		(priv->ctx, 0, NULL,
> +
> MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2,
> +		 MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
> +	if (!verbs_action)
> +		rte_flow_error_set(error, EINVAL,
> RTE_FLOW_ERROR_TYPE_ACTION,
> +				   NULL, "cannot create L2 decap action");
> +	return verbs_action;
> +}
> +
> +/**
>   * Verify the @p attributes will be correctly understood by the NIC and store
>   * them in the @p flow if everything is correct.
>   *
> @@ -648,7 +722,15 @@
>  			action_flags |=
> MLX5_FLOW_ACTION_VXLAN_ENCAP;
>  			++actions_n;
>  			break;
> -
> +		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
> +			ret =
> flow_dv_validate_action_l2_decap(action_flags,
> +							       actions, attr,
> +							       error);
> +			if (ret < 0)
> +				return ret;
> +			action_flags |=
> MLX5_FLOW_ACTION_VXLAN_DECAP;
> +			++actions_n;
> +			break;
>  		default:
>  			return rte_flow_error_set(error, ENOTSUP,
> 
> RTE_FLOW_ERROR_TYPE_ACTION,
> @@ -1435,6 +1517,19 @@
>  		flow->actions |= MLX5_FLOW_ACTION_VXLAN_ENCAP;
>  		actions_n++;
>  		break;
> +	case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
> +		dev_flow->dv.actions[actions_n].type =
> +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> +		dev_flow->dv.actions[actions_n].action =
> +				flow_dv_create_action_l2_decap(dev,
> action,
> +							       error);
> +		if (!(dev_flow->dv.actions[actions_n].action))
> +			return -rte_errno;
> +		dev_flow->dv.verbs_action =
> +			dev_flow->dv.actions[actions_n].action;
> +		flow->actions |= MLX5_FLOW_ACTION_VXLAN_DECAP;
> +		actions_n++;
> +		break;
>  	default:
>  		break;
>  	}
> --
> 1.8.3.1

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

* Re: [dpdk-dev] [PATCH v6 6/6] net/mlx5: add raw data encap decap to Direct Verbs
  2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 6/6] net/mlx5: add raw data encap decap " Dekel Peled
@ 2018-10-29 10:03           ` Shahaf Shuler
  2018-10-29 16:54             ` Dekel Peled
  0 siblings, 1 reply; 94+ messages in thread
From: Shahaf Shuler @ 2018-10-29 10:03 UTC (permalink / raw)
  To: Dekel Peled, Yongseok Koh; +Cc: dev, Ori Kam

Thursday, October 25, 2018 11:08 PM, Dekel Peled:
> Subject: [dpdk-dev] [PATCH v6 6/6] net/mlx5: add raw data encap decap to
> Direct Verbs
> 
> This patch implements the encap and decap actions, using raw data, in DV
> flow for MLX5 PMD.
> 
> Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> ---
>  drivers/net/mlx5/mlx5_flow.h    |  12 ++-
>  drivers/net/mlx5/mlx5_flow_dv.c | 227
> ++++++++++++++++++++++++++++++++++++++--
>  2 files changed, 224 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
> index 2d73a05..92ba111 100644
> --- a/drivers/net/mlx5/mlx5_flow.h
> +++ b/drivers/net/mlx5/mlx5_flow.h
> @@ -96,15 +96,19 @@
>  #define MLX5_FLOW_ACTION_VXLAN_DECAP (1u << 23)  #define
> MLX5_FLOW_ACTION_NVGRE_ENCAP (1u << 24)  #define
> MLX5_FLOW_ACTION_NVGRE_DECAP (1u << 25)
> +#define MLX5_FLOW_ACTION_RAW_ENCAP (1u << 26) #define
> +MLX5_FLOW_ACTION_RAW_DECAP (1u << 27)
> 
>  #define MLX5_FLOW_FATE_ACTIONS \
>  	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE |
> MLX5_FLOW_ACTION_RSS)
> 
> -#define MLX5_FLOW_ENCAP_ACTIONS	\
> -	(MLX5_FLOW_ACTION_VXLAN_ENCAP |
> MLX5_FLOW_ACTION_NVGRE_ENCAP)
> +#define MLX5_FLOW_ENCAP_ACTIONS
> 	(MLX5_FLOW_ACTION_VXLAN_ENCAP | \
> +				 MLX5_FLOW_ACTION_NVGRE_ENCAP | \
> +				 MLX5_FLOW_ACTION_RAW_ENCAP)
> 
> -#define MLX5_FLOW_DECAP_ACTIONS	\
> -	(MLX5_FLOW_ACTION_VXLAN_DECAP |
> MLX5_FLOW_ACTION_NVGRE_DECAP)
> +#define MLX5_FLOW_DECAP_ACTIONS
> 	(MLX5_FLOW_ACTION_VXLAN_DECAP | \
> +				 MLX5_FLOW_ACTION_NVGRE_DECAP | \
> +				 MLX5_FLOW_ACTION_RAW_DECAP)
> 
>  #ifndef IPPROTO_MPLS
>  #define IPPROTO_MPLS 137
> diff --git a/drivers/net/mlx5/mlx5_flow_dv.c
> b/drivers/net/mlx5/mlx5_flow_dv.c index d7d0c6b..ca75645 100644
> --- a/drivers/net/mlx5/mlx5_flow_dv.c
> +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> @@ -186,6 +186,82 @@
>  }
> 
>  /**
> + * Validate the raw encap action.
> + *
> + * @param[in] action_flags
> + *   Holds the actions detected until now.
> + * @param[in] action
> + *   Pointer to the encap action.
> + * @param[in] attr
> + *   Pointer to flow attributes
> + * @param[out] error
> + *   Pointer to error structure.
> + *
> + * @return
> + *   0 on success, a negative errno value otherwise and rte_errno is set.
> + */
> +static int
> +flow_dv_validate_action_raw_encap(uint64_t action_flags,
> +				  const struct rte_flow_action *action,
> +				  const struct rte_flow_attr *attr,
> +				  struct rte_flow_error *error)
> +{
> +	if (!(action->conf))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> action,
> +					  "configuration cannot be null");
> +	if (action_flags & MLX5_FLOW_ACTION_DROP)
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
> +					  "can't drop and encap in same
> flow");
> +	if (action_flags & MLX5_FLOW_ENCAP_ACTIONS)
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
> +					  "can only have a single encap"
> +					  " action in a flow");
> +	/* encap without preceding decap is not supported for ingress */
> +	if (attr->ingress && !(action_flags &
> MLX5_FLOW_ACTION_RAW_DECAP))
> +		return rte_flow_error_set(error, ENOTSUP,
> +
> RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> +					  NULL,
> +					  "encap action not supported for "
> +					  "ingress");

The error message doesn't seems informative enough. 

> +	return 0;
> +}
> +
> +/**
> + * Validate the raw decap action.
> + *
> + * @param[in] action_flags
> + *   Holds the actions detected until now.
> + * @param[out] error
> + *   Pointer to error structure.
> + *
> + * @return
> + *   0 on success, a negative errno value otherwise and rte_errno is set.
> + */
> +static int
> +flow_dv_validate_action_raw_decap(uint64_t action_flags,
> +				  struct rte_flow_error *error)
> +{
> +	if (action_flags & MLX5_FLOW_ACTION_DROP)
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
> +					  "can't drop and decap in same
> flow");
> +	if (action_flags & MLX5_FLOW_ENCAP_ACTIONS)
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
> +					  "can't have encap action before"
> +					  " decap action");
> +	if (action_flags & MLX5_FLOW_DECAP_ACTIONS)
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
> +					  "can only have a single decap"
> +					  " action in a flow");

Just like you don't allow to do only encap w/o decap on ingress, on egress we cannot do only decap w/o a subsequent encap. 

> +	return 0;
> +}
> +
> +/**
>   * Get the size of specific rte_flow_item_type
>   *
>   * @param[in] item_type
> @@ -396,6 +472,7 @@
>  /**
>   * Convert L2 encap action to DV specification.
>   * Used for VXLAN and NVGRE encap actions.
> + * Also used for raw encap action without preceding decap.
>   *
>   * @param[in] dev
>   *   Pointer to rte_eth_dev structure.
> @@ -414,23 +491,34 @@
>  {
>  	struct ibv_flow_action *verbs_action = NULL;
>  	const struct rte_flow_item *encap_data;
> +	const struct rte_flow_action_raw_encap *raw_encap_data;

This one can be declared inside the if statement 

>  	struct priv *priv = dev->data->dev_private;
>  	uint8_t buf[MLX5_ENCAP_MAX_LEN];
> +	uint8_t *buf_ptr = buf;

Why you need this buf_ptr? Compilation issue with the fixed sized array of buf?  

>  	size_t size = 0;
>  	int convert_result = 0;
> 
> -	if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP)
> -		encap_data = ((const struct rte_flow_action_vxlan_encap *)
> +	if (action->type == RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
> +		raw_encap_data =
> +			(const struct rte_flow_action_raw_encap *)action-
> >conf;
> +		buf_ptr = raw_encap_data->data;
> +		size = raw_encap_data->size;
> +	} else {
> +		if (action->type ==
> RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP)
> +			encap_data =
> +				((const struct rte_flow_action_vxlan_encap
> *)
>  						action->conf)->definition;
> -	else
> -		encap_data = ((const struct rte_flow_action_nvgre_encap *)
> +		else
> +			encap_data =
> +				((const struct rte_flow_action_nvgre_encap
> *)
>  						action->conf)->definition;
> -	convert_result = flow_dv_convert_encap_data(encap_data, buf,
> -						    &size, error);
> -	if (convert_result)
> -		return NULL;
> +		convert_result = flow_dv_convert_encap_data(encap_data,
> buf,
> +							    &size, error);
> +		if (convert_result)
> +			return NULL;
> +	}
>  	verbs_action = mlx5_glue-
> >dv_create_flow_action_packet_reformat
> -		(priv->ctx, size, (size ? buf : NULL),
> +		(priv->ctx, size, (size ? buf_ptr : NULL),
> 
> MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
>  		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
>  	if (!verbs_action)
> @@ -472,6 +560,50 @@
>  }
> 
>  /**
> + * Convert raw decap/encap (L3 tunnel) action to DV specification.
> + *
> + * @param[in] dev
> + *   Pointer to rte_eth_dev structure.
> + * @param[in] action
> + *   Pointer to action structure.
> + * @param[in] attr
> + *   Pointer to the flow attributes.
> + * @param[out] error
> + *   Pointer to the error structure.
> + *
> + * @return
> + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> + */
> +static struct ibv_flow_action *
> +flow_dv_create_action_raw_encap(struct rte_eth_dev *dev,

I would call it flow_dv_create_action_packet_reformat, as this is the only case this function is being called. 
For raw_encap only you will use the l2_encap function. 

> +				const struct rte_flow_action *action,
> +				const struct rte_flow_attr *attr,
> +				struct rte_flow_error *error)
> +{
> +	struct ibv_flow_action *verbs_action = NULL;
> +	const struct rte_flow_action_raw_encap *encap_data;
> +	struct priv *priv = dev->data->dev_private;
> +	enum mlx5dv_flow_action_packet_reformat_type reformat_type;
> +	enum mlx5dv_flow_table_type ft_type;
> +
> +	encap_data = (const struct rte_flow_action_raw_encap *)action-
> >conf;
> +	reformat_type = attr->egress ?
> +
> 	MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TU
> NNEL :
> +
> 	MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_T
> O_L2;
> +	ft_type = attr->egress ?
> +			MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
> +			MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
> +	verbs_action = mlx5_glue-
> >dv_create_flow_action_packet_reformat
> +				(priv->ctx, encap_data->size,
> +				(encap_data->size ? encap_data->data :
> NULL),
> +				reformat_type, ft_type);
> +	if (!verbs_action)
> +		rte_flow_error_set(error, EINVAL,
> RTE_FLOW_ERROR_TYPE_ACTION,
> +				   NULL, "cannot create encap action");
> +	return verbs_action;
> +}
> +
> +/**
>   * Verify the @p attributes will be correctly understood by the NIC and store
>   * them in the @p flow if everything is correct.
>   *
> @@ -726,7 +858,6 @@
> 
> 	RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP ?
> 
> 	MLX5_FLOW_ACTION_VXLAN_ENCAP :
> 
> 	MLX5_FLOW_ACTION_NVGRE_ENCAP;
> -
>  			++actions_n;
>  			break;
>  		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
> @@ -740,7 +871,23 @@
> 
> 	RTE_FLOW_ACTION_TYPE_VXLAN_DECAP ?
> 
> 	MLX5_FLOW_ACTION_VXLAN_DECAP :
> 
> 	MLX5_FLOW_ACTION_NVGRE_DECAP;
> -
> +			++actions_n;
> +			break;
> +		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
> +			ret =
> flow_dv_validate_action_raw_encap(action_flags,
> +								actions, attr,
> +								error);
> +			if (ret < 0)
> +				return ret;
> +			action_flags |= MLX5_FLOW_ACTION_RAW_ENCAP;
> +			++actions_n;
> +			break;
> +		case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
> +			ret =
> flow_dv_validate_action_raw_decap(action_flags,
> +								error);
> +			if (ret < 0)
> +				return ret;
> +			action_flags |= MLX5_FLOW_ACTION_RAW_DECAP;
>  			++actions_n;
>  			break;
>  		default:
> @@ -1550,6 +1697,64 @@
>  				 MLX5_FLOW_ACTION_NVGRE_DECAP;
>  		actions_n++;
>  		break;
> +	case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
> +		/* Handle encap action with preceding decap */
> +		if (flow->actions & MLX5_FLOW_ACTION_RAW_DECAP) {
> +			dev_flow->dv.actions[actions_n].type =
> +
> 	MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> +			dev_flow->dv.actions[actions_n].action =
> +					flow_dv_create_action_raw_encap
> +								(dev, action,
> +								 attr, error);
> +			if (!(dev_flow->dv.actions[actions_n].action))
> +				return -rte_errno;
> +			dev_flow->dv.verbs_action =
> +				dev_flow->dv.actions[actions_n].action;
> +		} else {
> +			/* Handle encap action without preceding decap */
> +			dev_flow->dv.actions[actions_n].type =
> +
> 	MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> +			dev_flow->dv.actions[actions_n].action =
> +					flow_dv_create_action_l2_encap
> +							(dev, action, error);
> +			if (!(dev_flow->dv.actions[actions_n].action))
> +				return -rte_errno;
> +			dev_flow->dv.verbs_action =
> +				dev_flow->dv.actions[actions_n].action;
> +		}
> +		flow->actions |= MLX5_FLOW_ACTION_RAW_ENCAP;
> +		actions_n++;
> +		break;
> +	case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
> +		/* Check if this decap action is followed by encap. */
> +		for (; action->type != RTE_FLOW_ACTION_TYPE_END &&
> +		       action->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP;
> +		       action++) {
> +		}
> +		/* Handle decap action only if it isn't followed by encap */
> +		if (action->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
> +			/* on egress, decap without following encap is error.
> */
> +			if (attr->egress)
> +				return rte_flow_error_set
> +					(error, ENOTSUP,
> +
> RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
> +					 NULL,
> +					 "decap action not supported for "
> +					 "egress");

This check should have been performed on the validate stage. 

> +			dev_flow->dv.actions[actions_n].type =
> +
> 	MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> +			dev_flow->dv.actions[actions_n].action =
> +					flow_dv_create_action_l2_decap
> +							(dev, action, error);
> +			if (!(dev_flow->dv.actions[actions_n].action))
> +				return -rte_errno;
> +			dev_flow->dv.verbs_action =
> +				dev_flow->dv.actions[actions_n].action;
> +			actions_n++;
> +		}
> +		/* If decap is followed by encap, handle it at encap case. */
> +		flow->actions |= MLX5_FLOW_ACTION_RAW_DECAP;
> +		break;
>  	default:
>  		break;
>  	}
> --
> 1.8.3.1

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

* Re: [dpdk-dev] [PATCH v6 0/6] add encap and decap actions to Direct Verbs flow in MLX5 PMD
  2018-10-29 10:03           ` Shahaf Shuler
@ 2018-10-29 14:42             ` Dekel Peled
  0 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-29 14:42 UTC (permalink / raw)
  To: Shahaf Shuler, Yongseok Koh; +Cc: dev, Ori Kam

Thanks, PSB.

> -----Original Message-----
> From: Shahaf Shuler
> Sent: Monday, October 29, 2018 12:03 PM
> To: Dekel Peled <dekelp@mellanox.com>; Yongseok Koh
> <yskoh@mellanox.com>
> Cc: dev@dpdk.org; Ori Kam <orika@mellanox.com>
> Subject: RE: [dpdk-dev] [PATCH v6 0/6] add encap and decap actions to
> Direct Verbs flow in MLX5 PMD
> 
> Hi Dekel,
> 
> Thursday, October 25, 2018 11:08 PM, Dekel Peled:
> > Subject: [dpdk-dev] [PATCH v6 0/6] add encap and decap actions to
> > Direct Verbs flow in MLX5 PMD
> >
> > This series adds support of encap and decap actions in DV format.
> > L2 tunnel support for VXLAN and NVGRE, and L2/L3 tunnel support using
> > raw data buffer.
> > It is using the generic encapsulation framework from [1].
> >
> > [1] "ethdev: add generic L2/L3 tunnel encapsulation actions"
> >
> >
> https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmail
> > s.dpdk.org%2Farchives%2Fdev%2F2018-
> >
> October%2F114654.html&amp;data=02%7C01%7Cshahafs%40mellanox.com
> >
> %7C5c61dd00f0ea45acba0608d63ab5c0e6%7Ca652971c7d2e4d9ba6a4d14925
> >
> 6f461b%7C0%7C0%7C636760949640981142&amp;sdata=tdOJhJfndTAP6Uotk
> > MJrkgBsa7AXljXJRMPsivfveUo%3D&amp;reserved=0
> 
> In general looks good, please see some comments to address.

Thanks, will do.

> 
> >
> > ---
> > v6:
> > * Adapt L2 tunnel to VXLAN and NVGRE
> > * Add encap/decap using raw data
> > v5:
> > * Move DV actions code under common DV flag.
> > v4:
> > * Update in glue functions.
> > v3:
> > * Apply additional code review comments.
> > v2:
> > * Rebase on tip.
> > * Apply code review comments.
> >
> >
> > Dekel Peled (6):
> >   net/mlx5: add flow action functions to glue
> >   net/mlx5: add VXLAN encap action to Direct Verbs
> >   net/mlx5: add VXLAN decap action to Direct Verbs
> >   net/mlx5: add NVGRE encap action to Direct Verbs
> >   net/mlx5: add NVGRE decap action to Direct Verbs
> >   net/mlx5: add raw data encap decap to Direct Verbs
> >
> >  drivers/net/mlx5/Makefile       |   2 +-
> >  drivers/net/mlx5/meson.build    |   2 +-
> >  drivers/net/mlx5/mlx5_flow.h    |  15 +
> >  drivers/net/mlx5/mlx5_flow_dv.c | 671
> > +++++++++++++++++++++++++++++++++++++++-
> >  drivers/net/mlx5/mlx5_glue.c    |  38 +++
> >  drivers/net/mlx5/mlx5_glue.h    |  10 +
> >  6 files changed, 731 insertions(+), 7 deletions(-)
> >
> > --
> > 1.8.3.1

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

* Re: [dpdk-dev] [PATCH v6 2/6] net/mlx5: add VXLAN encap action to Direct Verbs
  2018-10-29 10:03           ` Shahaf Shuler
@ 2018-10-29 16:44             ` Dekel Peled
  0 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-29 16:44 UTC (permalink / raw)
  To: Shahaf Shuler, Yongseok Koh; +Cc: dev, Ori Kam

Thanks, PSB.

> -----Original Message-----
> From: Shahaf Shuler
> Sent: Monday, October 29, 2018 12:03 PM
> To: Dekel Peled <dekelp@mellanox.com>; Yongseok Koh
> <yskoh@mellanox.com>
> Cc: dev@dpdk.org; Ori Kam <orika@mellanox.com>
> Subject: RE: [dpdk-dev] [PATCH v6 2/6] net/mlx5: add VXLAN encap action to
> Direct Verbs
> 
> Hi Dekel,
> 
> Thursday, October 25, 2018 11:08 PM, Dekel Peled:
> > Subject: [dpdk-dev] [PATCH v6 2/6] net/mlx5: add VXLAN encap action to
> > Direct Verbs
> >
> > This patch implements the VXLAN encap action in DV flow for MLX5 PMD.
> >
> > Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> > ---
> >  drivers/net/mlx5/mlx5_flow.h    |   2 +
> >  drivers/net/mlx5/mlx5_flow_dv.c | 351
> > +++++++++++++++++++++++++++++++++++++++-
> >  2 files changed, 348 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/net/mlx5/mlx5_flow.h
> > b/drivers/net/mlx5/mlx5_flow.h index 61299d6..6e92afe 100644
> > --- a/drivers/net/mlx5/mlx5_flow.h
> > +++ b/drivers/net/mlx5/mlx5_flow.h
> > @@ -92,6 +92,7 @@
> >  #define MLX5_FLOW_ACTION_DEC_TTL (1u << 19)  #define
> > MLX5_FLOW_ACTION_SET_MAC_SRC (1u << 20)  #define
> > MLX5_FLOW_ACTION_SET_MAC_DST (1u << 21)
> > +#define MLX5_FLOW_ACTION_VXLAN_ENCAP (1u << 22)
> >
> >  #define MLX5_FLOW_FATE_ACTIONS \
> >  	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE |
> > MLX5_FLOW_ACTION_RSS) @@ -181,6 +182,7 @@ struct mlx5_flow_dv {
> #ifdef
> > HAVE_IBV_FLOW_DV_SUPPORT
> >  	struct mlx5dv_flow_action_attr
> > actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS];
> >  	/**< Action list. */
> > +	struct ibv_flow_action *verbs_action; /**< Verbs encap/decap
> 
> The ibv_flow_action is already part of a union inside
> mlx5dv_flow_action_attr, why you need it separately?
> I see also in the below code that you copy it from the action list to this
> specific field. Can you elaborate why?
> 

I added it to use when flow rule is removed, for easy access to the action to destroy.
I am now changing the code per 17.11 PR 876, adding cache of encap/decap actions, so this member is no longer needed, and will be removed.

> > object.
> > +*/
> >  #endif
> >  	int actions_n; /**< number of actions. */  }; diff --git
> > a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
> > index 8f729f4..14110c5 100644
> > --- a/drivers/net/mlx5/mlx5_flow_dv.c
> > +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> > @@ -34,6 +34,12 @@
> >
> >  #ifdef HAVE_IBV_FLOW_DV_SUPPORT
> >
> > +/*
> > + * Encap buf length, max:
> > + *   Eth:14/VLAN:8/IPv6:40/TCP:36/TUNNEL:20/Eth:14
> 
> VLAN is 4B not 8B. which tunnel is for 20B?

This is code I reused from 17.11, I will verify it.

> 
> > + */
> > +#define MLX5_ENCAP_MAX_LEN 132
> > +
> >  /**
> >   * Validate META item.
> >   *
> > @@ -96,6 +102,300 @@
> >  }
> >
> >  /**
> > + * Validate the L2 encap action.
> > + * Used for VXLAN encap action.
> 
> No need for that. Later on you put more supported protocols. This is a
> generic function for L2 encap validation.

I will remove it.

> 
> > + *
> > + * @param[in] action_flags
> > + *   Holds the actions detected until now.
> > + * @param[in] action
> > + *   Pointer to the encap action.
> > + * @param[in] attr
> > + *   Pointer to flow attributes
> > + * @param[out] error
> > + *   Pointer to error structure.
> > + *
> > + * @return
> > + *   0 on success, a negative errno value otherwise and rte_errno is set.
> > + */
> > +static int
> > +flow_dv_validate_action_l2_encap(uint64_t action_flags,
> > +				 const struct rte_flow_action *action,
> > +				 const struct rte_flow_attr *attr,
> > +				 struct rte_flow_error *error)
> > +{
> > +	if (!(action->conf))
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > action,
> > +					  "configuration cannot be null");
> > +	if (action_flags & MLX5_FLOW_ACTION_DROP)
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > NULL,
> > +					  "can't drop and encap in same
> > flow");
> > +	if (action_flags & MLX5_FLOW_ACTION_VXLAN_ENCAP)
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > NULL,
> > +					  "can only have a single encap"
> > +					  " action in a flow");
> > +	if (attr->ingress)
> > +		return rte_flow_error_set(error, ENOTSUP,
> > +
> > RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> > +					  NULL,
> > +					  "encap action not supported for "
> > +					  "ingress");
> > +	return 0;
> > +}
> > +
> > +/**
> > + * Get the size of specific rte_flow_item_type
> > + *
> > + * @param[in] item_type
> > + *   Tested rte_flow_item_type.
> > + *
> > + * @return
> > + *   sizeof struct item_type, 0 if void or irrelevant.
> > + */
> > +static size_t
> > +flow_dv_get_item_len(const enum rte_flow_item_type item_type) {
> 
> Can we have this function as a macro?
> 
> #define flow_dv_get_item_len(t) (strncpm(t, VOID, 4) ? 0 : sizeof(struct
> rte_flow_item_##t)
> 
> Usage: flow_dv_get_item_len(ETH)
> 

I will change it.

> 
> > +	size_t retval;
> > +
> > +	switch (item_type) {
> > +	case RTE_FLOW_ITEM_TYPE_ETH:
> > +		retval = sizeof(struct rte_flow_item_eth);
> > +		break;
> > +	case RTE_FLOW_ITEM_TYPE_VLAN:
> > +		retval = sizeof(struct rte_flow_item_vlan);
> > +		break;
> > +	case RTE_FLOW_ITEM_TYPE_IPV4:
> > +		retval = sizeof(struct rte_flow_item_ipv4);
> > +		break;
> > +	case RTE_FLOW_ITEM_TYPE_IPV6:
> > +		retval = sizeof(struct rte_flow_item_ipv6);
> > +		break;
> > +	case RTE_FLOW_ITEM_TYPE_UDP:
> > +		retval = sizeof(struct rte_flow_item_udp);
> > +		break;
> > +	case RTE_FLOW_ITEM_TYPE_TCP:
> > +		retval = sizeof(struct rte_flow_item_tcp);
> > +		break;
> > +	case RTE_FLOW_ITEM_TYPE_VXLAN:
> > +		retval = sizeof(struct rte_flow_item_vxlan);
> > +		break;
> > +	case RTE_FLOW_ITEM_TYPE_GRE:
> > +		retval = sizeof(struct rte_flow_item_gre);
> > +		break;
> > +	case RTE_FLOW_ITEM_TYPE_NVGRE:
> > +		retval = sizeof(struct rte_flow_item_nvgre);
> > +		break;
> > +	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
> > +		retval = sizeof(struct rte_flow_item_vxlan_gpe);
> > +		break;
> > +	case RTE_FLOW_ITEM_TYPE_MPLS:
> > +		retval = sizeof(struct rte_flow_item_mpls);
> > +		break;
> > +	case RTE_FLOW_ITEM_TYPE_VOID: /* Fall through. */
> > +	default:
> > +		retval = 0;
> > +		break;
> > +	}
> > +	return retval;
> > +};
> > +
> > +/**
> > + * Convert the encap action data from rte_flow_item to raw buffer
> > + *
> > + * @param[in] item
> > + *   Pointer to rte_flow_item object.
> 
> Since it is an item list, "items" is preferable.

I will rename it.

> 
> > + * @param[out] buf
> > + *   Pointer to the output buffer.
> > + * @param[out] size
> > + *   Pointer to the output buffer size.
> > + * @param[out] error
> > + *   Pointer to the error structure.
> > + *
> > + * @return
> > + *   0 on success, a negative errno value otherwise and rte_errno is set.
> > + */
> > +static int
> > +flow_dv_convert_encap_data(const struct rte_flow_item *item, uint8_t
> > *buf,
> > +			   size_t *size, struct rte_flow_error *error) {
> > +	struct ether_hdr *eth = NULL;
> > +	struct vlan_hdr *vlan = NULL;
> > +	struct ipv4_hdr *ipv4 = NULL;
> > +	struct ipv6_hdr *ipv6 = NULL;
> > +	struct udp_hdr *udp = NULL;
> > +	struct vxlan_hdr *vxlan = NULL;
> > +	size_t len;
> > +	size_t temp_size = 0;
> > +
> > +	if (!item)
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > +					  NULL, "invalid empty data");
> > +	for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
> > +		len = flow_dv_get_item_len(item->type);
> > +		if (len + temp_size > MLX5_ENCAP_MAX_LEN)
> > +			return rte_flow_error_set(error, EINVAL,
> > +
> > RTE_FLOW_ERROR_TYPE_ACTION,
> > +						  (void *)item->type,
> > +						  "invalid item length");
> 
> It is not invalid item length, it is items total size is too big for encap.

I will change it.

> 
> > +		rte_memcpy((void *)&buf[temp_size], item->spec, len);
> > +		switch (item->type) {
> > +		case RTE_FLOW_ITEM_TYPE_ETH:
> > +			eth = (struct ether_hdr *)&buf[temp_size];
> > +			break;
> > +		case RTE_FLOW_ITEM_TYPE_VLAN:
> > +			vlan = (struct vlan_hdr *)&buf[temp_size];
> > +			if (!eth)
> > +				return rte_flow_error_set(error, EINVAL,
> > +
> > 	RTE_FLOW_ERROR_TYPE_ACTION,
> > +						(void *)item->type,
> > +						"eth header not found");
> > +			if (!eth->ether_type)
> > +				eth->ether_type =
> > RTE_BE16(ETHER_TYPE_VLAN);
> > +			break;
> > +		case RTE_FLOW_ITEM_TYPE_IPV4:
> > +			ipv4 = (struct ipv4_hdr *)&buf[temp_size];
> > +			if (!vlan && !eth)
> > +				return rte_flow_error_set(error, EINVAL,
> > +
> > 	RTE_FLOW_ERROR_TYPE_ACTION,
> > +						(void *)item->type,
> > +						"neither eth nor vlan"
> > +						" header found");
> > +			if (vlan && !vlan->eth_proto)
> > +				vlan->eth_proto =
> > RTE_BE16(ETHER_TYPE_IPv4);
> > +			else if (eth && !eth->ether_type)
> > +				eth->ether_type =
> > RTE_BE16(ETHER_TYPE_IPv4);
> > +			if (!ipv4->version_ihl)
> > +				ipv4->version_ihl = 0x45;
> > +			if (!ipv4->time_to_live)
> > +				ipv4->time_to_live = 0x40;
> 
> If no existing macro have those two above defined as ones.
> There are few more places on this function related to this comment.

I will change it.

> 
> > +			break;
> > +		case RTE_FLOW_ITEM_TYPE_IPV6:
> > +			ipv6 = (struct ipv6_hdr *)&buf[temp_size];
> > +			if (!vlan && !eth)
> > +				return rte_flow_error_set(error, EINVAL,
> > +
> > 	RTE_FLOW_ERROR_TYPE_ACTION,
> > +						(void *)item->type,
> > +						"neither eth nor vlan"
> > +						" header found");
> > +			if (vlan && !vlan->eth_proto)
> > +				vlan->eth_proto =
> > RTE_BE16(ETHER_TYPE_IPv6);
> > +			else if (eth && !eth->ether_type)
> > +				eth->ether_type =
> > RTE_BE16(ETHER_TYPE_IPv6);
> > +			if (!ipv6->vtc_flow)
> > +				ipv6->vtc_flow = RTE_BE32(0x60000000);
> > +			if (!ipv6->hop_limits)
> > +				ipv6->hop_limits = 0xff;
> > +			break;
> > +		case RTE_FLOW_ITEM_TYPE_UDP:
> > +			udp = (struct udp_hdr *)&buf[temp_size];
> > +			if (!ipv4 && !ipv6)
> > +				return rte_flow_error_set(error, EINVAL,
> > +
> > 	RTE_FLOW_ERROR_TYPE_ACTION,
> > +						(void *)item->type,
> > +						"ip header not found");
> > +			if (ipv4 && !ipv4->next_proto_id)
> > +				ipv4->next_proto_id = IPPROTO_UDP;
> > +			else if (ipv6 && !ipv6->proto)
> > +				ipv6->proto = IPPROTO_UDP;
> > +			break;
> > +		case RTE_FLOW_ITEM_TYPE_VXLAN:
> > +			vxlan = (struct vxlan_hdr *)&buf[temp_size];
> > +			if (!udp)
> > +				return rte_flow_error_set(error, EINVAL,
> > +
> > 	RTE_FLOW_ERROR_TYPE_ACTION,
> > +						(void *)item->type,
> > +						"udp header not found");
> > +			if (!udp->dst_port)
> > +				udp->dst_port =
> > RTE_BE16(MLX5_UDP_PORT_VXLAN);
> > +			if (!vxlan->vx_flags)
> > +				vxlan->vx_flags = RTE_BE32(0x08000000);
> > +			break;
> > +		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
> > +			vxlan = (struct vxlan_hdr *)&buf[temp_size];
> > +			if (!udp)
> > +				return rte_flow_error_set(error, EINVAL,
> > +
> > 	RTE_FLOW_ERROR_TYPE_ACTION,
> > +						(void *)item->type,
> > +						"udp header not found");
> > +			if (!udp->dst_port)
> > +				udp->dst_port =
> > +
> > 	RTE_BE16(MLX5_UDP_PORT_VXLAN_GPE);
> > +			if (!vxlan->vx_flags)
> > +				vxlan->vx_flags = RTE_BE32(0x0c000003);
> 
> I would say you cannot set internally the next protocol. Only the user know
> what it is.
> I think in case VXLAN_GPE is set on the item list, the next_proto field is a
> must, otherwise the rule should be rejected.

I will verify it.

> 
> > +			break;
> > +		case RTE_FLOW_ITEM_TYPE_GRE:
> > +		case RTE_FLOW_ITEM_TYPE_NVGRE:
> > +			if (!ipv4 && !ipv6)
> > +				return rte_flow_error_set(error, EINVAL,
> > +
> > 	RTE_FLOW_ERROR_TYPE_ACTION,
> > +						(void *)item->type,
> > +						"ip header not found");
> > +			if (ipv4 && !ipv4->next_proto_id)
> > +				ipv4->next_proto_id = IPPROTO_GRE;
> > +			else if (ipv6 && !ipv6->proto)
> > +				ipv6->proto = IPPROTO_GRE;
> 
> This patch is for VXLAN, yet you add a GRE/NVGRE code block. It is better to
> add it on the subsequent patches adding this feature.
> 

I will move it to next patch.

> Also you need to check if the user put the protocol type on the GRE header.
> Same as the VXLAN-GPE case, this is a must.
> 

I will add it.

> > +			break;
> > +		case RTE_FLOW_ITEM_TYPE_VOID:
> > +			break;
> > +		default:
> > +			return rte_flow_error_set(error, EINVAL,
> > +
> > RTE_FLOW_ERROR_TYPE_ACTION,
> > +						  (void *)item->type,
> > +						  "unsupported item type");
> > +			break;
> > +		}
> > +		temp_size += len;
> > +	}
> > +	*size = temp_size;
> > +	return 0;
> > +}
> > +
> > +/**
> > + * Convert L2 encap action to DV specification.
> > + * Used for VXLAN encap action.
> 
> Same - no need to specific which exact protocols.

I will remove it.

> 
> > + *
> > + * @param[in] dev
> > + *   Pointer to rte_eth_dev structure.
> > + * @param[in] action
> > + *   Pointer to action structure.
> > + * @param[out] error
> > + *   Pointer to the error structure.
> > + *
> > + * @return
> > + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> > + */
> > +static struct ibv_flow_action *
> > +flow_dv_create_action_l2_encap(struct rte_eth_dev *dev,
> > +			       const struct rte_flow_action *action,
> > +			       struct rte_flow_error *error) {
> > +	struct ibv_flow_action *verbs_action = NULL;
> > +	const struct rte_flow_item *encap_data;
> > +	struct priv *priv = dev->data->dev_private;
> > +	uint8_t buf[MLX5_ENCAP_MAX_LEN];
> > +	size_t size = 0;
> > +	int convert_result = 0;
> > +
> > +	encap_data = ((const struct rte_flow_action_vxlan_encap *)
> > +						action->conf)->definition;
> > +	convert_result = flow_dv_convert_encap_data(encap_data, buf,
> > +						    &size, error);
> > +	if (convert_result)
> > +		return NULL;
> > +	verbs_action = mlx5_glue-
> > >dv_create_flow_action_packet_reformat
> > +		(priv->ctx, size, (size ? buf : NULL),
> 
> How can size be 0 and yet the encap action is valid?

It can't, this is just for safety.
I will remove it.

> 
> > +
> > MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
> > +		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
> > +	if (!verbs_action)
> > +		rte_flow_error_set(error, EINVAL,
> > RTE_FLOW_ERROR_TYPE_ACTION,
> > +				   NULL, "cannot create L2 encap action");
> > +	return verbs_action;
> > +}
> > +
> > +/**
> >   * Verify the @p attributes will be correctly understood by the NIC and
> store
> >   * them in the @p flow if everything is correct.
> >   *
> > @@ -339,6 +639,16 @@
> >  			action_flags |= MLX5_FLOW_ACTION_COUNT;
> >  			++actions_n;
> >  			break;
> > +		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
> > +			ret =
> > flow_dv_validate_action_l2_encap(action_flags,
> > +							       actions, attr,
> > +							       error);
> > +			if (ret < 0)
> > +				return ret;
> > +			action_flags |=
> > MLX5_FLOW_ACTION_VXLAN_ENCAP;
> > +			++actions_n;
> > +			break;
> > +
> >  		default:
> >  			return rte_flow_error_set(error, ENOTSUP,
> >
> > RTE_FLOW_ERROR_TYPE_ACTION,
> > @@ -1045,14 +1355,26 @@
> >  /**
> >   * Store the requested actions in an array.
> >   *
> > + * @param[in] dev
> > + *   Pointer to rte_eth_dev structure.
> >   * @param[in] action
> >   *   Flow action to translate.
> >   * @param[in, out] dev_flow
> >   *   Pointer to the mlx5_flow.
> > + * @param[in] attr
> > + *   Pointer to the flow attributes.
> > + * @param[out] error
> > + *   Pointer to the error structure.
> > + *
> > + * @return
> > + *   0 on success, a negative errno value otherwise and rte_errno is set.
> >   */
> > -static void
> > -flow_dv_create_action(const struct rte_flow_action *action,
> > -		      struct mlx5_flow *dev_flow)
> > +static int
> > +flow_dv_create_action(struct rte_eth_dev *dev,
> > +		      const struct rte_flow_action *action,
> > +		      struct mlx5_flow *dev_flow,
> > +		      const struct rte_flow_attr *attr __rte_unused,
> 
> It was better to add this when you add the RAW encap feature. Now they
> marked as unused, and you didn't changed that when you actually started to
> use them.
> Need to choose one of the paths:
> 1. add them on the RAW encap/decap support (better) 2. remove the
> rte_unused on the RAW encap/decap support
> 

I will move it to later patch.

> 
> > +		      struct rte_flow_error *error)
> >  {
> >  	const struct rte_flow_action_queue *queue;
> >  	const struct rte_flow_action_rss *rss; @@ -1100,10 +1422,24 @@
> >  		/* Added to array only in apply since we need the QP */
> >  		flow->actions |= MLX5_FLOW_ACTION_RSS;
> >  		break;
> > +	case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
> > +		dev_flow->dv.actions[actions_n].type =
> > +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> > +		dev_flow->dv.actions[actions_n].action =
> > +				flow_dv_create_action_l2_encap(dev,
> > action,
> > +							       error);
> > +		if (!(dev_flow->dv.actions[actions_n].action))
> > +			return -rte_errno;
> > +		dev_flow->dv.verbs_action =
> > +			dev_flow->dv.actions[actions_n].action;
> > +		flow->actions |= MLX5_FLOW_ACTION_VXLAN_ENCAP;
> > +		actions_n++;
> > +		break;
> >  	default:
> >  		break;
> >  	}
> >  	dev_flow->dv.actions_n = actions_n;
> > +	return 0;
> >  }
> >
> >  static uint32_t matcher_zero[MLX5_ST_SZ_DW(fte_match_param)] = { 0 };
> > @@ -1217,7 +1553,6 @@
> >  	return 0;
> >  }
> >
> > -
> >  /**
> >   * Fill the flow with DV spec.
> >   *
> > @@ -1272,7 +1607,8 @@
> >  	if (flow_dv_matcher_register(dev, &matcher, dev_flow, error))
> >  		return -rte_errno;
> >  	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++)
> > -		flow_dv_create_action(actions, dev_flow);
> > +		if (flow_dv_create_action(dev, actions, dev_flow, attr,
> > error))
> > +			return -rte_errno;
> >  	return 0;
> >  }
> >
> > @@ -1457,6 +1793,11 @@
> >  		LIST_REMOVE(dev_flow, next);
> >  		if (dev_flow->dv.matcher)
> >  			flow_dv_matcher_release(dev, dev_flow);
> > +		if (dev_flow->dv.verbs_action) {
> 
> Like I said in the beginning, I don't understand why this field is separate from
> the mlx5dv action list.
> 
> > +			claim_zero(mlx5_glue->destroy_flow_action
> > +						(dev_flow-
> > >dv.verbs_action));
> > +			dev_flow->dv.verbs_action = NULL;
> > +		}
> >  		rte_free(dev_flow);
> >  	}
> >  }
> > --
> > 1.8.3.1

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

* Re: [dpdk-dev] [PATCH v6 3/6] net/mlx5: add VXLAN decap action to Direct Verbs
  2018-10-29 10:03           ` Shahaf Shuler
@ 2018-10-29 16:46             ` Dekel Peled
  0 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-29 16:46 UTC (permalink / raw)
  To: Shahaf Shuler, Yongseok Koh; +Cc: dev, Ori Kam

Thanks, PSB.

> -----Original Message-----
> From: Shahaf Shuler
> Sent: Monday, October 29, 2018 12:03 PM
> To: Dekel Peled <dekelp@mellanox.com>; Yongseok Koh
> <yskoh@mellanox.com>
> Cc: dev@dpdk.org; Ori Kam <orika@mellanox.com>
> Subject: RE: [dpdk-dev] [PATCH v6 3/6] net/mlx5: add VXLAN decap action to
> Direct Verbs
> 
> Thursday, October 25, 2018 11:08 PM, Dekel Peled:
> > Subject: [dpdk-dev] [PATCH v6 3/6] net/mlx5: add VXLAN decap action to
> > Direct Verbs
> >
> > This patch implements the VXLAN decap action in DV flow for MLX5 PMD.
> >
> > Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> > ---
> >  drivers/net/mlx5/mlx5_flow.h    |   1 +
> >  drivers/net/mlx5/mlx5_flow_dv.c | 103
> > ++++++++++++++++++++++++++++++++++++++--
> >  2 files changed, 100 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/net/mlx5/mlx5_flow.h
> > b/drivers/net/mlx5/mlx5_flow.h index 6e92afe..3795644 100644
> > --- a/drivers/net/mlx5/mlx5_flow.h
> > +++ b/drivers/net/mlx5/mlx5_flow.h
> > @@ -93,6 +93,7 @@
> >  #define MLX5_FLOW_ACTION_SET_MAC_SRC (1u << 20)  #define
> > MLX5_FLOW_ACTION_SET_MAC_DST (1u << 21)  #define
> > MLX5_FLOW_ACTION_VXLAN_ENCAP (1u << 22)
> > +#define MLX5_FLOW_ACTION_VXLAN_DECAP (1u << 23)
> >
> >  #define MLX5_FLOW_FATE_ACTIONS \
> >  	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE |
> > MLX5_FLOW_ACTION_RSS) diff --git a/drivers/net/mlx5/mlx5_flow_dv.c
> > b/drivers/net/mlx5/mlx5_flow_dv.c index 14110c5..e84a2b6 100644
> > --- a/drivers/net/mlx5/mlx5_flow_dv.c
> > +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> > @@ -131,11 +131,12 @@
> >  		return rte_flow_error_set(error, EINVAL,
> >  					  RTE_FLOW_ERROR_TYPE_ACTION,
> > NULL,
> >  					  "can't drop and encap in same
> > flow");
> > -	if (action_flags & MLX5_FLOW_ACTION_VXLAN_ENCAP)
> > +	if (action_flags & (MLX5_FLOW_ACTION_VXLAN_ENCAP |
> > +			    MLX5_FLOW_ACTION_VXLAN_DECAP))
> >  		return rte_flow_error_set(error, EINVAL,
> >  					  RTE_FLOW_ERROR_TYPE_ACTION,
> > NULL,
> > -					  "can only have a single encap"
> > -					  " action in a flow");
> > +					  "can only have a single encap or"
> > +					  " decap action in a flow");
> >  	if (attr->ingress)
> >  		return rte_flow_error_set(error, ENOTSUP,
> >
> > RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, @@ -146,6 +147,47 @@  }
> >
> >  /**
> > + * Validate the L2 decap action.
> > + * Used for VXLAN decap action.
> 
> Same like before

I will remove it.

> 
> > + *
> > + * @param[in] action_flags
> > + *   Holds the actions detected until now.
> > + * @param[in] action
> > + *   Pointer to the decap action.
> > + * @param[in] attr
> > + *   Pointer to flow attributes
> > + * @param[out] error
> > + *   Pointer to error structure.
> > + *
> > + * @return
> > + *   0 on success, a negative errno value otherwise and rte_errno is set.
> > + */
> > +static int
> > +flow_dv_validate_action_l2_decap(uint64_t action_flags,
> > +			const struct rte_flow_action *action __rte_unused,
> > +			const struct rte_flow_attr *attr,
> > +			struct rte_flow_error *error)
> > +{
> > +	if (action_flags & MLX5_FLOW_ACTION_DROP)
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > NULL,
> > +					  "can't drop and decap in same
> > flow");
> > +	if (action_flags & (MLX5_FLOW_ACTION_VXLAN_ENCAP |
> > +			    MLX5_FLOW_ACTION_VXLAN_DECAP))
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > NULL,
> > +					  "can only have a single encap or"
> > +					  " decap action in a flow");
> > +	if (attr->egress)
> > +		return rte_flow_error_set(error, ENOTSUP,
> > +
> > RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
> > +					  NULL,
> > +					  "decap action not supported for "
> > +					  "egress");
> > +	return 0;
> > +}
> > +
> > +/**
> >   * Get the size of specific rte_flow_item_type
> >   *
> >   * @param[in] item_type
> > @@ -396,6 +438,38 @@
> >  }
> >
> >  /**
> > + * Convert L2 decap action to DV specification.
> > + * Used for VXLAN decap action.
> 
> Same

I will remove it.

> 
> > + *
> > + * @param[in] dev
> > + *   Pointer to rte_eth_dev structure.
> > + * @param[in] action
> > + *   Pointer to action structure.
> > + * @param[out] error
> > + *   Pointer to the error structure.
> > + *
> > + * @return
> > + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> > + */
> > +static struct ibv_flow_action *
> > +flow_dv_create_action_l2_decap(struct rte_eth_dev *dev,
> > +			const struct rte_flow_action *action __rte_unused,
> > +			struct rte_flow_error *error)
> > +{
> > +	struct ibv_flow_action *verbs_action = NULL;
> > +	struct priv *priv = dev->data->dev_private;
> > +
> > +	verbs_action = mlx5_glue-
> > >dv_create_flow_action_packet_reformat
> > +		(priv->ctx, 0, NULL,
> > +
> > MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2,
> > +		 MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
> > +	if (!verbs_action)
> > +		rte_flow_error_set(error, EINVAL,
> > RTE_FLOW_ERROR_TYPE_ACTION,
> > +				   NULL, "cannot create L2 decap action");
> > +	return verbs_action;
> > +}
> > +
> > +/**
> >   * Verify the @p attributes will be correctly understood by the NIC and
> store
> >   * them in the @p flow if everything is correct.
> >   *
> > @@ -648,7 +722,15 @@
> >  			action_flags |=
> > MLX5_FLOW_ACTION_VXLAN_ENCAP;
> >  			++actions_n;
> >  			break;
> > -
> > +		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
> > +			ret =
> > flow_dv_validate_action_l2_decap(action_flags,
> > +							       actions, attr,
> > +							       error);
> > +			if (ret < 0)
> > +				return ret;
> > +			action_flags |=
> > MLX5_FLOW_ACTION_VXLAN_DECAP;
> > +			++actions_n;
> > +			break;
> >  		default:
> >  			return rte_flow_error_set(error, ENOTSUP,
> >
> > RTE_FLOW_ERROR_TYPE_ACTION,
> > @@ -1435,6 +1517,19 @@
> >  		flow->actions |= MLX5_FLOW_ACTION_VXLAN_ENCAP;
> >  		actions_n++;
> >  		break;
> > +	case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
> > +		dev_flow->dv.actions[actions_n].type =
> > +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> > +		dev_flow->dv.actions[actions_n].action =
> > +				flow_dv_create_action_l2_decap(dev,
> > action,
> > +							       error);
> > +		if (!(dev_flow->dv.actions[actions_n].action))
> > +			return -rte_errno;
> > +		dev_flow->dv.verbs_action =
> > +			dev_flow->dv.actions[actions_n].action;
> > +		flow->actions |= MLX5_FLOW_ACTION_VXLAN_DECAP;
> > +		actions_n++;
> > +		break;
> >  	default:
> >  		break;
> >  	}
> > --
> > 1.8.3.1

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

* Re: [dpdk-dev] [PATCH v6 6/6] net/mlx5: add raw data encap decap to Direct Verbs
  2018-10-29 10:03           ` Shahaf Shuler
@ 2018-10-29 16:54             ` Dekel Peled
  0 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-29 16:54 UTC (permalink / raw)
  To: Shahaf Shuler, Yongseok Koh; +Cc: dev, Ori Kam

Thanks, PSB.

> -----Original Message-----
> From: Shahaf Shuler
> Sent: Monday, October 29, 2018 12:03 PM
> To: Dekel Peled <dekelp@mellanox.com>; Yongseok Koh
> <yskoh@mellanox.com>
> Cc: dev@dpdk.org; Ori Kam <orika@mellanox.com>
> Subject: RE: [dpdk-dev] [PATCH v6 6/6] net/mlx5: add raw data encap decap
> to Direct Verbs
> 
> Thursday, October 25, 2018 11:08 PM, Dekel Peled:
> > Subject: [dpdk-dev] [PATCH v6 6/6] net/mlx5: add raw data encap decap
> > to Direct Verbs
> >
> > This patch implements the encap and decap actions, using raw data, in
> > DV flow for MLX5 PMD.
> >
> > Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> > ---
> >  drivers/net/mlx5/mlx5_flow.h    |  12 ++-
> >  drivers/net/mlx5/mlx5_flow_dv.c | 227
> > ++++++++++++++++++++++++++++++++++++++--
> >  2 files changed, 224 insertions(+), 15 deletions(-)
> >
> > diff --git a/drivers/net/mlx5/mlx5_flow.h
> > b/drivers/net/mlx5/mlx5_flow.h index 2d73a05..92ba111 100644
> > --- a/drivers/net/mlx5/mlx5_flow.h
> > +++ b/drivers/net/mlx5/mlx5_flow.h
> > @@ -96,15 +96,19 @@
> >  #define MLX5_FLOW_ACTION_VXLAN_DECAP (1u << 23)  #define
> > MLX5_FLOW_ACTION_NVGRE_ENCAP (1u << 24)  #define
> > MLX5_FLOW_ACTION_NVGRE_DECAP (1u << 25)
> > +#define MLX5_FLOW_ACTION_RAW_ENCAP (1u << 26) #define
> > +MLX5_FLOW_ACTION_RAW_DECAP (1u << 27)
> >
> >  #define MLX5_FLOW_FATE_ACTIONS \
> >  	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE |
> > MLX5_FLOW_ACTION_RSS)
> >
> > -#define MLX5_FLOW_ENCAP_ACTIONS	\
> > -	(MLX5_FLOW_ACTION_VXLAN_ENCAP |
> > MLX5_FLOW_ACTION_NVGRE_ENCAP)
> > +#define MLX5_FLOW_ENCAP_ACTIONS
> > 	(MLX5_FLOW_ACTION_VXLAN_ENCAP | \
> > +				 MLX5_FLOW_ACTION_NVGRE_ENCAP | \
> > +				 MLX5_FLOW_ACTION_RAW_ENCAP)
> >
> > -#define MLX5_FLOW_DECAP_ACTIONS	\
> > -	(MLX5_FLOW_ACTION_VXLAN_DECAP |
> > MLX5_FLOW_ACTION_NVGRE_DECAP)
> > +#define MLX5_FLOW_DECAP_ACTIONS
> > 	(MLX5_FLOW_ACTION_VXLAN_DECAP | \
> > +				 MLX5_FLOW_ACTION_NVGRE_DECAP | \
> > +				 MLX5_FLOW_ACTION_RAW_DECAP)
> >
> >  #ifndef IPPROTO_MPLS
> >  #define IPPROTO_MPLS 137
> > diff --git a/drivers/net/mlx5/mlx5_flow_dv.c
> > b/drivers/net/mlx5/mlx5_flow_dv.c index d7d0c6b..ca75645 100644
> > --- a/drivers/net/mlx5/mlx5_flow_dv.c
> > +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> > @@ -186,6 +186,82 @@
> >  }
> >
> >  /**
> > + * Validate the raw encap action.
> > + *
> > + * @param[in] action_flags
> > + *   Holds the actions detected until now.
> > + * @param[in] action
> > + *   Pointer to the encap action.
> > + * @param[in] attr
> > + *   Pointer to flow attributes
> > + * @param[out] error
> > + *   Pointer to error structure.
> > + *
> > + * @return
> > + *   0 on success, a negative errno value otherwise and rte_errno is set.
> > + */
> > +static int
> > +flow_dv_validate_action_raw_encap(uint64_t action_flags,
> > +				  const struct rte_flow_action *action,
> > +				  const struct rte_flow_attr *attr,
> > +				  struct rte_flow_error *error)
> > +{
> > +	if (!(action->conf))
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > action,
> > +					  "configuration cannot be null");
> > +	if (action_flags & MLX5_FLOW_ACTION_DROP)
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > NULL,
> > +					  "can't drop and encap in same
> > flow");
> > +	if (action_flags & MLX5_FLOW_ENCAP_ACTIONS)
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > NULL,
> > +					  "can only have a single encap"
> > +					  " action in a flow");
> > +	/* encap without preceding decap is not supported for ingress */
> > +	if (attr->ingress && !(action_flags &
> > MLX5_FLOW_ACTION_RAW_DECAP))
> > +		return rte_flow_error_set(error, ENOTSUP,
> > +
> > RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> > +					  NULL,
> > +					  "encap action not supported for "
> > +					  "ingress");
> 
> The error message doesn't seems informative enough.

This is the case when flow rule is created with ingress attribute, and only raw_encap action, without raw_decap.
I used the same error message as in L2 encap case.

> 
> > +	return 0;
> > +}
> > +
> > +/**
> > + * Validate the raw decap action.
> > + *
> > + * @param[in] action_flags
> > + *   Holds the actions detected until now.
> > + * @param[out] error
> > + *   Pointer to error structure.
> > + *
> > + * @return
> > + *   0 on success, a negative errno value otherwise and rte_errno is set.
> > + */
> > +static int
> > +flow_dv_validate_action_raw_decap(uint64_t action_flags,
> > +				  struct rte_flow_error *error)
> > +{
> > +	if (action_flags & MLX5_FLOW_ACTION_DROP)
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > NULL,
> > +					  "can't drop and decap in same
> > flow");
> > +	if (action_flags & MLX5_FLOW_ENCAP_ACTIONS)
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > NULL,
> > +					  "can't have encap action before"
> > +					  " decap action");
> > +	if (action_flags & MLX5_FLOW_DECAP_ACTIONS)
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > NULL,
> > +					  "can only have a single decap"
> > +					  " action in a flow");
> 
> Just like you don't allow to do only encap w/o decap on ingress, on egress we
> cannot do only decap w/o a subsequent encap.

This validation was implemented during action creation, to save the checking of later actions.
I will move it to here.

> 
> > +	return 0;
> > +}
> > +
> > +/**
> >   * Get the size of specific rte_flow_item_type
> >   *
> >   * @param[in] item_type
> > @@ -396,6 +472,7 @@
> >  /**
> >   * Convert L2 encap action to DV specification.
> >   * Used for VXLAN and NVGRE encap actions.
> > + * Also used for raw encap action without preceding decap.
> >   *
> >   * @param[in] dev
> >   *   Pointer to rte_eth_dev structure.
> > @@ -414,23 +491,34 @@
> >  {
> >  	struct ibv_flow_action *verbs_action = NULL;
> >  	const struct rte_flow_item *encap_data;
> > +	const struct rte_flow_action_raw_encap *raw_encap_data;
> 
> This one can be declared inside the if statement

I prefer all variable declarations at start of function.

> 
> >  	struct priv *priv = dev->data->dev_private;
> >  	uint8_t buf[MLX5_ENCAP_MAX_LEN];
> > +	uint8_t *buf_ptr = buf;
> 
> Why you need this buf_ptr? Compilation issue with the fixed sized array of
> buf?

I needed it to refer to different buffers, raw buffer in raw_encap_data, or buffer converted from encap_data.
It will be removed now when moving to use cache.

> 
> >  	size_t size = 0;
> >  	int convert_result = 0;
> >
> > -	if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP)
> > -		encap_data = ((const struct rte_flow_action_vxlan_encap *)
> > +	if (action->type == RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
> > +		raw_encap_data =
> > +			(const struct rte_flow_action_raw_encap *)action-
> > >conf;
> > +		buf_ptr = raw_encap_data->data;
> > +		size = raw_encap_data->size;
> > +	} else {
> > +		if (action->type ==
> > RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP)
> > +			encap_data =
> > +				((const struct rte_flow_action_vxlan_encap
> > *)
> >  						action->conf)->definition;
> > -	else
> > -		encap_data = ((const struct rte_flow_action_nvgre_encap *)
> > +		else
> > +			encap_data =
> > +				((const struct rte_flow_action_nvgre_encap
> > *)
> >  						action->conf)->definition;
> > -	convert_result = flow_dv_convert_encap_data(encap_data, buf,
> > -						    &size, error);
> > -	if (convert_result)
> > -		return NULL;
> > +		convert_result = flow_dv_convert_encap_data(encap_data,
> > buf,
> > +							    &size, error);
> > +		if (convert_result)
> > +			return NULL;
> > +	}
> >  	verbs_action = mlx5_glue-
> > >dv_create_flow_action_packet_reformat
> > -		(priv->ctx, size, (size ? buf : NULL),
> > +		(priv->ctx, size, (size ? buf_ptr : NULL),
> >
> > MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
> >  		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
> >  	if (!verbs_action)
> > @@ -472,6 +560,50 @@
> >  }
> >
> >  /**
> > + * Convert raw decap/encap (L3 tunnel) action to DV specification.
> > + *
> > + * @param[in] dev
> > + *   Pointer to rte_eth_dev structure.
> > + * @param[in] action
> > + *   Pointer to action structure.
> > + * @param[in] attr
> > + *   Pointer to the flow attributes.
> > + * @param[out] error
> > + *   Pointer to the error structure.
> > + *
> > + * @return
> > + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> > + */
> > +static struct ibv_flow_action *
> > +flow_dv_create_action_raw_encap(struct rte_eth_dev *dev,
> 
> I would call it flow_dv_create_action_packet_reformat, as this is the only
> case this function is being called.
> For raw_encap only you will use the l2_encap function.

I prefer this name, since L2 and L3 encap and decap use mlx5dv packet reformat function.

> 
> > +				const struct rte_flow_action *action,
> > +				const struct rte_flow_attr *attr,
> > +				struct rte_flow_error *error)
> > +{
> > +	struct ibv_flow_action *verbs_action = NULL;
> > +	const struct rte_flow_action_raw_encap *encap_data;
> > +	struct priv *priv = dev->data->dev_private;
> > +	enum mlx5dv_flow_action_packet_reformat_type reformat_type;
> > +	enum mlx5dv_flow_table_type ft_type;
> > +
> > +	encap_data = (const struct rte_flow_action_raw_encap *)action-
> > >conf;
> > +	reformat_type = attr->egress ?
> > +
> > 	MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TU
> > NNEL :
> > +
> > 	MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_T
> > O_L2;
> > +	ft_type = attr->egress ?
> > +			MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
> > +			MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
> > +	verbs_action = mlx5_glue-
> > >dv_create_flow_action_packet_reformat
> > +				(priv->ctx, encap_data->size,
> > +				(encap_data->size ? encap_data->data :
> > NULL),
> > +				reformat_type, ft_type);
> > +	if (!verbs_action)
> > +		rte_flow_error_set(error, EINVAL,
> > RTE_FLOW_ERROR_TYPE_ACTION,
> > +				   NULL, "cannot create encap action");
> > +	return verbs_action;
> > +}
> > +
> > +/**
> >   * Verify the @p attributes will be correctly understood by the NIC and
> store
> >   * them in the @p flow if everything is correct.
> >   *
> > @@ -726,7 +858,6 @@
> >
> > 	RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP ?
> >
> > 	MLX5_FLOW_ACTION_VXLAN_ENCAP :
> >
> > 	MLX5_FLOW_ACTION_NVGRE_ENCAP;
> > -
> >  			++actions_n;
> >  			break;
> >  		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
> > @@ -740,7 +871,23 @@
> >
> > 	RTE_FLOW_ACTION_TYPE_VXLAN_DECAP ?
> >
> > 	MLX5_FLOW_ACTION_VXLAN_DECAP :
> >
> > 	MLX5_FLOW_ACTION_NVGRE_DECAP;
> > -
> > +			++actions_n;
> > +			break;
> > +		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
> > +			ret =
> > flow_dv_validate_action_raw_encap(action_flags,
> > +								actions, attr,
> > +								error);
> > +			if (ret < 0)
> > +				return ret;
> > +			action_flags |= MLX5_FLOW_ACTION_RAW_ENCAP;
> > +			++actions_n;
> > +			break;
> > +		case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
> > +			ret =
> > flow_dv_validate_action_raw_decap(action_flags,
> > +								error);
> > +			if (ret < 0)
> > +				return ret;
> > +			action_flags |= MLX5_FLOW_ACTION_RAW_DECAP;
> >  			++actions_n;
> >  			break;
> >  		default:
> > @@ -1550,6 +1697,64 @@
> >  				 MLX5_FLOW_ACTION_NVGRE_DECAP;
> >  		actions_n++;
> >  		break;
> > +	case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
> > +		/* Handle encap action with preceding decap */
> > +		if (flow->actions & MLX5_FLOW_ACTION_RAW_DECAP) {
> > +			dev_flow->dv.actions[actions_n].type =
> > +
> > 	MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> > +			dev_flow->dv.actions[actions_n].action =
> > +					flow_dv_create_action_raw_encap
> > +								(dev, action,
> > +								 attr, error);
> > +			if (!(dev_flow->dv.actions[actions_n].action))
> > +				return -rte_errno;
> > +			dev_flow->dv.verbs_action =
> > +				dev_flow->dv.actions[actions_n].action;
> > +		} else {
> > +			/* Handle encap action without preceding decap */
> > +			dev_flow->dv.actions[actions_n].type =
> > +
> > 	MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> > +			dev_flow->dv.actions[actions_n].action =
> > +					flow_dv_create_action_l2_encap
> > +							(dev, action, error);
> > +			if (!(dev_flow->dv.actions[actions_n].action))
> > +				return -rte_errno;
> > +			dev_flow->dv.verbs_action =
> > +				dev_flow->dv.actions[actions_n].action;
> > +		}
> > +		flow->actions |= MLX5_FLOW_ACTION_RAW_ENCAP;
> > +		actions_n++;
> > +		break;
> > +	case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
> > +		/* Check if this decap action is followed by encap. */
> > +		for (; action->type != RTE_FLOW_ACTION_TYPE_END &&
> > +		       action->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP;
> > +		       action++) {
> > +		}
> > +		/* Handle decap action only if it isn't followed by encap */
> > +		if (action->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
> > +			/* on egress, decap without following encap is error.
> > */
> > +			if (attr->egress)
> > +				return rte_flow_error_set
> > +					(error, ENOTSUP,
> > +
> > RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
> > +					 NULL,
> > +					 "decap action not supported for "
> > +					 "egress");
> 
> This check should have been performed on the validate stage.

I will move it.

> 
> > +			dev_flow->dv.actions[actions_n].type =
> > +
> > 	MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> > +			dev_flow->dv.actions[actions_n].action =
> > +					flow_dv_create_action_l2_decap
> > +							(dev, action, error);
> > +			if (!(dev_flow->dv.actions[actions_n].action))
> > +				return -rte_errno;
> > +			dev_flow->dv.verbs_action =
> > +				dev_flow->dv.actions[actions_n].action;
> > +			actions_n++;
> > +		}
> > +		/* If decap is followed by encap, handle it at encap case. */
> > +		flow->actions |= MLX5_FLOW_ACTION_RAW_DECAP;
> > +		break;
> >  	default:
> >  		break;
> >  	}
> > --
> > 1.8.3.1

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

* [dpdk-dev] [PATCH v7 0/7] add encap and decap actions to Direct Verbs flow in MLX5 PMD
  2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 0/6] add encap and decap actions to Direct Verbs flow in MLX5 PMD Dekel Peled
  2018-10-29 10:03           ` Shahaf Shuler
@ 2018-10-31  7:10           ` Dekel Peled
  2018-10-31 15:09             ` Shahaf Shuler
                               ` (8 more replies)
  2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 1/7] net/mlx5: add flow action functions to glue Dekel Peled
                             ` (6 subsequent siblings)
  8 siblings, 9 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-31  7:10 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This series adds support of encap and decap actions in DV format.
L2 tunnel support for VXLAN and NVGRE, and L2/L3 tunnel support using raw data buffer.
It is using the generic encapsulation framework from [1].

[1] "ethdev: add generic L2/L3 tunnel encapsulation actions"
    http://mails.dpdk.org/archives/dev/2018-October/114654.html
    
---
v7:
* Apply code review comments.
* Add caching of encap decap actions.
v6:
* Adapt L2 tunnel to VXLAN and NVGRE.
* Add encap/decap using raw data.
v5:
* Move DV actions code under common DV flag.
v4:
* Update in glue functions.
v3:
* Apply additional code review comments.
v2:
* Rebase on tip.
* Apply code review comments.
---

Dekel Peled (7):
  net/mlx5: add flow action functions to glue
  net/mlx5: add VXLAN encap action to Direct Verbs
  net/mlx5: add VXLAN decap action to Direct Verbs
  net/mlx5: add NVGRE encap action to Direct Verbs
  net/mlx5: add NVGRE decap action to Direct Verbs
  net/mlx5: add raw data encap decap to Direct Verbs
  net/mlx5: add caching of encap decap actions

 drivers/net/mlx5/Makefile       |   2 +-
 drivers/net/mlx5/meson.build    |   2 +-
 drivers/net/mlx5/mlx5.h         |   1 +
 drivers/net/mlx5/mlx5_flow.h    |  30 ++
 drivers/net/mlx5/mlx5_flow_dv.c | 775 +++++++++++++++++++++++++++++++++++++++-
 drivers/net/mlx5/mlx5_glue.c    |  38 ++
 drivers/net/mlx5/mlx5_glue.h    |  10 +
 7 files changed, 850 insertions(+), 8 deletions(-)

-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v7 1/7] net/mlx5: add flow action functions to glue
  2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 0/6] add encap and decap actions to Direct Verbs flow in MLX5 PMD Dekel Peled
  2018-10-29 10:03           ` Shahaf Shuler
  2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 0/7] " Dekel Peled
@ 2018-10-31  7:10           ` Dekel Peled
  2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 2/7] net/mlx5: add VXLAN encap action to Direct Verbs Dekel Peled
                             ` (5 subsequent siblings)
  8 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-31  7:10 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch adds glue functions for operations:
- Create packet reformat (encap/decap) flow action.
- Destroy flow action.

The new operations depend on HAVE_IBV_FLOW_DV_SUPPORT.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
Acked-by: Yongseok Koh <yskoh@mellanox.com>
Acked-by: Shahaf Shuler <shahafs@mellanox.com>
---
 drivers/net/mlx5/Makefile    |  2 +-
 drivers/net/mlx5/meson.build |  2 +-
 drivers/net/mlx5/mlx5_glue.c | 38 ++++++++++++++++++++++++++++++++++++++
 drivers/net/mlx5/mlx5_glue.h | 10 ++++++++++
 4 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile
index fecb57c..073a2f4 100644
--- a/drivers/net/mlx5/Makefile
+++ b/drivers/net/mlx5/Makefile
@@ -139,7 +139,7 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh
 	$Q sh -- '$<' '$@' \
 		HAVE_IBV_FLOW_DV_SUPPORT \
 		infiniband/mlx5dv.h \
-		enum MLX5DV_FLOW_ACTION_TAG \
+		func mlx5dv_create_flow_action_packet_reformat \
 		$(AUTOCONF_OUTPUT)
 	$Q sh -- '$<' '$@' \
 		HAVE_ETHTOOL_LINK_MODE_25G \
diff --git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build
index e8cbe3e..1330a4f 100644
--- a/drivers/net/mlx5/meson.build
+++ b/drivers/net/mlx5/meson.build
@@ -97,7 +97,7 @@ if build
 		[ 'HAVE_IBV_MLX5_MOD_CQE_128B_COMP', 'infiniband/mlx5dv.h',
 		'MLX5DV_CONTEXT_FLAGS_CQE_128B_COMP' ],
 		[ 'HAVE_IBV_FLOW_DV_SUPPORT', 'infiniband/mlx5dv.h',
-		'MLX5DV_FLOW_ACTION_TAG' ],
+		'mlx5dv_create_flow_action_packet_reformat' ],
 		[ 'HAVE_IBV_DEVICE_MPLS_SUPPORT', 'infiniband/verbs.h',
 		'IBV_FLOW_SPEC_MPLS' ],
 		[ 'HAVE_IBV_WQ_FLAG_RX_END_PADDING', 'infiniband/verbs.h',
diff --git a/drivers/net/mlx5/mlx5_glue.c b/drivers/net/mlx5/mlx5_glue.c
index 1afb114..dd10ad6 100644
--- a/drivers/net/mlx5/mlx5_glue.c
+++ b/drivers/net/mlx5/mlx5_glue.c
@@ -174,6 +174,17 @@
 	return ibv_destroy_flow(flow_id);
 }
 
+static int
+mlx5_glue_destroy_flow_action(struct ibv_flow_action *action)
+{
+#ifdef HAVE_IBV_FLOW_DV_SUPPORT
+	return ibv_destroy_flow_action(action);
+#else
+	(void)action;
+	return ENOTSUP;
+#endif
+}
+
 static struct ibv_qp *
 mlx5_glue_create_qp(struct ibv_pd *pd, struct ibv_qp_init_attr *qp_init_attr)
 {
@@ -444,6 +455,30 @@
 #endif
 }
 
+static struct ibv_flow_action *
+mlx5_glue_dv_create_flow_action_packet_reformat
+		(struct ibv_context *ctx,
+		 size_t data_sz,
+		 void *data,
+		 enum mlx5dv_flow_action_packet_reformat_type reformat_type,
+		 enum mlx5dv_flow_table_type ft_type)
+{
+#ifdef HAVE_IBV_FLOW_DV_SUPPORT
+	return mlx5dv_create_flow_action_packet_reformat(ctx,
+							 data_sz,
+							 data,
+							 reformat_type,
+							 ft_type);
+#else
+	(void)ctx;
+	(void)data_sz;
+	(void)data;
+	(void)reformat_type;
+	(void)ft_type;
+	return NULL;
+#endif
+}
+
 alignas(RTE_CACHE_LINE_SIZE)
 const struct mlx5_glue *mlx5_glue = &(const struct mlx5_glue){
 	.version = MLX5_GLUE_VERSION,
@@ -470,6 +505,7 @@
 	.modify_wq = mlx5_glue_modify_wq,
 	.create_flow = mlx5_glue_create_flow,
 	.destroy_flow = mlx5_glue_destroy_flow,
+	.destroy_flow_action = mlx5_glue_destroy_flow_action,
 	.create_qp = mlx5_glue_create_qp,
 	.create_qp_ex = mlx5_glue_create_qp_ex,
 	.destroy_qp = mlx5_glue_destroy_qp,
@@ -497,4 +533,6 @@
 	.dv_create_flow_matcher = mlx5_glue_dv_create_flow_matcher,
 	.dv_destroy_flow_matcher = mlx5_glue_dv_destroy_flow_matcher,
 	.dv_create_flow = mlx5_glue_dv_create_flow,
+	.dv_create_flow_action_packet_reformat =
+			mlx5_glue_dv_create_flow_action_packet_reformat,
 };
diff --git a/drivers/net/mlx5/mlx5_glue.h b/drivers/net/mlx5/mlx5_glue.h
index 44bfefe..2d92ba8 100644
--- a/drivers/net/mlx5/mlx5_glue.h
+++ b/drivers/net/mlx5/mlx5_glue.h
@@ -50,6 +50,9 @@
 struct mlx5dv_flow_matcher_attr;
 struct mlx5dv_flow_action_attr;
 struct mlx5dv_flow_match_parameters;
+struct ibv_flow_action;
+enum mlx5dv_flow_action_packet_reformat_type { packet_reformat_type = 0, };
+enum mlx5dv_flow_table_type { flow_table_type = 0, };
 #endif
 
 /* LIB_GLUE_VERSION must be updated every time this structure is modified. */
@@ -91,6 +94,7 @@ struct mlx5_glue {
 	struct ibv_flow *(*create_flow)(struct ibv_qp *qp,
 					struct ibv_flow_attr *flow);
 	int (*destroy_flow)(struct ibv_flow *flow_id);
+	int (*destroy_flow_action)(struct ibv_flow_action *action);
 	struct ibv_qp *(*create_qp)(struct ibv_pd *pd,
 				    struct ibv_qp_init_attr *qp_init_attr);
 	struct ibv_qp *(*create_qp_ex)
@@ -154,6 +158,12 @@ struct mlx5_glue {
 			  struct mlx5dv_flow_match_parameters *match_value,
 			  size_t num_actions,
 			  struct mlx5dv_flow_action_attr *actions_attr);
+	struct ibv_flow_action *(*dv_create_flow_action_packet_reformat)
+		(struct ibv_context *ctx,
+		 size_t data_sz,
+		 void *data,
+		 enum mlx5dv_flow_action_packet_reformat_type reformat_type,
+		 enum mlx5dv_flow_table_type ft_type);
 };
 
 const struct mlx5_glue *mlx5_glue;
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v7 2/7] net/mlx5: add VXLAN encap action to Direct Verbs
  2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 0/6] add encap and decap actions to Direct Verbs flow in MLX5 PMD Dekel Peled
                             ` (2 preceding siblings ...)
  2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 1/7] net/mlx5: add flow action functions to glue Dekel Peled
@ 2018-10-31  7:10           ` Dekel Peled
  2018-10-31 15:09             ` Shahaf Shuler
  2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 3/7] net/mlx5: add VXLAN decap " Dekel Peled
                             ` (4 subsequent siblings)
  8 siblings, 1 reply; 94+ messages in thread
From: Dekel Peled @ 2018-10-31  7:10 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch implements the VXLAN encap action in DV flow for MLX5 PMD.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow.h    |   3 +
 drivers/net/mlx5/mlx5_flow_dv.c | 347 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 345 insertions(+), 5 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 61299d6..286d7bb 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -92,6 +92,7 @@
 #define MLX5_FLOW_ACTION_DEC_TTL (1u << 19)
 #define MLX5_FLOW_ACTION_SET_MAC_SRC (1u << 20)
 #define MLX5_FLOW_ACTION_SET_MAC_DST (1u << 21)
+#define MLX5_FLOW_ACTION_VXLAN_ENCAP (1u << 22)
 
 #define MLX5_FLOW_FATE_ACTIONS \
 	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS)
@@ -181,6 +182,8 @@ struct mlx5_flow_dv {
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
 	struct mlx5dv_flow_action_attr actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS];
 	/**< Action list. */
+	struct ibv_flow_action *encap_decap_verbs_action;
+	/**< Verbs encap/decap object. */
 #endif
 	int actions_n; /**< number of actions. */
 };
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 8f729f4..1f9a842 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -34,6 +34,8 @@
 
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
 
+#define MLX5_ENCAP_MAX_LEN 132
+
 /**
  * Validate META item.
  *
@@ -96,6 +98,303 @@
 }
 
 /**
+ * Validate the L2 encap action.
+ *
+ * @param[in] action_flags
+ *   Holds the actions detected until now.
+ * @param[in] action
+ *   Pointer to the encap action.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_validate_action_l2_encap(uint64_t action_flags,
+				 const struct rte_flow_action *action,
+				 const struct rte_flow_attr *attr,
+				 struct rte_flow_error *error)
+{
+	if (!(action->conf))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, action,
+					  "configuration cannot be null");
+	if (action_flags & MLX5_FLOW_ACTION_DROP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't drop and encap in same flow");
+	if (action_flags & MLX5_FLOW_ACTION_VXLAN_ENCAP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can only have a single encap"
+					  " action in a flow");
+	if (attr->ingress)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
+					  NULL,
+					  "encap action not supported for "
+					  "ingress");
+	return 0;
+}
+
+/**
+ * Get the size of specific rte_flow_item_type
+ *
+ * @param[in] item_type
+ *   Tested rte_flow_item_type.
+ *
+ * @return
+ *   sizeof struct item_type, 0 if void or irrelevant.
+ */
+static size_t
+flow_dv_get_item_len(const enum rte_flow_item_type item_type)
+{
+	size_t retval;
+
+	switch (item_type) {
+	case RTE_FLOW_ITEM_TYPE_ETH:
+		retval = sizeof(struct rte_flow_item_eth);
+		break;
+	case RTE_FLOW_ITEM_TYPE_VLAN:
+		retval = sizeof(struct rte_flow_item_vlan);
+		break;
+	case RTE_FLOW_ITEM_TYPE_IPV4:
+		retval = sizeof(struct rte_flow_item_ipv4);
+		break;
+	case RTE_FLOW_ITEM_TYPE_IPV6:
+		retval = sizeof(struct rte_flow_item_ipv6);
+		break;
+	case RTE_FLOW_ITEM_TYPE_UDP:
+		retval = sizeof(struct rte_flow_item_udp);
+		break;
+	case RTE_FLOW_ITEM_TYPE_TCP:
+		retval = sizeof(struct rte_flow_item_tcp);
+		break;
+	case RTE_FLOW_ITEM_TYPE_VXLAN:
+		retval = sizeof(struct rte_flow_item_vxlan);
+		break;
+	case RTE_FLOW_ITEM_TYPE_GRE:
+		retval = sizeof(struct rte_flow_item_gre);
+		break;
+	case RTE_FLOW_ITEM_TYPE_NVGRE:
+		retval = sizeof(struct rte_flow_item_nvgre);
+		break;
+	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
+		retval = sizeof(struct rte_flow_item_vxlan_gpe);
+		break;
+	case RTE_FLOW_ITEM_TYPE_MPLS:
+		retval = sizeof(struct rte_flow_item_mpls);
+		break;
+	case RTE_FLOW_ITEM_TYPE_VOID: /* Fall through. */
+	default:
+		retval = 0;
+		break;
+	}
+	return retval;
+};
+
+#define MLX5_IPV4_VERSION	0x40
+#define MLX5_IPV4_IHL_MIN	0x05
+#define MLX5_IPV4_TTL_DEF	0x40
+#define MLX5_IPV6_VTC_FLOW	0x60000000
+#define MLX5_IPV6_HOP_LIMIT	0xff
+#define MLX5_VXLAN_FLAGS	0x08000000
+#define MLX5_VXLAN_GPE_FLAGS	0x0c000003
+
+/**
+ * Convert the encap action data from list of rte_flow_item to raw buffer
+ *
+ * @param[in] items
+ *   Pointer to rte_flow_item objects list.
+ * @param[out] buf
+ *   Pointer to the output buffer.
+ * @param[out] size
+ *   Pointer to the output buffer size.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_convert_encap_data(const struct rte_flow_item *item, uint8_t *buf,
+			   size_t *size, struct rte_flow_error *error)
+{
+	struct ether_hdr *eth = NULL;
+	struct vlan_hdr *vlan = NULL;
+	struct ipv4_hdr *ipv4 = NULL;
+	struct ipv6_hdr *ipv6 = NULL;
+	struct udp_hdr *udp = NULL;
+	struct vxlan_hdr *vxlan = NULL;
+	size_t len;
+	size_t temp_size = 0;
+
+	if (!item)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  NULL, "invalid empty data");
+	for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+		len = flow_dv_get_item_len(item->type);
+		if (len + temp_size > MLX5_ENCAP_MAX_LEN)
+			return rte_flow_error_set(error, EINVAL,
+						  RTE_FLOW_ERROR_TYPE_ACTION,
+						  (void *)item->type,
+						  "items total size is too big"
+						  " for encap action");
+		rte_memcpy((void *)&buf[temp_size], item->spec, len);
+		switch (item->type) {
+		case RTE_FLOW_ITEM_TYPE_ETH:
+			eth = (struct ether_hdr *)&buf[temp_size];
+			break;
+		case RTE_FLOW_ITEM_TYPE_VLAN:
+			vlan = (struct vlan_hdr *)&buf[temp_size];
+			if (!eth)
+				return rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						(void *)item->type,
+						"eth header not found");
+			if (!eth->ether_type)
+				eth->ether_type = RTE_BE16(ETHER_TYPE_VLAN);
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV4:
+			ipv4 = (struct ipv4_hdr *)&buf[temp_size];
+			if (!vlan && !eth)
+				return rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						(void *)item->type,
+						"neither eth nor vlan"
+						" header found");
+			if (vlan && !vlan->eth_proto)
+				vlan->eth_proto = RTE_BE16(ETHER_TYPE_IPv4);
+			else if (eth && !eth->ether_type)
+				eth->ether_type = RTE_BE16(ETHER_TYPE_IPv4);
+			if (!ipv4->version_ihl)
+				ipv4->version_ihl = MLX5_IPV4_VERSION |
+						    MLX5_IPV4_IHL_MIN;
+			if (!ipv4->time_to_live)
+				ipv4->time_to_live = MLX5_IPV4_TTL_DEF;
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV6:
+			ipv6 = (struct ipv6_hdr *)&buf[temp_size];
+			if (!vlan && !eth)
+				return rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						(void *)item->type,
+						"neither eth nor vlan"
+						" header found");
+			if (vlan && !vlan->eth_proto)
+				vlan->eth_proto = RTE_BE16(ETHER_TYPE_IPv6);
+			else if (eth && !eth->ether_type)
+				eth->ether_type = RTE_BE16(ETHER_TYPE_IPv6);
+			if (!ipv6->vtc_flow)
+				ipv6->vtc_flow = RTE_BE32(MLX5_IPV6_VTC_FLOW);
+			if (!ipv6->hop_limits)
+				ipv6->hop_limits = MLX5_IPV6_HOP_LIMIT;
+			break;
+		case RTE_FLOW_ITEM_TYPE_UDP:
+			udp = (struct udp_hdr *)&buf[temp_size];
+			if (!ipv4 && !ipv6)
+				return rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						(void *)item->type,
+						"ip header not found");
+			if (ipv4 && !ipv4->next_proto_id)
+				ipv4->next_proto_id = IPPROTO_UDP;
+			else if (ipv6 && !ipv6->proto)
+				ipv6->proto = IPPROTO_UDP;
+			break;
+		case RTE_FLOW_ITEM_TYPE_VXLAN:
+			vxlan = (struct vxlan_hdr *)&buf[temp_size];
+			if (!udp)
+				return rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						(void *)item->type,
+						"udp header not found");
+			if (!udp->dst_port)
+				udp->dst_port = RTE_BE16(MLX5_UDP_PORT_VXLAN);
+			if (!vxlan->vx_flags)
+				vxlan->vx_flags = RTE_BE32(MLX5_VXLAN_FLAGS);
+			break;
+		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
+			vxlan = (struct vxlan_hdr *)&buf[temp_size];
+			if (!udp)
+				return rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						(void *)item->type,
+						"udp header not found");
+			if ((ipv4 && !ipv4->next_proto_id) ||
+			    (ipv6 && !ipv6->proto))
+				return rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						(void *)item->type,
+						"next protocol not found");
+			if (!udp->dst_port)
+				udp->dst_port =
+					RTE_BE16(MLX5_UDP_PORT_VXLAN_GPE);
+			if (!vxlan->vx_flags)
+				vxlan->vx_flags =
+						RTE_BE32(MLX5_VXLAN_GPE_FLAGS);
+			break;
+		case RTE_FLOW_ITEM_TYPE_VOID:
+			break;
+		default:
+			return rte_flow_error_set(error, EINVAL,
+						  RTE_FLOW_ERROR_TYPE_ACTION,
+						  (void *)item->type,
+						  "unsupported item type");
+			break;
+		}
+		temp_size += len;
+	}
+	*size = temp_size;
+	return 0;
+}
+
+/**
+ * Convert L2 encap action to DV specification.
+ *
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[in] action
+ *   Pointer to action structure.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+flow_dv_create_action_l2_encap(struct rte_eth_dev *dev,
+			       const struct rte_flow_action *action,
+			       struct rte_flow_error *error)
+{
+	struct ibv_flow_action *verbs_action = NULL;
+	const struct rte_flow_item *encap_data;
+	struct priv *priv = dev->data->dev_private;
+	uint8_t buf[MLX5_ENCAP_MAX_LEN];
+	size_t size = 0;
+	int convert_result = 0;
+
+	encap_data = ((const struct rte_flow_action_vxlan_encap *)
+						action->conf)->definition;
+	convert_result = flow_dv_convert_encap_data(encap_data, buf,
+						    &size, error);
+	if (convert_result)
+		return NULL;
+	verbs_action = mlx5_glue->dv_create_flow_action_packet_reformat
+		(priv->ctx, size, buf,
+		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
+		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
+	if (!verbs_action)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create L2 encap action");
+	return verbs_action;
+}
+
+/**
  * Verify the @p attributes will be correctly understood by the NIC and store
  * them in the @p flow if everything is correct.
  *
@@ -339,6 +638,16 @@
 			action_flags |= MLX5_FLOW_ACTION_COUNT;
 			++actions_n;
 			break;
+		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
+			ret = flow_dv_validate_action_l2_encap(action_flags,
+							       actions, attr,
+							       error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_VXLAN_ENCAP;
+			++actions_n;
+			break;
+
 		default:
 			return rte_flow_error_set(error, ENOTSUP,
 						  RTE_FLOW_ERROR_TYPE_ACTION,
@@ -1045,14 +1354,23 @@
 /**
  * Store the requested actions in an array.
  *
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
  * @param[in] action
  *   Flow action to translate.
  * @param[in, out] dev_flow
  *   Pointer to the mlx5_flow.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
-static void
-flow_dv_create_action(const struct rte_flow_action *action,
-		      struct mlx5_flow *dev_flow)
+static int
+flow_dv_create_action(struct rte_eth_dev *dev,
+		      const struct rte_flow_action *action,
+		      struct mlx5_flow *dev_flow,
+		      struct rte_flow_error *error)
 {
 	const struct rte_flow_action_queue *queue;
 	const struct rte_flow_action_rss *rss;
@@ -1100,10 +1418,24 @@
 		/* Added to array only in apply since we need the QP */
 		flow->actions |= MLX5_FLOW_ACTION_RSS;
 		break;
+	case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
+		dev_flow->dv.actions[actions_n].type =
+			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+		dev_flow->dv.actions[actions_n].action =
+				flow_dv_create_action_l2_encap(dev, action,
+							       error);
+		if (!(dev_flow->dv.actions[actions_n].action))
+			return -rte_errno;
+		dev_flow->dv.encap_decap_verbs_action =
+			dev_flow->dv.actions[actions_n].action;
+		flow->actions |= MLX5_FLOW_ACTION_VXLAN_ENCAP;
+		actions_n++;
+		break;
 	default:
 		break;
 	}
 	dev_flow->dv.actions_n = actions_n;
+	return 0;
 }
 
 static uint32_t matcher_zero[MLX5_ST_SZ_DW(fte_match_param)] = { 0 };
@@ -1217,7 +1549,6 @@
 	return 0;
 }
 
-
 /**
  * Fill the flow with DV spec.
  *
@@ -1272,7 +1603,8 @@
 	if (flow_dv_matcher_register(dev, &matcher, dev_flow, error))
 		return -rte_errno;
 	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++)
-		flow_dv_create_action(actions, dev_flow);
+		if (flow_dv_create_action(dev, actions, dev_flow, error))
+			return -rte_errno;
 	return 0;
 }
 
@@ -1457,6 +1789,11 @@
 		LIST_REMOVE(dev_flow, next);
 		if (dev_flow->dv.matcher)
 			flow_dv_matcher_release(dev, dev_flow);
+		if (dev_flow->dv.encap_decap_verbs_action) {
+			claim_zero(mlx5_glue->destroy_flow_action
+				(dev_flow->dv.encap_decap_verbs_action));
+			dev_flow->dv.encap_decap_verbs_action = NULL;
+		}
 		rte_free(dev_flow);
 	}
 }
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v7 3/7] net/mlx5: add VXLAN decap action to Direct Verbs
  2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 0/6] add encap and decap actions to Direct Verbs flow in MLX5 PMD Dekel Peled
                             ` (3 preceding siblings ...)
  2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 2/7] net/mlx5: add VXLAN encap action to Direct Verbs Dekel Peled
@ 2018-10-31  7:10           ` Dekel Peled
  2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 4/7] net/mlx5: add NVGRE encap " Dekel Peled
                             ` (3 subsequent siblings)
  8 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-31  7:10 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch implements the VXLAN decap action in DV flow for MLX5 PMD.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow.h    |  1 +
 drivers/net/mlx5/mlx5_flow_dv.c | 93 +++++++++++++++++++++++++++++++++++++++--
 2 files changed, 90 insertions(+), 4 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 286d7bb..8955a12 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -93,6 +93,7 @@
 #define MLX5_FLOW_ACTION_SET_MAC_SRC (1u << 20)
 #define MLX5_FLOW_ACTION_SET_MAC_DST (1u << 21)
 #define MLX5_FLOW_ACTION_VXLAN_ENCAP (1u << 22)
+#define MLX5_FLOW_ACTION_VXLAN_DECAP (1u << 23)
 
 #define MLX5_FLOW_FATE_ACTIONS \
 	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS)
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 1f9a842..7de65bb 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -126,11 +126,12 @@
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't drop and encap in same flow");
-	if (action_flags & MLX5_FLOW_ACTION_VXLAN_ENCAP)
+	if (action_flags & (MLX5_FLOW_ACTION_VXLAN_ENCAP |
+			    MLX5_FLOW_ACTION_VXLAN_DECAP))
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
-					  "can only have a single encap"
-					  " action in a flow");
+					  "can only have a single encap or"
+					  " decap action in a flow");
 	if (attr->ingress)
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
@@ -141,6 +142,43 @@
 }
 
 /**
+ * Validate the L2 decap action.
+ *
+ * @param[in] action_flags
+ *   Holds the actions detected until now.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_validate_action_l2_decap(uint64_t action_flags,
+				 const struct rte_flow_attr *attr,
+				 struct rte_flow_error *error)
+{
+	if (action_flags & MLX5_FLOW_ACTION_DROP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't drop and decap in same flow");
+	if (action_flags & (MLX5_FLOW_ACTION_VXLAN_ENCAP |
+			    MLX5_FLOW_ACTION_VXLAN_DECAP))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can only have a single encap or"
+					  " decap action in a flow");
+	if (attr->egress)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
+					  NULL,
+					  "decap action not supported for "
+					  "egress");
+	return 0;
+}
+
+/**
  * Get the size of specific rte_flow_item_type
  *
  * @param[in] item_type
@@ -395,6 +433,34 @@
 }
 
 /**
+ * Convert L2 decap action to DV specification.
+ *
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+flow_dv_create_action_l2_decap(struct rte_eth_dev *dev,
+			       struct rte_flow_error *error)
+{
+	struct ibv_flow_action *verbs_action = NULL;
+	struct priv *priv = dev->data->dev_private;
+
+	verbs_action = mlx5_glue->dv_create_flow_action_packet_reformat
+		(priv->ctx, 0, NULL,
+		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2,
+		 MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
+	if (!verbs_action)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create L2 decap action");
+	return verbs_action;
+}
+
+/**
  * Verify the @p attributes will be correctly understood by the NIC and store
  * them in the @p flow if everything is correct.
  *
@@ -647,7 +713,14 @@
 			action_flags |= MLX5_FLOW_ACTION_VXLAN_ENCAP;
 			++actions_n;
 			break;
-
+		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
+			ret = flow_dv_validate_action_l2_decap(action_flags,
+							       attr, error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_VXLAN_DECAP;
+			++actions_n;
+			break;
 		default:
 			return rte_flow_error_set(error, ENOTSUP,
 						  RTE_FLOW_ERROR_TYPE_ACTION,
@@ -1431,6 +1504,18 @@
 		flow->actions |= MLX5_FLOW_ACTION_VXLAN_ENCAP;
 		actions_n++;
 		break;
+	case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
+		dev_flow->dv.actions[actions_n].type =
+			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+		dev_flow->dv.actions[actions_n].action =
+				flow_dv_create_action_l2_decap(dev, error);
+		if (!(dev_flow->dv.actions[actions_n].action))
+			return -rte_errno;
+		dev_flow->dv.encap_decap_verbs_action =
+			dev_flow->dv.actions[actions_n].action;
+		flow->actions |= MLX5_FLOW_ACTION_VXLAN_DECAP;
+		actions_n++;
+		break;
 	default:
 		break;
 	}
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v7 4/7] net/mlx5: add NVGRE encap action to Direct Verbs
  2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 0/6] add encap and decap actions to Direct Verbs flow in MLX5 PMD Dekel Peled
                             ` (4 preceding siblings ...)
  2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 3/7] net/mlx5: add VXLAN decap " Dekel Peled
@ 2018-10-31  7:10           ` Dekel Peled
  2018-10-31 15:09             ` Shahaf Shuler
  2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 5/7] net/mlx5: add NVGRE decap " Dekel Peled
                             ` (2 subsequent siblings)
  8 siblings, 1 reply; 94+ messages in thread
From: Dekel Peled @ 2018-10-31  7:10 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch implements the nvgre encap action in DV flow for MLX5 PMD.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow.h    |  4 ++++
 drivers/net/mlx5/mlx5_flow_dv.c | 37 ++++++++++++++++++++++++++++++++-----
 2 files changed, 36 insertions(+), 5 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 8955a12..c03a3af 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -94,10 +94,14 @@
 #define MLX5_FLOW_ACTION_SET_MAC_DST (1u << 21)
 #define MLX5_FLOW_ACTION_VXLAN_ENCAP (1u << 22)
 #define MLX5_FLOW_ACTION_VXLAN_DECAP (1u << 23)
+#define MLX5_FLOW_ACTION_NVGRE_ENCAP (1u << 24)
 
 #define MLX5_FLOW_FATE_ACTIONS \
 	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS)
 
+#define MLX5_FLOW_ENCAP_ACTIONS	\
+	(MLX5_FLOW_ACTION_VXLAN_ENCAP | MLX5_FLOW_ACTION_NVGRE_ENCAP)
+
 #ifndef IPPROTO_MPLS
 #define IPPROTO_MPLS 137
 #endif
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 7de65bb..7078397 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -126,7 +126,7 @@
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't drop and encap in same flow");
-	if (action_flags & (MLX5_FLOW_ACTION_VXLAN_ENCAP |
+	if (action_flags & (MLX5_FLOW_ENCAP_ACTIONS |
 			    MLX5_FLOW_ACTION_VXLAN_DECAP))
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
@@ -163,7 +163,7 @@
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't drop and decap in same flow");
-	if (action_flags & (MLX5_FLOW_ACTION_VXLAN_ENCAP |
+	if (action_flags & (MLX5_FLOW_ENCAP_ACTIONS |
 			    MLX5_FLOW_ACTION_VXLAN_DECAP))
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
@@ -376,6 +376,20 @@
 				vxlan->vx_flags =
 						RTE_BE32(MLX5_VXLAN_GPE_FLAGS);
 			break;
+		case RTE_FLOW_ITEM_TYPE_GRE:
+		case RTE_FLOW_ITEM_TYPE_NVGRE:
+			if (!ipv4 && !ipv6)
+				return rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						(void *)item->type,
+						"ip header not found");
+			if ((ipv4 && !ipv4->next_proto_id) ||
+			    (ipv6 && !ipv6->proto))
+				return rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						(void *)item->type,
+						"next protocol not found");
+			break;
 		case RTE_FLOW_ITEM_TYPE_VOID:
 			break;
 		default:
@@ -416,7 +430,11 @@
 	size_t size = 0;
 	int convert_result = 0;
 
-	encap_data = ((const struct rte_flow_action_vxlan_encap *)
+	if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP)
+		encap_data = ((const struct rte_flow_action_vxlan_encap *)
+						action->conf)->definition;
+	else
+		encap_data = ((const struct rte_flow_action_nvgre_encap *)
 						action->conf)->definition;
 	convert_result = flow_dv_convert_encap_data(encap_data, buf,
 						    &size, error);
@@ -705,12 +723,17 @@
 			++actions_n;
 			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
+		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
 			ret = flow_dv_validate_action_l2_encap(action_flags,
 							       actions, attr,
 							       error);
 			if (ret < 0)
 				return ret;
-			action_flags |= MLX5_FLOW_ACTION_VXLAN_ENCAP;
+			action_flags |= actions->type ==
+					RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP ?
+					MLX5_FLOW_ACTION_VXLAN_ENCAP :
+					MLX5_FLOW_ACTION_NVGRE_ENCAP;
+
 			++actions_n;
 			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
@@ -1492,6 +1515,7 @@
 		flow->actions |= MLX5_FLOW_ACTION_RSS;
 		break;
 	case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
+	case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
 		dev_flow->dv.actions[actions_n].type =
 			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
 		dev_flow->dv.actions[actions_n].action =
@@ -1501,7 +1525,10 @@
 			return -rte_errno;
 		dev_flow->dv.encap_decap_verbs_action =
 			dev_flow->dv.actions[actions_n].action;
-		flow->actions |= MLX5_FLOW_ACTION_VXLAN_ENCAP;
+		flow->actions |= action->type ==
+				 RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP ?
+				 MLX5_FLOW_ACTION_VXLAN_ENCAP :
+				 MLX5_FLOW_ACTION_NVGRE_ENCAP;
 		actions_n++;
 		break;
 	case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v7 5/7] net/mlx5: add NVGRE decap action to Direct Verbs
  2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 0/6] add encap and decap actions to Direct Verbs flow in MLX5 PMD Dekel Peled
                             ` (5 preceding siblings ...)
  2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 4/7] net/mlx5: add NVGRE encap " Dekel Peled
@ 2018-10-31  7:10           ` Dekel Peled
  2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 6/7] net/mlx5: add raw data encap decap " Dekel Peled
  2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 7/7] net/mlx5: add caching of encap decap actions Dekel Peled
  8 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-31  7:10 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch implements the NVGRE decap action in DV flow for MLX5 PMD.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow.h    |  4 ++++
 drivers/net/mlx5/mlx5_flow_dv.c | 19 +++++++++++++------
 2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index c03a3af..104a1e6 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -95,6 +95,7 @@
 #define MLX5_FLOW_ACTION_VXLAN_ENCAP (1u << 22)
 #define MLX5_FLOW_ACTION_VXLAN_DECAP (1u << 23)
 #define MLX5_FLOW_ACTION_NVGRE_ENCAP (1u << 24)
+#define MLX5_FLOW_ACTION_NVGRE_DECAP (1u << 25)
 
 #define MLX5_FLOW_FATE_ACTIONS \
 	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS)
@@ -102,6 +103,9 @@
 #define MLX5_FLOW_ENCAP_ACTIONS	\
 	(MLX5_FLOW_ACTION_VXLAN_ENCAP | MLX5_FLOW_ACTION_NVGRE_ENCAP)
 
+#define MLX5_FLOW_DECAP_ACTIONS	\
+	(MLX5_FLOW_ACTION_VXLAN_DECAP | MLX5_FLOW_ACTION_NVGRE_DECAP)
+
 #ifndef IPPROTO_MPLS
 #define IPPROTO_MPLS 137
 #endif
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 7078397..b3ee237 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -126,8 +126,7 @@
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't drop and encap in same flow");
-	if (action_flags & (MLX5_FLOW_ENCAP_ACTIONS |
-			    MLX5_FLOW_ACTION_VXLAN_DECAP))
+	if (action_flags & (MLX5_FLOW_ENCAP_ACTIONS | MLX5_FLOW_DECAP_ACTIONS))
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can only have a single encap or"
@@ -163,8 +162,7 @@
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't drop and decap in same flow");
-	if (action_flags & (MLX5_FLOW_ENCAP_ACTIONS |
-			    MLX5_FLOW_ACTION_VXLAN_DECAP))
+	if (action_flags & (MLX5_FLOW_ENCAP_ACTIONS | MLX5_FLOW_DECAP_ACTIONS))
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can only have a single encap or"
@@ -737,11 +735,16 @@
 			++actions_n;
 			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
+		case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
 			ret = flow_dv_validate_action_l2_decap(action_flags,
 							       attr, error);
 			if (ret < 0)
 				return ret;
-			action_flags |= MLX5_FLOW_ACTION_VXLAN_DECAP;
+			action_flags |= actions->type ==
+					RTE_FLOW_ACTION_TYPE_VXLAN_DECAP ?
+					MLX5_FLOW_ACTION_VXLAN_DECAP :
+					MLX5_FLOW_ACTION_NVGRE_DECAP;
+
 			++actions_n;
 			break;
 		default:
@@ -1532,6 +1535,7 @@
 		actions_n++;
 		break;
 	case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
+	case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
 		dev_flow->dv.actions[actions_n].type =
 			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
 		dev_flow->dv.actions[actions_n].action =
@@ -1540,7 +1544,10 @@
 			return -rte_errno;
 		dev_flow->dv.encap_decap_verbs_action =
 			dev_flow->dv.actions[actions_n].action;
-		flow->actions |= MLX5_FLOW_ACTION_VXLAN_DECAP;
+		flow->actions |= action->type ==
+				 RTE_FLOW_ACTION_TYPE_VXLAN_DECAP ?
+				 MLX5_FLOW_ACTION_VXLAN_DECAP :
+				 MLX5_FLOW_ACTION_NVGRE_DECAP;
 		actions_n++;
 		break;
 	default:
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v7 6/7] net/mlx5: add raw data encap decap to Direct Verbs
  2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 0/6] add encap and decap actions to Direct Verbs flow in MLX5 PMD Dekel Peled
                             ` (6 preceding siblings ...)
  2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 5/7] net/mlx5: add NVGRE decap " Dekel Peled
@ 2018-10-31  7:10           ` Dekel Peled
  2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 7/7] net/mlx5: add caching of encap decap actions Dekel Peled
  8 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-10-31  7:10 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch implements the encap and decap actions, using raw data,
in DV flow for MLX5 PMD.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow.h    |  12 +-
 drivers/net/mlx5/mlx5_flow_dv.c | 246 +++++++++++++++++++++++++++++++++++++---
 2 files changed, 241 insertions(+), 17 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 104a1e6..908123f 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -96,15 +96,19 @@
 #define MLX5_FLOW_ACTION_VXLAN_DECAP (1u << 23)
 #define MLX5_FLOW_ACTION_NVGRE_ENCAP (1u << 24)
 #define MLX5_FLOW_ACTION_NVGRE_DECAP (1u << 25)
+#define MLX5_FLOW_ACTION_RAW_ENCAP (1u << 26)
+#define MLX5_FLOW_ACTION_RAW_DECAP (1u << 27)
 
 #define MLX5_FLOW_FATE_ACTIONS \
 	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS)
 
-#define MLX5_FLOW_ENCAP_ACTIONS	\
-	(MLX5_FLOW_ACTION_VXLAN_ENCAP | MLX5_FLOW_ACTION_NVGRE_ENCAP)
+#define MLX5_FLOW_ENCAP_ACTIONS	(MLX5_FLOW_ACTION_VXLAN_ENCAP | \
+				 MLX5_FLOW_ACTION_NVGRE_ENCAP | \
+				 MLX5_FLOW_ACTION_RAW_ENCAP)
 
-#define MLX5_FLOW_DECAP_ACTIONS	\
-	(MLX5_FLOW_ACTION_VXLAN_DECAP | MLX5_FLOW_ACTION_NVGRE_DECAP)
+#define MLX5_FLOW_DECAP_ACTIONS	(MLX5_FLOW_ACTION_VXLAN_DECAP | \
+				 MLX5_FLOW_ACTION_NVGRE_DECAP | \
+				 MLX5_FLOW_ACTION_RAW_DECAP)
 
 #ifndef IPPROTO_MPLS
 #define IPPROTO_MPLS 137
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index b3ee237..d1c811f 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -177,6 +177,101 @@
 }
 
 /**
+ * Validate the raw encap action.
+ *
+ * @param[in] action_flags
+ *   Holds the actions detected until now.
+ * @param[in] action
+ *   Pointer to the encap action.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_validate_action_raw_encap(uint64_t action_flags,
+				  const struct rte_flow_action *action,
+				  const struct rte_flow_attr *attr,
+				  struct rte_flow_error *error)
+{
+	if (!(action->conf))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, action,
+					  "configuration cannot be null");
+	if (action_flags & MLX5_FLOW_ACTION_DROP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't drop and encap in same flow");
+	if (action_flags & MLX5_FLOW_ENCAP_ACTIONS)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can only have a single encap"
+					  " action in a flow");
+	/* encap without preceding decap is not supported for ingress */
+	if (attr->ingress && !(action_flags & MLX5_FLOW_ACTION_RAW_DECAP))
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
+					  NULL,
+					  "encap action not supported for "
+					  "ingress");
+	return 0;
+}
+
+/**
+ * Validate the raw decap action.
+ *
+ * @param[in] action_flags
+ *   Holds the actions detected until now.
+ * @param[in] action
+ *   Pointer to the encap action.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_validate_action_raw_decap(uint64_t action_flags,
+				  const struct rte_flow_action *action,
+				  const struct rte_flow_attr *attr,
+				  struct rte_flow_error *error)
+{
+	if (action_flags & MLX5_FLOW_ACTION_DROP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't drop and decap in same flow");
+	if (action_flags & MLX5_FLOW_ENCAP_ACTIONS)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't have encap action before"
+					  " decap action");
+	if (action_flags & MLX5_FLOW_DECAP_ACTIONS)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can only have a single decap"
+					  " action in a flow");
+	/* decap action is valid on egress only if it is followed by encap */
+	if (attr->egress) {
+		for (; action->type != RTE_FLOW_ACTION_TYPE_END &&
+		       action->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP;
+		       action++) {
+		}
+		if (action->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP)
+			return rte_flow_error_set
+					(error, ENOTSUP,
+					 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
+					 NULL, "decap action not supported"
+					 " for egress");
+	}
+	return 0;
+}
+
+/**
  * Get the size of specific rte_flow_item_type
  *
  * @param[in] item_type
@@ -423,23 +518,34 @@
 {
 	struct ibv_flow_action *verbs_action = NULL;
 	const struct rte_flow_item *encap_data;
+	const struct rte_flow_action_raw_encap *raw_encap_data;
 	struct priv *priv = dev->data->dev_private;
 	uint8_t buf[MLX5_ENCAP_MAX_LEN];
+	uint8_t *buf_ptr = buf;
 	size_t size = 0;
 	int convert_result = 0;
 
-	if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP)
-		encap_data = ((const struct rte_flow_action_vxlan_encap *)
+	if (action->type == RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
+		raw_encap_data =
+			(const struct rte_flow_action_raw_encap *)action->conf;
+		buf_ptr = raw_encap_data->data;
+		size = raw_encap_data->size;
+	} else {
+		if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP)
+			encap_data =
+				((const struct rte_flow_action_vxlan_encap *)
 						action->conf)->definition;
-	else
-		encap_data = ((const struct rte_flow_action_nvgre_encap *)
+		else
+			encap_data =
+				((const struct rte_flow_action_nvgre_encap *)
 						action->conf)->definition;
-	convert_result = flow_dv_convert_encap_data(encap_data, buf,
-						    &size, error);
-	if (convert_result)
-		return NULL;
+		convert_result = flow_dv_convert_encap_data(encap_data, buf,
+							    &size, error);
+		if (convert_result)
+			return NULL;
+	}
 	verbs_action = mlx5_glue->dv_create_flow_action_packet_reformat
-		(priv->ctx, size, buf,
+		(priv->ctx, size, buf_ptr,
 		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
 		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
 	if (!verbs_action)
@@ -477,6 +583,50 @@
 }
 
 /**
+ * Convert raw decap/encap (L3 tunnel) action to DV specification.
+ *
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[in] action
+ *   Pointer to action structure.
+ * @param[in] attr
+ *   Pointer to the flow attributes.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+flow_dv_create_action_raw_encap(struct rte_eth_dev *dev,
+				const struct rte_flow_action *action,
+				const struct rte_flow_attr *attr,
+				struct rte_flow_error *error)
+{
+	struct ibv_flow_action *verbs_action = NULL;
+	const struct rte_flow_action_raw_encap *encap_data;
+	struct priv *priv = dev->data->dev_private;
+	enum mlx5dv_flow_action_packet_reformat_type reformat_type;
+	enum mlx5dv_flow_table_type ft_type;
+
+	encap_data = (const struct rte_flow_action_raw_encap *)action->conf;
+	reformat_type = attr->egress ?
+		MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL :
+		MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2;
+	ft_type = attr->egress ?
+			MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
+			MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
+	verbs_action = mlx5_glue->dv_create_flow_action_packet_reformat
+				(priv->ctx, encap_data->size,
+				(encap_data->size ? encap_data->data : NULL),
+				reformat_type, ft_type);
+	if (!verbs_action)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create encap action");
+	return verbs_action;
+}
+
+/**
  * Verify the @p attributes will be correctly understood by the NIC and store
  * them in the @p flow if everything is correct.
  *
@@ -731,7 +881,6 @@
 					RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP ?
 					MLX5_FLOW_ACTION_VXLAN_ENCAP :
 					MLX5_FLOW_ACTION_NVGRE_ENCAP;
-
 			++actions_n;
 			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
@@ -744,7 +893,24 @@
 					RTE_FLOW_ACTION_TYPE_VXLAN_DECAP ?
 					MLX5_FLOW_ACTION_VXLAN_DECAP :
 					MLX5_FLOW_ACTION_NVGRE_DECAP;
-
+			++actions_n;
+			break;
+		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
+			ret = flow_dv_validate_action_raw_encap(action_flags,
+								actions, attr,
+								error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_RAW_ENCAP;
+			++actions_n;
+			break;
+		case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
+			ret = flow_dv_validate_action_raw_decap(action_flags,
+								actions, attr,
+								error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_RAW_DECAP;
 			++actions_n;
 			break;
 		default:
@@ -1459,6 +1625,8 @@
  *   Flow action to translate.
  * @param[in, out] dev_flow
  *   Pointer to the mlx5_flow.
+ * @param[in] attr
+ *   Pointer to the flow attributes.
  * @param[out] error
  *   Pointer to the error structure.
  *
@@ -1469,12 +1637,14 @@
 flow_dv_create_action(struct rte_eth_dev *dev,
 		      const struct rte_flow_action *action,
 		      struct mlx5_flow *dev_flow,
+		      const struct rte_flow_attr *attr,
 		      struct rte_flow_error *error)
 {
 	const struct rte_flow_action_queue *queue;
 	const struct rte_flow_action_rss *rss;
 	int actions_n = dev_flow->dv.actions_n;
 	struct rte_flow *flow = dev_flow->flow;
+	const struct rte_flow_action *action_ptr = action;
 
 	switch (action->type) {
 	case RTE_FLOW_ACTION_TYPE_VOID:
@@ -1550,6 +1720,56 @@
 				 MLX5_FLOW_ACTION_NVGRE_DECAP;
 		actions_n++;
 		break;
+	case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
+		/* Handle encap action with preceding decap */
+		if (flow->actions & MLX5_FLOW_ACTION_RAW_DECAP) {
+			dev_flow->dv.actions[actions_n].type =
+				MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+			dev_flow->dv.actions[actions_n].action =
+					flow_dv_create_action_raw_encap
+								(dev, action,
+								 attr, error);
+			if (!(dev_flow->dv.actions[actions_n].action))
+				return -rte_errno;
+			dev_flow->dv.encap_decap_verbs_action =
+				dev_flow->dv.actions[actions_n].action;
+		} else {
+			/* Handle encap action without preceding decap */
+			dev_flow->dv.actions[actions_n].type =
+				MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+			dev_flow->dv.actions[actions_n].action =
+					flow_dv_create_action_l2_encap
+							(dev, action, error);
+			if (!(dev_flow->dv.actions[actions_n].action))
+				return -rte_errno;
+			dev_flow->dv.encap_decap_verbs_action =
+				dev_flow->dv.actions[actions_n].action;
+		}
+		flow->actions |= MLX5_FLOW_ACTION_RAW_ENCAP;
+		actions_n++;
+		break;
+	case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
+		/* Check if this decap action is followed by encap. */
+		for (; action_ptr->type != RTE_FLOW_ACTION_TYPE_END &&
+		       action_ptr->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP;
+		       action_ptr++) {
+		}
+		/* Handle decap action only if it isn't followed by encap */
+		if (action_ptr->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
+			dev_flow->dv.actions[actions_n].type =
+				MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+			dev_flow->dv.actions[actions_n].action =
+					flow_dv_create_action_l2_decap(dev,
+								       error);
+			if (!(dev_flow->dv.actions[actions_n].action))
+				return -rte_errno;
+			dev_flow->dv.encap_decap_verbs_action =
+				dev_flow->dv.actions[actions_n].action;
+			actions_n++;
+		}
+		/* If decap is followed by encap, handle it at encap case. */
+		flow->actions |= MLX5_FLOW_ACTION_RAW_DECAP;
+		break;
 	default:
 		break;
 	}
@@ -1692,7 +1912,7 @@
 		  struct mlx5_flow *dev_flow,
 		  const struct rte_flow_attr *attr,
 		  const struct rte_flow_item items[],
-		  const struct rte_flow_action actions[] __rte_unused,
+		  const struct rte_flow_action actions[],
 		  struct rte_flow_error *error)
 {
 	struct priv *priv = dev->data->dev_private;
@@ -1722,7 +1942,7 @@
 	if (flow_dv_matcher_register(dev, &matcher, dev_flow, error))
 		return -rte_errno;
 	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++)
-		if (flow_dv_create_action(dev, actions, dev_flow, error))
+		if (flow_dv_create_action(dev, actions, dev_flow, attr, error))
 			return -rte_errno;
 	return 0;
 }
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v7 7/7] net/mlx5: add caching of encap decap actions
  2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 0/6] add encap and decap actions to Direct Verbs flow in MLX5 PMD Dekel Peled
                             ` (7 preceding siblings ...)
  2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 6/7] net/mlx5: add raw data encap decap " Dekel Peled
@ 2018-10-31  7:10           ` Dekel Peled
  2018-10-31 15:09             ` Shahaf Shuler
  8 siblings, 1 reply; 94+ messages in thread
From: Dekel Peled @ 2018-10-31  7:10 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

Make flow encap and decap Verbs actions cacheable resources.
Reuse 17.11 PR 876.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/mlx5.h         |   1 +
 drivers/net/mlx5/mlx5_flow.h    |  18 ++-
 drivers/net/mlx5/mlx5_flow_dv.c | 265 ++++++++++++++++++++++++++--------------
 3 files changed, 193 insertions(+), 91 deletions(-)

diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 74d87c0..0422803 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -219,6 +219,7 @@ struct priv {
 	/* Verbs Indirection tables. */
 	LIST_HEAD(ind_tables, mlx5_ind_table_ibv) ind_tbls;
 	LIST_HEAD(matchers, mlx5_flow_dv_matcher) matchers;
+	LIST_HEAD(encap_decap, mlx5_flow_dv_encap_decap_resource) encaps_decaps;
 	uint32_t link_speed_capa; /* Link speed capabilities. */
 	struct mlx5_xstats_ctrl xstats_ctrl; /* Extended stats control. */
 	int primary_socket; /* Unix socket for primary process. */
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 908123f..25cd9c5 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -170,6 +170,7 @@ struct mlx5_flow_dv_match_params {
 };
 
 #define MLX5_DV_MAX_NUMBER_OF_ACTIONS 8
+#define MLX5_ENCAP_MAX_LEN 132
 
 /* Matcher structure. */
 struct mlx5_flow_dv_matcher {
@@ -183,6 +184,19 @@ struct mlx5_flow_dv_matcher {
 	struct mlx5_flow_dv_match_params mask; /**< Matcher mask. */
 };
 
+/* Encap/decap resource structure. */
+struct mlx5_flow_dv_encap_decap_resource {
+	LIST_ENTRY(mlx5_flow_dv_encap_decap_resource) next;
+	/* Pointer to next element. */
+	rte_atomic32_t refcnt; /**< Reference counter. */
+	struct ibv_flow_action *verbs_action;
+	/**< Verbs encap/decap action object. */
+	uint8_t buf[MLX5_ENCAP_MAX_LEN];
+	size_t size;
+	uint8_t reformat_type;
+	uint8_t ft_type;
+};
+
 /* DV flows structure. */
 struct mlx5_flow_dv {
 	uint64_t hash_fields; /**< Fields that participate in the hash. */
@@ -191,12 +205,12 @@ struct mlx5_flow_dv {
 	struct mlx5_flow_dv_matcher *matcher; /**< Cache to matcher. */
 	struct mlx5_flow_dv_match_params value;
 	/**< Holds the value that the packet is compared to. */
+	struct mlx5_flow_dv_encap_decap_resource *encap_decap;
+	/**< Pointer to encap/decap resource in cache. */
 	struct ibv_flow *flow; /**< Installed flow. */
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
 	struct mlx5dv_flow_action_attr actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS];
 	/**< Action list. */
-	struct ibv_flow_action *encap_decap_verbs_action;
-	/**< Verbs encap/decap object. */
 #endif
 	int actions_n; /**< number of actions. */
 };
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index d1c811f..818b30c 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -34,8 +34,6 @@
 
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
 
-#define MLX5_ENCAP_MAX_LEN 132
-
 /**
  * Validate META item.
  *
@@ -271,6 +269,77 @@
 	return 0;
 }
 
+
+/**
+ * Find existing encap/decap resource or create and register a new one.
+ *
+ * @param dev[in, out]
+ *   Pointer to rte_eth_dev structure.
+ * @param[in, out] resource
+ *   Pointer to encap/decap resource.
+ * @parm[in, out] dev_flow
+ *   Pointer to the dev_flow.
+ * @param[out] error
+ *   pointer to error structure.
+ *
+ * @return
+ *   0 on success otherwise -errno and errno is set.
+ */
+static int
+flow_dv_encap_decap_resource_register
+			(struct rte_eth_dev *dev,
+			 struct mlx5_flow_dv_encap_decap_resource *resource,
+			 struct mlx5_flow *dev_flow,
+			 struct rte_flow_error *error)
+{
+	struct priv *priv = dev->data->dev_private;
+	struct mlx5_flow_dv_encap_decap_resource *cache_resource;
+
+	/* Lookup a matching resource from cache. */
+	LIST_FOREACH(cache_resource, &priv->encaps_decaps, next) {
+		if (resource->reformat_type == cache_resource->reformat_type &&
+		    resource->ft_type == cache_resource->ft_type &&
+		    resource->size == cache_resource->size &&
+		    !memcmp((const void *)resource->buf,
+			    (const void *)cache_resource->buf,
+			    resource->size)) {
+			DRV_LOG(DEBUG, "encap/decap resource %p: refcnt %d++",
+				(void *)cache_resource,
+				rte_atomic32_read(&cache_resource->refcnt));
+			rte_atomic32_inc(&cache_resource->refcnt);
+			dev_flow->dv.encap_decap = cache_resource;
+			return 0;
+		}
+	}
+	/* Register new encap/decap resource. */
+	cache_resource = rte_calloc(__func__, 1, sizeof(*cache_resource), 0);
+	if (!cache_resource)
+		return rte_flow_error_set(error, ENOMEM,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					  "cannot allocate resource memory");
+	*cache_resource = *resource;
+	cache_resource->verbs_action =
+		mlx5_glue->dv_create_flow_action_packet_reformat
+			(priv->ctx, cache_resource->size,
+			 (cache_resource->size ? cache_resource->buf : NULL),
+			 cache_resource->reformat_type,
+			 cache_resource->ft_type);
+	if (!cache_resource->verbs_action) {
+		rte_free(cache_resource);
+		return rte_flow_error_set(error, ENOMEM,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					  NULL, "cannot create action");
+	}
+	rte_atomic32_init(&cache_resource->refcnt);
+	rte_atomic32_inc(&cache_resource->refcnt);
+	LIST_INSERT_HEAD(&priv->encaps_decaps, cache_resource, next);
+	dev_flow->dv.encap_decap = cache_resource;
+	DRV_LOG(DEBUG, "new encap/decap resource %p: refcnt %d++",
+		(void *)cache_resource,
+		rte_atomic32_read(&cache_resource->refcnt));
+	return 0;
+}
+
 /**
  * Get the size of specific rte_flow_item_type
  *
@@ -505,31 +574,33 @@
  *   Pointer to rte_eth_dev structure.
  * @param[in] action
  *   Pointer to action structure.
+ * @param[in, out] dev_flow
+ *   Pointer to the mlx5_flow.
  * @param[out] error
  *   Pointer to the error structure.
  *
  * @return
- *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
-static struct ibv_flow_action *
+static int
 flow_dv_create_action_l2_encap(struct rte_eth_dev *dev,
 			       const struct rte_flow_action *action,
+			       struct mlx5_flow *dev_flow,
 			       struct rte_flow_error *error)
 {
-	struct ibv_flow_action *verbs_action = NULL;
 	const struct rte_flow_item *encap_data;
 	const struct rte_flow_action_raw_encap *raw_encap_data;
-	struct priv *priv = dev->data->dev_private;
-	uint8_t buf[MLX5_ENCAP_MAX_LEN];
-	uint8_t *buf_ptr = buf;
-	size_t size = 0;
-	int convert_result = 0;
+	struct mlx5_flow_dv_encap_decap_resource res = {
+		.reformat_type =
+			MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
+		.ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_TX,
+	};
 
 	if (action->type == RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
 		raw_encap_data =
 			(const struct rte_flow_action_raw_encap *)action->conf;
-		buf_ptr = raw_encap_data->data;
-		size = raw_encap_data->size;
+		res.size = raw_encap_data->size;
+		memcpy(res.buf, raw_encap_data->data, res.size);
 	} else {
 		if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP)
 			encap_data =
@@ -539,19 +610,15 @@
 			encap_data =
 				((const struct rte_flow_action_nvgre_encap *)
 						action->conf)->definition;
-		convert_result = flow_dv_convert_encap_data(encap_data, buf,
-							    &size, error);
-		if (convert_result)
-			return NULL;
+		if (flow_dv_convert_encap_data(encap_data, res.buf,
+					       &res.size, error))
+			return -rte_errno;
 	}
-	verbs_action = mlx5_glue->dv_create_flow_action_packet_reformat
-		(priv->ctx, size, buf_ptr,
-		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
-		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
-	if (!verbs_action)
-		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
-				   NULL, "cannot create L2 encap action");
-	return verbs_action;
+	if (flow_dv_encap_decap_resource_register(dev, &res, dev_flow, error))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  NULL, "can't create L2 encap action");
+	return 0;
 }
 
 /**
@@ -559,27 +626,31 @@
  *
  * @param[in] dev
  *   Pointer to rte_eth_dev structure.
+ * @param[in, out] dev_flow
+ *   Pointer to the mlx5_flow.
  * @param[out] error
  *   Pointer to the error structure.
  *
  * @return
- *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
-static struct ibv_flow_action *
+static int
 flow_dv_create_action_l2_decap(struct rte_eth_dev *dev,
+			       struct mlx5_flow *dev_flow,
 			       struct rte_flow_error *error)
 {
-	struct ibv_flow_action *verbs_action = NULL;
-	struct priv *priv = dev->data->dev_private;
+	struct mlx5_flow_dv_encap_decap_resource res = {
+		.size = 0,
+		.reformat_type =
+			MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2,
+		.ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_RX,
+	};
 
-	verbs_action = mlx5_glue->dv_create_flow_action_packet_reformat
-		(priv->ctx, 0, NULL,
-		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2,
-		 MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
-	if (!verbs_action)
-		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
-				   NULL, "cannot create L2 decap action");
-	return verbs_action;
+	if (flow_dv_encap_decap_resource_register(dev, &res, dev_flow, error))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  NULL, "can't create L2 decap action");
+	return 0;
 }
 
 /**
@@ -589,41 +660,39 @@
  *   Pointer to rte_eth_dev structure.
  * @param[in] action
  *   Pointer to action structure.
+ * @param[in, out] dev_flow
+ *   Pointer to the mlx5_flow.
  * @param[in] attr
  *   Pointer to the flow attributes.
  * @param[out] error
  *   Pointer to the error structure.
  *
  * @return
- *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
-static struct ibv_flow_action *
+static int
 flow_dv_create_action_raw_encap(struct rte_eth_dev *dev,
 				const struct rte_flow_action *action,
+				struct mlx5_flow *dev_flow,
 				const struct rte_flow_attr *attr,
 				struct rte_flow_error *error)
 {
-	struct ibv_flow_action *verbs_action = NULL;
 	const struct rte_flow_action_raw_encap *encap_data;
-	struct priv *priv = dev->data->dev_private;
-	enum mlx5dv_flow_action_packet_reformat_type reformat_type;
-	enum mlx5dv_flow_table_type ft_type;
+	struct mlx5_flow_dv_encap_decap_resource res;
 
 	encap_data = (const struct rte_flow_action_raw_encap *)action->conf;
-	reformat_type = attr->egress ?
+	res.size = encap_data->size;
+	memcpy(res.buf, encap_data->data, res.size);
+	res.reformat_type = attr->egress ?
 		MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL :
 		MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2;
-	ft_type = attr->egress ?
-			MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
-			MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
-	verbs_action = mlx5_glue->dv_create_flow_action_packet_reformat
-				(priv->ctx, encap_data->size,
-				(encap_data->size ? encap_data->data : NULL),
-				reformat_type, ft_type);
-	if (!verbs_action)
-		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
-				   NULL, "cannot create encap action");
-	return verbs_action;
+	res.ft_type = attr->egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
+				     MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
+	if (flow_dv_encap_decap_resource_register(dev, &res, dev_flow, error))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  NULL, "can't create encap action");
+	return 0;
 }
 
 /**
@@ -1689,15 +1758,13 @@
 		break;
 	case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
 	case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
+		if (flow_dv_create_action_l2_encap(dev, action,
+						   dev_flow, error))
+			return -rte_errno;
 		dev_flow->dv.actions[actions_n].type =
 			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
 		dev_flow->dv.actions[actions_n].action =
-				flow_dv_create_action_l2_encap(dev, action,
-							       error);
-		if (!(dev_flow->dv.actions[actions_n].action))
-			return -rte_errno;
-		dev_flow->dv.encap_decap_verbs_action =
-			dev_flow->dv.actions[actions_n].action;
+			dev_flow->dv.encap_decap->verbs_action;
 		flow->actions |= action->type ==
 				 RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP ?
 				 MLX5_FLOW_ACTION_VXLAN_ENCAP :
@@ -1706,14 +1773,12 @@
 		break;
 	case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
 	case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
+		if (flow_dv_create_action_l2_decap(dev, dev_flow, error))
+			return -rte_errno;
 		dev_flow->dv.actions[actions_n].type =
 			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
 		dev_flow->dv.actions[actions_n].action =
-				flow_dv_create_action_l2_decap(dev, error);
-		if (!(dev_flow->dv.actions[actions_n].action))
-			return -rte_errno;
-		dev_flow->dv.encap_decap_verbs_action =
-			dev_flow->dv.actions[actions_n].action;
+			dev_flow->dv.encap_decap->verbs_action;
 		flow->actions |= action->type ==
 				 RTE_FLOW_ACTION_TYPE_VXLAN_DECAP ?
 				 MLX5_FLOW_ACTION_VXLAN_DECAP :
@@ -1723,27 +1788,23 @@
 	case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
 		/* Handle encap action with preceding decap */
 		if (flow->actions & MLX5_FLOW_ACTION_RAW_DECAP) {
+			if (flow_dv_create_action_raw_encap(dev, action,
+							    dev_flow,
+							    attr, error))
+				return -rte_errno;
 			dev_flow->dv.actions[actions_n].type =
 				MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
 			dev_flow->dv.actions[actions_n].action =
-					flow_dv_create_action_raw_encap
-								(dev, action,
-								 attr, error);
-			if (!(dev_flow->dv.actions[actions_n].action))
-				return -rte_errno;
-			dev_flow->dv.encap_decap_verbs_action =
-				dev_flow->dv.actions[actions_n].action;
+					dev_flow->dv.encap_decap->verbs_action;
 		} else {
 			/* Handle encap action without preceding decap */
+			if (flow_dv_create_action_l2_encap(dev, action,
+							   dev_flow, error))
+				return -rte_errno;
 			dev_flow->dv.actions[actions_n].type =
 				MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
 			dev_flow->dv.actions[actions_n].action =
-					flow_dv_create_action_l2_encap
-							(dev, action, error);
-			if (!(dev_flow->dv.actions[actions_n].action))
-				return -rte_errno;
-			dev_flow->dv.encap_decap_verbs_action =
-				dev_flow->dv.actions[actions_n].action;
+					dev_flow->dv.encap_decap->verbs_action;
 		}
 		flow->actions |= MLX5_FLOW_ACTION_RAW_ENCAP;
 		actions_n++;
@@ -1756,15 +1817,13 @@
 		}
 		/* Handle decap action only if it isn't followed by encap */
 		if (action_ptr->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
+			if (flow_dv_create_action_l2_decap(dev, dev_flow,
+							   error))
+				return -rte_errno;
 			dev_flow->dv.actions[actions_n].type =
 				MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
 			dev_flow->dv.actions[actions_n].action =
-					flow_dv_create_action_l2_decap(dev,
-								       error);
-			if (!(dev_flow->dv.actions[actions_n].action))
-				return -rte_errno;
-			dev_flow->dv.encap_decap_verbs_action =
-				dev_flow->dv.actions[actions_n].action;
+					dev_flow->dv.encap_decap->verbs_action;
 			actions_n++;
 		}
 		/* If decap is followed by encap, handle it at encap case. */
@@ -2074,6 +2133,37 @@
 }
 
 /**
+ * Release an encap/decap resource.
+ *
+ * @param flow
+ *   Pointer to mlx5_flow.
+ *
+ * @return
+ *   1 while a reference on it exists, 0 when freed.
+ */
+static int
+flow_dv_encap_decap_resource_release(struct mlx5_flow *flow)
+{
+	struct mlx5_flow_dv_encap_decap_resource *cache_resource =
+						flow->dv.encap_decap;
+
+	assert(cache_resource->verbs_action);
+	DRV_LOG(DEBUG, "encap/decap resource %p: refcnt %d--",
+		(void *)cache_resource,
+		rte_atomic32_read(&cache_resource->refcnt));
+	if (rte_atomic32_dec_and_test(&cache_resource->refcnt)) {
+		claim_zero(mlx5_glue->destroy_flow_action
+				(cache_resource->verbs_action));
+		LIST_REMOVE(cache_resource, next);
+		rte_free(cache_resource);
+		DRV_LOG(DEBUG, "encap/decap resource %p: removed",
+			cache_resource);
+		return 0;
+	}
+	return 1;
+}
+
+/**
  * Remove the flow from the NIC but keeps it in memory.
  *
  * @param[in] dev
@@ -2128,11 +2218,8 @@
 		LIST_REMOVE(dev_flow, next);
 		if (dev_flow->dv.matcher)
 			flow_dv_matcher_release(dev, dev_flow);
-		if (dev_flow->dv.encap_decap_verbs_action) {
-			claim_zero(mlx5_glue->destroy_flow_action
-				(dev_flow->dv.encap_decap_verbs_action));
-			dev_flow->dv.encap_decap_verbs_action = NULL;
-		}
+		if (dev_flow->dv.encap_decap)
+			flow_dv_encap_decap_resource_release(dev_flow);
 		rte_free(dev_flow);
 	}
 }
-- 
1.8.3.1

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

* Re: [dpdk-dev] [PATCH v7 0/7] add encap and decap actions to Direct Verbs flow in MLX5 PMD
  2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 0/7] " Dekel Peled
@ 2018-10-31 15:09             ` Shahaf Shuler
  2018-11-01  9:37             ` [dpdk-dev] [PATCH v8 " Dekel Peled
                               ` (7 subsequent siblings)
  8 siblings, 0 replies; 94+ messages in thread
From: Shahaf Shuler @ 2018-10-31 15:09 UTC (permalink / raw)
  To: Dekel Peled, Yongseok Koh; +Cc: dev, Ori Kam

Hi Dekel,

Wednesday, October 31, 2018 9:11 AM, Dekel Peled:
> Subject: [PATCH v7 0/7] add encap and decap actions to Direct Verbs flow in
> MLX5 PMD
> 
> This series adds support of encap and decap actions in DV format.
> L2 tunnel support for VXLAN and NVGRE, and L2/L3 tunnel support using raw
> data buffer.
> It is using the generic encapsulation framework from [1].
> 
> [1] "ethdev: add generic L2/L3 tunnel encapsulation actions"
>     http://mails.dpdk.org/archives/dev/2018-October/114654.html
> 
> ---

See final comments, hope the last version will be the last. 


> v7:
> * Apply code review comments.
> * Add caching of encap decap actions.
> v6:
> * Adapt L2 tunnel to VXLAN and NVGRE.
> * Add encap/decap using raw data.
> v5:
> * Move DV actions code under common DV flag.
> v4:
> * Update in glue functions.
> v3:
> * Apply additional code review comments.
> v2:
> * Rebase on tip.
> * Apply code review comments.
> ---
> 
> Dekel Peled (7):
>   net/mlx5: add flow action functions to glue
>   net/mlx5: add VXLAN encap action to Direct Verbs
>   net/mlx5: add VXLAN decap action to Direct Verbs
>   net/mlx5: add NVGRE encap action to Direct Verbs
>   net/mlx5: add NVGRE decap action to Direct Verbs
>   net/mlx5: add raw data encap decap to Direct Verbs
>   net/mlx5: add caching of encap decap actions
> 
>  drivers/net/mlx5/Makefile       |   2 +-
>  drivers/net/mlx5/meson.build    |   2 +-
>  drivers/net/mlx5/mlx5.h         |   1 +
>  drivers/net/mlx5/mlx5_flow.h    |  30 ++
>  drivers/net/mlx5/mlx5_flow_dv.c | 775
> +++++++++++++++++++++++++++++++++++++++-
>  drivers/net/mlx5/mlx5_glue.c    |  38 ++
>  drivers/net/mlx5/mlx5_glue.h    |  10 +
>  7 files changed, 850 insertions(+), 8 deletions(-)
> 
> --
> 1.8.3.1

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

* Re: [dpdk-dev] [PATCH v7 2/7] net/mlx5: add VXLAN encap action to Direct Verbs
  2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 2/7] net/mlx5: add VXLAN encap action to Direct Verbs Dekel Peled
@ 2018-10-31 15:09             ` Shahaf Shuler
  2018-11-01  8:22               ` Dekel Peled
  0 siblings, 1 reply; 94+ messages in thread
From: Shahaf Shuler @ 2018-10-31 15:09 UTC (permalink / raw)
  To: Dekel Peled, Yongseok Koh; +Cc: dev, Ori Kam

Wednesday, October 31, 2018 9:11 AM, Dekel Peled:
> Subject: [PATCH v7 2/7] net/mlx5: add VXLAN encap action to Direct Verbs
> 
> This patch implements the VXLAN encap action in DV flow for MLX5 PMD.
> 
> Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> ---
>  drivers/net/mlx5/mlx5_flow.h    |   3 +
>  drivers/net/mlx5/mlx5_flow_dv.c | 347
> +++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 345 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
> index 61299d6..286d7bb 100644
> --- a/drivers/net/mlx5/mlx5_flow.h
> +++ b/drivers/net/mlx5/mlx5_flow.h
> @@ -92,6 +92,7 @@
>  #define MLX5_FLOW_ACTION_DEC_TTL (1u << 19)  #define
> MLX5_FLOW_ACTION_SET_MAC_SRC (1u << 20)  #define
> MLX5_FLOW_ACTION_SET_MAC_DST (1u << 21)
> +#define MLX5_FLOW_ACTION_VXLAN_ENCAP (1u << 22)
> 
>  #define MLX5_FLOW_FATE_ACTIONS \
>  	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE |
> MLX5_FLOW_ACTION_RSS) @@ -181,6 +182,8 @@ struct mlx5_flow_dv {
> #ifdef HAVE_IBV_FLOW_DV_SUPPORT
>  	struct mlx5dv_flow_action_attr
> actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS];
>  	/**< Action list. */
> +	struct ibv_flow_action *encap_decap_verbs_action;
> +	/**< Verbs encap/decap object. */
>  #endif
>  	int actions_n; /**< number of actions. */  }; diff --git
> a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
> index 8f729f4..1f9a842 100644
> --- a/drivers/net/mlx5/mlx5_flow_dv.c
> +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> @@ -34,6 +34,8 @@
> 
>  #ifdef HAVE_IBV_FLOW_DV_SUPPORT
> 
> +#define MLX5_ENCAP_MAX_LEN 132
> +
>  /**
>   * Validate META item.
>   *
> @@ -96,6 +98,303 @@
>  }
> 
>  /**
> + * Validate the L2 encap action.
> + *
> + * @param[in] action_flags
> + *   Holds the actions detected until now.
> + * @param[in] action
> + *   Pointer to the encap action.
> + * @param[in] attr
> + *   Pointer to flow attributes
> + * @param[out] error
> + *   Pointer to error structure.
> + *
> + * @return
> + *   0 on success, a negative errno value otherwise and rte_errno is set.
> + */
> +static int
> +flow_dv_validate_action_l2_encap(uint64_t action_flags,
> +				 const struct rte_flow_action *action,
> +				 const struct rte_flow_attr *attr,
> +				 struct rte_flow_error *error)
> +{
> +	if (!(action->conf))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> action,
> +					  "configuration cannot be null");
> +	if (action_flags & MLX5_FLOW_ACTION_DROP)
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
> +					  "can't drop and encap in same
> flow");
> +	if (action_flags & MLX5_FLOW_ACTION_VXLAN_ENCAP)
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
> +					  "can only have a single encap"
> +					  " action in a flow");
> +	if (attr->ingress)
> +		return rte_flow_error_set(error, ENOTSUP,
> +
> RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> +					  NULL,
> +					  "encap action not supported for "
> +					  "ingress");
> +	return 0;
> +}
> +
> +/**
> + * Get the size of specific rte_flow_item_type
> + *
> + * @param[in] item_type
> + *   Tested rte_flow_item_type.
> + *
> + * @return
> + *   sizeof struct item_type, 0 if void or irrelevant.
> + */
> +static size_t
> +flow_dv_get_item_len(const enum rte_flow_item_type item_type) {
> +	size_t retval;
> +
> +	switch (item_type) {
> +	case RTE_FLOW_ITEM_TYPE_ETH:
> +		retval = sizeof(struct rte_flow_item_eth);
> +		break;
> +	case RTE_FLOW_ITEM_TYPE_VLAN:
> +		retval = sizeof(struct rte_flow_item_vlan);
> +		break;
> +	case RTE_FLOW_ITEM_TYPE_IPV4:
> +		retval = sizeof(struct rte_flow_item_ipv4);
> +		break;
> +	case RTE_FLOW_ITEM_TYPE_IPV6:
> +		retval = sizeof(struct rte_flow_item_ipv6);
> +		break;
> +	case RTE_FLOW_ITEM_TYPE_UDP:
> +		retval = sizeof(struct rte_flow_item_udp);
> +		break;
> +	case RTE_FLOW_ITEM_TYPE_TCP:
> +		retval = sizeof(struct rte_flow_item_tcp);
> +		break;
> +	case RTE_FLOW_ITEM_TYPE_VXLAN:
> +		retval = sizeof(struct rte_flow_item_vxlan);
> +		break;
> +	case RTE_FLOW_ITEM_TYPE_GRE:
> +		retval = sizeof(struct rte_flow_item_gre);
> +		break;
> +	case RTE_FLOW_ITEM_TYPE_NVGRE:
> +		retval = sizeof(struct rte_flow_item_nvgre);
> +		break;
> +	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
> +		retval = sizeof(struct rte_flow_item_vxlan_gpe);
> +		break;
> +	case RTE_FLOW_ITEM_TYPE_MPLS:
> +		retval = sizeof(struct rte_flow_item_mpls);
> +		break;
> +	case RTE_FLOW_ITEM_TYPE_VOID: /* Fall through. */
> +	default:
> +		retval = 0;
> +		break;
> +	}
> +	return retval;
> +};
> +
> +#define MLX5_IPV4_VERSION	0x40
> +#define MLX5_IPV4_IHL_MIN	0x05
> +#define MLX5_IPV4_TTL_DEF	0x40
> +#define MLX5_IPV6_VTC_FLOW	0x60000000
> +#define MLX5_IPV6_HOP_LIMIT	0xff
> +#define MLX5_VXLAN_FLAGS	0x08000000
> +#define MLX5_VXLAN_GPE_FLAGS	0x0c000003

Better to prefix them all w/ MLX5_ENCAP_*

> +
> +/**
> + * Convert the encap action data from list of rte_flow_item to raw
> +buffer
> + *
> + * @param[in] items
> + *   Pointer to rte_flow_item objects list.
> + * @param[out] buf
> + *   Pointer to the output buffer.
> + * @param[out] size
> + *   Pointer to the output buffer size.
> + * @param[out] error
> + *   Pointer to the error structure.
> + *
> + * @return
> + *   0 on success, a negative errno value otherwise and rte_errno is set.
> + */
> +static int
> +flow_dv_convert_encap_data(const struct rte_flow_item *item, uint8_t

Here it is also items

> *buf,
> +			   size_t *size, struct rte_flow_error *error) {
> +	struct ether_hdr *eth = NULL;
> +	struct vlan_hdr *vlan = NULL;
> +	struct ipv4_hdr *ipv4 = NULL;
> +	struct ipv6_hdr *ipv6 = NULL;
> +	struct udp_hdr *udp = NULL;
> +	struct vxlan_hdr *vxlan = NULL;
> +	size_t len;
> +	size_t temp_size = 0;
> +
> +	if (!item)
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> +					  NULL, "invalid empty data");
> +	for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
> +		len = flow_dv_get_item_len(item->type);
> +		if (len + temp_size > MLX5_ENCAP_MAX_LEN)
> +			return rte_flow_error_set(error, EINVAL,
> +
> RTE_FLOW_ERROR_TYPE_ACTION,
> +						  (void *)item->type,
> +						  "items total size is too big"
> +						  " for encap action");
> +		rte_memcpy((void *)&buf[temp_size], item->spec, len);
> +		switch (item->type) {
> +		case RTE_FLOW_ITEM_TYPE_ETH:
> +			eth = (struct ether_hdr *)&buf[temp_size];
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_VLAN:
> +			vlan = (struct vlan_hdr *)&buf[temp_size];
> +			if (!eth)
> +				return rte_flow_error_set(error, EINVAL,
> +
> 	RTE_FLOW_ERROR_TYPE_ACTION,
> +						(void *)item->type,
> +						"eth header not found");
> +			if (!eth->ether_type)
> +				eth->ether_type =
> RTE_BE16(ETHER_TYPE_VLAN);
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_IPV4:
> +			ipv4 = (struct ipv4_hdr *)&buf[temp_size];
> +			if (!vlan && !eth)
> +				return rte_flow_error_set(error, EINVAL,
> +
> 	RTE_FLOW_ERROR_TYPE_ACTION,
> +						(void *)item->type,
> +						"neither eth nor vlan"
> +						" header found");
> +			if (vlan && !vlan->eth_proto)
> +				vlan->eth_proto =
> RTE_BE16(ETHER_TYPE_IPv4);
> +			else if (eth && !eth->ether_type)
> +				eth->ether_type =
> RTE_BE16(ETHER_TYPE_IPv4);
> +			if (!ipv4->version_ihl)
> +				ipv4->version_ihl = MLX5_IPV4_VERSION |
> +						    MLX5_IPV4_IHL_MIN;
> +			if (!ipv4->time_to_live)
> +				ipv4->time_to_live = MLX5_IPV4_TTL_DEF;
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_IPV6:
> +			ipv6 = (struct ipv6_hdr *)&buf[temp_size];
> +			if (!vlan && !eth)
> +				return rte_flow_error_set(error, EINVAL,
> +
> 	RTE_FLOW_ERROR_TYPE_ACTION,
> +						(void *)item->type,
> +						"neither eth nor vlan"
> +						" header found");
> +			if (vlan && !vlan->eth_proto)
> +				vlan->eth_proto =
> RTE_BE16(ETHER_TYPE_IPv6);
> +			else if (eth && !eth->ether_type)
> +				eth->ether_type =
> RTE_BE16(ETHER_TYPE_IPv6);
> +			if (!ipv6->vtc_flow)
> +				ipv6->vtc_flow =
> RTE_BE32(MLX5_IPV6_VTC_FLOW);
> +			if (!ipv6->hop_limits)
> +				ipv6->hop_limits = MLX5_IPV6_HOP_LIMIT;
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_UDP:
> +			udp = (struct udp_hdr *)&buf[temp_size];
> +			if (!ipv4 && !ipv6)
> +				return rte_flow_error_set(error, EINVAL,
> +
> 	RTE_FLOW_ERROR_TYPE_ACTION,
> +						(void *)item->type,
> +						"ip header not found");
> +			if (ipv4 && !ipv4->next_proto_id)
> +				ipv4->next_proto_id = IPPROTO_UDP;
> +			else if (ipv6 && !ipv6->proto)
> +				ipv6->proto = IPPROTO_UDP;

This is not what I meant. I meant to check the vxlan GPE next protocol. This one must be set by the App

> +			break;
> +		case RTE_FLOW_ITEM_TYPE_VXLAN:
> +			vxlan = (struct vxlan_hdr *)&buf[temp_size];
> +			if (!udp)
> +				return rte_flow_error_set(error, EINVAL,
> +
> 	RTE_FLOW_ERROR_TYPE_ACTION,
> +						(void *)item->type,
> +						"udp header not found");
> +			if (!udp->dst_port)
> +				udp->dst_port =
> RTE_BE16(MLX5_UDP_PORT_VXLAN);
> +			if (!vxlan->vx_flags)
> +				vxlan->vx_flags =
> RTE_BE32(MLX5_VXLAN_FLAGS);
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
> +			vxlan = (struct vxlan_hdr *)&buf[temp_size];
> +			if (!udp)
> +				return rte_flow_error_set(error, EINVAL,
> +
> 	RTE_FLOW_ERROR_TYPE_ACTION,
> +						(void *)item->type,
> +						"udp header not found");
> +			if ((ipv4 && !ipv4->next_proto_id) ||
> +			    (ipv6 && !ipv6->proto))
> +				return rte_flow_error_set(error, EINVAL,
> +
> 	RTE_FLOW_ERROR_TYPE_ACTION,
> +						(void *)item->type,
> +						"next protocol not found");
> +			if (!udp->dst_port)
> +				udp->dst_port =
> +
> 	RTE_BE16(MLX5_UDP_PORT_VXLAN_GPE);
> +			if (!vxlan->vx_flags)
> +				vxlan->vx_flags =
> +
> 	RTE_BE32(MLX5_VXLAN_GPE_FLAGS);
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_VOID:
> +			break;
> +		default:
> +			return rte_flow_error_set(error, EINVAL,
> +
> RTE_FLOW_ERROR_TYPE_ACTION,
> +						  (void *)item->type,
> +						  "unsupported item type");
> +			break;
> +		}
> +		temp_size += len;
> +	}
> +	*size = temp_size;
> +	return 0;
> +}
> +
> +/**
> + * Convert L2 encap action to DV specification.
> + *
> + * @param[in] dev
> + *   Pointer to rte_eth_dev structure.
> + * @param[in] action
> + *   Pointer to action structure.
> + * @param[out] error
> + *   Pointer to the error structure.
> + *
> + * @return
> + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> + */
> +static struct ibv_flow_action *
> +flow_dv_create_action_l2_encap(struct rte_eth_dev *dev,
> +			       const struct rte_flow_action *action,
> +			       struct rte_flow_error *error) {
> +	struct ibv_flow_action *verbs_action = NULL;
> +	const struct rte_flow_item *encap_data;
> +	struct priv *priv = dev->data->dev_private;
> +	uint8_t buf[MLX5_ENCAP_MAX_LEN];
> +	size_t size = 0;
> +	int convert_result = 0;
> +
> +	encap_data = ((const struct rte_flow_action_vxlan_encap *)
> +						action->conf)->definition;
> +	convert_result = flow_dv_convert_encap_data(encap_data, buf,
> +						    &size, error);
> +	if (convert_result)
> +		return NULL;
> +	verbs_action = mlx5_glue-
> >dv_create_flow_action_packet_reformat
> +		(priv->ctx, size, buf,
> +
> MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
> +		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
> +	if (!verbs_action)
> +		rte_flow_error_set(error, EINVAL,
> RTE_FLOW_ERROR_TYPE_ACTION,
> +				   NULL, "cannot create L2 encap action");
> +	return verbs_action;
> +}
> +
> +/**
>   * Verify the @p attributes will be correctly understood by the NIC and store
>   * them in the @p flow if everything is correct.
>   *
> @@ -339,6 +638,16 @@
>  			action_flags |= MLX5_FLOW_ACTION_COUNT;
>  			++actions_n;
>  			break;
> +		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
> +			ret =
> flow_dv_validate_action_l2_encap(action_flags,
> +							       actions, attr,
> +							       error);
> +			if (ret < 0)
> +				return ret;
> +			action_flags |=
> MLX5_FLOW_ACTION_VXLAN_ENCAP;
> +			++actions_n;
> +			break;
> +
>  		default:
>  			return rte_flow_error_set(error, ENOTSUP,
> 
> RTE_FLOW_ERROR_TYPE_ACTION,
> @@ -1045,14 +1354,23 @@
>  /**
>   * Store the requested actions in an array.
>   *
> + * @param[in] dev
> + *   Pointer to rte_eth_dev structure.
>   * @param[in] action
>   *   Flow action to translate.
>   * @param[in, out] dev_flow
>   *   Pointer to the mlx5_flow.
> + * @param[out] error
> + *   Pointer to the error structure.
> + *
> + * @return
> + *   0 on success, a negative errno value otherwise and rte_errno is set.
>   */
> -static void
> -flow_dv_create_action(const struct rte_flow_action *action,
> -		      struct mlx5_flow *dev_flow)
> +static int
> +flow_dv_create_action(struct rte_eth_dev *dev,
> +		      const struct rte_flow_action *action,
> +		      struct mlx5_flow *dev_flow,
> +		      struct rte_flow_error *error)
>  {
>  	const struct rte_flow_action_queue *queue;
>  	const struct rte_flow_action_rss *rss; @@ -1100,10 +1418,24 @@
>  		/* Added to array only in apply since we need the QP */
>  		flow->actions |= MLX5_FLOW_ACTION_RSS;
>  		break;
> +	case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
> +		dev_flow->dv.actions[actions_n].type =
> +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> +		dev_flow->dv.actions[actions_n].action =
> +				flow_dv_create_action_l2_encap(dev,
> action,
> +							       error);
> +		if (!(dev_flow->dv.actions[actions_n].action))
> +			return -rte_errno;
> +		dev_flow->dv.encap_decap_verbs_action =
> +			dev_flow->dv.actions[actions_n].action;
> +		flow->actions |= MLX5_FLOW_ACTION_VXLAN_ENCAP;
> +		actions_n++;
> +		break;
>  	default:
>  		break;
>  	}
>  	dev_flow->dv.actions_n = actions_n;
> +	return 0;
>  }
> 
>  static uint32_t matcher_zero[MLX5_ST_SZ_DW(fte_match_param)] = { 0 };
> @@ -1217,7 +1549,6 @@
>  	return 0;
>  }
> 
> -
>  /**
>   * Fill the flow with DV spec.
>   *
> @@ -1272,7 +1603,8 @@
>  	if (flow_dv_matcher_register(dev, &matcher, dev_flow, error))
>  		return -rte_errno;
>  	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++)
> -		flow_dv_create_action(actions, dev_flow);
> +		if (flow_dv_create_action(dev, actions, dev_flow, error))
> +			return -rte_errno;
>  	return 0;
>  }
> 
> @@ -1457,6 +1789,11 @@
>  		LIST_REMOVE(dev_flow, next);
>  		if (dev_flow->dv.matcher)
>  			flow_dv_matcher_release(dev, dev_flow);
> +		if (dev_flow->dv.encap_decap_verbs_action) {
> +			claim_zero(mlx5_glue->destroy_flow_action
> +				(dev_flow->dv.encap_decap_verbs_action));
> +			dev_flow->dv.encap_decap_verbs_action = NULL;
> +		}
>  		rte_free(dev_flow);
>  	}
>  }
> --
> 1.8.3.1

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

* Re: [dpdk-dev] [PATCH v7 4/7] net/mlx5: add NVGRE encap action to Direct Verbs
  2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 4/7] net/mlx5: add NVGRE encap " Dekel Peled
@ 2018-10-31 15:09             ` Shahaf Shuler
  2018-11-01  9:13               ` Dekel Peled
  0 siblings, 1 reply; 94+ messages in thread
From: Shahaf Shuler @ 2018-10-31 15:09 UTC (permalink / raw)
  To: Dekel Peled, Yongseok Koh; +Cc: dev, Ori Kam

Wednesday, October 31, 2018 9:11 AM, Dekel Peled:
> Subject: [dpdk-dev] [PATCH v7 4/7] net/mlx5: add NVGRE encap action to
> Direct Verbs
> 
> This patch implements the nvgre encap action in DV flow for MLX5 PMD.
> 
> Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> ---
>  drivers/net/mlx5/mlx5_flow.h    |  4 ++++
>  drivers/net/mlx5/mlx5_flow_dv.c | 37
> ++++++++++++++++++++++++++++++++-----
>  2 files changed, 36 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
> index 8955a12..c03a3af 100644
> --- a/drivers/net/mlx5/mlx5_flow.h
> +++ b/drivers/net/mlx5/mlx5_flow.h
> @@ -94,10 +94,14 @@
>  #define MLX5_FLOW_ACTION_SET_MAC_DST (1u << 21)  #define
> MLX5_FLOW_ACTION_VXLAN_ENCAP (1u << 22)  #define
> MLX5_FLOW_ACTION_VXLAN_DECAP (1u << 23)
> +#define MLX5_FLOW_ACTION_NVGRE_ENCAP (1u << 24)
> 
>  #define MLX5_FLOW_FATE_ACTIONS \
>  	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE |
> MLX5_FLOW_ACTION_RSS)
> 
> +#define MLX5_FLOW_ENCAP_ACTIONS	\
> +	(MLX5_FLOW_ACTION_VXLAN_ENCAP |
> MLX5_FLOW_ACTION_NVGRE_ENCAP)
> +
>  #ifndef IPPROTO_MPLS
>  #define IPPROTO_MPLS 137
>  #endif
> diff --git a/drivers/net/mlx5/mlx5_flow_dv.c
> b/drivers/net/mlx5/mlx5_flow_dv.c index 7de65bb..7078397 100644
> --- a/drivers/net/mlx5/mlx5_flow_dv.c
> +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> @@ -126,7 +126,7 @@
>  		return rte_flow_error_set(error, EINVAL,
>  					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
>  					  "can't drop and encap in same
> flow");
> -	if (action_flags & (MLX5_FLOW_ACTION_VXLAN_ENCAP |
> +	if (action_flags & (MLX5_FLOW_ENCAP_ACTIONS |
>  			    MLX5_FLOW_ACTION_VXLAN_DECAP))
>  		return rte_flow_error_set(error, EINVAL,
>  					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL, @@ -163,7 +163,7 @@
>  		return rte_flow_error_set(error, EINVAL,
>  					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL,
>  					  "can't drop and decap in same
> flow");
> -	if (action_flags & (MLX5_FLOW_ACTION_VXLAN_ENCAP |
> +	if (action_flags & (MLX5_FLOW_ENCAP_ACTIONS |
>  			    MLX5_FLOW_ACTION_VXLAN_DECAP))
>  		return rte_flow_error_set(error, EINVAL,
>  					  RTE_FLOW_ERROR_TYPE_ACTION,
> NULL, @@ -376,6 +376,20 @@
>  				vxlan->vx_flags =
> 
> 	RTE_BE32(MLX5_VXLAN_GPE_FLAGS);
>  			break;
> +		case RTE_FLOW_ITEM_TYPE_GRE:
> +		case RTE_FLOW_ITEM_TYPE_NVGRE:
> +			if (!ipv4 && !ipv6)
> +				return rte_flow_error_set(error, EINVAL,
> +
> 	RTE_FLOW_ERROR_TYPE_ACTION,
> +						(void *)item->type,
> +						"ip header not found");
> +			if ((ipv4 && !ipv4->next_proto_id) ||
> +			    (ipv6 && !ipv6->proto))
> +				return rte_flow_error_set(error, EINVAL,

Same comment like in the VXLAN-GPE. It is not the ip next proto you need to check it is the GRE protocol. 

> +
> 	RTE_FLOW_ERROR_TYPE_ACTION,
> +						(void *)item->type,
> +						"next protocol not found");
> +			break;
>  		case RTE_FLOW_ITEM_TYPE_VOID:
>  			break;
>  		default:
> @@ -416,7 +430,11 @@
>  	size_t size = 0;
>  	int convert_result = 0;
> 
> -	encap_data = ((const struct rte_flow_action_vxlan_encap *)
> +	if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP)
> +		encap_data = ((const struct rte_flow_action_vxlan_encap *)
> +						action->conf)->definition;
> +	else
> +		encap_data = ((const struct rte_flow_action_nvgre_encap *)
>  						action->conf)->definition;
>  	convert_result = flow_dv_convert_encap_data(encap_data, buf,
>  						    &size, error);
> @@ -705,12 +723,17 @@
>  			++actions_n;
>  			break;
>  		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
> +		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
>  			ret =
> flow_dv_validate_action_l2_encap(action_flags,
>  							       actions, attr,
>  							       error);
>  			if (ret < 0)
>  				return ret;
> -			action_flags |=
> MLX5_FLOW_ACTION_VXLAN_ENCAP;
> +			action_flags |= actions->type ==
> +
> 	RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP ?
> +
> 	MLX5_FLOW_ACTION_VXLAN_ENCAP :
> +
> 	MLX5_FLOW_ACTION_NVGRE_ENCAP;
> +
>  			++actions_n;
>  			break;
>  		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
> @@ -1492,6 +1515,7 @@
>  		flow->actions |= MLX5_FLOW_ACTION_RSS;
>  		break;
>  	case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
> +	case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
>  		dev_flow->dv.actions[actions_n].type =
>  			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
>  		dev_flow->dv.actions[actions_n].action = @@ -1501,7
> +1525,10 @@
>  			return -rte_errno;
>  		dev_flow->dv.encap_decap_verbs_action =
>  			dev_flow->dv.actions[actions_n].action;
> -		flow->actions |= MLX5_FLOW_ACTION_VXLAN_ENCAP;
> +		flow->actions |= action->type ==
> +				 RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP ?
> +				 MLX5_FLOW_ACTION_VXLAN_ENCAP :
> +				 MLX5_FLOW_ACTION_NVGRE_ENCAP;
>  		actions_n++;
>  		break;
>  	case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
> --
> 1.8.3.1

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

* Re: [dpdk-dev] [PATCH v7 7/7] net/mlx5: add caching of encap decap actions
  2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 7/7] net/mlx5: add caching of encap decap actions Dekel Peled
@ 2018-10-31 15:09             ` Shahaf Shuler
  2018-11-01  9:15               ` Dekel Peled
  0 siblings, 1 reply; 94+ messages in thread
From: Shahaf Shuler @ 2018-10-31 15:09 UTC (permalink / raw)
  To: Dekel Peled, Yongseok Koh; +Cc: dev, Ori Kam

Wednesday, October 31, 2018 9:11 AM, Dekel Peled:
> Subject: [dpdk-dev] [PATCH v7 7/7] net/mlx5: add caching of encap decap
> actions
> 
> Make flow encap and decap Verbs actions cacheable resources.
> Reuse 17.11 PR 876.

No one knows what is PR 876 in the mailing list, also this code is not in 17.11 community. 
Need to make a proper commit log here explains how you do the caching and why it is needed. 

> 
> Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> ---
>  drivers/net/mlx5/mlx5.h         |   1 +
>  drivers/net/mlx5/mlx5_flow.h    |  18 ++-
>  drivers/net/mlx5/mlx5_flow_dv.c | 265 ++++++++++++++++++++++++++---
> -----------
>  3 files changed, 193 insertions(+), 91 deletions(-)
> 
> diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index
> 74d87c0..0422803 100644
> --- a/drivers/net/mlx5/mlx5.h
> +++ b/drivers/net/mlx5/mlx5.h
> @@ -219,6 +219,7 @@ struct priv {
>  	/* Verbs Indirection tables. */
>  	LIST_HEAD(ind_tables, mlx5_ind_table_ibv) ind_tbls;
>  	LIST_HEAD(matchers, mlx5_flow_dv_matcher) matchers;
> +	LIST_HEAD(encap_decap, mlx5_flow_dv_encap_decap_resource)
> +encaps_decaps;
>  	uint32_t link_speed_capa; /* Link speed capabilities. */
>  	struct mlx5_xstats_ctrl xstats_ctrl; /* Extended stats control. */
>  	int primary_socket; /* Unix socket for primary process. */ diff --git
> a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h index
> 908123f..25cd9c5 100644
> --- a/drivers/net/mlx5/mlx5_flow.h
> +++ b/drivers/net/mlx5/mlx5_flow.h
> @@ -170,6 +170,7 @@ struct mlx5_flow_dv_match_params {  };
> 
>  #define MLX5_DV_MAX_NUMBER_OF_ACTIONS 8
> +#define MLX5_ENCAP_MAX_LEN 132
> 
>  /* Matcher structure. */
>  struct mlx5_flow_dv_matcher {
> @@ -183,6 +184,19 @@ struct mlx5_flow_dv_matcher {
>  	struct mlx5_flow_dv_match_params mask; /**< Matcher mask. */  };
> 
> +/* Encap/decap resource structure. */
> +struct mlx5_flow_dv_encap_decap_resource {
> +	LIST_ENTRY(mlx5_flow_dv_encap_decap_resource) next;
> +	/* Pointer to next element. */
> +	rte_atomic32_t refcnt; /**< Reference counter. */
> +	struct ibv_flow_action *verbs_action;
> +	/**< Verbs encap/decap action object. */
> +	uint8_t buf[MLX5_ENCAP_MAX_LEN];
> +	size_t size;
> +	uint8_t reformat_type;
> +	uint8_t ft_type;
> +};
> +
>  /* DV flows structure. */
>  struct mlx5_flow_dv {
>  	uint64_t hash_fields; /**< Fields that participate in the hash. */ @@
> -191,12 +205,12 @@ struct mlx5_flow_dv {
>  	struct mlx5_flow_dv_matcher *matcher; /**< Cache to matcher. */
>  	struct mlx5_flow_dv_match_params value;
>  	/**< Holds the value that the packet is compared to. */
> +	struct mlx5_flow_dv_encap_decap_resource *encap_decap;
> +	/**< Pointer to encap/decap resource in cache. */
>  	struct ibv_flow *flow; /**< Installed flow. */  #ifdef
> HAVE_IBV_FLOW_DV_SUPPORT
>  	struct mlx5dv_flow_action_attr
> actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS];
>  	/**< Action list. */
> -	struct ibv_flow_action *encap_decap_verbs_action;
> -	/**< Verbs encap/decap object. */
>  #endif
>  	int actions_n; /**< number of actions. */  }; diff --git
> a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
> index d1c811f..818b30c 100644
> --- a/drivers/net/mlx5/mlx5_flow_dv.c
> +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> @@ -34,8 +34,6 @@
> 
>  #ifdef HAVE_IBV_FLOW_DV_SUPPORT
> 
> -#define MLX5_ENCAP_MAX_LEN 132
> -
>  /**
>   * Validate META item.
>   *
> @@ -271,6 +269,77 @@
>  	return 0;
>  }
> 
> +
> +/**
> + * Find existing encap/decap resource or create and register a new one.
> + *
> + * @param dev[in, out]
> + *   Pointer to rte_eth_dev structure.
> + * @param[in, out] resource
> + *   Pointer to encap/decap resource.
> + * @parm[in, out] dev_flow
> + *   Pointer to the dev_flow.
> + * @param[out] error
> + *   pointer to error structure.
> + *
> + * @return
> + *   0 on success otherwise -errno and errno is set.
> + */
> +static int
> +flow_dv_encap_decap_resource_register
> +			(struct rte_eth_dev *dev,
> +			 struct mlx5_flow_dv_encap_decap_resource
> *resource,
> +			 struct mlx5_flow *dev_flow,
> +			 struct rte_flow_error *error)
> +{
> +	struct priv *priv = dev->data->dev_private;
> +	struct mlx5_flow_dv_encap_decap_resource *cache_resource;
> +
> +	/* Lookup a matching resource from cache. */
> +	LIST_FOREACH(cache_resource, &priv->encaps_decaps, next) {
> +		if (resource->reformat_type == cache_resource-
> >reformat_type &&
> +		    resource->ft_type == cache_resource->ft_type &&
> +		    resource->size == cache_resource->size &&
> +		    !memcmp((const void *)resource->buf,
> +			    (const void *)cache_resource->buf,
> +			    resource->size)) {
> +			DRV_LOG(DEBUG, "encap/decap resource %p: refcnt
> %d++",
> +				(void *)cache_resource,
> +				rte_atomic32_read(&cache_resource-
> >refcnt));
> +			rte_atomic32_inc(&cache_resource->refcnt);
> +			dev_flow->dv.encap_decap = cache_resource;
> +			return 0;
> +		}
> +	}
> +	/* Register new encap/decap resource. */
> +	cache_resource = rte_calloc(__func__, 1, sizeof(*cache_resource),
> 0);
> +	if (!cache_resource)
> +		return rte_flow_error_set(error, ENOMEM,
> +
> RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
> +					  "cannot allocate resource
> memory");
> +	*cache_resource = *resource;
> +	cache_resource->verbs_action =
> +		mlx5_glue->dv_create_flow_action_packet_reformat
> +			(priv->ctx, cache_resource->size,
> +			 (cache_resource->size ? cache_resource->buf :
> NULL),
> +			 cache_resource->reformat_type,
> +			 cache_resource->ft_type);
> +	if (!cache_resource->verbs_action) {
> +		rte_free(cache_resource);
> +		return rte_flow_error_set(error, ENOMEM,
> +
> RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
> +					  NULL, "cannot create action");
> +	}
> +	rte_atomic32_init(&cache_resource->refcnt);
> +	rte_atomic32_inc(&cache_resource->refcnt);
> +	LIST_INSERT_HEAD(&priv->encaps_decaps, cache_resource, next);
> +	dev_flow->dv.encap_decap = cache_resource;
> +	DRV_LOG(DEBUG, "new encap/decap resource %p: refcnt %d++",
> +		(void *)cache_resource,
> +		rte_atomic32_read(&cache_resource->refcnt));
> +	return 0;
> +}
> +
>  /**
>   * Get the size of specific rte_flow_item_type
>   *
> @@ -505,31 +574,33 @@
>   *   Pointer to rte_eth_dev structure.
>   * @param[in] action
>   *   Pointer to action structure.
> + * @param[in, out] dev_flow
> + *   Pointer to the mlx5_flow.
>   * @param[out] error
>   *   Pointer to the error structure.
>   *
>   * @return
> - *   Pointer to action on success, NULL otherwise and rte_errno is set.
> + *   0 on success, a negative errno value otherwise and rte_errno is set.
>   */
> -static struct ibv_flow_action *
> +static int
>  flow_dv_create_action_l2_encap(struct rte_eth_dev *dev,
>  			       const struct rte_flow_action *action,
> +			       struct mlx5_flow *dev_flow,
>  			       struct rte_flow_error *error)  {
> -	struct ibv_flow_action *verbs_action = NULL;
>  	const struct rte_flow_item *encap_data;
>  	const struct rte_flow_action_raw_encap *raw_encap_data;
> -	struct priv *priv = dev->data->dev_private;
> -	uint8_t buf[MLX5_ENCAP_MAX_LEN];
> -	uint8_t *buf_ptr = buf;
> -	size_t size = 0;
> -	int convert_result = 0;
> +	struct mlx5_flow_dv_encap_decap_resource res = {
> +		.reformat_type =
> +
> 	MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TU
> NNEL,
> +		.ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_TX,
> +	};
> 
>  	if (action->type == RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
>  		raw_encap_data =
>  			(const struct rte_flow_action_raw_encap *)action-
> >conf;
> -		buf_ptr = raw_encap_data->data;
> -		size = raw_encap_data->size;
> +		res.size = raw_encap_data->size;
> +		memcpy(res.buf, raw_encap_data->data, res.size);
>  	} else {
>  		if (action->type ==
> RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP)
>  			encap_data =
> @@ -539,19 +610,15 @@
>  			encap_data =
>  				((const struct rte_flow_action_nvgre_encap
> *)
>  						action->conf)->definition;
> -		convert_result = flow_dv_convert_encap_data(encap_data,
> buf,
> -							    &size, error);
> -		if (convert_result)
> -			return NULL;
> +		if (flow_dv_convert_encap_data(encap_data, res.buf,
> +					       &res.size, error))
> +			return -rte_errno;
>  	}
> -	verbs_action = mlx5_glue-
> >dv_create_flow_action_packet_reformat
> -		(priv->ctx, size, buf_ptr,
> -
> MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
> -		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
> -	if (!verbs_action)
> -		rte_flow_error_set(error, EINVAL,
> RTE_FLOW_ERROR_TYPE_ACTION,
> -				   NULL, "cannot create L2 encap action");
> -	return verbs_action;
> +	if (flow_dv_encap_decap_resource_register(dev, &res, dev_flow,
> error))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> +					  NULL, "can't create L2 encap
> action");
> +	return 0;
>  }
> 
>  /**
> @@ -559,27 +626,31 @@
>   *
>   * @param[in] dev
>   *   Pointer to rte_eth_dev structure.
> + * @param[in, out] dev_flow
> + *   Pointer to the mlx5_flow.
>   * @param[out] error
>   *   Pointer to the error structure.
>   *
>   * @return
> - *   Pointer to action on success, NULL otherwise and rte_errno is set.
> + *   0 on success, a negative errno value otherwise and rte_errno is set.
>   */
> -static struct ibv_flow_action *
> +static int
>  flow_dv_create_action_l2_decap(struct rte_eth_dev *dev,
> +			       struct mlx5_flow *dev_flow,
>  			       struct rte_flow_error *error)  {
> -	struct ibv_flow_action *verbs_action = NULL;
> -	struct priv *priv = dev->data->dev_private;
> +	struct mlx5_flow_dv_encap_decap_resource res = {
> +		.size = 0,
> +		.reformat_type =
> +
> 	MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_T
> O_L2,
> +		.ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_RX,
> +	};
> 
> -	verbs_action = mlx5_glue-
> >dv_create_flow_action_packet_reformat
> -		(priv->ctx, 0, NULL,
> -
> MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2,
> -		 MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
> -	if (!verbs_action)
> -		rte_flow_error_set(error, EINVAL,
> RTE_FLOW_ERROR_TYPE_ACTION,
> -				   NULL, "cannot create L2 decap action");
> -	return verbs_action;
> +	if (flow_dv_encap_decap_resource_register(dev, &res, dev_flow,
> error))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> +					  NULL, "can't create L2 decap
> action");
> +	return 0;
>  }
> 
>  /**
> @@ -589,41 +660,39 @@
>   *   Pointer to rte_eth_dev structure.
>   * @param[in] action
>   *   Pointer to action structure.
> + * @param[in, out] dev_flow
> + *   Pointer to the mlx5_flow.
>   * @param[in] attr
>   *   Pointer to the flow attributes.
>   * @param[out] error
>   *   Pointer to the error structure.
>   *
>   * @return
> - *   Pointer to action on success, NULL otherwise and rte_errno is set.
> + *   0 on success, a negative errno value otherwise and rte_errno is set.
>   */
> -static struct ibv_flow_action *
> +static int
>  flow_dv_create_action_raw_encap(struct rte_eth_dev *dev,
>  				const struct rte_flow_action *action,
> +				struct mlx5_flow *dev_flow,
>  				const struct rte_flow_attr *attr,
>  				struct rte_flow_error *error)
>  {
> -	struct ibv_flow_action *verbs_action = NULL;
>  	const struct rte_flow_action_raw_encap *encap_data;
> -	struct priv *priv = dev->data->dev_private;
> -	enum mlx5dv_flow_action_packet_reformat_type reformat_type;
> -	enum mlx5dv_flow_table_type ft_type;
> +	struct mlx5_flow_dv_encap_decap_resource res;
> 
>  	encap_data = (const struct rte_flow_action_raw_encap *)action-
> >conf;
> -	reformat_type = attr->egress ?
> +	res.size = encap_data->size;
> +	memcpy(res.buf, encap_data->data, res.size);
> +	res.reformat_type = attr->egress ?
> 
> 	MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TU
> NNEL :
> 
> 	MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_T
> O_L2;
> -	ft_type = attr->egress ?
> -			MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
> -			MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
> -	verbs_action = mlx5_glue-
> >dv_create_flow_action_packet_reformat
> -				(priv->ctx, encap_data->size,
> -				(encap_data->size ? encap_data->data :
> NULL),
> -				reformat_type, ft_type);
> -	if (!verbs_action)
> -		rte_flow_error_set(error, EINVAL,
> RTE_FLOW_ERROR_TYPE_ACTION,
> -				   NULL, "cannot create encap action");
> -	return verbs_action;
> +	res.ft_type = attr->egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
> +				     MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
> +	if (flow_dv_encap_decap_resource_register(dev, &res, dev_flow,
> error))
> +		return rte_flow_error_set(error, EINVAL,
> +					  RTE_FLOW_ERROR_TYPE_ACTION,
> +					  NULL, "can't create encap action");
> +	return 0;
>  }
> 
>  /**
> @@ -1689,15 +1758,13 @@
>  		break;
>  	case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
>  	case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
> +		if (flow_dv_create_action_l2_encap(dev, action,
> +						   dev_flow, error))
> +			return -rte_errno;
>  		dev_flow->dv.actions[actions_n].type =
>  			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
>  		dev_flow->dv.actions[actions_n].action =
> -				flow_dv_create_action_l2_encap(dev,
> action,
> -							       error);
> -		if (!(dev_flow->dv.actions[actions_n].action))
> -			return -rte_errno;
> -		dev_flow->dv.encap_decap_verbs_action =
> -			dev_flow->dv.actions[actions_n].action;
> +			dev_flow->dv.encap_decap->verbs_action;
>  		flow->actions |= action->type ==
>  				 RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP ?
>  				 MLX5_FLOW_ACTION_VXLAN_ENCAP :
> @@ -1706,14 +1773,12 @@
>  		break;
>  	case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
>  	case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
> +		if (flow_dv_create_action_l2_decap(dev, dev_flow, error))
> +			return -rte_errno;
>  		dev_flow->dv.actions[actions_n].type =
>  			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
>  		dev_flow->dv.actions[actions_n].action =
> -				flow_dv_create_action_l2_decap(dev,
> error);
> -		if (!(dev_flow->dv.actions[actions_n].action))
> -			return -rte_errno;
> -		dev_flow->dv.encap_decap_verbs_action =
> -			dev_flow->dv.actions[actions_n].action;
> +			dev_flow->dv.encap_decap->verbs_action;
>  		flow->actions |= action->type ==
>  				 RTE_FLOW_ACTION_TYPE_VXLAN_DECAP ?
>  				 MLX5_FLOW_ACTION_VXLAN_DECAP :
> @@ -1723,27 +1788,23 @@
>  	case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
>  		/* Handle encap action with preceding decap */
>  		if (flow->actions & MLX5_FLOW_ACTION_RAW_DECAP) {
> +			if (flow_dv_create_action_raw_encap(dev, action,
> +							    dev_flow,
> +							    attr, error))
> +				return -rte_errno;
>  			dev_flow->dv.actions[actions_n].type =
> 
> 	MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
>  			dev_flow->dv.actions[actions_n].action =
> -					flow_dv_create_action_raw_encap
> -								(dev, action,
> -								 attr, error);
> -			if (!(dev_flow->dv.actions[actions_n].action))
> -				return -rte_errno;
> -			dev_flow->dv.encap_decap_verbs_action =
> -				dev_flow->dv.actions[actions_n].action;
> +					dev_flow->dv.encap_decap-
> >verbs_action;
>  		} else {
>  			/* Handle encap action without preceding decap */
> +			if (flow_dv_create_action_l2_encap(dev, action,
> +							   dev_flow, error))
> +				return -rte_errno;
>  			dev_flow->dv.actions[actions_n].type =
> 
> 	MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
>  			dev_flow->dv.actions[actions_n].action =
> -					flow_dv_create_action_l2_encap
> -							(dev, action, error);
> -			if (!(dev_flow->dv.actions[actions_n].action))
> -				return -rte_errno;
> -			dev_flow->dv.encap_decap_verbs_action =
> -				dev_flow->dv.actions[actions_n].action;
> +					dev_flow->dv.encap_decap-
> >verbs_action;
>  		}
>  		flow->actions |= MLX5_FLOW_ACTION_RAW_ENCAP;
>  		actions_n++;
> @@ -1756,15 +1817,13 @@
>  		}
>  		/* Handle decap action only if it isn't followed by encap */
>  		if (action_ptr->type !=
> RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
> +			if (flow_dv_create_action_l2_decap(dev, dev_flow,
> +							   error))
> +				return -rte_errno;
>  			dev_flow->dv.actions[actions_n].type =
> 
> 	MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
>  			dev_flow->dv.actions[actions_n].action =
> -
> 	flow_dv_create_action_l2_decap(dev,
> -								       error);
> -			if (!(dev_flow->dv.actions[actions_n].action))
> -				return -rte_errno;
> -			dev_flow->dv.encap_decap_verbs_action =
> -				dev_flow->dv.actions[actions_n].action;
> +					dev_flow->dv.encap_decap-
> >verbs_action;
>  			actions_n++;
>  		}
>  		/* If decap is followed by encap, handle it at encap case. */
> @@ -2074,6 +2133,37 @@  }
> 
>  /**
> + * Release an encap/decap resource.
> + *
> + * @param flow
> + *   Pointer to mlx5_flow.
> + *
> + * @return
> + *   1 while a reference on it exists, 0 when freed.
> + */
> +static int
> +flow_dv_encap_decap_resource_release(struct mlx5_flow *flow) {
> +	struct mlx5_flow_dv_encap_decap_resource *cache_resource =
> +						flow->dv.encap_decap;
> +
> +	assert(cache_resource->verbs_action);
> +	DRV_LOG(DEBUG, "encap/decap resource %p: refcnt %d--",
> +		(void *)cache_resource,
> +		rte_atomic32_read(&cache_resource->refcnt));
> +	if (rte_atomic32_dec_and_test(&cache_resource->refcnt)) {
> +		claim_zero(mlx5_glue->destroy_flow_action
> +				(cache_resource->verbs_action));
> +		LIST_REMOVE(cache_resource, next);
> +		rte_free(cache_resource);
> +		DRV_LOG(DEBUG, "encap/decap resource %p: removed",
> +			cache_resource);
> +		return 0;
> +	}
> +	return 1;
> +}
> +
> +/**
>   * Remove the flow from the NIC but keeps it in memory.
>   *
>   * @param[in] dev
> @@ -2128,11 +2218,8 @@
>  		LIST_REMOVE(dev_flow, next);
>  		if (dev_flow->dv.matcher)
>  			flow_dv_matcher_release(dev, dev_flow);
> -		if (dev_flow->dv.encap_decap_verbs_action) {
> -			claim_zero(mlx5_glue->destroy_flow_action
> -				(dev_flow->dv.encap_decap_verbs_action));
> -			dev_flow->dv.encap_decap_verbs_action = NULL;
> -		}
> +		if (dev_flow->dv.encap_decap)
> +
> 	flow_dv_encap_decap_resource_release(dev_flow);
>  		rte_free(dev_flow);
>  	}
>  }
> --
> 1.8.3.1

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

* Re: [dpdk-dev] [PATCH v7 2/7] net/mlx5: add VXLAN encap action to Direct Verbs
  2018-10-31 15:09             ` Shahaf Shuler
@ 2018-11-01  8:22               ` Dekel Peled
  0 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-11-01  8:22 UTC (permalink / raw)
  To: Shahaf Shuler, Yongseok Koh; +Cc: dev, Ori Kam

Thanks, PSB.

> -----Original Message-----
> From: Shahaf Shuler
> Sent: Wednesday, October 31, 2018 5:10 PM
> To: Dekel Peled <dekelp@mellanox.com>; Yongseok Koh
> <yskoh@mellanox.com>
> Cc: dev@dpdk.org; Ori Kam <orika@mellanox.com>
> Subject: RE: [PATCH v7 2/7] net/mlx5: add VXLAN encap action to Direct
> Verbs
> 
> Wednesday, October 31, 2018 9:11 AM, Dekel Peled:
> > Subject: [PATCH v7 2/7] net/mlx5: add VXLAN encap action to Direct
> > Verbs
> >
> > This patch implements the VXLAN encap action in DV flow for MLX5 PMD.
> >
> > Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> > ---
> >  drivers/net/mlx5/mlx5_flow.h    |   3 +
> >  drivers/net/mlx5/mlx5_flow_dv.c | 347
> > +++++++++++++++++++++++++++++++++++++++-
> >  2 files changed, 345 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/net/mlx5/mlx5_flow.h
> > b/drivers/net/mlx5/mlx5_flow.h index 61299d6..286d7bb 100644
> > --- a/drivers/net/mlx5/mlx5_flow.h
> > +++ b/drivers/net/mlx5/mlx5_flow.h
> > @@ -92,6 +92,7 @@
> >  #define MLX5_FLOW_ACTION_DEC_TTL (1u << 19)  #define
> > MLX5_FLOW_ACTION_SET_MAC_SRC (1u << 20)  #define
> > MLX5_FLOW_ACTION_SET_MAC_DST (1u << 21)
> > +#define MLX5_FLOW_ACTION_VXLAN_ENCAP (1u << 22)
> >
> >  #define MLX5_FLOW_FATE_ACTIONS \
> >  	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE |
> > MLX5_FLOW_ACTION_RSS) @@ -181,6 +182,8 @@ struct mlx5_flow_dv {
> #ifdef
> > HAVE_IBV_FLOW_DV_SUPPORT
> >  	struct mlx5dv_flow_action_attr
> > actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS];
> >  	/**< Action list. */
> > +	struct ibv_flow_action *encap_decap_verbs_action;
> > +	/**< Verbs encap/decap object. */
> >  #endif
> >  	int actions_n; /**< number of actions. */  }; diff --git
> > a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
> > index 8f729f4..1f9a842 100644
> > --- a/drivers/net/mlx5/mlx5_flow_dv.c
> > +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> > @@ -34,6 +34,8 @@
> >
> >  #ifdef HAVE_IBV_FLOW_DV_SUPPORT
> >
> > +#define MLX5_ENCAP_MAX_LEN 132
> > +
> >  /**
> >   * Validate META item.
> >   *
> > @@ -96,6 +98,303 @@
> >  }
> >
> >  /**
> > + * Validate the L2 encap action.
> > + *
> > + * @param[in] action_flags
> > + *   Holds the actions detected until now.
> > + * @param[in] action
> > + *   Pointer to the encap action.
> > + * @param[in] attr
> > + *   Pointer to flow attributes
> > + * @param[out] error
> > + *   Pointer to error structure.
> > + *
> > + * @return
> > + *   0 on success, a negative errno value otherwise and rte_errno is set.
> > + */
> > +static int
> > +flow_dv_validate_action_l2_encap(uint64_t action_flags,
> > +				 const struct rte_flow_action *action,
> > +				 const struct rte_flow_attr *attr,
> > +				 struct rte_flow_error *error)
> > +{
> > +	if (!(action->conf))
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > action,
> > +					  "configuration cannot be null");
> > +	if (action_flags & MLX5_FLOW_ACTION_DROP)
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > NULL,
> > +					  "can't drop and encap in same
> > flow");
> > +	if (action_flags & MLX5_FLOW_ACTION_VXLAN_ENCAP)
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > NULL,
> > +					  "can only have a single encap"
> > +					  " action in a flow");
> > +	if (attr->ingress)
> > +		return rte_flow_error_set(error, ENOTSUP,
> > +
> > RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> > +					  NULL,
> > +					  "encap action not supported for "
> > +					  "ingress");
> > +	return 0;
> > +}
> > +
> > +/**
> > + * Get the size of specific rte_flow_item_type
> > + *
> > + * @param[in] item_type
> > + *   Tested rte_flow_item_type.
> > + *
> > + * @return
> > + *   sizeof struct item_type, 0 if void or irrelevant.
> > + */
> > +static size_t
> > +flow_dv_get_item_len(const enum rte_flow_item_type item_type) {
> > +	size_t retval;
> > +
> > +	switch (item_type) {
> > +	case RTE_FLOW_ITEM_TYPE_ETH:
> > +		retval = sizeof(struct rte_flow_item_eth);
> > +		break;
> > +	case RTE_FLOW_ITEM_TYPE_VLAN:
> > +		retval = sizeof(struct rte_flow_item_vlan);
> > +		break;
> > +	case RTE_FLOW_ITEM_TYPE_IPV4:
> > +		retval = sizeof(struct rte_flow_item_ipv4);
> > +		break;
> > +	case RTE_FLOW_ITEM_TYPE_IPV6:
> > +		retval = sizeof(struct rte_flow_item_ipv6);
> > +		break;
> > +	case RTE_FLOW_ITEM_TYPE_UDP:
> > +		retval = sizeof(struct rte_flow_item_udp);
> > +		break;
> > +	case RTE_FLOW_ITEM_TYPE_TCP:
> > +		retval = sizeof(struct rte_flow_item_tcp);
> > +		break;
> > +	case RTE_FLOW_ITEM_TYPE_VXLAN:
> > +		retval = sizeof(struct rte_flow_item_vxlan);
> > +		break;
> > +	case RTE_FLOW_ITEM_TYPE_GRE:
> > +		retval = sizeof(struct rte_flow_item_gre);
> > +		break;
> > +	case RTE_FLOW_ITEM_TYPE_NVGRE:
> > +		retval = sizeof(struct rte_flow_item_nvgre);
> > +		break;
> > +	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
> > +		retval = sizeof(struct rte_flow_item_vxlan_gpe);
> > +		break;
> > +	case RTE_FLOW_ITEM_TYPE_MPLS:
> > +		retval = sizeof(struct rte_flow_item_mpls);
> > +		break;
> > +	case RTE_FLOW_ITEM_TYPE_VOID: /* Fall through. */
> > +	default:
> > +		retval = 0;
> > +		break;
> > +	}
> > +	return retval;
> > +};
> > +
> > +#define MLX5_IPV4_VERSION	0x40
> > +#define MLX5_IPV4_IHL_MIN	0x05
> > +#define MLX5_IPV4_TTL_DEF	0x40
> > +#define MLX5_IPV6_VTC_FLOW	0x60000000
> > +#define MLX5_IPV6_HOP_LIMIT	0xff
> > +#define MLX5_VXLAN_FLAGS	0x08000000
> > +#define MLX5_VXLAN_GPE_FLAGS	0x0c000003
> 
> Better to prefix them all w/ MLX5_ENCAP_*

Will change.

> 
> > +
> > +/**
> > + * Convert the encap action data from list of rte_flow_item to raw
> > +buffer
> > + *
> > + * @param[in] items
> > + *   Pointer to rte_flow_item objects list.
> > + * @param[out] buf
> > + *   Pointer to the output buffer.
> > + * @param[out] size
> > + *   Pointer to the output buffer size.
> > + * @param[out] error
> > + *   Pointer to the error structure.
> > + *
> > + * @return
> > + *   0 on success, a negative errno value otherwise and rte_errno is set.
> > + */
> > +static int
> > +flow_dv_convert_encap_data(const struct rte_flow_item *item, uint8_t
> 
> Here it is also items

Will change.

> 
> > *buf,
> > +			   size_t *size, struct rte_flow_error *error) {
> > +	struct ether_hdr *eth = NULL;
> > +	struct vlan_hdr *vlan = NULL;
> > +	struct ipv4_hdr *ipv4 = NULL;
> > +	struct ipv6_hdr *ipv6 = NULL;
> > +	struct udp_hdr *udp = NULL;
> > +	struct vxlan_hdr *vxlan = NULL;
> > +	size_t len;
> > +	size_t temp_size = 0;
> > +
> > +	if (!item)
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > +					  NULL, "invalid empty data");
> > +	for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
> > +		len = flow_dv_get_item_len(item->type);
> > +		if (len + temp_size > MLX5_ENCAP_MAX_LEN)
> > +			return rte_flow_error_set(error, EINVAL,
> > +
> > RTE_FLOW_ERROR_TYPE_ACTION,
> > +						  (void *)item->type,
> > +						  "items total size is too big"
> > +						  " for encap action");
> > +		rte_memcpy((void *)&buf[temp_size], item->spec, len);
> > +		switch (item->type) {
> > +		case RTE_FLOW_ITEM_TYPE_ETH:
> > +			eth = (struct ether_hdr *)&buf[temp_size];
> > +			break;
> > +		case RTE_FLOW_ITEM_TYPE_VLAN:
> > +			vlan = (struct vlan_hdr *)&buf[temp_size];
> > +			if (!eth)
> > +				return rte_flow_error_set(error, EINVAL,
> > +
> > 	RTE_FLOW_ERROR_TYPE_ACTION,
> > +						(void *)item->type,
> > +						"eth header not found");
> > +			if (!eth->ether_type)
> > +				eth->ether_type =
> > RTE_BE16(ETHER_TYPE_VLAN);
> > +			break;
> > +		case RTE_FLOW_ITEM_TYPE_IPV4:
> > +			ipv4 = (struct ipv4_hdr *)&buf[temp_size];
> > +			if (!vlan && !eth)
> > +				return rte_flow_error_set(error, EINVAL,
> > +
> > 	RTE_FLOW_ERROR_TYPE_ACTION,
> > +						(void *)item->type,
> > +						"neither eth nor vlan"
> > +						" header found");
> > +			if (vlan && !vlan->eth_proto)
> > +				vlan->eth_proto =
> > RTE_BE16(ETHER_TYPE_IPv4);
> > +			else if (eth && !eth->ether_type)
> > +				eth->ether_type =
> > RTE_BE16(ETHER_TYPE_IPv4);
> > +			if (!ipv4->version_ihl)
> > +				ipv4->version_ihl = MLX5_IPV4_VERSION |
> > +						    MLX5_IPV4_IHL_MIN;
> > +			if (!ipv4->time_to_live)
> > +				ipv4->time_to_live = MLX5_IPV4_TTL_DEF;
> > +			break;
> > +		case RTE_FLOW_ITEM_TYPE_IPV6:
> > +			ipv6 = (struct ipv6_hdr *)&buf[temp_size];
> > +			if (!vlan && !eth)
> > +				return rte_flow_error_set(error, EINVAL,
> > +
> > 	RTE_FLOW_ERROR_TYPE_ACTION,
> > +						(void *)item->type,
> > +						"neither eth nor vlan"
> > +						" header found");
> > +			if (vlan && !vlan->eth_proto)
> > +				vlan->eth_proto =
> > RTE_BE16(ETHER_TYPE_IPv6);
> > +			else if (eth && !eth->ether_type)
> > +				eth->ether_type =
> > RTE_BE16(ETHER_TYPE_IPv6);
> > +			if (!ipv6->vtc_flow)
> > +				ipv6->vtc_flow =
> > RTE_BE32(MLX5_IPV6_VTC_FLOW);
> > +			if (!ipv6->hop_limits)
> > +				ipv6->hop_limits = MLX5_IPV6_HOP_LIMIT;
> > +			break;
> > +		case RTE_FLOW_ITEM_TYPE_UDP:
> > +			udp = (struct udp_hdr *)&buf[temp_size];
> > +			if (!ipv4 && !ipv6)
> > +				return rte_flow_error_set(error, EINVAL,
> > +
> > 	RTE_FLOW_ERROR_TYPE_ACTION,
> > +						(void *)item->type,
> > +						"ip header not found");
> > +			if (ipv4 && !ipv4->next_proto_id)
> > +				ipv4->next_proto_id = IPPROTO_UDP;
> > +			else if (ipv6 && !ipv6->proto)
> > +				ipv6->proto = IPPROTO_UDP;
> 
> This is not what I meant. I meant to check the vxlan GPE next protocol. This
> one must be set by the App

Will change.

> 
> > +			break;
> > +		case RTE_FLOW_ITEM_TYPE_VXLAN:
> > +			vxlan = (struct vxlan_hdr *)&buf[temp_size];
> > +			if (!udp)
> > +				return rte_flow_error_set(error, EINVAL,
> > +
> > 	RTE_FLOW_ERROR_TYPE_ACTION,
> > +						(void *)item->type,
> > +						"udp header not found");
> > +			if (!udp->dst_port)
> > +				udp->dst_port =
> > RTE_BE16(MLX5_UDP_PORT_VXLAN);
> > +			if (!vxlan->vx_flags)
> > +				vxlan->vx_flags =
> > RTE_BE32(MLX5_VXLAN_FLAGS);
> > +			break;
> > +		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
> > +			vxlan = (struct vxlan_hdr *)&buf[temp_size];
> > +			if (!udp)
> > +				return rte_flow_error_set(error, EINVAL,
> > +
> > 	RTE_FLOW_ERROR_TYPE_ACTION,
> > +						(void *)item->type,
> > +						"udp header not found");
> > +			if ((ipv4 && !ipv4->next_proto_id) ||
> > +			    (ipv6 && !ipv6->proto))
> > +				return rte_flow_error_set(error, EINVAL,
> > +
> > 	RTE_FLOW_ERROR_TYPE_ACTION,
> > +						(void *)item->type,
> > +						"next protocol not found");
> > +			if (!udp->dst_port)
> > +				udp->dst_port =
> > +
> > 	RTE_BE16(MLX5_UDP_PORT_VXLAN_GPE);
> > +			if (!vxlan->vx_flags)
> > +				vxlan->vx_flags =
> > +
> > 	RTE_BE32(MLX5_VXLAN_GPE_FLAGS);
> > +			break;
> > +		case RTE_FLOW_ITEM_TYPE_VOID:
> > +			break;
> > +		default:
> > +			return rte_flow_error_set(error, EINVAL,
> > +
> > RTE_FLOW_ERROR_TYPE_ACTION,
> > +						  (void *)item->type,
> > +						  "unsupported item type");
> > +			break;
> > +		}
> > +		temp_size += len;
> > +	}
> > +	*size = temp_size;
> > +	return 0;
> > +}
> > +
> > +/**
> > + * Convert L2 encap action to DV specification.
> > + *
> > + * @param[in] dev
> > + *   Pointer to rte_eth_dev structure.
> > + * @param[in] action
> > + *   Pointer to action structure.
> > + * @param[out] error
> > + *   Pointer to the error structure.
> > + *
> > + * @return
> > + *   Pointer to action on success, NULL otherwise and rte_errno is set.
> > + */
> > +static struct ibv_flow_action *
> > +flow_dv_create_action_l2_encap(struct rte_eth_dev *dev,
> > +			       const struct rte_flow_action *action,
> > +			       struct rte_flow_error *error) {
> > +	struct ibv_flow_action *verbs_action = NULL;
> > +	const struct rte_flow_item *encap_data;
> > +	struct priv *priv = dev->data->dev_private;
> > +	uint8_t buf[MLX5_ENCAP_MAX_LEN];
> > +	size_t size = 0;
> > +	int convert_result = 0;
> > +
> > +	encap_data = ((const struct rte_flow_action_vxlan_encap *)
> > +						action->conf)->definition;
> > +	convert_result = flow_dv_convert_encap_data(encap_data, buf,
> > +						    &size, error);
> > +	if (convert_result)
> > +		return NULL;
> > +	verbs_action = mlx5_glue-
> > >dv_create_flow_action_packet_reformat
> > +		(priv->ctx, size, buf,
> > +
> > MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
> > +		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
> > +	if (!verbs_action)
> > +		rte_flow_error_set(error, EINVAL,
> > RTE_FLOW_ERROR_TYPE_ACTION,
> > +				   NULL, "cannot create L2 encap action");
> > +	return verbs_action;
> > +}
> > +
> > +/**
> >   * Verify the @p attributes will be correctly understood by the NIC and
> store
> >   * them in the @p flow if everything is correct.
> >   *
> > @@ -339,6 +638,16 @@
> >  			action_flags |= MLX5_FLOW_ACTION_COUNT;
> >  			++actions_n;
> >  			break;
> > +		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
> > +			ret =
> > flow_dv_validate_action_l2_encap(action_flags,
> > +							       actions, attr,
> > +							       error);
> > +			if (ret < 0)
> > +				return ret;
> > +			action_flags |=
> > MLX5_FLOW_ACTION_VXLAN_ENCAP;
> > +			++actions_n;
> > +			break;
> > +
> >  		default:
> >  			return rte_flow_error_set(error, ENOTSUP,
> >
> > RTE_FLOW_ERROR_TYPE_ACTION,
> > @@ -1045,14 +1354,23 @@
> >  /**
> >   * Store the requested actions in an array.
> >   *
> > + * @param[in] dev
> > + *   Pointer to rte_eth_dev structure.
> >   * @param[in] action
> >   *   Flow action to translate.
> >   * @param[in, out] dev_flow
> >   *   Pointer to the mlx5_flow.
> > + * @param[out] error
> > + *   Pointer to the error structure.
> > + *
> > + * @return
> > + *   0 on success, a negative errno value otherwise and rte_errno is set.
> >   */
> > -static void
> > -flow_dv_create_action(const struct rte_flow_action *action,
> > -		      struct mlx5_flow *dev_flow)
> > +static int
> > +flow_dv_create_action(struct rte_eth_dev *dev,
> > +		      const struct rte_flow_action *action,
> > +		      struct mlx5_flow *dev_flow,
> > +		      struct rte_flow_error *error)
> >  {
> >  	const struct rte_flow_action_queue *queue;
> >  	const struct rte_flow_action_rss *rss; @@ -1100,10 +1418,24 @@
> >  		/* Added to array only in apply since we need the QP */
> >  		flow->actions |= MLX5_FLOW_ACTION_RSS;
> >  		break;
> > +	case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
> > +		dev_flow->dv.actions[actions_n].type =
> > +			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> > +		dev_flow->dv.actions[actions_n].action =
> > +				flow_dv_create_action_l2_encap(dev,
> > action,
> > +							       error);
> > +		if (!(dev_flow->dv.actions[actions_n].action))
> > +			return -rte_errno;
> > +		dev_flow->dv.encap_decap_verbs_action =
> > +			dev_flow->dv.actions[actions_n].action;
> > +		flow->actions |= MLX5_FLOW_ACTION_VXLAN_ENCAP;
> > +		actions_n++;
> > +		break;
> >  	default:
> >  		break;
> >  	}
> >  	dev_flow->dv.actions_n = actions_n;
> > +	return 0;
> >  }
> >
> >  static uint32_t matcher_zero[MLX5_ST_SZ_DW(fte_match_param)] = { 0 };
> > @@ -1217,7 +1549,6 @@
> >  	return 0;
> >  }
> >
> > -
> >  /**
> >   * Fill the flow with DV spec.
> >   *
> > @@ -1272,7 +1603,8 @@
> >  	if (flow_dv_matcher_register(dev, &matcher, dev_flow, error))
> >  		return -rte_errno;
> >  	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++)
> > -		flow_dv_create_action(actions, dev_flow);
> > +		if (flow_dv_create_action(dev, actions, dev_flow, error))
> > +			return -rte_errno;
> >  	return 0;
> >  }
> >
> > @@ -1457,6 +1789,11 @@
> >  		LIST_REMOVE(dev_flow, next);
> >  		if (dev_flow->dv.matcher)
> >  			flow_dv_matcher_release(dev, dev_flow);
> > +		if (dev_flow->dv.encap_decap_verbs_action) {
> > +			claim_zero(mlx5_glue->destroy_flow_action
> > +				(dev_flow->dv.encap_decap_verbs_action));
> > +			dev_flow->dv.encap_decap_verbs_action = NULL;
> > +		}
> >  		rte_free(dev_flow);
> >  	}
> >  }
> > --
> > 1.8.3.1

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

* Re: [dpdk-dev] [PATCH v7 4/7] net/mlx5: add NVGRE encap action to Direct Verbs
  2018-10-31 15:09             ` Shahaf Shuler
@ 2018-11-01  9:13               ` Dekel Peled
  0 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-11-01  9:13 UTC (permalink / raw)
  To: Shahaf Shuler, Yongseok Koh; +Cc: dev, Ori Kam

Thanks, PSB.

> -----Original Message-----
> From: Shahaf Shuler
> Sent: Wednesday, October 31, 2018 5:10 PM
> To: Dekel Peled <dekelp@mellanox.com>; Yongseok Koh
> <yskoh@mellanox.com>
> Cc: dev@dpdk.org; Ori Kam <orika@mellanox.com>
> Subject: RE: [dpdk-dev] [PATCH v7 4/7] net/mlx5: add NVGRE encap action to
> Direct Verbs
> 
> Wednesday, October 31, 2018 9:11 AM, Dekel Peled:
> > Subject: [dpdk-dev] [PATCH v7 4/7] net/mlx5: add NVGRE encap action to
> > Direct Verbs
> >
> > This patch implements the nvgre encap action in DV flow for MLX5 PMD.
> >
> > Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> > ---
> >  drivers/net/mlx5/mlx5_flow.h    |  4 ++++
> >  drivers/net/mlx5/mlx5_flow_dv.c | 37
> > ++++++++++++++++++++++++++++++++-----
> >  2 files changed, 36 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/net/mlx5/mlx5_flow.h
> > b/drivers/net/mlx5/mlx5_flow.h index 8955a12..c03a3af 100644
> > --- a/drivers/net/mlx5/mlx5_flow.h
> > +++ b/drivers/net/mlx5/mlx5_flow.h
> > @@ -94,10 +94,14 @@
> >  #define MLX5_FLOW_ACTION_SET_MAC_DST (1u << 21)  #define
> > MLX5_FLOW_ACTION_VXLAN_ENCAP (1u << 22)  #define
> > MLX5_FLOW_ACTION_VXLAN_DECAP (1u << 23)
> > +#define MLX5_FLOW_ACTION_NVGRE_ENCAP (1u << 24)
> >
> >  #define MLX5_FLOW_FATE_ACTIONS \
> >  	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE |
> > MLX5_FLOW_ACTION_RSS)
> >
> > +#define MLX5_FLOW_ENCAP_ACTIONS	\
> > +	(MLX5_FLOW_ACTION_VXLAN_ENCAP |
> > MLX5_FLOW_ACTION_NVGRE_ENCAP)
> > +
> >  #ifndef IPPROTO_MPLS
> >  #define IPPROTO_MPLS 137
> >  #endif
> > diff --git a/drivers/net/mlx5/mlx5_flow_dv.c
> > b/drivers/net/mlx5/mlx5_flow_dv.c index 7de65bb..7078397 100644
> > --- a/drivers/net/mlx5/mlx5_flow_dv.c
> > +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> > @@ -126,7 +126,7 @@
> >  		return rte_flow_error_set(error, EINVAL,
> >  					  RTE_FLOW_ERROR_TYPE_ACTION,
> > NULL,
> >  					  "can't drop and encap in same
> > flow");
> > -	if (action_flags & (MLX5_FLOW_ACTION_VXLAN_ENCAP |
> > +	if (action_flags & (MLX5_FLOW_ENCAP_ACTIONS |
> >  			    MLX5_FLOW_ACTION_VXLAN_DECAP))
> >  		return rte_flow_error_set(error, EINVAL,
> >  					  RTE_FLOW_ERROR_TYPE_ACTION,
> > NULL, @@ -163,7 +163,7 @@
> >  		return rte_flow_error_set(error, EINVAL,
> >  					  RTE_FLOW_ERROR_TYPE_ACTION,
> > NULL,
> >  					  "can't drop and decap in same
> > flow");
> > -	if (action_flags & (MLX5_FLOW_ACTION_VXLAN_ENCAP |
> > +	if (action_flags & (MLX5_FLOW_ENCAP_ACTIONS |
> >  			    MLX5_FLOW_ACTION_VXLAN_DECAP))
> >  		return rte_flow_error_set(error, EINVAL,
> >  					  RTE_FLOW_ERROR_TYPE_ACTION,
> > NULL, @@ -376,6 +376,20 @@
> >  				vxlan->vx_flags =
> >
> > 	RTE_BE32(MLX5_VXLAN_GPE_FLAGS);
> >  			break;
> > +		case RTE_FLOW_ITEM_TYPE_GRE:
> > +		case RTE_FLOW_ITEM_TYPE_NVGRE:
> > +			if (!ipv4 && !ipv6)
> > +				return rte_flow_error_set(error, EINVAL,
> > +
> > 	RTE_FLOW_ERROR_TYPE_ACTION,
> > +						(void *)item->type,
> > +						"ip header not found");
> > +			if ((ipv4 && !ipv4->next_proto_id) ||
> > +			    (ipv6 && !ipv6->proto))
> > +				return rte_flow_error_set(error, EINVAL,
> 
> Same comment like in the VXLAN-GPE. It is not the ip next proto you need to
> check it is the GRE protocol.

Will change.

> 
> > +
> > 	RTE_FLOW_ERROR_TYPE_ACTION,
> > +						(void *)item->type,
> > +						"next protocol not found");
> > +			break;
> >  		case RTE_FLOW_ITEM_TYPE_VOID:
> >  			break;
> >  		default:
> > @@ -416,7 +430,11 @@
> >  	size_t size = 0;
> >  	int convert_result = 0;
> >
> > -	encap_data = ((const struct rte_flow_action_vxlan_encap *)
> > +	if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP)
> > +		encap_data = ((const struct rte_flow_action_vxlan_encap *)
> > +						action->conf)->definition;
> > +	else
> > +		encap_data = ((const struct rte_flow_action_nvgre_encap *)
> >  						action->conf)->definition;
> >  	convert_result = flow_dv_convert_encap_data(encap_data, buf,
> >  						    &size, error);
> > @@ -705,12 +723,17 @@
> >  			++actions_n;
> >  			break;
> >  		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
> > +		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
> >  			ret =
> > flow_dv_validate_action_l2_encap(action_flags,
> >  							       actions, attr,
> >  							       error);
> >  			if (ret < 0)
> >  				return ret;
> > -			action_flags |=
> > MLX5_FLOW_ACTION_VXLAN_ENCAP;
> > +			action_flags |= actions->type ==
> > +
> > 	RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP ?
> > +
> > 	MLX5_FLOW_ACTION_VXLAN_ENCAP :
> > +
> > 	MLX5_FLOW_ACTION_NVGRE_ENCAP;
> > +
> >  			++actions_n;
> >  			break;
> >  		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
> > @@ -1492,6 +1515,7 @@
> >  		flow->actions |= MLX5_FLOW_ACTION_RSS;
> >  		break;
> >  	case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
> > +	case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
> >  		dev_flow->dv.actions[actions_n].type =
> >  			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> >  		dev_flow->dv.actions[actions_n].action = @@ -1501,7
> > +1525,10 @@
> >  			return -rte_errno;
> >  		dev_flow->dv.encap_decap_verbs_action =
> >  			dev_flow->dv.actions[actions_n].action;
> > -		flow->actions |= MLX5_FLOW_ACTION_VXLAN_ENCAP;
> > +		flow->actions |= action->type ==
> > +				 RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP ?
> > +				 MLX5_FLOW_ACTION_VXLAN_ENCAP :
> > +				 MLX5_FLOW_ACTION_NVGRE_ENCAP;
> >  		actions_n++;
> >  		break;
> >  	case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
> > --
> > 1.8.3.1

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

* Re: [dpdk-dev] [PATCH v7 7/7] net/mlx5: add caching of encap decap actions
  2018-10-31 15:09             ` Shahaf Shuler
@ 2018-11-01  9:15               ` Dekel Peled
  0 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-11-01  9:15 UTC (permalink / raw)
  To: Shahaf Shuler, Yongseok Koh; +Cc: dev, Ori Kam

Thanks, PSB.

> -----Original Message-----
> From: Shahaf Shuler
> Sent: Wednesday, October 31, 2018 5:10 PM
> To: Dekel Peled <dekelp@mellanox.com>; Yongseok Koh
> <yskoh@mellanox.com>
> Cc: dev@dpdk.org; Ori Kam <orika@mellanox.com>
> Subject: RE: [dpdk-dev] [PATCH v7 7/7] net/mlx5: add caching of encap
> decap actions
> 
> Wednesday, October 31, 2018 9:11 AM, Dekel Peled:
> > Subject: [dpdk-dev] [PATCH v7 7/7] net/mlx5: add caching of encap
> > decap actions
> >
> > Make flow encap and decap Verbs actions cacheable resources.
> > Reuse 17.11 PR 876.
> 
> No one knows what is PR 876 in the mailing list, also this code is not in 17.11
> community.
> Need to make a proper commit log here explains how you do the caching and
> why it is needed.

Will change.

> 
> >
> > Signed-off-by: Dekel Peled <dekelp@mellanox.com>
> > ---
> >  drivers/net/mlx5/mlx5.h         |   1 +
> >  drivers/net/mlx5/mlx5_flow.h    |  18 ++-
> >  drivers/net/mlx5/mlx5_flow_dv.c | 265
> ++++++++++++++++++++++++++---
> > -----------
> >  3 files changed, 193 insertions(+), 91 deletions(-)
> >
> > diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index
> > 74d87c0..0422803 100644
> > --- a/drivers/net/mlx5/mlx5.h
> > +++ b/drivers/net/mlx5/mlx5.h
> > @@ -219,6 +219,7 @@ struct priv {
> >  	/* Verbs Indirection tables. */
> >  	LIST_HEAD(ind_tables, mlx5_ind_table_ibv) ind_tbls;
> >  	LIST_HEAD(matchers, mlx5_flow_dv_matcher) matchers;
> > +	LIST_HEAD(encap_decap, mlx5_flow_dv_encap_decap_resource)
> > +encaps_decaps;
> >  	uint32_t link_speed_capa; /* Link speed capabilities. */
> >  	struct mlx5_xstats_ctrl xstats_ctrl; /* Extended stats control. */
> >  	int primary_socket; /* Unix socket for primary process. */ diff
> > --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
> > index
> > 908123f..25cd9c5 100644
> > --- a/drivers/net/mlx5/mlx5_flow.h
> > +++ b/drivers/net/mlx5/mlx5_flow.h
> > @@ -170,6 +170,7 @@ struct mlx5_flow_dv_match_params {  };
> >
> >  #define MLX5_DV_MAX_NUMBER_OF_ACTIONS 8
> > +#define MLX5_ENCAP_MAX_LEN 132
> >
> >  /* Matcher structure. */
> >  struct mlx5_flow_dv_matcher {
> > @@ -183,6 +184,19 @@ struct mlx5_flow_dv_matcher {
> >  	struct mlx5_flow_dv_match_params mask; /**< Matcher mask. */  };
> >
> > +/* Encap/decap resource structure. */ struct
> > +mlx5_flow_dv_encap_decap_resource {
> > +	LIST_ENTRY(mlx5_flow_dv_encap_decap_resource) next;
> > +	/* Pointer to next element. */
> > +	rte_atomic32_t refcnt; /**< Reference counter. */
> > +	struct ibv_flow_action *verbs_action;
> > +	/**< Verbs encap/decap action object. */
> > +	uint8_t buf[MLX5_ENCAP_MAX_LEN];
> > +	size_t size;
> > +	uint8_t reformat_type;
> > +	uint8_t ft_type;
> > +};
> > +
> >  /* DV flows structure. */
> >  struct mlx5_flow_dv {
> >  	uint64_t hash_fields; /**< Fields that participate in the hash. */
> > @@
> > -191,12 +205,12 @@ struct mlx5_flow_dv {
> >  	struct mlx5_flow_dv_matcher *matcher; /**< Cache to matcher. */
> >  	struct mlx5_flow_dv_match_params value;
> >  	/**< Holds the value that the packet is compared to. */
> > +	struct mlx5_flow_dv_encap_decap_resource *encap_decap;
> > +	/**< Pointer to encap/decap resource in cache. */
> >  	struct ibv_flow *flow; /**< Installed flow. */  #ifdef
> > HAVE_IBV_FLOW_DV_SUPPORT
> >  	struct mlx5dv_flow_action_attr
> > actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS];
> >  	/**< Action list. */
> > -	struct ibv_flow_action *encap_decap_verbs_action;
> > -	/**< Verbs encap/decap object. */
> >  #endif
> >  	int actions_n; /**< number of actions. */  }; diff --git
> > a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
> > index d1c811f..818b30c 100644
> > --- a/drivers/net/mlx5/mlx5_flow_dv.c
> > +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> > @@ -34,8 +34,6 @@
> >
> >  #ifdef HAVE_IBV_FLOW_DV_SUPPORT
> >
> > -#define MLX5_ENCAP_MAX_LEN 132
> > -
> >  /**
> >   * Validate META item.
> >   *
> > @@ -271,6 +269,77 @@
> >  	return 0;
> >  }
> >
> > +
> > +/**
> > + * Find existing encap/decap resource or create and register a new one.
> > + *
> > + * @param dev[in, out]
> > + *   Pointer to rte_eth_dev structure.
> > + * @param[in, out] resource
> > + *   Pointer to encap/decap resource.
> > + * @parm[in, out] dev_flow
> > + *   Pointer to the dev_flow.
> > + * @param[out] error
> > + *   pointer to error structure.
> > + *
> > + * @return
> > + *   0 on success otherwise -errno and errno is set.
> > + */
> > +static int
> > +flow_dv_encap_decap_resource_register
> > +			(struct rte_eth_dev *dev,
> > +			 struct mlx5_flow_dv_encap_decap_resource
> > *resource,
> > +			 struct mlx5_flow *dev_flow,
> > +			 struct rte_flow_error *error)
> > +{
> > +	struct priv *priv = dev->data->dev_private;
> > +	struct mlx5_flow_dv_encap_decap_resource *cache_resource;
> > +
> > +	/* Lookup a matching resource from cache. */
> > +	LIST_FOREACH(cache_resource, &priv->encaps_decaps, next) {
> > +		if (resource->reformat_type == cache_resource-
> > >reformat_type &&
> > +		    resource->ft_type == cache_resource->ft_type &&
> > +		    resource->size == cache_resource->size &&
> > +		    !memcmp((const void *)resource->buf,
> > +			    (const void *)cache_resource->buf,
> > +			    resource->size)) {
> > +			DRV_LOG(DEBUG, "encap/decap resource %p: refcnt
> > %d++",
> > +				(void *)cache_resource,
> > +				rte_atomic32_read(&cache_resource-
> > >refcnt));
> > +			rte_atomic32_inc(&cache_resource->refcnt);
> > +			dev_flow->dv.encap_decap = cache_resource;
> > +			return 0;
> > +		}
> > +	}
> > +	/* Register new encap/decap resource. */
> > +	cache_resource = rte_calloc(__func__, 1, sizeof(*cache_resource),
> > 0);
> > +	if (!cache_resource)
> > +		return rte_flow_error_set(error, ENOMEM,
> > +
> > RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
> > +					  "cannot allocate resource
> > memory");
> > +	*cache_resource = *resource;
> > +	cache_resource->verbs_action =
> > +		mlx5_glue->dv_create_flow_action_packet_reformat
> > +			(priv->ctx, cache_resource->size,
> > +			 (cache_resource->size ? cache_resource->buf :
> > NULL),
> > +			 cache_resource->reformat_type,
> > +			 cache_resource->ft_type);
> > +	if (!cache_resource->verbs_action) {
> > +		rte_free(cache_resource);
> > +		return rte_flow_error_set(error, ENOMEM,
> > +
> > RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
> > +					  NULL, "cannot create action");
> > +	}
> > +	rte_atomic32_init(&cache_resource->refcnt);
> > +	rte_atomic32_inc(&cache_resource->refcnt);
> > +	LIST_INSERT_HEAD(&priv->encaps_decaps, cache_resource, next);
> > +	dev_flow->dv.encap_decap = cache_resource;
> > +	DRV_LOG(DEBUG, "new encap/decap resource %p: refcnt %d++",
> > +		(void *)cache_resource,
> > +		rte_atomic32_read(&cache_resource->refcnt));
> > +	return 0;
> > +}
> > +
> >  /**
> >   * Get the size of specific rte_flow_item_type
> >   *
> > @@ -505,31 +574,33 @@
> >   *   Pointer to rte_eth_dev structure.
> >   * @param[in] action
> >   *   Pointer to action structure.
> > + * @param[in, out] dev_flow
> > + *   Pointer to the mlx5_flow.
> >   * @param[out] error
> >   *   Pointer to the error structure.
> >   *
> >   * @return
> > - *   Pointer to action on success, NULL otherwise and rte_errno is set.
> > + *   0 on success, a negative errno value otherwise and rte_errno is set.
> >   */
> > -static struct ibv_flow_action *
> > +static int
> >  flow_dv_create_action_l2_encap(struct rte_eth_dev *dev,
> >  			       const struct rte_flow_action *action,
> > +			       struct mlx5_flow *dev_flow,
> >  			       struct rte_flow_error *error)  {
> > -	struct ibv_flow_action *verbs_action = NULL;
> >  	const struct rte_flow_item *encap_data;
> >  	const struct rte_flow_action_raw_encap *raw_encap_data;
> > -	struct priv *priv = dev->data->dev_private;
> > -	uint8_t buf[MLX5_ENCAP_MAX_LEN];
> > -	uint8_t *buf_ptr = buf;
> > -	size_t size = 0;
> > -	int convert_result = 0;
> > +	struct mlx5_flow_dv_encap_decap_resource res = {
> > +		.reformat_type =
> > +
> > 	MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TU
> > NNEL,
> > +		.ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_TX,
> > +	};
> >
> >  	if (action->type == RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
> >  		raw_encap_data =
> >  			(const struct rte_flow_action_raw_encap *)action-
> > >conf;
> > -		buf_ptr = raw_encap_data->data;
> > -		size = raw_encap_data->size;
> > +		res.size = raw_encap_data->size;
> > +		memcpy(res.buf, raw_encap_data->data, res.size);
> >  	} else {
> >  		if (action->type ==
> > RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP)
> >  			encap_data =
> > @@ -539,19 +610,15 @@
> >  			encap_data =
> >  				((const struct rte_flow_action_nvgre_encap
> > *)
> >  						action->conf)->definition;
> > -		convert_result = flow_dv_convert_encap_data(encap_data,
> > buf,
> > -							    &size, error);
> > -		if (convert_result)
> > -			return NULL;
> > +		if (flow_dv_convert_encap_data(encap_data, res.buf,
> > +					       &res.size, error))
> > +			return -rte_errno;
> >  	}
> > -	verbs_action = mlx5_glue-
> > >dv_create_flow_action_packet_reformat
> > -		(priv->ctx, size, buf_ptr,
> > -
> > MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
> > -		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
> > -	if (!verbs_action)
> > -		rte_flow_error_set(error, EINVAL,
> > RTE_FLOW_ERROR_TYPE_ACTION,
> > -				   NULL, "cannot create L2 encap action");
> > -	return verbs_action;
> > +	if (flow_dv_encap_decap_resource_register(dev, &res, dev_flow,
> > error))
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > +					  NULL, "can't create L2 encap
> > action");
> > +	return 0;
> >  }
> >
> >  /**
> > @@ -559,27 +626,31 @@
> >   *
> >   * @param[in] dev
> >   *   Pointer to rte_eth_dev structure.
> > + * @param[in, out] dev_flow
> > + *   Pointer to the mlx5_flow.
> >   * @param[out] error
> >   *   Pointer to the error structure.
> >   *
> >   * @return
> > - *   Pointer to action on success, NULL otherwise and rte_errno is set.
> > + *   0 on success, a negative errno value otherwise and rte_errno is set.
> >   */
> > -static struct ibv_flow_action *
> > +static int
> >  flow_dv_create_action_l2_decap(struct rte_eth_dev *dev,
> > +			       struct mlx5_flow *dev_flow,
> >  			       struct rte_flow_error *error)  {
> > -	struct ibv_flow_action *verbs_action = NULL;
> > -	struct priv *priv = dev->data->dev_private;
> > +	struct mlx5_flow_dv_encap_decap_resource res = {
> > +		.size = 0,
> > +		.reformat_type =
> > +
> > 	MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_T
> > O_L2,
> > +		.ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_RX,
> > +	};
> >
> > -	verbs_action = mlx5_glue-
> > >dv_create_flow_action_packet_reformat
> > -		(priv->ctx, 0, NULL,
> > -
> > MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2,
> > -		 MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
> > -	if (!verbs_action)
> > -		rte_flow_error_set(error, EINVAL,
> > RTE_FLOW_ERROR_TYPE_ACTION,
> > -				   NULL, "cannot create L2 decap action");
> > -	return verbs_action;
> > +	if (flow_dv_encap_decap_resource_register(dev, &res, dev_flow,
> > error))
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > +					  NULL, "can't create L2 decap
> > action");
> > +	return 0;
> >  }
> >
> >  /**
> > @@ -589,41 +660,39 @@
> >   *   Pointer to rte_eth_dev structure.
> >   * @param[in] action
> >   *   Pointer to action structure.
> > + * @param[in, out] dev_flow
> > + *   Pointer to the mlx5_flow.
> >   * @param[in] attr
> >   *   Pointer to the flow attributes.
> >   * @param[out] error
> >   *   Pointer to the error structure.
> >   *
> >   * @return
> > - *   Pointer to action on success, NULL otherwise and rte_errno is set.
> > + *   0 on success, a negative errno value otherwise and rte_errno is set.
> >   */
> > -static struct ibv_flow_action *
> > +static int
> >  flow_dv_create_action_raw_encap(struct rte_eth_dev *dev,
> >  				const struct rte_flow_action *action,
> > +				struct mlx5_flow *dev_flow,
> >  				const struct rte_flow_attr *attr,
> >  				struct rte_flow_error *error)
> >  {
> > -	struct ibv_flow_action *verbs_action = NULL;
> >  	const struct rte_flow_action_raw_encap *encap_data;
> > -	struct priv *priv = dev->data->dev_private;
> > -	enum mlx5dv_flow_action_packet_reformat_type reformat_type;
> > -	enum mlx5dv_flow_table_type ft_type;
> > +	struct mlx5_flow_dv_encap_decap_resource res;
> >
> >  	encap_data = (const struct rte_flow_action_raw_encap *)action-
> > >conf;
> > -	reformat_type = attr->egress ?
> > +	res.size = encap_data->size;
> > +	memcpy(res.buf, encap_data->data, res.size);
> > +	res.reformat_type = attr->egress ?
> >
> > 	MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TU
> > NNEL :
> >
> > 	MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_T
> > O_L2;
> > -	ft_type = attr->egress ?
> > -			MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
> > -			MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
> > -	verbs_action = mlx5_glue-
> > >dv_create_flow_action_packet_reformat
> > -				(priv->ctx, encap_data->size,
> > -				(encap_data->size ? encap_data->data :
> > NULL),
> > -				reformat_type, ft_type);
> > -	if (!verbs_action)
> > -		rte_flow_error_set(error, EINVAL,
> > RTE_FLOW_ERROR_TYPE_ACTION,
> > -				   NULL, "cannot create encap action");
> > -	return verbs_action;
> > +	res.ft_type = attr->egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
> > +				     MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
> > +	if (flow_dv_encap_decap_resource_register(dev, &res, dev_flow,
> > error))
> > +		return rte_flow_error_set(error, EINVAL,
> > +					  RTE_FLOW_ERROR_TYPE_ACTION,
> > +					  NULL, "can't create encap action");
> > +	return 0;
> >  }
> >
> >  /**
> > @@ -1689,15 +1758,13 @@
> >  		break;
> >  	case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
> >  	case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
> > +		if (flow_dv_create_action_l2_encap(dev, action,
> > +						   dev_flow, error))
> > +			return -rte_errno;
> >  		dev_flow->dv.actions[actions_n].type =
> >  			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> >  		dev_flow->dv.actions[actions_n].action =
> > -				flow_dv_create_action_l2_encap(dev,
> > action,
> > -							       error);
> > -		if (!(dev_flow->dv.actions[actions_n].action))
> > -			return -rte_errno;
> > -		dev_flow->dv.encap_decap_verbs_action =
> > -			dev_flow->dv.actions[actions_n].action;
> > +			dev_flow->dv.encap_decap->verbs_action;
> >  		flow->actions |= action->type ==
> >  				 RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP ?
> >  				 MLX5_FLOW_ACTION_VXLAN_ENCAP :
> > @@ -1706,14 +1773,12 @@
> >  		break;
> >  	case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
> >  	case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
> > +		if (flow_dv_create_action_l2_decap(dev, dev_flow, error))
> > +			return -rte_errno;
> >  		dev_flow->dv.actions[actions_n].type =
> >  			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> >  		dev_flow->dv.actions[actions_n].action =
> > -				flow_dv_create_action_l2_decap(dev,
> > error);
> > -		if (!(dev_flow->dv.actions[actions_n].action))
> > -			return -rte_errno;
> > -		dev_flow->dv.encap_decap_verbs_action =
> > -			dev_flow->dv.actions[actions_n].action;
> > +			dev_flow->dv.encap_decap->verbs_action;
> >  		flow->actions |= action->type ==
> >  				 RTE_FLOW_ACTION_TYPE_VXLAN_DECAP ?
> >  				 MLX5_FLOW_ACTION_VXLAN_DECAP :
> > @@ -1723,27 +1788,23 @@
> >  	case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
> >  		/* Handle encap action with preceding decap */
> >  		if (flow->actions & MLX5_FLOW_ACTION_RAW_DECAP) {
> > +			if (flow_dv_create_action_raw_encap(dev, action,
> > +							    dev_flow,
> > +							    attr, error))
> > +				return -rte_errno;
> >  			dev_flow->dv.actions[actions_n].type =
> >
> > 	MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> >  			dev_flow->dv.actions[actions_n].action =
> > -					flow_dv_create_action_raw_encap
> > -								(dev, action,
> > -								 attr, error);
> > -			if (!(dev_flow->dv.actions[actions_n].action))
> > -				return -rte_errno;
> > -			dev_flow->dv.encap_decap_verbs_action =
> > -				dev_flow->dv.actions[actions_n].action;
> > +					dev_flow->dv.encap_decap-
> > >verbs_action;
> >  		} else {
> >  			/* Handle encap action without preceding decap */
> > +			if (flow_dv_create_action_l2_encap(dev, action,
> > +							   dev_flow, error))
> > +				return -rte_errno;
> >  			dev_flow->dv.actions[actions_n].type =
> >
> > 	MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> >  			dev_flow->dv.actions[actions_n].action =
> > -					flow_dv_create_action_l2_encap
> > -							(dev, action, error);
> > -			if (!(dev_flow->dv.actions[actions_n].action))
> > -				return -rte_errno;
> > -			dev_flow->dv.encap_decap_verbs_action =
> > -				dev_flow->dv.actions[actions_n].action;
> > +					dev_flow->dv.encap_decap-
> > >verbs_action;
> >  		}
> >  		flow->actions |= MLX5_FLOW_ACTION_RAW_ENCAP;
> >  		actions_n++;
> > @@ -1756,15 +1817,13 @@
> >  		}
> >  		/* Handle decap action only if it isn't followed by encap */
> >  		if (action_ptr->type !=
> > RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
> > +			if (flow_dv_create_action_l2_decap(dev, dev_flow,
> > +							   error))
> > +				return -rte_errno;
> >  			dev_flow->dv.actions[actions_n].type =
> >
> > 	MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
> >  			dev_flow->dv.actions[actions_n].action =
> > -
> > 	flow_dv_create_action_l2_decap(dev,
> > -								       error);
> > -			if (!(dev_flow->dv.actions[actions_n].action))
> > -				return -rte_errno;
> > -			dev_flow->dv.encap_decap_verbs_action =
> > -				dev_flow->dv.actions[actions_n].action;
> > +					dev_flow->dv.encap_decap-
> > >verbs_action;
> >  			actions_n++;
> >  		}
> >  		/* If decap is followed by encap, handle it at encap case. */
> @@
> > -2074,6 +2133,37 @@  }
> >
> >  /**
> > + * Release an encap/decap resource.
> > + *
> > + * @param flow
> > + *   Pointer to mlx5_flow.
> > + *
> > + * @return
> > + *   1 while a reference on it exists, 0 when freed.
> > + */
> > +static int
> > +flow_dv_encap_decap_resource_release(struct mlx5_flow *flow) {
> > +	struct mlx5_flow_dv_encap_decap_resource *cache_resource =
> > +						flow->dv.encap_decap;
> > +
> > +	assert(cache_resource->verbs_action);
> > +	DRV_LOG(DEBUG, "encap/decap resource %p: refcnt %d--",
> > +		(void *)cache_resource,
> > +		rte_atomic32_read(&cache_resource->refcnt));
> > +	if (rte_atomic32_dec_and_test(&cache_resource->refcnt)) {
> > +		claim_zero(mlx5_glue->destroy_flow_action
> > +				(cache_resource->verbs_action));
> > +		LIST_REMOVE(cache_resource, next);
> > +		rte_free(cache_resource);
> > +		DRV_LOG(DEBUG, "encap/decap resource %p: removed",
> > +			cache_resource);
> > +		return 0;
> > +	}
> > +	return 1;
> > +}
> > +
> > +/**
> >   * Remove the flow from the NIC but keeps it in memory.
> >   *
> >   * @param[in] dev
> > @@ -2128,11 +2218,8 @@
> >  		LIST_REMOVE(dev_flow, next);
> >  		if (dev_flow->dv.matcher)
> >  			flow_dv_matcher_release(dev, dev_flow);
> > -		if (dev_flow->dv.encap_decap_verbs_action) {
> > -			claim_zero(mlx5_glue->destroy_flow_action
> > -				(dev_flow->dv.encap_decap_verbs_action));
> > -			dev_flow->dv.encap_decap_verbs_action = NULL;
> > -		}
> > +		if (dev_flow->dv.encap_decap)
> > +
> > 	flow_dv_encap_decap_resource_release(dev_flow);
> >  		rte_free(dev_flow);
> >  	}
> >  }
> > --
> > 1.8.3.1

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

* [dpdk-dev] [PATCH v8 0/7] add encap and decap actions to Direct Verbs flow in MLX5 PMD
  2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 0/7] " Dekel Peled
  2018-10-31 15:09             ` Shahaf Shuler
@ 2018-11-01  9:37             ` Dekel Peled
  2018-11-01 12:51               ` Shahaf Shuler
  2018-11-01  9:37             ` [dpdk-dev] [PATCH v8 1/7] net/mlx5: add flow action functions to glue Dekel Peled
                               ` (6 subsequent siblings)
  8 siblings, 1 reply; 94+ messages in thread
From: Dekel Peled @ 2018-11-01  9:37 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This series adds support of encap and decap actions in DV format.
L2 tunnel support for VXLAN and NVGRE, and L2/L3 tunnel support using raw data buffer.
It is using the generic encapsulation framework from [1].

[1] "ethdev: add generic L2/L3 tunnel encapsulation actions"
    http://mails.dpdk.org/archives/dev/2018-October/114654.html
    
---
v8:
* Apply code review comments.
v7:
* Apply code review comments.
* Add caching of encap decap actions.
v6:
* Adapt L2 tunnel to VXLAN and NVGRE.
* Add encap/decap using raw data.
v5:
* Move DV actions code under common DV flag.
v4:
* Update in glue functions.
v3:
* Apply additional code review comments.
v2:
* Rebase on tip.
* Apply code review comments.
---

Dekel Peled (7):
  net/mlx5: add flow action functions to glue
  net/mlx5: add VXLAN encap action to Direct Verbs
  net/mlx5: add VXLAN decap action to Direct Verbs
  net/mlx5: add NVGRE encap action to Direct Verbs
  net/mlx5: add NVGRE decap action to Direct Verbs
  net/mlx5: add raw data encap decap to Direct Verbs
  net/mlx5: add caching of encap decap actions

 drivers/net/mlx5/Makefile       |   2 +-
 drivers/net/mlx5/meson.build    |   2 +-
 drivers/net/mlx5/mlx5.h         |   1 +
 drivers/net/mlx5/mlx5_flow.h    |  30 ++
 drivers/net/mlx5/mlx5_flow_dv.c | 783 +++++++++++++++++++++++++++++++++++++++-
 drivers/net/mlx5/mlx5_glue.c    |  38 ++
 drivers/net/mlx5/mlx5_glue.h    |  10 +
 7 files changed, 858 insertions(+), 8 deletions(-)

-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v8 1/7] net/mlx5: add flow action functions to glue
  2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 0/7] " Dekel Peled
  2018-10-31 15:09             ` Shahaf Shuler
  2018-11-01  9:37             ` [dpdk-dev] [PATCH v8 " Dekel Peled
@ 2018-11-01  9:37             ` Dekel Peled
  2018-11-01  9:37             ` [dpdk-dev] [PATCH v8 2/7] net/mlx5: add VXLAN encap action to Direct Verbs Dekel Peled
                               ` (5 subsequent siblings)
  8 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-11-01  9:37 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch adds glue functions for operations:
- Create packet reformat (encap/decap) flow action.
- Destroy flow action.

The new operations depend on HAVE_IBV_FLOW_DV_SUPPORT.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
Acked-by: Yongseok Koh <yskoh@mellanox.com>
Acked-by: Shahaf Shuler <shahafs@mellanox.com>
---
 drivers/net/mlx5/Makefile    |  2 +-
 drivers/net/mlx5/meson.build |  2 +-
 drivers/net/mlx5/mlx5_glue.c | 38 ++++++++++++++++++++++++++++++++++++++
 drivers/net/mlx5/mlx5_glue.h | 10 ++++++++++
 4 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile
index fecb57c..073a2f4 100644
--- a/drivers/net/mlx5/Makefile
+++ b/drivers/net/mlx5/Makefile
@@ -139,7 +139,7 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh
 	$Q sh -- '$<' '$@' \
 		HAVE_IBV_FLOW_DV_SUPPORT \
 		infiniband/mlx5dv.h \
-		enum MLX5DV_FLOW_ACTION_TAG \
+		func mlx5dv_create_flow_action_packet_reformat \
 		$(AUTOCONF_OUTPUT)
 	$Q sh -- '$<' '$@' \
 		HAVE_ETHTOOL_LINK_MODE_25G \
diff --git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build
index e8cbe3e..1330a4f 100644
--- a/drivers/net/mlx5/meson.build
+++ b/drivers/net/mlx5/meson.build
@@ -97,7 +97,7 @@ if build
 		[ 'HAVE_IBV_MLX5_MOD_CQE_128B_COMP', 'infiniband/mlx5dv.h',
 		'MLX5DV_CONTEXT_FLAGS_CQE_128B_COMP' ],
 		[ 'HAVE_IBV_FLOW_DV_SUPPORT', 'infiniband/mlx5dv.h',
-		'MLX5DV_FLOW_ACTION_TAG' ],
+		'mlx5dv_create_flow_action_packet_reformat' ],
 		[ 'HAVE_IBV_DEVICE_MPLS_SUPPORT', 'infiniband/verbs.h',
 		'IBV_FLOW_SPEC_MPLS' ],
 		[ 'HAVE_IBV_WQ_FLAG_RX_END_PADDING', 'infiniband/verbs.h',
diff --git a/drivers/net/mlx5/mlx5_glue.c b/drivers/net/mlx5/mlx5_glue.c
index 1afb114..dd10ad6 100644
--- a/drivers/net/mlx5/mlx5_glue.c
+++ b/drivers/net/mlx5/mlx5_glue.c
@@ -174,6 +174,17 @@
 	return ibv_destroy_flow(flow_id);
 }
 
+static int
+mlx5_glue_destroy_flow_action(struct ibv_flow_action *action)
+{
+#ifdef HAVE_IBV_FLOW_DV_SUPPORT
+	return ibv_destroy_flow_action(action);
+#else
+	(void)action;
+	return ENOTSUP;
+#endif
+}
+
 static struct ibv_qp *
 mlx5_glue_create_qp(struct ibv_pd *pd, struct ibv_qp_init_attr *qp_init_attr)
 {
@@ -444,6 +455,30 @@
 #endif
 }
 
+static struct ibv_flow_action *
+mlx5_glue_dv_create_flow_action_packet_reformat
+		(struct ibv_context *ctx,
+		 size_t data_sz,
+		 void *data,
+		 enum mlx5dv_flow_action_packet_reformat_type reformat_type,
+		 enum mlx5dv_flow_table_type ft_type)
+{
+#ifdef HAVE_IBV_FLOW_DV_SUPPORT
+	return mlx5dv_create_flow_action_packet_reformat(ctx,
+							 data_sz,
+							 data,
+							 reformat_type,
+							 ft_type);
+#else
+	(void)ctx;
+	(void)data_sz;
+	(void)data;
+	(void)reformat_type;
+	(void)ft_type;
+	return NULL;
+#endif
+}
+
 alignas(RTE_CACHE_LINE_SIZE)
 const struct mlx5_glue *mlx5_glue = &(const struct mlx5_glue){
 	.version = MLX5_GLUE_VERSION,
@@ -470,6 +505,7 @@
 	.modify_wq = mlx5_glue_modify_wq,
 	.create_flow = mlx5_glue_create_flow,
 	.destroy_flow = mlx5_glue_destroy_flow,
+	.destroy_flow_action = mlx5_glue_destroy_flow_action,
 	.create_qp = mlx5_glue_create_qp,
 	.create_qp_ex = mlx5_glue_create_qp_ex,
 	.destroy_qp = mlx5_glue_destroy_qp,
@@ -497,4 +533,6 @@
 	.dv_create_flow_matcher = mlx5_glue_dv_create_flow_matcher,
 	.dv_destroy_flow_matcher = mlx5_glue_dv_destroy_flow_matcher,
 	.dv_create_flow = mlx5_glue_dv_create_flow,
+	.dv_create_flow_action_packet_reformat =
+			mlx5_glue_dv_create_flow_action_packet_reformat,
 };
diff --git a/drivers/net/mlx5/mlx5_glue.h b/drivers/net/mlx5/mlx5_glue.h
index 44bfefe..2d92ba8 100644
--- a/drivers/net/mlx5/mlx5_glue.h
+++ b/drivers/net/mlx5/mlx5_glue.h
@@ -50,6 +50,9 @@
 struct mlx5dv_flow_matcher_attr;
 struct mlx5dv_flow_action_attr;
 struct mlx5dv_flow_match_parameters;
+struct ibv_flow_action;
+enum mlx5dv_flow_action_packet_reformat_type { packet_reformat_type = 0, };
+enum mlx5dv_flow_table_type { flow_table_type = 0, };
 #endif
 
 /* LIB_GLUE_VERSION must be updated every time this structure is modified. */
@@ -91,6 +94,7 @@ struct mlx5_glue {
 	struct ibv_flow *(*create_flow)(struct ibv_qp *qp,
 					struct ibv_flow_attr *flow);
 	int (*destroy_flow)(struct ibv_flow *flow_id);
+	int (*destroy_flow_action)(struct ibv_flow_action *action);
 	struct ibv_qp *(*create_qp)(struct ibv_pd *pd,
 				    struct ibv_qp_init_attr *qp_init_attr);
 	struct ibv_qp *(*create_qp_ex)
@@ -154,6 +158,12 @@ struct mlx5_glue {
 			  struct mlx5dv_flow_match_parameters *match_value,
 			  size_t num_actions,
 			  struct mlx5dv_flow_action_attr *actions_attr);
+	struct ibv_flow_action *(*dv_create_flow_action_packet_reformat)
+		(struct ibv_context *ctx,
+		 size_t data_sz,
+		 void *data,
+		 enum mlx5dv_flow_action_packet_reformat_type reformat_type,
+		 enum mlx5dv_flow_table_type ft_type);
 };
 
 const struct mlx5_glue *mlx5_glue;
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v8 2/7] net/mlx5: add VXLAN encap action to Direct Verbs
  2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 0/7] " Dekel Peled
                               ` (2 preceding siblings ...)
  2018-11-01  9:37             ` [dpdk-dev] [PATCH v8 1/7] net/mlx5: add flow action functions to glue Dekel Peled
@ 2018-11-01  9:37             ` Dekel Peled
  2018-11-01  9:37             ` [dpdk-dev] [PATCH v8 3/7] net/mlx5: add VXLAN decap " Dekel Peled
                               ` (4 subsequent siblings)
  8 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-11-01  9:37 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch implements the VXLAN encap action in DV flow for MLX5 PMD.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow.h    |   3 +
 drivers/net/mlx5/mlx5_flow_dv.c | 349 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 347 insertions(+), 5 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 61299d6..286d7bb 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -92,6 +92,7 @@
 #define MLX5_FLOW_ACTION_DEC_TTL (1u << 19)
 #define MLX5_FLOW_ACTION_SET_MAC_SRC (1u << 20)
 #define MLX5_FLOW_ACTION_SET_MAC_DST (1u << 21)
+#define MLX5_FLOW_ACTION_VXLAN_ENCAP (1u << 22)
 
 #define MLX5_FLOW_FATE_ACTIONS \
 	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS)
@@ -181,6 +182,8 @@ struct mlx5_flow_dv {
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
 	struct mlx5dv_flow_action_attr actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS];
 	/**< Action list. */
+	struct ibv_flow_action *encap_decap_verbs_action;
+	/**< Verbs encap/decap object. */
 #endif
 	int actions_n; /**< number of actions. */
 };
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 8f729f4..e44b1e6 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -34,6 +34,8 @@
 
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
 
+#define MLX5_ENCAP_MAX_LEN 132
+
 /**
  * Validate META item.
  *
@@ -96,6 +98,305 @@
 }
 
 /**
+ * Validate the L2 encap action.
+ *
+ * @param[in] action_flags
+ *   Holds the actions detected until now.
+ * @param[in] action
+ *   Pointer to the encap action.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_validate_action_l2_encap(uint64_t action_flags,
+				 const struct rte_flow_action *action,
+				 const struct rte_flow_attr *attr,
+				 struct rte_flow_error *error)
+{
+	if (!(action->conf))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, action,
+					  "configuration cannot be null");
+	if (action_flags & MLX5_FLOW_ACTION_DROP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't drop and encap in same flow");
+	if (action_flags & MLX5_FLOW_ACTION_VXLAN_ENCAP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can only have a single encap"
+					  " action in a flow");
+	if (attr->ingress)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
+					  NULL,
+					  "encap action not supported for "
+					  "ingress");
+	return 0;
+}
+
+/**
+ * Get the size of specific rte_flow_item_type
+ *
+ * @param[in] item_type
+ *   Tested rte_flow_item_type.
+ *
+ * @return
+ *   sizeof struct item_type, 0 if void or irrelevant.
+ */
+static size_t
+flow_dv_get_item_len(const enum rte_flow_item_type item_type)
+{
+	size_t retval;
+
+	switch (item_type) {
+	case RTE_FLOW_ITEM_TYPE_ETH:
+		retval = sizeof(struct rte_flow_item_eth);
+		break;
+	case RTE_FLOW_ITEM_TYPE_VLAN:
+		retval = sizeof(struct rte_flow_item_vlan);
+		break;
+	case RTE_FLOW_ITEM_TYPE_IPV4:
+		retval = sizeof(struct rte_flow_item_ipv4);
+		break;
+	case RTE_FLOW_ITEM_TYPE_IPV6:
+		retval = sizeof(struct rte_flow_item_ipv6);
+		break;
+	case RTE_FLOW_ITEM_TYPE_UDP:
+		retval = sizeof(struct rte_flow_item_udp);
+		break;
+	case RTE_FLOW_ITEM_TYPE_TCP:
+		retval = sizeof(struct rte_flow_item_tcp);
+		break;
+	case RTE_FLOW_ITEM_TYPE_VXLAN:
+		retval = sizeof(struct rte_flow_item_vxlan);
+		break;
+	case RTE_FLOW_ITEM_TYPE_GRE:
+		retval = sizeof(struct rte_flow_item_gre);
+		break;
+	case RTE_FLOW_ITEM_TYPE_NVGRE:
+		retval = sizeof(struct rte_flow_item_nvgre);
+		break;
+	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
+		retval = sizeof(struct rte_flow_item_vxlan_gpe);
+		break;
+	case RTE_FLOW_ITEM_TYPE_MPLS:
+		retval = sizeof(struct rte_flow_item_mpls);
+		break;
+	case RTE_FLOW_ITEM_TYPE_VOID: /* Fall through. */
+	default:
+		retval = 0;
+		break;
+	}
+	return retval;
+};
+
+#define MLX5_ENCAP_IPV4_VERSION		0x40
+#define MLX5_ENCAP_IPV4_IHL_MIN		0x05
+#define MLX5_ENCAP_IPV4_TTL_DEF		0x40
+#define MLX5_ENCAP_IPV6_VTC_FLOW	0x60000000
+#define MLX5_ENCAP_IPV6_HOP_LIMIT	0xff
+#define MLX5_ENCAP_VXLAN_FLAGS		0x08000000
+#define MLX5_ENCAP_VXLAN_GPE_FLAGS	0x04
+
+/**
+ * Convert the encap action data from list of rte_flow_item to raw buffer
+ *
+ * @param[in] items
+ *   Pointer to rte_flow_item objects list.
+ * @param[out] buf
+ *   Pointer to the output buffer.
+ * @param[out] size
+ *   Pointer to the output buffer size.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_convert_encap_data(const struct rte_flow_item *items, uint8_t *buf,
+			   size_t *size, struct rte_flow_error *error)
+{
+	struct ether_hdr *eth = NULL;
+	struct vlan_hdr *vlan = NULL;
+	struct ipv4_hdr *ipv4 = NULL;
+	struct ipv6_hdr *ipv6 = NULL;
+	struct udp_hdr *udp = NULL;
+	struct vxlan_hdr *vxlan = NULL;
+	struct vxlan_gpe_hdr *vxlan_gpe = NULL;
+	size_t len;
+	size_t temp_size = 0;
+
+	if (!items)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  NULL, "invalid empty data");
+	for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
+		len = flow_dv_get_item_len(items->type);
+		if (len + temp_size > MLX5_ENCAP_MAX_LEN)
+			return rte_flow_error_set(error, EINVAL,
+						  RTE_FLOW_ERROR_TYPE_ACTION,
+						  (void *)items->type,
+						  "items total size is too big"
+						  " for encap action");
+		rte_memcpy((void *)&buf[temp_size], items->spec, len);
+		switch (items->type) {
+		case RTE_FLOW_ITEM_TYPE_ETH:
+			eth = (struct ether_hdr *)&buf[temp_size];
+			break;
+		case RTE_FLOW_ITEM_TYPE_VLAN:
+			vlan = (struct vlan_hdr *)&buf[temp_size];
+			if (!eth)
+				return rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						(void *)items->type,
+						"eth header not found");
+			if (!eth->ether_type)
+				eth->ether_type = RTE_BE16(ETHER_TYPE_VLAN);
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV4:
+			ipv4 = (struct ipv4_hdr *)&buf[temp_size];
+			if (!vlan && !eth)
+				return rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						(void *)items->type,
+						"neither eth nor vlan"
+						" header found");
+			if (vlan && !vlan->eth_proto)
+				vlan->eth_proto = RTE_BE16(ETHER_TYPE_IPv4);
+			else if (eth && !eth->ether_type)
+				eth->ether_type = RTE_BE16(ETHER_TYPE_IPv4);
+			if (!ipv4->version_ihl)
+				ipv4->version_ihl = MLX5_ENCAP_IPV4_VERSION |
+						    MLX5_ENCAP_IPV4_IHL_MIN;
+			if (!ipv4->time_to_live)
+				ipv4->time_to_live = MLX5_ENCAP_IPV4_TTL_DEF;
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV6:
+			ipv6 = (struct ipv6_hdr *)&buf[temp_size];
+			if (!vlan && !eth)
+				return rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						(void *)items->type,
+						"neither eth nor vlan"
+						" header found");
+			if (vlan && !vlan->eth_proto)
+				vlan->eth_proto = RTE_BE16(ETHER_TYPE_IPv6);
+			else if (eth && !eth->ether_type)
+				eth->ether_type = RTE_BE16(ETHER_TYPE_IPv6);
+			if (!ipv6->vtc_flow)
+				ipv6->vtc_flow =
+					RTE_BE32(MLX5_ENCAP_IPV6_VTC_FLOW);
+			if (!ipv6->hop_limits)
+				ipv6->hop_limits = MLX5_ENCAP_IPV6_HOP_LIMIT;
+			break;
+		case RTE_FLOW_ITEM_TYPE_UDP:
+			udp = (struct udp_hdr *)&buf[temp_size];
+			if (!ipv4 && !ipv6)
+				return rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						(void *)items->type,
+						"ip header not found");
+			if (ipv4 && !ipv4->next_proto_id)
+				ipv4->next_proto_id = IPPROTO_UDP;
+			else if (ipv6 && !ipv6->proto)
+				ipv6->proto = IPPROTO_UDP;
+			break;
+		case RTE_FLOW_ITEM_TYPE_VXLAN:
+			vxlan = (struct vxlan_hdr *)&buf[temp_size];
+			if (!udp)
+				return rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						(void *)items->type,
+						"udp header not found");
+			if (!udp->dst_port)
+				udp->dst_port = RTE_BE16(MLX5_UDP_PORT_VXLAN);
+			if (!vxlan->vx_flags)
+				vxlan->vx_flags =
+					RTE_BE32(MLX5_ENCAP_VXLAN_FLAGS);
+			break;
+		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
+			vxlan_gpe = (struct vxlan_gpe_hdr *)&buf[temp_size];
+			if (!udp)
+				return rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						(void *)items->type,
+						"udp header not found");
+			if (!vxlan_gpe->proto)
+				return rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						(void *)items->type,
+						"next protocol not found");
+			if (!udp->dst_port)
+				udp->dst_port =
+					RTE_BE16(MLX5_UDP_PORT_VXLAN_GPE);
+			if (!vxlan_gpe->vx_flags)
+				vxlan_gpe->vx_flags =
+						MLX5_ENCAP_VXLAN_GPE_FLAGS;
+			break;
+		case RTE_FLOW_ITEM_TYPE_VOID:
+			break;
+		default:
+			return rte_flow_error_set(error, EINVAL,
+						  RTE_FLOW_ERROR_TYPE_ACTION,
+						  (void *)items->type,
+						  "unsupported item type");
+			break;
+		}
+		temp_size += len;
+	}
+	*size = temp_size;
+	return 0;
+}
+
+/**
+ * Convert L2 encap action to DV specification.
+ *
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[in] action
+ *   Pointer to action structure.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+flow_dv_create_action_l2_encap(struct rte_eth_dev *dev,
+			       const struct rte_flow_action *action,
+			       struct rte_flow_error *error)
+{
+	struct ibv_flow_action *verbs_action = NULL;
+	const struct rte_flow_item *encap_data;
+	struct priv *priv = dev->data->dev_private;
+	uint8_t buf[MLX5_ENCAP_MAX_LEN];
+	size_t size = 0;
+	int convert_result = 0;
+
+	encap_data = ((const struct rte_flow_action_vxlan_encap *)
+						action->conf)->definition;
+	convert_result = flow_dv_convert_encap_data(encap_data, buf,
+						    &size, error);
+	if (convert_result)
+		return NULL;
+	verbs_action = mlx5_glue->dv_create_flow_action_packet_reformat
+		(priv->ctx, size, buf,
+		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
+		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
+	if (!verbs_action)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create L2 encap action");
+	return verbs_action;
+}
+
+/**
  * Verify the @p attributes will be correctly understood by the NIC and store
  * them in the @p flow if everything is correct.
  *
@@ -339,6 +640,16 @@
 			action_flags |= MLX5_FLOW_ACTION_COUNT;
 			++actions_n;
 			break;
+		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
+			ret = flow_dv_validate_action_l2_encap(action_flags,
+							       actions, attr,
+							       error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_VXLAN_ENCAP;
+			++actions_n;
+			break;
+
 		default:
 			return rte_flow_error_set(error, ENOTSUP,
 						  RTE_FLOW_ERROR_TYPE_ACTION,
@@ -1045,14 +1356,23 @@
 /**
  * Store the requested actions in an array.
  *
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
  * @param[in] action
  *   Flow action to translate.
  * @param[in, out] dev_flow
  *   Pointer to the mlx5_flow.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
-static void
-flow_dv_create_action(const struct rte_flow_action *action,
-		      struct mlx5_flow *dev_flow)
+static int
+flow_dv_create_action(struct rte_eth_dev *dev,
+		      const struct rte_flow_action *action,
+		      struct mlx5_flow *dev_flow,
+		      struct rte_flow_error *error)
 {
 	const struct rte_flow_action_queue *queue;
 	const struct rte_flow_action_rss *rss;
@@ -1100,10 +1420,24 @@
 		/* Added to array only in apply since we need the QP */
 		flow->actions |= MLX5_FLOW_ACTION_RSS;
 		break;
+	case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
+		dev_flow->dv.actions[actions_n].type =
+			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+		dev_flow->dv.actions[actions_n].action =
+				flow_dv_create_action_l2_encap(dev, action,
+							       error);
+		if (!(dev_flow->dv.actions[actions_n].action))
+			return -rte_errno;
+		dev_flow->dv.encap_decap_verbs_action =
+			dev_flow->dv.actions[actions_n].action;
+		flow->actions |= MLX5_FLOW_ACTION_VXLAN_ENCAP;
+		actions_n++;
+		break;
 	default:
 		break;
 	}
 	dev_flow->dv.actions_n = actions_n;
+	return 0;
 }
 
 static uint32_t matcher_zero[MLX5_ST_SZ_DW(fte_match_param)] = { 0 };
@@ -1217,7 +1551,6 @@
 	return 0;
 }
 
-
 /**
  * Fill the flow with DV spec.
  *
@@ -1272,7 +1605,8 @@
 	if (flow_dv_matcher_register(dev, &matcher, dev_flow, error))
 		return -rte_errno;
 	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++)
-		flow_dv_create_action(actions, dev_flow);
+		if (flow_dv_create_action(dev, actions, dev_flow, error))
+			return -rte_errno;
 	return 0;
 }
 
@@ -1457,6 +1791,11 @@
 		LIST_REMOVE(dev_flow, next);
 		if (dev_flow->dv.matcher)
 			flow_dv_matcher_release(dev, dev_flow);
+		if (dev_flow->dv.encap_decap_verbs_action) {
+			claim_zero(mlx5_glue->destroy_flow_action
+				(dev_flow->dv.encap_decap_verbs_action));
+			dev_flow->dv.encap_decap_verbs_action = NULL;
+		}
 		rte_free(dev_flow);
 	}
 }
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v8 3/7] net/mlx5: add VXLAN decap action to Direct Verbs
  2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 0/7] " Dekel Peled
                               ` (3 preceding siblings ...)
  2018-11-01  9:37             ` [dpdk-dev] [PATCH v8 2/7] net/mlx5: add VXLAN encap action to Direct Verbs Dekel Peled
@ 2018-11-01  9:37             ` Dekel Peled
  2018-11-01  9:37             ` [dpdk-dev] [PATCH v8 4/7] net/mlx5: add NVGRE encap " Dekel Peled
                               ` (3 subsequent siblings)
  8 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-11-01  9:37 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch implements the VXLAN decap action in DV flow for MLX5 PMD.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow.h    |  1 +
 drivers/net/mlx5/mlx5_flow_dv.c | 93 +++++++++++++++++++++++++++++++++++++++--
 2 files changed, 90 insertions(+), 4 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 286d7bb..8955a12 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -93,6 +93,7 @@
 #define MLX5_FLOW_ACTION_SET_MAC_SRC (1u << 20)
 #define MLX5_FLOW_ACTION_SET_MAC_DST (1u << 21)
 #define MLX5_FLOW_ACTION_VXLAN_ENCAP (1u << 22)
+#define MLX5_FLOW_ACTION_VXLAN_DECAP (1u << 23)
 
 #define MLX5_FLOW_FATE_ACTIONS \
 	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS)
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index e44b1e6..9ea19a4 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -126,11 +126,12 @@
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't drop and encap in same flow");
-	if (action_flags & MLX5_FLOW_ACTION_VXLAN_ENCAP)
+	if (action_flags & (MLX5_FLOW_ACTION_VXLAN_ENCAP |
+			    MLX5_FLOW_ACTION_VXLAN_DECAP))
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
-					  "can only have a single encap"
-					  " action in a flow");
+					  "can only have a single encap or"
+					  " decap action in a flow");
 	if (attr->ingress)
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
@@ -141,6 +142,43 @@
 }
 
 /**
+ * Validate the L2 decap action.
+ *
+ * @param[in] action_flags
+ *   Holds the actions detected until now.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_validate_action_l2_decap(uint64_t action_flags,
+				 const struct rte_flow_attr *attr,
+				 struct rte_flow_error *error)
+{
+	if (action_flags & MLX5_FLOW_ACTION_DROP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't drop and decap in same flow");
+	if (action_flags & (MLX5_FLOW_ACTION_VXLAN_ENCAP |
+			    MLX5_FLOW_ACTION_VXLAN_DECAP))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can only have a single encap or"
+					  " decap action in a flow");
+	if (attr->egress)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
+					  NULL,
+					  "decap action not supported for "
+					  "egress");
+	return 0;
+}
+
+/**
  * Get the size of specific rte_flow_item_type
  *
  * @param[in] item_type
@@ -397,6 +435,34 @@
 }
 
 /**
+ * Convert L2 decap action to DV specification.
+ *
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+flow_dv_create_action_l2_decap(struct rte_eth_dev *dev,
+			       struct rte_flow_error *error)
+{
+	struct ibv_flow_action *verbs_action = NULL;
+	struct priv *priv = dev->data->dev_private;
+
+	verbs_action = mlx5_glue->dv_create_flow_action_packet_reformat
+		(priv->ctx, 0, NULL,
+		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2,
+		 MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
+	if (!verbs_action)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create L2 decap action");
+	return verbs_action;
+}
+
+/**
  * Verify the @p attributes will be correctly understood by the NIC and store
  * them in the @p flow if everything is correct.
  *
@@ -649,7 +715,14 @@
 			action_flags |= MLX5_FLOW_ACTION_VXLAN_ENCAP;
 			++actions_n;
 			break;
-
+		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
+			ret = flow_dv_validate_action_l2_decap(action_flags,
+							       attr, error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_VXLAN_DECAP;
+			++actions_n;
+			break;
 		default:
 			return rte_flow_error_set(error, ENOTSUP,
 						  RTE_FLOW_ERROR_TYPE_ACTION,
@@ -1433,6 +1506,18 @@
 		flow->actions |= MLX5_FLOW_ACTION_VXLAN_ENCAP;
 		actions_n++;
 		break;
+	case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
+		dev_flow->dv.actions[actions_n].type =
+			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+		dev_flow->dv.actions[actions_n].action =
+				flow_dv_create_action_l2_decap(dev, error);
+		if (!(dev_flow->dv.actions[actions_n].action))
+			return -rte_errno;
+		dev_flow->dv.encap_decap_verbs_action =
+			dev_flow->dv.actions[actions_n].action;
+		flow->actions |= MLX5_FLOW_ACTION_VXLAN_DECAP;
+		actions_n++;
+		break;
 	default:
 		break;
 	}
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v8 4/7] net/mlx5: add NVGRE encap action to Direct Verbs
  2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 0/7] " Dekel Peled
                               ` (4 preceding siblings ...)
  2018-11-01  9:37             ` [dpdk-dev] [PATCH v8 3/7] net/mlx5: add VXLAN decap " Dekel Peled
@ 2018-11-01  9:37             ` Dekel Peled
  2018-11-01  9:37             ` [dpdk-dev] [PATCH v8 5/7] net/mlx5: add NVGRE decap " Dekel Peled
                               ` (2 subsequent siblings)
  8 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-11-01  9:37 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch implements the nvgre encap action in DV flow for MLX5 PMD.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow.h    |  4 ++++
 drivers/net/mlx5/mlx5_flow_dv.c | 43 ++++++++++++++++++++++++++++++++++++-----
 2 files changed, 42 insertions(+), 5 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 8955a12..c03a3af 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -94,10 +94,14 @@
 #define MLX5_FLOW_ACTION_SET_MAC_DST (1u << 21)
 #define MLX5_FLOW_ACTION_VXLAN_ENCAP (1u << 22)
 #define MLX5_FLOW_ACTION_VXLAN_DECAP (1u << 23)
+#define MLX5_FLOW_ACTION_NVGRE_ENCAP (1u << 24)
 
 #define MLX5_FLOW_FATE_ACTIONS \
 	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS)
 
+#define MLX5_FLOW_ENCAP_ACTIONS	\
+	(MLX5_FLOW_ACTION_VXLAN_ENCAP | MLX5_FLOW_ACTION_NVGRE_ENCAP)
+
 #ifndef IPPROTO_MPLS
 #define IPPROTO_MPLS 137
 #endif
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 9ea19a4..7c29606 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -25,6 +25,7 @@
 #include <rte_flow_driver.h>
 #include <rte_malloc.h>
 #include <rte_ip.h>
+#include <rte_gre.h>
 
 #include "mlx5.h"
 #include "mlx5_defs.h"
@@ -126,7 +127,7 @@
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't drop and encap in same flow");
-	if (action_flags & (MLX5_FLOW_ACTION_VXLAN_ENCAP |
+	if (action_flags & (MLX5_FLOW_ENCAP_ACTIONS |
 			    MLX5_FLOW_ACTION_VXLAN_DECAP))
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
@@ -163,7 +164,7 @@
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't drop and decap in same flow");
-	if (action_flags & (MLX5_FLOW_ACTION_VXLAN_ENCAP |
+	if (action_flags & (MLX5_FLOW_ENCAP_ACTIONS |
 			    MLX5_FLOW_ACTION_VXLAN_DECAP))
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
@@ -268,6 +269,7 @@
 	struct udp_hdr *udp = NULL;
 	struct vxlan_hdr *vxlan = NULL;
 	struct vxlan_gpe_hdr *vxlan_gpe = NULL;
+	struct gre_hdr *gre = NULL;
 	size_t len;
 	size_t temp_size = 0;
 
@@ -378,6 +380,24 @@
 				vxlan_gpe->vx_flags =
 						MLX5_ENCAP_VXLAN_GPE_FLAGS;
 			break;
+		case RTE_FLOW_ITEM_TYPE_GRE:
+		case RTE_FLOW_ITEM_TYPE_NVGRE:
+			gre = (struct gre_hdr *)&buf[temp_size];
+			if (!gre->proto)
+				return rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						(void *)items->type,
+						"next protocol not found");
+			if (!ipv4 && !ipv6)
+				return rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						(void *)items->type,
+						"ip header not found");
+			if (ipv4 && !ipv4->next_proto_id)
+				ipv4->next_proto_id = IPPROTO_GRE;
+			else if (ipv6 && !ipv6->proto)
+				ipv6->proto = IPPROTO_GRE;
+			break;
 		case RTE_FLOW_ITEM_TYPE_VOID:
 			break;
 		default:
@@ -418,7 +438,11 @@
 	size_t size = 0;
 	int convert_result = 0;
 
-	encap_data = ((const struct rte_flow_action_vxlan_encap *)
+	if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP)
+		encap_data = ((const struct rte_flow_action_vxlan_encap *)
+						action->conf)->definition;
+	else
+		encap_data = ((const struct rte_flow_action_nvgre_encap *)
 						action->conf)->definition;
 	convert_result = flow_dv_convert_encap_data(encap_data, buf,
 						    &size, error);
@@ -707,12 +731,17 @@
 			++actions_n;
 			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
+		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
 			ret = flow_dv_validate_action_l2_encap(action_flags,
 							       actions, attr,
 							       error);
 			if (ret < 0)
 				return ret;
-			action_flags |= MLX5_FLOW_ACTION_VXLAN_ENCAP;
+			action_flags |= actions->type ==
+					RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP ?
+					MLX5_FLOW_ACTION_VXLAN_ENCAP :
+					MLX5_FLOW_ACTION_NVGRE_ENCAP;
+
 			++actions_n;
 			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
@@ -1494,6 +1523,7 @@
 		flow->actions |= MLX5_FLOW_ACTION_RSS;
 		break;
 	case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
+	case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
 		dev_flow->dv.actions[actions_n].type =
 			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
 		dev_flow->dv.actions[actions_n].action =
@@ -1503,7 +1533,10 @@
 			return -rte_errno;
 		dev_flow->dv.encap_decap_verbs_action =
 			dev_flow->dv.actions[actions_n].action;
-		flow->actions |= MLX5_FLOW_ACTION_VXLAN_ENCAP;
+		flow->actions |= action->type ==
+				 RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP ?
+				 MLX5_FLOW_ACTION_VXLAN_ENCAP :
+				 MLX5_FLOW_ACTION_NVGRE_ENCAP;
 		actions_n++;
 		break;
 	case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v8 5/7] net/mlx5: add NVGRE decap action to Direct Verbs
  2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 0/7] " Dekel Peled
                               ` (5 preceding siblings ...)
  2018-11-01  9:37             ` [dpdk-dev] [PATCH v8 4/7] net/mlx5: add NVGRE encap " Dekel Peled
@ 2018-11-01  9:37             ` Dekel Peled
  2018-11-01  9:37             ` [dpdk-dev] [PATCH v8 6/7] net/mlx5: add raw data encap decap " Dekel Peled
  2018-11-01  9:37             ` [dpdk-dev] [PATCH v8 7/7] net/mlx5: add caching of encap decap actions Dekel Peled
  8 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-11-01  9:37 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch implements the NVGRE decap action in DV flow for MLX5 PMD.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow.h    |  4 ++++
 drivers/net/mlx5/mlx5_flow_dv.c | 19 +++++++++++++------
 2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index c03a3af..104a1e6 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -95,6 +95,7 @@
 #define MLX5_FLOW_ACTION_VXLAN_ENCAP (1u << 22)
 #define MLX5_FLOW_ACTION_VXLAN_DECAP (1u << 23)
 #define MLX5_FLOW_ACTION_NVGRE_ENCAP (1u << 24)
+#define MLX5_FLOW_ACTION_NVGRE_DECAP (1u << 25)
 
 #define MLX5_FLOW_FATE_ACTIONS \
 	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS)
@@ -102,6 +103,9 @@
 #define MLX5_FLOW_ENCAP_ACTIONS	\
 	(MLX5_FLOW_ACTION_VXLAN_ENCAP | MLX5_FLOW_ACTION_NVGRE_ENCAP)
 
+#define MLX5_FLOW_DECAP_ACTIONS	\
+	(MLX5_FLOW_ACTION_VXLAN_DECAP | MLX5_FLOW_ACTION_NVGRE_DECAP)
+
 #ifndef IPPROTO_MPLS
 #define IPPROTO_MPLS 137
 #endif
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 7c29606..6517688 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -127,8 +127,7 @@
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't drop and encap in same flow");
-	if (action_flags & (MLX5_FLOW_ENCAP_ACTIONS |
-			    MLX5_FLOW_ACTION_VXLAN_DECAP))
+	if (action_flags & (MLX5_FLOW_ENCAP_ACTIONS | MLX5_FLOW_DECAP_ACTIONS))
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can only have a single encap or"
@@ -164,8 +163,7 @@
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't drop and decap in same flow");
-	if (action_flags & (MLX5_FLOW_ENCAP_ACTIONS |
-			    MLX5_FLOW_ACTION_VXLAN_DECAP))
+	if (action_flags & (MLX5_FLOW_ENCAP_ACTIONS | MLX5_FLOW_DECAP_ACTIONS))
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can only have a single encap or"
@@ -745,11 +743,16 @@
 			++actions_n;
 			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
+		case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
 			ret = flow_dv_validate_action_l2_decap(action_flags,
 							       attr, error);
 			if (ret < 0)
 				return ret;
-			action_flags |= MLX5_FLOW_ACTION_VXLAN_DECAP;
+			action_flags |= actions->type ==
+					RTE_FLOW_ACTION_TYPE_VXLAN_DECAP ?
+					MLX5_FLOW_ACTION_VXLAN_DECAP :
+					MLX5_FLOW_ACTION_NVGRE_DECAP;
+
 			++actions_n;
 			break;
 		default:
@@ -1540,6 +1543,7 @@
 		actions_n++;
 		break;
 	case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
+	case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
 		dev_flow->dv.actions[actions_n].type =
 			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
 		dev_flow->dv.actions[actions_n].action =
@@ -1548,7 +1552,10 @@
 			return -rte_errno;
 		dev_flow->dv.encap_decap_verbs_action =
 			dev_flow->dv.actions[actions_n].action;
-		flow->actions |= MLX5_FLOW_ACTION_VXLAN_DECAP;
+		flow->actions |= action->type ==
+				 RTE_FLOW_ACTION_TYPE_VXLAN_DECAP ?
+				 MLX5_FLOW_ACTION_VXLAN_DECAP :
+				 MLX5_FLOW_ACTION_NVGRE_DECAP;
 		actions_n++;
 		break;
 	default:
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v8 6/7] net/mlx5: add raw data encap decap to Direct Verbs
  2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 0/7] " Dekel Peled
                               ` (6 preceding siblings ...)
  2018-11-01  9:37             ` [dpdk-dev] [PATCH v8 5/7] net/mlx5: add NVGRE decap " Dekel Peled
@ 2018-11-01  9:37             ` Dekel Peled
  2018-11-01  9:37             ` [dpdk-dev] [PATCH v8 7/7] net/mlx5: add caching of encap decap actions Dekel Peled
  8 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-11-01  9:37 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

This patch implements the encap and decap actions, using raw data,
in DV flow for MLX5 PMD.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow.h    |  12 +-
 drivers/net/mlx5/mlx5_flow_dv.c | 246 +++++++++++++++++++++++++++++++++++++---
 2 files changed, 241 insertions(+), 17 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 104a1e6..908123f 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -96,15 +96,19 @@
 #define MLX5_FLOW_ACTION_VXLAN_DECAP (1u << 23)
 #define MLX5_FLOW_ACTION_NVGRE_ENCAP (1u << 24)
 #define MLX5_FLOW_ACTION_NVGRE_DECAP (1u << 25)
+#define MLX5_FLOW_ACTION_RAW_ENCAP (1u << 26)
+#define MLX5_FLOW_ACTION_RAW_DECAP (1u << 27)
 
 #define MLX5_FLOW_FATE_ACTIONS \
 	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS)
 
-#define MLX5_FLOW_ENCAP_ACTIONS	\
-	(MLX5_FLOW_ACTION_VXLAN_ENCAP | MLX5_FLOW_ACTION_NVGRE_ENCAP)
+#define MLX5_FLOW_ENCAP_ACTIONS	(MLX5_FLOW_ACTION_VXLAN_ENCAP | \
+				 MLX5_FLOW_ACTION_NVGRE_ENCAP | \
+				 MLX5_FLOW_ACTION_RAW_ENCAP)
 
-#define MLX5_FLOW_DECAP_ACTIONS	\
-	(MLX5_FLOW_ACTION_VXLAN_DECAP | MLX5_FLOW_ACTION_NVGRE_DECAP)
+#define MLX5_FLOW_DECAP_ACTIONS	(MLX5_FLOW_ACTION_VXLAN_DECAP | \
+				 MLX5_FLOW_ACTION_NVGRE_DECAP | \
+				 MLX5_FLOW_ACTION_RAW_DECAP)
 
 #ifndef IPPROTO_MPLS
 #define IPPROTO_MPLS 137
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 6517688..dd99f00 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -178,6 +178,101 @@
 }
 
 /**
+ * Validate the raw encap action.
+ *
+ * @param[in] action_flags
+ *   Holds the actions detected until now.
+ * @param[in] action
+ *   Pointer to the encap action.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_validate_action_raw_encap(uint64_t action_flags,
+				  const struct rte_flow_action *action,
+				  const struct rte_flow_attr *attr,
+				  struct rte_flow_error *error)
+{
+	if (!(action->conf))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, action,
+					  "configuration cannot be null");
+	if (action_flags & MLX5_FLOW_ACTION_DROP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't drop and encap in same flow");
+	if (action_flags & MLX5_FLOW_ENCAP_ACTIONS)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can only have a single encap"
+					  " action in a flow");
+	/* encap without preceding decap is not supported for ingress */
+	if (attr->ingress && !(action_flags & MLX5_FLOW_ACTION_RAW_DECAP))
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
+					  NULL,
+					  "encap action not supported for "
+					  "ingress");
+	return 0;
+}
+
+/**
+ * Validate the raw decap action.
+ *
+ * @param[in] action_flags
+ *   Holds the actions detected until now.
+ * @param[in] action
+ *   Pointer to the encap action.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_validate_action_raw_decap(uint64_t action_flags,
+				  const struct rte_flow_action *action,
+				  const struct rte_flow_attr *attr,
+				  struct rte_flow_error *error)
+{
+	if (action_flags & MLX5_FLOW_ACTION_DROP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't drop and decap in same flow");
+	if (action_flags & MLX5_FLOW_ENCAP_ACTIONS)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can't have encap action before"
+					  " decap action");
+	if (action_flags & MLX5_FLOW_DECAP_ACTIONS)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "can only have a single decap"
+					  " action in a flow");
+	/* decap action is valid on egress only if it is followed by encap */
+	if (attr->egress) {
+		for (; action->type != RTE_FLOW_ACTION_TYPE_END &&
+		       action->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP;
+		       action++) {
+		}
+		if (action->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP)
+			return rte_flow_error_set
+					(error, ENOTSUP,
+					 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
+					 NULL, "decap action not supported"
+					 " for egress");
+	}
+	return 0;
+}
+
+/**
  * Get the size of specific rte_flow_item_type
  *
  * @param[in] item_type
@@ -431,23 +526,34 @@
 {
 	struct ibv_flow_action *verbs_action = NULL;
 	const struct rte_flow_item *encap_data;
+	const struct rte_flow_action_raw_encap *raw_encap_data;
 	struct priv *priv = dev->data->dev_private;
 	uint8_t buf[MLX5_ENCAP_MAX_LEN];
+	uint8_t *buf_ptr = buf;
 	size_t size = 0;
 	int convert_result = 0;
 
-	if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP)
-		encap_data = ((const struct rte_flow_action_vxlan_encap *)
+	if (action->type == RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
+		raw_encap_data =
+			(const struct rte_flow_action_raw_encap *)action->conf;
+		buf_ptr = raw_encap_data->data;
+		size = raw_encap_data->size;
+	} else {
+		if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP)
+			encap_data =
+				((const struct rte_flow_action_vxlan_encap *)
 						action->conf)->definition;
-	else
-		encap_data = ((const struct rte_flow_action_nvgre_encap *)
+		else
+			encap_data =
+				((const struct rte_flow_action_nvgre_encap *)
 						action->conf)->definition;
-	convert_result = flow_dv_convert_encap_data(encap_data, buf,
-						    &size, error);
-	if (convert_result)
-		return NULL;
+		convert_result = flow_dv_convert_encap_data(encap_data, buf,
+							    &size, error);
+		if (convert_result)
+			return NULL;
+	}
 	verbs_action = mlx5_glue->dv_create_flow_action_packet_reformat
-		(priv->ctx, size, buf,
+		(priv->ctx, size, buf_ptr,
 		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
 		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
 	if (!verbs_action)
@@ -485,6 +591,50 @@
 }
 
 /**
+ * Convert raw decap/encap (L3 tunnel) action to DV specification.
+ *
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[in] action
+ *   Pointer to action structure.
+ * @param[in] attr
+ *   Pointer to the flow attributes.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ */
+static struct ibv_flow_action *
+flow_dv_create_action_raw_encap(struct rte_eth_dev *dev,
+				const struct rte_flow_action *action,
+				const struct rte_flow_attr *attr,
+				struct rte_flow_error *error)
+{
+	struct ibv_flow_action *verbs_action = NULL;
+	const struct rte_flow_action_raw_encap *encap_data;
+	struct priv *priv = dev->data->dev_private;
+	enum mlx5dv_flow_action_packet_reformat_type reformat_type;
+	enum mlx5dv_flow_table_type ft_type;
+
+	encap_data = (const struct rte_flow_action_raw_encap *)action->conf;
+	reformat_type = attr->egress ?
+		MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL :
+		MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2;
+	ft_type = attr->egress ?
+			MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
+			MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
+	verbs_action = mlx5_glue->dv_create_flow_action_packet_reformat
+				(priv->ctx, encap_data->size,
+				(encap_data->size ? encap_data->data : NULL),
+				reformat_type, ft_type);
+	if (!verbs_action)
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   NULL, "cannot create encap action");
+	return verbs_action;
+}
+
+/**
  * Verify the @p attributes will be correctly understood by the NIC and store
  * them in the @p flow if everything is correct.
  *
@@ -739,7 +889,6 @@
 					RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP ?
 					MLX5_FLOW_ACTION_VXLAN_ENCAP :
 					MLX5_FLOW_ACTION_NVGRE_ENCAP;
-
 			++actions_n;
 			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
@@ -752,7 +901,24 @@
 					RTE_FLOW_ACTION_TYPE_VXLAN_DECAP ?
 					MLX5_FLOW_ACTION_VXLAN_DECAP :
 					MLX5_FLOW_ACTION_NVGRE_DECAP;
-
+			++actions_n;
+			break;
+		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
+			ret = flow_dv_validate_action_raw_encap(action_flags,
+								actions, attr,
+								error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_RAW_ENCAP;
+			++actions_n;
+			break;
+		case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
+			ret = flow_dv_validate_action_raw_decap(action_flags,
+								actions, attr,
+								error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_RAW_DECAP;
 			++actions_n;
 			break;
 		default:
@@ -1467,6 +1633,8 @@
  *   Flow action to translate.
  * @param[in, out] dev_flow
  *   Pointer to the mlx5_flow.
+ * @param[in] attr
+ *   Pointer to the flow attributes.
  * @param[out] error
  *   Pointer to the error structure.
  *
@@ -1477,12 +1645,14 @@
 flow_dv_create_action(struct rte_eth_dev *dev,
 		      const struct rte_flow_action *action,
 		      struct mlx5_flow *dev_flow,
+		      const struct rte_flow_attr *attr,
 		      struct rte_flow_error *error)
 {
 	const struct rte_flow_action_queue *queue;
 	const struct rte_flow_action_rss *rss;
 	int actions_n = dev_flow->dv.actions_n;
 	struct rte_flow *flow = dev_flow->flow;
+	const struct rte_flow_action *action_ptr = action;
 
 	switch (action->type) {
 	case RTE_FLOW_ACTION_TYPE_VOID:
@@ -1558,6 +1728,56 @@
 				 MLX5_FLOW_ACTION_NVGRE_DECAP;
 		actions_n++;
 		break;
+	case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
+		/* Handle encap action with preceding decap */
+		if (flow->actions & MLX5_FLOW_ACTION_RAW_DECAP) {
+			dev_flow->dv.actions[actions_n].type =
+				MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+			dev_flow->dv.actions[actions_n].action =
+					flow_dv_create_action_raw_encap
+								(dev, action,
+								 attr, error);
+			if (!(dev_flow->dv.actions[actions_n].action))
+				return -rte_errno;
+			dev_flow->dv.encap_decap_verbs_action =
+				dev_flow->dv.actions[actions_n].action;
+		} else {
+			/* Handle encap action without preceding decap */
+			dev_flow->dv.actions[actions_n].type =
+				MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+			dev_flow->dv.actions[actions_n].action =
+					flow_dv_create_action_l2_encap
+							(dev, action, error);
+			if (!(dev_flow->dv.actions[actions_n].action))
+				return -rte_errno;
+			dev_flow->dv.encap_decap_verbs_action =
+				dev_flow->dv.actions[actions_n].action;
+		}
+		flow->actions |= MLX5_FLOW_ACTION_RAW_ENCAP;
+		actions_n++;
+		break;
+	case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
+		/* Check if this decap action is followed by encap. */
+		for (; action_ptr->type != RTE_FLOW_ACTION_TYPE_END &&
+		       action_ptr->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP;
+		       action_ptr++) {
+		}
+		/* Handle decap action only if it isn't followed by encap */
+		if (action_ptr->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
+			dev_flow->dv.actions[actions_n].type =
+				MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
+			dev_flow->dv.actions[actions_n].action =
+					flow_dv_create_action_l2_decap(dev,
+								       error);
+			if (!(dev_flow->dv.actions[actions_n].action))
+				return -rte_errno;
+			dev_flow->dv.encap_decap_verbs_action =
+				dev_flow->dv.actions[actions_n].action;
+			actions_n++;
+		}
+		/* If decap is followed by encap, handle it at encap case. */
+		flow->actions |= MLX5_FLOW_ACTION_RAW_DECAP;
+		break;
 	default:
 		break;
 	}
@@ -1700,7 +1920,7 @@
 		  struct mlx5_flow *dev_flow,
 		  const struct rte_flow_attr *attr,
 		  const struct rte_flow_item items[],
-		  const struct rte_flow_action actions[] __rte_unused,
+		  const struct rte_flow_action actions[],
 		  struct rte_flow_error *error)
 {
 	struct priv *priv = dev->data->dev_private;
@@ -1730,7 +1950,7 @@
 	if (flow_dv_matcher_register(dev, &matcher, dev_flow, error))
 		return -rte_errno;
 	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++)
-		if (flow_dv_create_action(dev, actions, dev_flow, error))
+		if (flow_dv_create_action(dev, actions, dev_flow, attr, error))
 			return -rte_errno;
 	return 0;
 }
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v8 7/7] net/mlx5: add caching of encap decap actions
  2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 0/7] " Dekel Peled
                               ` (7 preceding siblings ...)
  2018-11-01  9:37             ` [dpdk-dev] [PATCH v8 6/7] net/mlx5: add raw data encap decap " Dekel Peled
@ 2018-11-01  9:37             ` Dekel Peled
  8 siblings, 0 replies; 94+ messages in thread
From: Dekel Peled @ 2018-11-01  9:37 UTC (permalink / raw)
  To: yskoh, shahafs; +Cc: dev, orika

Make flow encap and decap Verbs actions cacheable resources.
Store created actions in local database.
This enables MLX5 PMD reuse of existing actions.

Signed-off-by: Dekel Peled <dekelp@mellanox.com>
---
 drivers/net/mlx5/mlx5.h         |   1 +
 drivers/net/mlx5/mlx5_flow.h    |  18 ++-
 drivers/net/mlx5/mlx5_flow_dv.c | 265 ++++++++++++++++++++++++++--------------
 3 files changed, 193 insertions(+), 91 deletions(-)

diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 74d87c0..0422803 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -219,6 +219,7 @@ struct priv {
 	/* Verbs Indirection tables. */
 	LIST_HEAD(ind_tables, mlx5_ind_table_ibv) ind_tbls;
 	LIST_HEAD(matchers, mlx5_flow_dv_matcher) matchers;
+	LIST_HEAD(encap_decap, mlx5_flow_dv_encap_decap_resource) encaps_decaps;
 	uint32_t link_speed_capa; /* Link speed capabilities. */
 	struct mlx5_xstats_ctrl xstats_ctrl; /* Extended stats control. */
 	int primary_socket; /* Unix socket for primary process. */
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 908123f..25cd9c5 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -170,6 +170,7 @@ struct mlx5_flow_dv_match_params {
 };
 
 #define MLX5_DV_MAX_NUMBER_OF_ACTIONS 8
+#define MLX5_ENCAP_MAX_LEN 132
 
 /* Matcher structure. */
 struct mlx5_flow_dv_matcher {
@@ -183,6 +184,19 @@ struct mlx5_flow_dv_matcher {
 	struct mlx5_flow_dv_match_params mask; /**< Matcher mask. */
 };
 
+/* Encap/decap resource structure. */
+struct mlx5_flow_dv_encap_decap_resource {
+	LIST_ENTRY(mlx5_flow_dv_encap_decap_resource) next;
+	/* Pointer to next element. */
+	rte_atomic32_t refcnt; /**< Reference counter. */
+	struct ibv_flow_action *verbs_action;
+	/**< Verbs encap/decap action object. */
+	uint8_t buf[MLX5_ENCAP_MAX_LEN];
+	size_t size;
+	uint8_t reformat_type;
+	uint8_t ft_type;
+};
+
 /* DV flows structure. */
 struct mlx5_flow_dv {
 	uint64_t hash_fields; /**< Fields that participate in the hash. */
@@ -191,12 +205,12 @@ struct mlx5_flow_dv {
 	struct mlx5_flow_dv_matcher *matcher; /**< Cache to matcher. */
 	struct mlx5_flow_dv_match_params value;
 	/**< Holds the value that the packet is compared to. */
+	struct mlx5_flow_dv_encap_decap_resource *encap_decap;
+	/**< Pointer to encap/decap resource in cache. */
 	struct ibv_flow *flow; /**< Installed flow. */
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
 	struct mlx5dv_flow_action_attr actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS];
 	/**< Action list. */
-	struct ibv_flow_action *encap_decap_verbs_action;
-	/**< Verbs encap/decap object. */
 #endif
 	int actions_n; /**< number of actions. */
 };
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index dd99f00..4898150 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -35,8 +35,6 @@
 
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
 
-#define MLX5_ENCAP_MAX_LEN 132
-
 /**
  * Validate META item.
  *
@@ -272,6 +270,77 @@
 	return 0;
 }
 
+
+/**
+ * Find existing encap/decap resource or create and register a new one.
+ *
+ * @param dev[in, out]
+ *   Pointer to rte_eth_dev structure.
+ * @param[in, out] resource
+ *   Pointer to encap/decap resource.
+ * @parm[in, out] dev_flow
+ *   Pointer to the dev_flow.
+ * @param[out] error
+ *   pointer to error structure.
+ *
+ * @return
+ *   0 on success otherwise -errno and errno is set.
+ */
+static int
+flow_dv_encap_decap_resource_register
+			(struct rte_eth_dev *dev,
+			 struct mlx5_flow_dv_encap_decap_resource *resource,
+			 struct mlx5_flow *dev_flow,
+			 struct rte_flow_error *error)
+{
+	struct priv *priv = dev->data->dev_private;
+	struct mlx5_flow_dv_encap_decap_resource *cache_resource;
+
+	/* Lookup a matching resource from cache. */
+	LIST_FOREACH(cache_resource, &priv->encaps_decaps, next) {
+		if (resource->reformat_type == cache_resource->reformat_type &&
+		    resource->ft_type == cache_resource->ft_type &&
+		    resource->size == cache_resource->size &&
+		    !memcmp((const void *)resource->buf,
+			    (const void *)cache_resource->buf,
+			    resource->size)) {
+			DRV_LOG(DEBUG, "encap/decap resource %p: refcnt %d++",
+				(void *)cache_resource,
+				rte_atomic32_read(&cache_resource->refcnt));
+			rte_atomic32_inc(&cache_resource->refcnt);
+			dev_flow->dv.encap_decap = cache_resource;
+			return 0;
+		}
+	}
+	/* Register new encap/decap resource. */
+	cache_resource = rte_calloc(__func__, 1, sizeof(*cache_resource), 0);
+	if (!cache_resource)
+		return rte_flow_error_set(error, ENOMEM,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					  "cannot allocate resource memory");
+	*cache_resource = *resource;
+	cache_resource->verbs_action =
+		mlx5_glue->dv_create_flow_action_packet_reformat
+			(priv->ctx, cache_resource->size,
+			 (cache_resource->size ? cache_resource->buf : NULL),
+			 cache_resource->reformat_type,
+			 cache_resource->ft_type);
+	if (!cache_resource->verbs_action) {
+		rte_free(cache_resource);
+		return rte_flow_error_set(error, ENOMEM,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					  NULL, "cannot create action");
+	}
+	rte_atomic32_init(&cache_resource->refcnt);
+	rte_atomic32_inc(&cache_resource->refcnt);
+	LIST_INSERT_HEAD(&priv->encaps_decaps, cache_resource, next);
+	dev_flow->dv.encap_decap = cache_resource;
+	DRV_LOG(DEBUG, "new encap/decap resource %p: refcnt %d++",
+		(void *)cache_resource,
+		rte_atomic32_read(&cache_resource->refcnt));
+	return 0;
+}
+
 /**
  * Get the size of specific rte_flow_item_type
  *
@@ -513,31 +582,33 @@
  *   Pointer to rte_eth_dev structure.
  * @param[in] action
  *   Pointer to action structure.
+ * @param[in, out] dev_flow
+ *   Pointer to the mlx5_flow.
  * @param[out] error
  *   Pointer to the error structure.
  *
  * @return
- *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
-static struct ibv_flow_action *
+static int
 flow_dv_create_action_l2_encap(struct rte_eth_dev *dev,
 			       const struct rte_flow_action *action,
+			       struct mlx5_flow *dev_flow,
 			       struct rte_flow_error *error)
 {
-	struct ibv_flow_action *verbs_action = NULL;
 	const struct rte_flow_item *encap_data;
 	const struct rte_flow_action_raw_encap *raw_encap_data;
-	struct priv *priv = dev->data->dev_private;
-	uint8_t buf[MLX5_ENCAP_MAX_LEN];
-	uint8_t *buf_ptr = buf;
-	size_t size = 0;
-	int convert_result = 0;
+	struct mlx5_flow_dv_encap_decap_resource res = {
+		.reformat_type =
+			MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
+		.ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_TX,
+	};
 
 	if (action->type == RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
 		raw_encap_data =
 			(const struct rte_flow_action_raw_encap *)action->conf;
-		buf_ptr = raw_encap_data->data;
-		size = raw_encap_data->size;
+		res.size = raw_encap_data->size;
+		memcpy(res.buf, raw_encap_data->data, res.size);
 	} else {
 		if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP)
 			encap_data =
@@ -547,19 +618,15 @@
 			encap_data =
 				((const struct rte_flow_action_nvgre_encap *)
 						action->conf)->definition;
-		convert_result = flow_dv_convert_encap_data(encap_data, buf,
-							    &size, error);
-		if (convert_result)
-			return NULL;
+		if (flow_dv_convert_encap_data(encap_data, res.buf,
+					       &res.size, error))
+			return -rte_errno;
 	}
-	verbs_action = mlx5_glue->dv_create_flow_action_packet_reformat
-		(priv->ctx, size, buf_ptr,
-		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL,
-		 MLX5DV_FLOW_TABLE_TYPE_NIC_TX);
-	if (!verbs_action)
-		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
-				   NULL, "cannot create L2 encap action");
-	return verbs_action;
+	if (flow_dv_encap_decap_resource_register(dev, &res, dev_flow, error))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  NULL, "can't create L2 encap action");
+	return 0;
 }
 
 /**
@@ -567,27 +634,31 @@
  *
  * @param[in] dev
  *   Pointer to rte_eth_dev structure.
+ * @param[in, out] dev_flow
+ *   Pointer to the mlx5_flow.
  * @param[out] error
  *   Pointer to the error structure.
  *
  * @return
- *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
-static struct ibv_flow_action *
+static int
 flow_dv_create_action_l2_decap(struct rte_eth_dev *dev,
+			       struct mlx5_flow *dev_flow,
 			       struct rte_flow_error *error)
 {
-	struct ibv_flow_action *verbs_action = NULL;
-	struct priv *priv = dev->data->dev_private;
+	struct mlx5_flow_dv_encap_decap_resource res = {
+		.size = 0,
+		.reformat_type =
+			MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2,
+		.ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_RX,
+	};
 
-	verbs_action = mlx5_glue->dv_create_flow_action_packet_reformat
-		(priv->ctx, 0, NULL,
-		 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2,
-		 MLX5DV_FLOW_TABLE_TYPE_NIC_RX);
-	if (!verbs_action)
-		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
-				   NULL, "cannot create L2 decap action");
-	return verbs_action;
+	if (flow_dv_encap_decap_resource_register(dev, &res, dev_flow, error))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  NULL, "can't create L2 decap action");
+	return 0;
 }
 
 /**
@@ -597,41 +668,39 @@
  *   Pointer to rte_eth_dev structure.
  * @param[in] action
  *   Pointer to action structure.
+ * @param[in, out] dev_flow
+ *   Pointer to the mlx5_flow.
  * @param[in] attr
  *   Pointer to the flow attributes.
  * @param[out] error
  *   Pointer to the error structure.
  *
  * @return
- *   Pointer to action on success, NULL otherwise and rte_errno is set.
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
-static struct ibv_flow_action *
+static int
 flow_dv_create_action_raw_encap(struct rte_eth_dev *dev,
 				const struct rte_flow_action *action,
+				struct mlx5_flow *dev_flow,
 				const struct rte_flow_attr *attr,
 				struct rte_flow_error *error)
 {
-	struct ibv_flow_action *verbs_action = NULL;
 	const struct rte_flow_action_raw_encap *encap_data;
-	struct priv *priv = dev->data->dev_private;
-	enum mlx5dv_flow_action_packet_reformat_type reformat_type;
-	enum mlx5dv_flow_table_type ft_type;
+	struct mlx5_flow_dv_encap_decap_resource res;
 
 	encap_data = (const struct rte_flow_action_raw_encap *)action->conf;
-	reformat_type = attr->egress ?
+	res.size = encap_data->size;
+	memcpy(res.buf, encap_data->data, res.size);
+	res.reformat_type = attr->egress ?
 		MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL :
 		MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2;
-	ft_type = attr->egress ?
-			MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
-			MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
-	verbs_action = mlx5_glue->dv_create_flow_action_packet_reformat
-				(priv->ctx, encap_data->size,
-				(encap_data->size ? encap_data->data : NULL),
-				reformat_type, ft_type);
-	if (!verbs_action)
-		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
-				   NULL, "cannot create encap action");
-	return verbs_action;
+	res.ft_type = attr->egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
+				     MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
+	if (flow_dv_encap_decap_resource_register(dev, &res, dev_flow, error))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  NULL, "can't create encap action");
+	return 0;
 }
 
 /**
@@ -1697,15 +1766,13 @@
 		break;
 	case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
 	case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
+		if (flow_dv_create_action_l2_encap(dev, action,
+						   dev_flow, error))
+			return -rte_errno;
 		dev_flow->dv.actions[actions_n].type =
 			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
 		dev_flow->dv.actions[actions_n].action =
-				flow_dv_create_action_l2_encap(dev, action,
-							       error);
-		if (!(dev_flow->dv.actions[actions_n].action))
-			return -rte_errno;
-		dev_flow->dv.encap_decap_verbs_action =
-			dev_flow->dv.actions[actions_n].action;
+			dev_flow->dv.encap_decap->verbs_action;
 		flow->actions |= action->type ==
 				 RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP ?
 				 MLX5_FLOW_ACTION_VXLAN_ENCAP :
@@ -1714,14 +1781,12 @@
 		break;
 	case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
 	case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
+		if (flow_dv_create_action_l2_decap(dev, dev_flow, error))
+			return -rte_errno;
 		dev_flow->dv.actions[actions_n].type =
 			MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
 		dev_flow->dv.actions[actions_n].action =
-				flow_dv_create_action_l2_decap(dev, error);
-		if (!(dev_flow->dv.actions[actions_n].action))
-			return -rte_errno;
-		dev_flow->dv.encap_decap_verbs_action =
-			dev_flow->dv.actions[actions_n].action;
+			dev_flow->dv.encap_decap->verbs_action;
 		flow->actions |= action->type ==
 				 RTE_FLOW_ACTION_TYPE_VXLAN_DECAP ?
 				 MLX5_FLOW_ACTION_VXLAN_DECAP :
@@ -1731,27 +1796,23 @@
 	case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
 		/* Handle encap action with preceding decap */
 		if (flow->actions & MLX5_FLOW_ACTION_RAW_DECAP) {
+			if (flow_dv_create_action_raw_encap(dev, action,
+							    dev_flow,
+							    attr, error))
+				return -rte_errno;
 			dev_flow->dv.actions[actions_n].type =
 				MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
 			dev_flow->dv.actions[actions_n].action =
-					flow_dv_create_action_raw_encap
-								(dev, action,
-								 attr, error);
-			if (!(dev_flow->dv.actions[actions_n].action))
-				return -rte_errno;
-			dev_flow->dv.encap_decap_verbs_action =
-				dev_flow->dv.actions[actions_n].action;
+					dev_flow->dv.encap_decap->verbs_action;
 		} else {
 			/* Handle encap action without preceding decap */
+			if (flow_dv_create_action_l2_encap(dev, action,
+							   dev_flow, error))
+				return -rte_errno;
 			dev_flow->dv.actions[actions_n].type =
 				MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
 			dev_flow->dv.actions[actions_n].action =
-					flow_dv_create_action_l2_encap
-							(dev, action, error);
-			if (!(dev_flow->dv.actions[actions_n].action))
-				return -rte_errno;
-			dev_flow->dv.encap_decap_verbs_action =
-				dev_flow->dv.actions[actions_n].action;
+					dev_flow->dv.encap_decap->verbs_action;
 		}
 		flow->actions |= MLX5_FLOW_ACTION_RAW_ENCAP;
 		actions_n++;
@@ -1764,15 +1825,13 @@
 		}
 		/* Handle decap action only if it isn't followed by encap */
 		if (action_ptr->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
+			if (flow_dv_create_action_l2_decap(dev, dev_flow,
+							   error))
+				return -rte_errno;
 			dev_flow->dv.actions[actions_n].type =
 				MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
 			dev_flow->dv.actions[actions_n].action =
-					flow_dv_create_action_l2_decap(dev,
-								       error);
-			if (!(dev_flow->dv.actions[actions_n].action))
-				return -rte_errno;
-			dev_flow->dv.encap_decap_verbs_action =
-				dev_flow->dv.actions[actions_n].action;
+					dev_flow->dv.encap_decap->verbs_action;
 			actions_n++;
 		}
 		/* If decap is followed by encap, handle it at encap case. */
@@ -2082,6 +2141,37 @@
 }
 
 /**
+ * Release an encap/decap resource.
+ *
+ * @param flow
+ *   Pointer to mlx5_flow.
+ *
+ * @return
+ *   1 while a reference on it exists, 0 when freed.
+ */
+static int
+flow_dv_encap_decap_resource_release(struct mlx5_flow *flow)
+{
+	struct mlx5_flow_dv_encap_decap_resource *cache_resource =
+						flow->dv.encap_decap;
+
+	assert(cache_resource->verbs_action);
+	DRV_LOG(DEBUG, "encap/decap resource %p: refcnt %d--",
+		(void *)cache_resource,
+		rte_atomic32_read(&cache_resource->refcnt));
+	if (rte_atomic32_dec_and_test(&cache_resource->refcnt)) {
+		claim_zero(mlx5_glue->destroy_flow_action
+				(cache_resource->verbs_action));
+		LIST_REMOVE(cache_resource, next);
+		rte_free(cache_resource);
+		DRV_LOG(DEBUG, "encap/decap resource %p: removed",
+			cache_resource);
+		return 0;
+	}
+	return 1;
+}
+
+/**
  * Remove the flow from the NIC but keeps it in memory.
  *
  * @param[in] dev
@@ -2136,11 +2226,8 @@
 		LIST_REMOVE(dev_flow, next);
 		if (dev_flow->dv.matcher)
 			flow_dv_matcher_release(dev, dev_flow);
-		if (dev_flow->dv.encap_decap_verbs_action) {
-			claim_zero(mlx5_glue->destroy_flow_action
-				(dev_flow->dv.encap_decap_verbs_action));
-			dev_flow->dv.encap_decap_verbs_action = NULL;
-		}
+		if (dev_flow->dv.encap_decap)
+			flow_dv_encap_decap_resource_release(dev_flow);
 		rte_free(dev_flow);
 	}
 }
-- 
1.8.3.1

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

* Re: [dpdk-dev] [PATCH v8 0/7] add encap and decap actions to Direct Verbs flow in MLX5 PMD
  2018-11-01  9:37             ` [dpdk-dev] [PATCH v8 " Dekel Peled
@ 2018-11-01 12:51               ` Shahaf Shuler
  2018-11-01 17:17                 ` Ferruh Yigit
  0 siblings, 1 reply; 94+ messages in thread
From: Shahaf Shuler @ 2018-11-01 12:51 UTC (permalink / raw)
  To: Dekel Peled, Yongseok Koh; +Cc: dev, Ori Kam

Thursday, November 1, 2018 11:37 AM, Dekel Peled:
> Subject: [dpdk-dev] [PATCH v8 0/7] add encap and decap actions to Direct
> Verbs flow in MLX5 PMD
> 
> This series adds support of encap and decap actions in DV format.
> L2 tunnel support for VXLAN and NVGRE, and L2/L3 tunnel support using raw
> data buffer.
> It is using the generic encapsulation framework from [1].
> 
> [1] "ethdev: add generic L2/L3 tunnel encapsulation actions"
> 
> https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmail
> s.dpdk.org%2Farchives%2Fdev%2F2018-
> October%2F114654.html&amp;data=02%7C01%7Cshahafs%40mellanox.com
> %7Cfcb2ee95be4d41ce3c6508d63fddcf5d%7Ca652971c7d2e4d9ba6a4d149256
> f461b%7C0%7C0%7C636766619229826892&amp;sdata=Lgp9Dl3jVsrSAbvrWIe
> 6QNfUvdBJir7opduWpcnBvN0%3D&amp;reserved=0

There were few compilation issues. Fixed locally, please have a look on the diff and confirm.

Ferruh - please note this patchset depends on the following patch to fix compilation issues:
https://patches.dpdk.org/patch/47676/

Series applied to next-net-mlx, thanks. 

> 
> ---
> v8:
> * Apply code review comments.
> v7:
> * Apply code review comments.
> * Add caching of encap decap actions.
> v6:
> * Adapt L2 tunnel to VXLAN and NVGRE.
> * Add encap/decap using raw data.
> v5:
> * Move DV actions code under common DV flag.
> v4:
> * Update in glue functions.
> v3:
> * Apply additional code review comments.
> v2:
> * Rebase on tip.
> * Apply code review comments.
> ---
> 
> Dekel Peled (7):
>   net/mlx5: add flow action functions to glue
>   net/mlx5: add VXLAN encap action to Direct Verbs
>   net/mlx5: add VXLAN decap action to Direct Verbs
>   net/mlx5: add NVGRE encap action to Direct Verbs
>   net/mlx5: add NVGRE decap action to Direct Verbs
>   net/mlx5: add raw data encap decap to Direct Verbs
>   net/mlx5: add caching of encap decap actions
> 
>  drivers/net/mlx5/Makefile       |   2 +-
>  drivers/net/mlx5/meson.build    |   2 +-
>  drivers/net/mlx5/mlx5.h         |   1 +
>  drivers/net/mlx5/mlx5_flow.h    |  30 ++
>  drivers/net/mlx5/mlx5_flow_dv.c | 783
> +++++++++++++++++++++++++++++++++++++++-
>  drivers/net/mlx5/mlx5_glue.c    |  38 ++
>  drivers/net/mlx5/mlx5_glue.h    |  10 +
>  7 files changed, 858 insertions(+), 8 deletions(-)
> 
> --
> 1.8.3.1

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

* Re: [dpdk-dev] [PATCH v8 0/7] add encap and decap actions to Direct Verbs flow in MLX5 PMD
  2018-11-01 12:51               ` Shahaf Shuler
@ 2018-11-01 17:17                 ` Ferruh Yigit
  2018-11-04  7:12                   ` Shahaf Shuler
  0 siblings, 1 reply; 94+ messages in thread
From: Ferruh Yigit @ 2018-11-01 17:17 UTC (permalink / raw)
  To: Shahaf Shuler, Dekel Peled, Yongseok Koh; +Cc: dev, Ori Kam

On 11/1/2018 12:51 PM, Shahaf Shuler wrote:
> Thursday, November 1, 2018 11:37 AM, Dekel Peled:
>> Subject: [dpdk-dev] [PATCH v8 0/7] add encap and decap actions to Direct
>> Verbs flow in MLX5 PMD
>>
>> This series adds support of encap and decap actions in DV format.
>> L2 tunnel support for VXLAN and NVGRE, and L2/L3 tunnel support using raw
>> data buffer.
>> It is using the generic encapsulation framework from [1].
>>
>> [1] "ethdev: add generic L2/L3 tunnel encapsulation actions"
>>
>> https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmail
>> s.dpdk.org%2Farchives%2Fdev%2F2018-
>> October%2F114654.html&amp;data=02%7C01%7Cshahafs%40mellanox.com
>> %7Cfcb2ee95be4d41ce3c6508d63fddcf5d%7Ca652971c7d2e4d9ba6a4d149256
>> f461b%7C0%7C0%7C636766619229826892&amp;sdata=Lgp9Dl3jVsrSAbvrWIe
>> 6QNfUvdBJir7opduWpcnBvN0%3D&amp;reserved=0
> 
> There were few compilation issues. Fixed locally, please have a look on the diff and confirm.
> 
> Ferruh - please note this patchset depends on the following patch to fix compilation issues:
> https://patches.dpdk.org/patch/47676/

The dependent patch looks OK, but I wonder why I don't see the build error.

mlx5_flow_dv.c has a big `#ifdef HAVE_IBV_FLOW_DV_SUPPORT` block

And `HAVE_IBV_FLOW_DV_SUPPORT` set:
if `infiniband/mlx5dv.h` has `mlx5dv_create_flow_action_packet_reformat()`

In the rdma-core I have this function is not set, so I guess I don't compile
this file at all.

What is the dependency to have `mlx5dv_create_flow_action_packet_reformat()`?
All the rdma-core versions I checked doesn't have this function, am I doing
something wrong? Or is direct verbs feature something not released yet?

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

* Re: [dpdk-dev] [PATCH v8 0/7] add encap and decap actions to Direct Verbs flow in MLX5 PMD
  2018-11-01 17:17                 ` Ferruh Yigit
@ 2018-11-04  7:12                   ` Shahaf Shuler
  0 siblings, 0 replies; 94+ messages in thread
From: Shahaf Shuler @ 2018-11-04  7:12 UTC (permalink / raw)
  To: Ferruh Yigit, Dekel Peled, Yongseok Koh; +Cc: dev, Ori Kam

Thursday, November 1, 2018 7:18 PM, Ferruh Yigit:
> 
> The dependent patch looks OK, but I wonder why I don't see the build error.
> 
> mlx5_flow_dv.c has a big `#ifdef HAVE_IBV_FLOW_DV_SUPPORT` block
> 
> And `HAVE_IBV_FLOW_DV_SUPPORT` set:
> if `infiniband/mlx5dv.h` has `mlx5dv_create_flow_action_packet_reformat()`
> 
> In the rdma-core I have this function is not set, so I guess I don't compile this
> file at all.
> 

That is probably why.

> What is the dependency to have
> `mlx5dv_create_flow_action_packet_reformat()`?
> All the rdma-core versions I checked doesn't have this function, am I doing
> something wrong? Or is direct verbs feature something not released yet?

This feature will be in rdma-core v21. It is introduced by commit:
a59af12 mlx5: Add packet reformat flow action

you can take the latest master from https://github.com/linux-rdma/rdma-core.git  

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

end of thread, other threads:[~2018-11-04  7:12 UTC | newest]

Thread overview: 94+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-27 14:50 [dpdk-dev] [PATCH 0/4] support DV encap and decap actions Dekel Peled
2018-09-27 14:50 ` [dpdk-dev] [PATCH 1/4] net/mlx5: add flow action functions to glue Dekel Peled
2018-10-02  1:02   ` Yongseok Koh
2018-10-03  6:59     ` Dekel Peled
2018-09-27 14:50 ` [dpdk-dev] [PATCH 2/4] net/mlx5: add definitions for DV encap and decap Dekel Peled
2018-10-03  2:58   ` Yongseok Koh
2018-10-03  7:27     ` Dekel Peled
2018-09-27 14:50 ` [dpdk-dev] [PATCH 3/4] net/mlx5: add DV encap L2 and L3 operations Dekel Peled
2018-10-03  6:58   ` Yongseok Koh
2018-10-03  8:35     ` Dekel Peled
2018-10-03  9:32       ` Yongseok Koh
2018-10-03 11:35         ` Dekel Peled
2018-10-03 11:47       ` Dekel Peled
2018-10-03 13:55         ` Dekel Peled
2018-09-27 14:50 ` [dpdk-dev] [PATCH 4/4] net/mlx5: add DV decap " Dekel Peled
2018-10-03  7:07   ` Yongseok Koh
2018-10-03 16:14     ` Dekel Peled
2018-10-07 14:25 ` [dpdk-dev] [PATCH v2 0/4] add support of Direct Verbs encap and decap actions Dekel Peled
2018-10-09 19:25   ` [dpdk-dev] [PATCH v3 " Dekel Peled
2018-10-10  8:35     ` [dpdk-dev] [PATCH v4 " Dekel Peled
2018-10-11 12:12       ` [dpdk-dev] [PATCH v5 " Dekel Peled
2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 0/6] add encap and decap actions to Direct Verbs flow in MLX5 PMD Dekel Peled
2018-10-29 10:03           ` Shahaf Shuler
2018-10-29 14:42             ` Dekel Peled
2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 0/7] " Dekel Peled
2018-10-31 15:09             ` Shahaf Shuler
2018-11-01  9:37             ` [dpdk-dev] [PATCH v8 " Dekel Peled
2018-11-01 12:51               ` Shahaf Shuler
2018-11-01 17:17                 ` Ferruh Yigit
2018-11-04  7:12                   ` Shahaf Shuler
2018-11-01  9:37             ` [dpdk-dev] [PATCH v8 1/7] net/mlx5: add flow action functions to glue Dekel Peled
2018-11-01  9:37             ` [dpdk-dev] [PATCH v8 2/7] net/mlx5: add VXLAN encap action to Direct Verbs Dekel Peled
2018-11-01  9:37             ` [dpdk-dev] [PATCH v8 3/7] net/mlx5: add VXLAN decap " Dekel Peled
2018-11-01  9:37             ` [dpdk-dev] [PATCH v8 4/7] net/mlx5: add NVGRE encap " Dekel Peled
2018-11-01  9:37             ` [dpdk-dev] [PATCH v8 5/7] net/mlx5: add NVGRE decap " Dekel Peled
2018-11-01  9:37             ` [dpdk-dev] [PATCH v8 6/7] net/mlx5: add raw data encap decap " Dekel Peled
2018-11-01  9:37             ` [dpdk-dev] [PATCH v8 7/7] net/mlx5: add caching of encap decap actions Dekel Peled
2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 1/7] net/mlx5: add flow action functions to glue Dekel Peled
2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 2/7] net/mlx5: add VXLAN encap action to Direct Verbs Dekel Peled
2018-10-31 15:09             ` Shahaf Shuler
2018-11-01  8:22               ` Dekel Peled
2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 3/7] net/mlx5: add VXLAN decap " Dekel Peled
2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 4/7] net/mlx5: add NVGRE encap " Dekel Peled
2018-10-31 15:09             ` Shahaf Shuler
2018-11-01  9:13               ` Dekel Peled
2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 5/7] net/mlx5: add NVGRE decap " Dekel Peled
2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 6/7] net/mlx5: add raw data encap decap " Dekel Peled
2018-10-31  7:10           ` [dpdk-dev] [PATCH v7 7/7] net/mlx5: add caching of encap decap actions Dekel Peled
2018-10-31 15:09             ` Shahaf Shuler
2018-11-01  9:15               ` Dekel Peled
2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 1/6] net/mlx5: add flow action functions to glue Dekel Peled
2018-10-29 10:03           ` Shahaf Shuler
2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 2/6] net/mlx5: add VXLAN encap action to Direct Verbs Dekel Peled
2018-10-29 10:03           ` Shahaf Shuler
2018-10-29 16:44             ` Dekel Peled
2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 3/6] net/mlx5: add VXLAN decap " Dekel Peled
2018-10-29 10:03           ` Shahaf Shuler
2018-10-29 16:46             ` Dekel Peled
2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 4/6] net/mlx5: add NVGRE encap " Dekel Peled
2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 5/6] net/mlx5: add NVGRE decap " Dekel Peled
2018-10-25 20:08         ` [dpdk-dev] [PATCH v6 6/6] net/mlx5: add raw data encap decap " Dekel Peled
2018-10-29 10:03           ` Shahaf Shuler
2018-10-29 16:54             ` Dekel Peled
2018-10-11 12:12       ` [dpdk-dev] [PATCH v5 1/4] net/mlx5: add flow action functions to glue Dekel Peled
2018-10-11 17:05         ` Yongseok Koh
2018-10-11 12:12       ` [dpdk-dev] [PATCH v5 2/4] net/mlx5: add Direct Verbs encap and decap defs Dekel Peled
2018-10-11 12:12       ` [dpdk-dev] [PATCH v5 3/4] net/mlx5: add L2 and L3 encap to Direct Verbs flow Dekel Peled
2018-10-11 12:12       ` [dpdk-dev] [PATCH v5 4/4] net/mlx5: add L2 and L3 decap " Dekel Peled
2018-10-10  8:35     ` [dpdk-dev] [PATCH v4 1/4] net/mlx5: add flow action functions to glue Dekel Peled
2018-10-10 21:22       ` Yongseok Koh
2018-10-10  8:35     ` [dpdk-dev] [PATCH v4 2/4] net/mlx5: add Direct Verbs encap and decap defs Dekel Peled
2018-10-10  8:35     ` [dpdk-dev] [PATCH v4 3/4] net/mlx5: add L2 and L3 encap to Direct Verbs flow Dekel Peled
2018-10-10  8:35     ` [dpdk-dev] [PATCH v4 4/4] net/mlx5: add L2 and L3 decap " Dekel Peled
2018-10-09 19:25   ` [dpdk-dev] [PATCH v3 1/4] net/mlx5: add flow action functions to glue Dekel Peled
2018-10-10  0:36     ` Yongseok Koh
2018-10-10  7:41       ` Dekel Peled
2018-10-10  0:38     ` Yongseok Koh
2018-10-09 19:25   ` [dpdk-dev] [PATCH v3 2/4] net/mlx5: add Direct Verbs encap and decap defs Dekel Peled
2018-10-10  0:40     ` Yongseok Koh
2018-10-09 19:25   ` [dpdk-dev] [PATCH v3 3/4] net/mlx5: add L2 and L3 encap to Direct Verbs flow Dekel Peled
2018-10-10  0:43     ` Yongseok Koh
2018-10-09 19:25   ` [dpdk-dev] [PATCH v3 4/4] net/mlx5: add L2 and L3 decap " Dekel Peled
2018-10-10  0:45     ` Yongseok Koh
2018-10-07 14:25 ` [dpdk-dev] [PATCH v2 1/4] net/mlx5: add flow action functions to glue Dekel Peled
2018-10-08 19:43   ` Yongseok Koh
2018-10-09 18:49     ` Dekel Peled
2018-10-07 14:25 ` [dpdk-dev] [PATCH v2 2/4] net/mlx5: add Direct Verbs encap and decap defs Dekel Peled
2018-10-08 20:46   ` Yongseok Koh
2018-10-07 14:25 ` [dpdk-dev] [PATCH v2 3/4] net/mlx5: add L2 and L3 encap to Direct Verbs flow Dekel Peled
2018-10-08 21:04   ` Yongseok Koh
2018-10-09 15:55     ` Dekel Peled
2018-10-07 14:25 ` [dpdk-dev] [PATCH v2 4/4] net/mlx5: add L2 and L3 decap " Dekel Peled
2018-10-08 21:19   ` Yongseok Koh
2018-10-09 16:56     ` Dekel Peled

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