[v2,2/5] net/mlx5: support E-Switch mirroring and jump in one flow
diff mbox series

Message ID 1610447359-411658-3-git-send-email-jiaweiw@nvidia.com
State New
Delegated to: Raslan Darawsheh
Headers show
Series
  • Add the E-Switch mirroring and jump supports
Related show

Checks

Context Check Description
ci/intel-Testing success Testing PASS
ci/checkpatch success coding style OK

Commit Message

Jiawei Wang Jan. 12, 2021, 10:29 a.m. UTC
mlx5 E-Switch mirroring is implemented as multiple destination array in
one steering table. The array currently supports only port ID as
destination actions.

This patch adds the jump action support to the array as one of
destination.
The packets can be mirrored to the port and jump to the next table in the
same destination array allowing to continue handling in the new table.

For example:
    set sample_actions 0 port_id id 1 / end
    flow create 0 ingress transfer pattern eth / end actions
    sample ratio 1 index 0 / jump group 1 / end
    flow create 1 ingress transfer group 1 pattern eth / end actions
    set_mac_dst mac_addr 00:aa:bb:cc:dd:ee / port_id id 2 / end

The flow results all the matched ingress packets are mirrored
to port id 1 and go to group 1. In the group 1, packets are modified
with the destination mac and sent to port id 2.

Signed-off-by: Jiawei Wang <jiaweiw@nvidia.com>
Acked-by: Viacheslav Ovsiienko <viacheslavo@nvidia.com>
---
 drivers/net/mlx5/mlx5_flow.c    | 36 ++++++++++--------
 drivers/net/mlx5/mlx5_flow.h    |  2 +
 drivers/net/mlx5/mlx5_flow_dv.c | 81 +++++++++++++++++++++++++++++------------
 3 files changed, 80 insertions(+), 39 deletions(-)

Patch
diff mbox series

diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 2a4073c..217090a 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -4503,7 +4503,6 @@  struct mlx5_hlist_entry *
 {
 	const struct rte_flow_action_sample *sample;
 	int actions_n = 0;
-	int jump_flag = 0;
 	uint32_t ratio = 0;
 	int sub_type = 0;
 	int flag = 0;
@@ -4518,8 +4517,6 @@  struct mlx5_hlist_entry *
 		if (actions->type == RTE_FLOW_ACTION_TYPE_QUEUE ||
 		    actions->type == RTE_FLOW_ACTION_TYPE_RSS)
 			*qrss_action_pos = actions_n;
-		if (actions->type == RTE_FLOW_ACTION_TYPE_JUMP)
-			jump_flag = 1;
 		if (actions->type == RTE_FLOW_ACTION_TYPE_SAMPLE) {
 			sample = actions->conf;
 			ratio = sample->ratio;
@@ -4530,10 +4527,10 @@  struct mlx5_hlist_entry *
 	}
 	if (flag && action == RTE_FLOW_ACTION_TYPE_SAMPLE && attr->transfer) {
 		if (ratio == 1) {
-			/* JUMP Action not support for Mirroring;
-			 * Mirroring support multi-destination;
+			/* FDB mirroring uses the destination array to implement
+			 * instead of FLOW_SAMPLER object.
 			 */
-			if (!jump_flag && sub_type != RTE_FLOW_ACTION_TYPE_END)
+			if (sub_type != RTE_FLOW_ACTION_TYPE_END)
 				flag = 0;
 		}
 	}
@@ -4554,8 +4551,8 @@  struct mlx5_hlist_entry *
  *
  * @param dev
  *   Pointer to Ethernet device.
- * @param[in] fdb_tx
- *   FDB egress flow flag.
+ * @param[in] add_tag
+ *   Add extra tag action flag.
  * @param[out] sfx_items
  *   Suffix flow match items (list terminated by the END pattern item).
  * @param[in] actions
@@ -4579,7 +4576,7 @@  struct mlx5_hlist_entry *
  */
 static int
 flow_sample_split_prep(struct rte_eth_dev *dev,
-		       uint32_t fdb_tx,
+		       int add_tag,
 		       struct rte_flow_item sfx_items[],
 		       const struct rte_flow_action actions[],
 		       struct rte_flow_action actions_sfx[],
@@ -4602,7 +4599,11 @@  struct mlx5_hlist_entry *
 					  RTE_FLOW_ERROR_TYPE_ACTION,
 					  NULL, "invalid position of sample "
 					  "action in list");
-	if (!fdb_tx) {
+	/* For CX5, add an extra tag action for NIC-RX and E-Switch ingress.
+	 * For CX6DX and above, metadata registers Cx preserve their value,
+	 * add an extra tag action for NIC-RX and E-Switch ingress and egress.
+	 */
+	if (add_tag) {
 		/* Prepare the prefix tag action. */
 		set_tag = (void *)(actions_pre + actions_n + 1);
 		ret = mlx5_flow_get_reg_id(dev, MLX5_APP_TAG, 0, error);
@@ -4653,8 +4654,7 @@  struct mlx5_hlist_entry *
 			memcpy(actions_pre, actions,
 			       sizeof(struct rte_flow_action) * index);
 	}
-	/* Add the extra tag action for NIC-RX and E-Switch ingress. */
-	if (!fdb_tx) {
+	if (add_tag) {
 		actions_pre[index++] =
 			(struct rte_flow_action){
 			.type = (enum rte_flow_action_type)
@@ -5067,6 +5067,7 @@  struct mlx5_hlist_entry *
 	int actions_n = 0;
 	int sample_action_pos;
 	int qrss_action_pos;
+	int add_tag = 0;
 	int ret = 0;
 
 	if (priv->sampler_en)
@@ -5088,16 +5089,21 @@  struct mlx5_hlist_entry *
 						  "sample flow");
 		/* The representor_id is -1 for uplink. */
 		fdb_tx = (attr->transfer && priv->representor_id != -1);
-		if (!fdb_tx)
+		/*
+		 * When reg_c_preserve is set, metadata registers Cx preserve
+		 * their value even through packet duplication.
+		 */
+		add_tag = (!fdb_tx || priv->config.hca_attr.reg_c_preserve);
+		if (add_tag)
 			sfx_items = (struct rte_flow_item *)((char *)sfx_actions
 					+ act_size);
 		pre_actions = sfx_actions + actions_n;
-		tag_id = flow_sample_split_prep(dev, fdb_tx, sfx_items,
+		tag_id = flow_sample_split_prep(dev, add_tag, sfx_items,
 						actions, sfx_actions,
 						pre_actions, actions_n,
 						sample_action_pos,
 						qrss_action_pos, error);
-		if (tag_id < 0 || (!fdb_tx && !tag_id)) {
+		if (tag_id < 0 || (add_tag && !tag_id)) {
 			ret = -rte_errno;
 			goto exit;
 		}
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index ee85c9d..18d5cfc 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -552,6 +552,7 @@  struct mlx5_flow_sub_actions_list {
 	void *dr_cnt_action;
 	void *dr_port_id_action;
 	void *dr_encap_action;
+	void *dr_jump_action;
 };
 
 /* Sample sub-actions resource list. */
@@ -561,6 +562,7 @@  struct mlx5_flow_sub_actions_idx {
 	uint32_t cnt;
 	uint32_t rix_port_id_action; /**< Index to port ID action resource. */
 	uint32_t rix_encap_decap; /**< Index to encap/decap resource. */
+	uint32_t rix_jump; /**< Index to the jump action resource. */
 };
 
 /* Sample action resource structure. */
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index e4736ee..d82d22e 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -76,7 +76,7 @@ 
 
 static int
 flow_dv_encap_decap_resource_release(struct rte_eth_dev *dev,
-				      uint32_t encap_decap_idx);
+				     uint32_t encap_decap_idx);
 
 static int
 flow_dv_port_id_action_resource_release(struct rte_eth_dev *dev,
@@ -84,6 +84,10 @@ 
 static void
 flow_dv_shared_rss_action_release(struct rte_eth_dev *dev, uint32_t srss);
 
+static int
+flow_dv_jump_tbl_resource_release(struct rte_eth_dev *dev,
+				  uint32_t rix_jump);
+
 /**
  * Initialize flow attributes structure according to flow items' types.
  *
@@ -3596,7 +3600,7 @@  struct mlx5_cache_entry *
 					    (dev, &res, dev_flow, error);
 }
 
-static int fdb_mirror;
+static int fdb_mirror_limit;
 
 /**
  * Validate the modify-header actions.
@@ -3625,7 +3629,7 @@  struct mlx5_cache_entry *
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't have encap action before"
 					  " modify action");
-	if ((action_flags & MLX5_FLOW_ACTION_SAMPLE) && fdb_mirror)
+	if ((action_flags & MLX5_FLOW_ACTION_SAMPLE) && fdb_mirror_limit)
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't support sample action before"
@@ -3961,12 +3965,6 @@  struct mlx5_cache_entry *
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "jump with meter not support");
-	if ((action_flags & MLX5_FLOW_ACTION_SAMPLE) && fdb_mirror)
-		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
-					  "E-Switch mirroring can't support"
-					  " Sample action and jump action in"
-					  " same flow now");
 	if (!action->conf)
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION_CONF,
@@ -4366,8 +4364,8 @@  struct mlx5_hlist_entry *
 	uint16_t queue_index = 0xFFFF;
 	int actions_n = 0;
 	int ret;
-	fdb_mirror = 0;
 
+	fdb_mirror_limit = 0;
 	if (!sample)
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, action,
@@ -4484,7 +4482,7 @@  struct mlx5_hlist_entry *
 						  "E-Switch doesn't support "
 						  "any optional action "
 						  "for sampling");
-		fdb_mirror = 1;
+		fdb_mirror_limit = 1;
 		if (sub_action_flags & MLX5_FLOW_ACTION_QUEUE)
 			return rte_flow_error_set(error, ENOTSUP,
 						  RTE_FLOW_ERROR_TYPE_ACTION,
@@ -8706,6 +8704,10 @@  struct mlx5_hlist_entry *
 		flow_dv_counter_free(dev, act_res->cnt);
 		act_res->cnt = 0;
 	}
+	if (act_res->rix_jump) {
+		flow_dv_jump_tbl_resource_release(dev, act_res->rix_jump);
+		act_res->rix_jump = 0;
+	}
 }
 
 int
@@ -8918,6 +8920,7 @@  struct mlx5_cache_entry *
 	struct mlx5dv_dr_domain *domain;
 	uint32_t idx = 0, res_idx = 0;
 	struct rte_flow_error *error = ctx->error;
+	uint64_t action_flags;
 	int ret;
 
 	/* Register new destination array resource. */
@@ -8951,19 +8954,31 @@  struct mlx5_cache_entry *
 		}
 		dest_attr[idx]->type = MLX5DV_DR_ACTION_DEST;
 		sample_act = &resource->sample_act[idx];
-		if (sample_act->action_flags == MLX5_FLOW_ACTION_QUEUE) {
+		action_flags = sample_act->action_flags;
+		switch (action_flags) {
+		case MLX5_FLOW_ACTION_QUEUE:
 			dest_attr[idx]->dest = sample_act->dr_queue_action;
-		} else if (sample_act->action_flags ==
-			  (MLX5_FLOW_ACTION_PORT_ID | MLX5_FLOW_ACTION_ENCAP)) {
+			break;
+		case (MLX5_FLOW_ACTION_PORT_ID | MLX5_FLOW_ACTION_ENCAP):
 			dest_attr[idx]->type = MLX5DV_DR_ACTION_DEST_REFORMAT;
 			dest_attr[idx]->dest_reformat = &dest_reformat[idx];
 			dest_attr[idx]->dest_reformat->reformat =
 					sample_act->dr_encap_action;
 			dest_attr[idx]->dest_reformat->dest =
 					sample_act->dr_port_id_action;
-		} else if (sample_act->action_flags ==
-			   MLX5_FLOW_ACTION_PORT_ID) {
+			break;
+		case MLX5_FLOW_ACTION_PORT_ID:
 			dest_attr[idx]->dest = sample_act->dr_port_id_action;
+			break;
+		case MLX5_FLOW_ACTION_JUMP:
+			dest_attr[idx]->dest = sample_act->dr_jump_action;
+			break;
+		default:
+			rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ACTION,
+					   NULL,
+					   "unsupported actions type");
+			goto error;
 		}
 	}
 	/* create a dest array actioin */
@@ -9000,6 +9015,10 @@  struct mlx5_cache_entry *
 			!flow_dv_port_id_action_resource_release(dev,
 				act_res->rix_port_id_action))
 			act_res->rix_port_id_action = 0;
+		if (act_res->rix_jump &&
+			!flow_dv_jump_tbl_resource_release(dev,
+				act_res->rix_jump))
+			act_res->rix_jump = 0;
 		if (dest_attr[idx])
 			mlx5_free(dest_attr[idx]);
 	}
@@ -9336,6 +9355,14 @@  struct mlx5_cache_entry *
 			sample_act->dr_port_id_action =
 				dev_flow->dv.port_id_action->action;
 		}
+		if (sample_act->action_flags & MLX5_FLOW_ACTION_JUMP) {
+			normal_idx++;
+			mdest_res->sample_idx[dest_index].rix_jump =
+				dev_flow->handle->rix_jump;
+			sample_act->dr_jump_action =
+				dev_flow->dv.jump->action;
+			dev_flow->handle->rix_jump = 0;
+		}
 		sample_act->actions_num = normal_idx;
 		/* update sample action resource into first index of array */
 		mdest_res->ft_type = res->ft_type;
@@ -10094,6 +10121,8 @@  struct mlx5_cache_entry *
 					dev_flow->dv.jump->action;
 			action_flags |= MLX5_FLOW_ACTION_JUMP;
 			dev_flow->handle->fate_action = MLX5_FLOW_FATE_JUMP;
+			sample_act->action_flags |= MLX5_FLOW_ACTION_JUMP;
+			num_of_dest++;
 			break;
 		case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:
 		case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:
@@ -10316,7 +10345,8 @@  struct mlx5_cache_entry *
 	 * So need remove the original these actions in the flow and only
 	 * use the sample action instead of.
 	 */
-	if (num_of_dest > 1 && sample_act->dr_port_id_action) {
+	if (num_of_dest > 1 &&
+	    (sample_act->dr_port_id_action || sample_act->dr_jump_action)) {
 		int i;
 		void *temp_actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS] = {0};
 
@@ -10326,6 +10356,9 @@  struct mlx5_cache_entry *
 				dev_flow->dv.actions[i]) ||
 				(sample_act->dr_port_id_action &&
 				sample_act->dr_port_id_action ==
+				dev_flow->dv.actions[i]) ||
+				(sample_act->dr_jump_action &&
+				sample_act->dr_jump_action ==
 				dev_flow->dv.actions[i]))
 				continue;
 			temp_actions[tmp_actions_n++] = dev_flow->dv.actions[i];
