[v2,4/5] net/mlx5: update modify actions support for E-Switch mirror
diff mbox series

Message ID 1610447359-411658-5-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/checkpatch success coding style OK

Commit Message

Jiawei Wang Jan. 12, 2021, 10:29 a.m. UTC
While there's the modify action and sample action with ratio=1
in the E-Switch flow, and modify action is after the sample
action, means that the modify should only impact on after sample.
MLX5 PMD will monitor the above case and split the E-Switch flow
into two sub flows, similar as sample flow did before:

 - the prefix sub flow with all actions preceding the sample and the
   sample action itself, also append the new jump action after sample
   in the prefix sub flow;
 - the suffix sub flow with the modify action and other actions
   following the sample action.

The flow split as below:

Original flow: items / actions pre / sample / modify / actions sfx
    prefix sub flow -
    items / actions pre / set_tag action / sample / jump
    suffix sub flow -
    tag_item / modify / actions sfx

Signed-off-by: Jiawei Wang <jiaweiw@nvidia.com>
Acked-by: Viacheslav Ovsiienko <viacheslavo@nvidia.com>
---
 drivers/net/mlx5/mlx5_flow.c    | 175 ++++++++++++++++++++++++++++------------
 drivers/net/mlx5/mlx5_flow_dv.c |  10 ---
 2 files changed, 123 insertions(+), 62 deletions(-)

Patch
diff mbox series

diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 055474b..df79318 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -4490,6 +4490,8 @@  struct mlx5_hlist_entry *
  *   Pointer to the position of the matched action if exists, otherwise is -1.
  * @param[out] qrss_action_pos
  *   Pointer to the position of the Queue/RSS action if exists, otherwise is -1.
+ * @param[out] modify_after_mirror
+ *   Pointer to the flag of modify action after FDB mirroring.
  *
  * @return
  *   > 0 the total number of actions.
@@ -4499,13 +4501,15 @@  struct mlx5_hlist_entry *
 flow_check_match_action(const struct rte_flow_action actions[],
 			const struct rte_flow_attr *attr,
 			enum rte_flow_action_type action,
-			int *match_action_pos, int *qrss_action_pos)
+			int *match_action_pos, int *qrss_action_pos,
+			int *modify_after_mirror)
 {
 	const struct rte_flow_action_sample *sample;
 	int actions_n = 0;
 	uint32_t ratio = 0;
 	int sub_type = 0;
 	int flag = 0;
+	int fdb_mirror = 0;
 
 	*match_action_pos = -1;
 	*qrss_action_pos = -1;
@@ -4514,25 +4518,53 @@  struct mlx5_hlist_entry *
 			flag = 1;
 			*match_action_pos = actions_n;
 		}
-		if (actions->type == RTE_FLOW_ACTION_TYPE_QUEUE ||
-		    actions->type == RTE_FLOW_ACTION_TYPE_RSS)
+		switch (actions->type) {
+		case RTE_FLOW_ACTION_TYPE_QUEUE:
+		case RTE_FLOW_ACTION_TYPE_RSS:
 			*qrss_action_pos = actions_n;
-		if (actions->type == RTE_FLOW_ACTION_TYPE_SAMPLE) {
+			break;
+		case RTE_FLOW_ACTION_TYPE_SAMPLE:
 			sample = actions->conf;
 			ratio = sample->ratio;
 			sub_type = ((const struct rte_flow_action *)
 					(sample->actions))->type;
+			if (ratio == 1 && attr->transfer)
+				fdb_mirror = 1;
+			break;
+		case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:
+		case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:
+		case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
+		case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
+		case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:
+		case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:
+		case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
+		case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
+		case RTE_FLOW_ACTION_TYPE_DEC_TTL:
+		case RTE_FLOW_ACTION_TYPE_SET_TTL:
+		case RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ:
+		case RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ:
+		case RTE_FLOW_ACTION_TYPE_INC_TCP_ACK:
+		case RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK:
+		case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP:
+		case RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP:
+		case RTE_FLOW_ACTION_TYPE_FLAG:
+		case RTE_FLOW_ACTION_TYPE_MARK:
+		case RTE_FLOW_ACTION_TYPE_SET_META:
+		case RTE_FLOW_ACTION_TYPE_SET_TAG:
+			if (fdb_mirror)
+				*modify_after_mirror = 1;
+			break;
+		default:
+			break;
 		}
 		actions_n++;
 	}
-	if (flag && action == RTE_FLOW_ACTION_TYPE_SAMPLE && attr->transfer) {
-		if (ratio == 1) {
-			/* FDB mirroring uses the destination array to implement
-			 * instead of FLOW_SAMPLER object.
-			 */
-			if (sub_type != RTE_FLOW_ACTION_TYPE_END)
-				flag = 0;
-		}
+	if (flag && fdb_mirror && !*modify_after_mirror) {
+		/* FDB mirroring uses the destination array to implement
+		 * instead of FLOW_SAMPLER object.
+		 */
+		if (sub_type != RTE_FLOW_ACTION_TYPE_END)
+			flag = 0;
 	}
 	/* Count RTE_FLOW_ACTION_TYPE_END. */
 	return flag ? actions_n + 1 : 0;
@@ -4567,6 +4599,8 @@  struct mlx5_hlist_entry *
  *   The sample action position.
  * @param[in] qrss_action_pos
  *   The Queue/RSS action position.
+ * @param[in] jump_table
+ *   Add extra jump action flag.
  * @param[out] error
  *   Perform verbose error reporting if not NULL.
  *
@@ -4584,14 +4618,17 @@  struct mlx5_hlist_entry *
 		       int actions_n,
 		       int sample_action_pos,
 		       int qrss_action_pos,
+		       int jump_table,
 		       struct rte_flow_error *error)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_rte_flow_action_set_tag *set_tag;
 	struct mlx5_rte_flow_item_tag *tag_spec;
 	struct mlx5_rte_flow_item_tag *tag_mask;
+	struct rte_flow_action_jump *jump_action;
 	uint32_t tag_id = 0;
 	int index;
+	int append_index = 0;
 	int ret;
 
 	if (sample_action_pos < 0)
@@ -4599,13 +4636,37 @@  struct mlx5_hlist_entry *
 					  RTE_FLOW_ERROR_TYPE_ACTION,
 					  NULL, "invalid position of sample "
 					  "action in list");
+	/* Prepare the actions for prefix and suffix flow. */
+	if (qrss_action_pos >= 0 && qrss_action_pos < sample_action_pos) {
+		index = qrss_action_pos;
+		/* Put the preceding the Queue/RSS action into prefix flow. */
+		if (index != 0)
+			memcpy(actions_pre, actions,
+			       sizeof(struct rte_flow_action) * index);
+		/* Put others preceding the sample action into prefix flow. */
+		if (sample_action_pos > index + 1)
+			memcpy(actions_pre + index, actions + index + 1,
+			       sizeof(struct rte_flow_action) *
+			       (sample_action_pos - index - 1));
+		index = sample_action_pos - 1;
+		/* Put Queue/RSS action into Suffix flow. */
+		memcpy(actions_sfx, actions + qrss_action_pos,
+		       sizeof(struct rte_flow_action));
+		actions_sfx++;
+	} else {
+		index = sample_action_pos;
+		if (index != 0)
+			memcpy(actions_pre, actions,
+			       sizeof(struct rte_flow_action) * index);
+	}
 	/* 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.
+	 * add an extra tag action for NIC-RX and E-Switch Domain.
 	 */
 	if (add_tag) {
 		/* Prepare the prefix tag action. */
-		set_tag = (void *)(actions_pre + actions_n + 1);
+		append_index++;
+		set_tag = (void *)(actions_pre + actions_n + append_index);
 		ret = mlx5_flow_get_reg_id(dev, MLX5_APP_TAG, 0, error);
 		if (ret < 0)
 			return ret;
@@ -4630,31 +4691,7 @@  struct mlx5_hlist_entry *
 			.type = (enum rte_flow_item_type)
 				RTE_FLOW_ITEM_TYPE_END,
 		};