@@ -10924,21 +10957,21 @@  struct mlx5_cache_entry *
  *
  * @param dev
  *   Pointer to Ethernet device.
- * @param handle
- *   Pointer to mlx5_flow_handle.
+ * @param rix_jump
+ *   Index to the jump action resource.
  *
  * @return
  *   1 while a reference on it exists, 0 when freed.
  */
 static int
 flow_dv_jump_tbl_resource_release(struct rte_eth_dev *dev,
-				  struct mlx5_flow_handle *handle)
+				  uint32_t rix_jump)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_flow_tbl_data_entry *tbl_data;
 
 	tbl_data = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_JUMP],
-			     handle->rix_jump);
+				  rix_jump);
 	if (!tbl_data)
 		return 0;
 	return flow_dv_tbl_resource_release(MLX5_SH(dev), &tbl_data->tbl);
@@ -11092,7 +11125,7 @@  struct mlx5_cache_entry *
 		mlx5_hrxq_release(dev, handle->rix_hrxq);
 		break;
 	case MLX5_FLOW_FATE_JUMP:
-		flow_dv_jump_tbl_resource_release(dev, handle);
+		flow_dv_jump_tbl_resource_release(dev, handle->rix_jump);
 		break;
 	case MLX5_FLOW_FATE_PORT_ID:
 		flow_dv_port_id_action_resource_release(dev,
@@ -11188,8 +11221,8 @@  struct mlx5_cache_entry *
  *
  * @param dev
  *   Pointer to Ethernet device.
- * @param handle
- *   Pointer to mlx5_flow_handle.
+ * @param port_id
+ *   Index to port ID action resource.
  *
  * @return
  *   1 while a reference on it exists, 0 when freed.