-	}
-	/* Prepare the actions for prefix and suffix flow. */
-	if (qrss_action_pos >= 0 && qrss_action_pos < sample_action_pos) {
-		index = qrss_action_pos;
-		/* Put the preceding the Queue/RSS action into prefix flow. */
-		if (index != 0)
-			memcpy(actions_pre, actions,
-			       sizeof(struct rte_flow_action) * index);
-		/* Put others preceding the sample action into prefix flow. */
-		if (sample_action_pos > index + 1)
-			memcpy(actions_pre + index, actions + index + 1,
-			       sizeof(struct rte_flow_action) *
-			       (sample_action_pos - index - 1));
-		index = sample_action_pos - 1;
-		/* Put Queue/RSS action into Suffix flow. */
-		memcpy(actions_sfx, actions + qrss_action_pos,
-		       sizeof(struct rte_flow_action));
-		actions_sfx++;
-	} else {
-		index = sample_action_pos;
-		if (index != 0)
-			memcpy(actions_pre, actions,
-			       sizeof(struct rte_flow_action) * index);
-	}
-	if (add_tag) {
+		/* Prepare the tag action in prefix subflow. */
 		actions_pre[index++] =
 			(struct rte_flow_action){
 			.type = (enum rte_flow_action_type)
@@ -4665,6 +4702,22 @@  struct mlx5_hlist_entry *
 	memcpy(actions_pre + index, actions + sample_action_pos,
 	       sizeof(struct rte_flow_action));
 	index += 1;
+	/* For the modify action after the sample action in E-Switch mirroring,
+	 * Add the extra jump action in prefix subflow and jump into the next
+	 * table, then do the modify action in the new table.
+	 */
+	if (jump_table) {
+		/* Prepare the prefix jump action. */
+		append_index++;
+		jump_action = (void *)(actions_pre + actions_n + append_index);
+		jump_action->group = jump_table;
+		actions_pre[index++] =
+			(struct rte_flow_action){
+			.type = (enum rte_flow_action_type)
+				RTE_FLOW_ACTION_TYPE_JUMP,
+			.conf = jump_action,
+		};
+	}
 	actions_pre[index] = (struct rte_flow_action){
 		.type = (enum rte_flow_action_type)
 			RTE_FLOW_ACTION_TYPE_END,
@@ -5068,12 +5121,16 @@  struct mlx5_hlist_entry *
 	int sample_action_pos;
 	int qrss_action_pos;
 	int add_tag = 0;
+	int modify_after_mirror = 0;
+	uint16_t jump_table = 0;
+	const uint32_t next_ft_step = 1;
 	int ret = 0;
 
 	if (priv->sampler_en)
 		actions_n = flow_check_match_action(actions, attr,
 					RTE_FLOW_ACTION_TYPE_SAMPLE,
-					&sample_action_pos, &qrss_action_pos);
+					&sample_action_pos, &qrss_action_pos,
+					&modify_after_mirror);
 	if (actions_n) {
 		/* The prefix actions must includes sample, tag, end. */
 		act_size = sizeof(struct rte_flow_action) * (actions_n * 2 + 1)
@@ -5097,16 +5154,23 @@  struct mlx5_hlist_entry *
 		if (add_tag)
 			sfx_items = (struct rte_flow_item *)((char *)sfx_actions
 					+ act_size);
+		if (modify_after_mirror)
+			jump_table = attr->group * MLX5_FLOW_TABLE_FACTOR +
+				     next_ft_step;
 		pre_actions = sfx_actions + actions_n;
 		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);
+						qrss_action_pos, jump_table,
+						error);
 		if (tag_id < 0 || (add_tag && !tag_id)) {
 			ret = -rte_errno;
 			goto exit;
 		}
+		if (modify_after_mirror)
+			flow_split_info->skip_scale =
+					1 << MLX5_SCALE_JUMP_FLOW_GROUP_BIT;
 		/* Add the prefix subflow. */
 		ret = flow_create_split_inner(dev, flow, &dev_flow, attr,
 					      items, pre_actions,
@@ -5117,21 +5181,28 @@  struct mlx5_hlist_entry *
 		}
 		dev_flow->handle->split_flow_id = tag_id;
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
-		/* Set the sfx group attr. */
-		sample_res = (struct mlx5_flow_dv_sample_resource *)
-					dev_flow->dv.sample_res;
-		sfx_tbl = (struct mlx5_flow_tbl_resource *)
-					sample_res->normal_path_tbl;
-		sfx_tbl_data = container_of(sfx_tbl,
-					struct mlx5_flow_tbl_data_entry, tbl);
-		sfx_attr.group = sfx_attr.transfer ?
-					(sfx_tbl_data->table_id - 1) :
-					 sfx_tbl_data->table_id;
+		if (!modify_after_mirror) {
+			/* Set the sfx group attr. */
+			sample_res = (struct mlx5_flow_dv_sample_resource *)
+						dev_flow->dv.sample_res;
+			sfx_tbl = (struct mlx5_flow_tbl_resource *)
+						sample_res->normal_path_tbl;
+			sfx_tbl_data = container_of(sfx_tbl,
+						struct mlx5_flow_tbl_data_entry,
+						tbl);
+			sfx_attr.group = sfx_attr.transfer ?
+						(sfx_tbl_data->table_id - 1) :
+						sfx_tbl_data->table_id;
+		} else {
+			MLX5_ASSERT(attr->transfer);
+			sfx_attr.group = jump_table;
+		}
 		flow_split_info->prefix_layers =
 				flow_get_prefix_layer_flags(dev_flow);
 		flow_split_info->prefix_mark = dev_flow->handle->mark;
 		/* Suffix group level already be scaled with factor, set
-		 * skip_scale to 1 to avoid scale again in translation.
+		 * MLX5_SCALE_FLOW_GROUP_BIT of skip_scale to 1 to avoid scale
+		 * again in translation.
 		 */
 		flow_split_info->skip_scale = 1 << MLX5_SCALE_FLOW_GROUP_BIT;
 #endif
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 63569ad..4b191fd 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -3600,8 +3600,6 @@  struct mlx5_cache_entry *
 					    (dev, &res, dev_flow, error);
 }
 
-static int fdb_mirror_limit;
-
 /**
  * Validate the modify-header actions.
  *
@@ -3629,12 +3627,6 @@  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_limit)
-		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
-					  "can't support sample action before"
-					  " modify action for E-Switch"
-					  " mirroring");
 	return 0;
 }
 
@@ -4365,7 +4357,6 @@  struct mlx5_hlist_entry *
 	int actions_n = 0;
 	int ret;
 
-	fdb_mirror_limit = 0;
 	if (!sample)
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, action,
@@ -4482,7 +4473,6 @@  struct mlx5_hlist_entry *
 						  "E-Switch doesn't support "
 						  "any optional action "
 						  "for sampling");
-		fdb_mirror_limit = 1;
 		if (sub_action_flags & MLX5_FLOW_ACTION_QUEUE)
 			return rte_flow_error_set(error, ENOTSUP,
 						  RTE_FLOW_ERROR_TYPE_ACTION,