DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [RFC 0/4] Add the E-Switch mirroring and jump supports
@ 2020-12-15  7:49 Jiawei Wang
  2020-12-15  7:49 ` [dpdk-dev] [RFC 1/4] common/mlx5: query register c preserve capability via DevX Jiawei Wang
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Jiawei Wang @ 2020-12-15  7:49 UTC (permalink / raw)
  To: viacheslavo, matan, orika; +Cc: dev, rasland

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 RFC adds the below supports for MLX5 PMD driver:
  - Supports the metadata register Cx preserve capability query.
  - Supports the jump action support as one of destination of array.
  - Supports the modify action only impact on the one of destination.

The examples for the E-Switch flow use case and result as below:
    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.

Jiawei Wang (4):
  common/mlx5: query register c preserve capability via DevX
  net/mlx5: support E-Switch mirroring and jump in one flow
  net/mlx5: extend the skip scale flag
  net/mlx5: supports modify one port in E-Switch mirroring

 drivers/common/mlx5/mlx5_devx_cmds.c |   2 +
 drivers/common/mlx5/mlx5_devx_cmds.h |   1 +
 drivers/common/mlx5/mlx5_prm.h       |   4 +-
 drivers/net/mlx5/mlx5_flow.c         | 203 ++++++++++++++++++++++++-----------
 drivers/net/mlx5/mlx5_flow.h         |  23 +++-
 drivers/net/mlx5/mlx5_flow_dv.c      |  92 ++++++++++------
 6 files changed, 226 insertions(+), 99 deletions(-)

-- 
1.8.3.1


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

* [dpdk-dev] [RFC 1/4] common/mlx5: query register c preserve capability via DevX
  2020-12-15  7:49 [dpdk-dev] [RFC 0/4] Add the E-Switch mirroring and jump supports Jiawei Wang
@ 2020-12-15  7:49 ` Jiawei Wang
  2020-12-15  7:49 ` [dpdk-dev] [RFC 2/4] net/mlx5: support E-Switch mirroring and jump in one flow Jiawei Wang
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Jiawei Wang @ 2020-12-15  7:49 UTC (permalink / raw)
  To: viacheslavo, matan, orika; +Cc: dev, rasland

Update function mlx5_devx_cmd_query_hca_attr() to add the
reg_c_preserve bit query.

The stored metadata in register C may be lost in NIC Tx and
FDB egress while doing one one of the following operations:
 - packet encapsulation.
 - packet mirroring (multiple processing paths).
 - packet sampling (using Flow Sampler).

If the reg_c_preserve bit is set to 1, then the above
limitation is obsolete, the all metadata registers Cx
preserve their values even through the operations mentioned
above.

Signed-off-by: Jiawei Wang <jiaweiw@nvidia.com>
---
 drivers/common/mlx5/mlx5_devx_cmds.c | 2 ++
 drivers/common/mlx5/mlx5_devx_cmds.h | 1 +
 drivers/common/mlx5/mlx5_prm.h       | 4 +++-
 3 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/common/mlx5/mlx5_devx_cmds.c b/drivers/common/mlx5/mlx5_devx_cmds.c
index 9c1d188..084368a 100644
--- a/drivers/common/mlx5/mlx5_devx_cmds.c
+++ b/drivers/common/mlx5/mlx5_devx_cmds.c
@@ -720,6 +720,8 @@ struct mlx5_devx_obj *
 	attr->flow_hit_aso = !!(MLX5_GET64(cmd_hca_cap, hcattr,
 					   general_obj_types) &
 				MLX5_GENERAL_OBJ_TYPES_CAP_FLOW_HIT_ASO);
+	attr->reg_c_preserve =
+		MLX5_GET(cmd_hca_cap, hcattr, reg_c_preserve);
 	if (attr->qos.sup) {
 		MLX5_SET(query_hca_cap_in, in, op_mod,
 			 MLX5_GET_HCA_CAP_OP_MOD_QOS_CAP |
diff --git a/drivers/common/mlx5/mlx5_devx_cmds.h b/drivers/common/mlx5/mlx5_devx_cmds.h
index 726e9f5..177320e 100644
--- a/drivers/common/mlx5/mlx5_devx_cmds.h
+++ b/drivers/common/mlx5/mlx5_devx_cmds.h
@@ -113,6 +113,7 @@ struct mlx5_hca_attr {
 	uint32_t scatter_fcs_w_decap_disable:1;
 	uint32_t flow_hit_aso:1; /* General obj type FLOW_HIT_ASO supported. */
 	uint32_t regex:1;
+	uint32_t reg_c_preserve:1;
 	uint32_t regexp_num_of_engines;
 	uint32_t log_max_ft_sampler_num:8;
 	struct mlx5_hca_qos_attr qos;
diff --git a/drivers/common/mlx5/mlx5_prm.h b/drivers/common/mlx5/mlx5_prm.h
index 58d1804..c62c3a6 100644
--- a/drivers/common/mlx5/mlx5_prm.h
+++ b/drivers/common/mlx5/mlx5_prm.h
@@ -1113,7 +1113,9 @@ struct mlx5_ifc_cmd_hca_cap_bits {
 	u8 regexp[0x1];
 	u8 reserved_at_a1[0x3];
 	u8 regexp_num_of_engines[0x4];
-	u8 reserved_at_a8[0x3];
+	u8 reserved_at_a8[0x1];
+	u8 reg_c_preserve[0x1];
+	u8 reserved_at_aa[0x1];
 	u8 log_max_srq[0x5];
 	u8 reserved_at_b0[0x3];
 	u8 regexp_log_crspace_size[0x5];
-- 
1.8.3.1


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

* [dpdk-dev] [RFC 2/4] net/mlx5: support E-Switch mirroring and jump in one flow
  2020-12-15  7:49 [dpdk-dev] [RFC 0/4] Add the E-Switch mirroring and jump supports Jiawei Wang
  2020-12-15  7:49 ` [dpdk-dev] [RFC 1/4] common/mlx5: query register c preserve capability via DevX Jiawei Wang
@ 2020-12-15  7:49 ` Jiawei Wang
  2020-12-15  7:49 ` [dpdk-dev] [RFC 3/4] net/mlx5: extend the skip scale flag Jiawei Wang
  2020-12-15  7:49 ` [dpdk-dev] [RFC 4/4] net/mlx5: supports modify one port in E-Switch mirroring Jiawei Wang
  3 siblings, 0 replies; 5+ messages in thread
From: Jiawei Wang @ 2020-12-15  7:49 UTC (permalink / raw)
  To: viacheslavo, matan, orika; +Cc: dev, rasland

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 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>
---
 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(-)

diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 82e24d7..3bf4484 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -4478,7 +4478,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;
@@ -4493,8 +4492,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;
@@ -4505,10 +4502,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;
 		}
 	}
@@ -4529,8 +4526,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
@@ -4554,7 +4551,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[],
@@ -4577,7 +4574,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);
@@ -4628,8 +4629,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)
@@ -5042,6 +5042,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)
@@ -5063,16 +5064,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 d85dd19..0172ee5 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 c317376..4a8154f 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.
  *
@@ -3580,7 +3584,7 @@ struct mlx5_cache_entry *
 					    (dev, &res, dev_flow, error);
 }
 
-static int fdb_mirror;
+static int fdb_mirror_limit;
 
 /**
  * Validate the modify-header actions.
@@ -3609,7 +3613,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"
@@ -3945,12 +3949,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,
@@ -4347,8 +4345,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,
@@ -4465,7 +4463,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,
@@ -8685,6 +8683,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
@@ -8896,6 +8898,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;
 
 	/* Register new destination array resource. */
 	cache_resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_DEST_ARRAY],
@@ -8928,19 +8931,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 */
@@ -8976,6 +8991,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]);
 	}
@@ -9312,6 +9331,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;
@@ -10070,6 +10097,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:
@@ -10292,7 +10321,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};
 
@@ -10302,6 +10332,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];
@@ -10923,21 +10956,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);
@@ -11091,7 +11124,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,
@@ -11190,8 +11223,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.
-- 
1.8.3.1


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

* [dpdk-dev] [RFC 3/4] net/mlx5: extend the skip scale flag
  2020-12-15  7:49 [dpdk-dev] [RFC 0/4] Add the E-Switch mirroring and jump supports Jiawei Wang
  2020-12-15  7:49 ` [dpdk-dev] [RFC 1/4] common/mlx5: query register c preserve capability via DevX Jiawei Wang
  2020-12-15  7:49 ` [dpdk-dev] [RFC 2/4] net/mlx5: support E-Switch mirroring and jump in one flow Jiawei Wang
@ 2020-12-15  7:49 ` Jiawei Wang
  2020-12-15  7:49 ` [dpdk-dev] [RFC 4/4] net/mlx5: supports modify one port in E-Switch mirroring Jiawei Wang
  3 siblings, 0 replies; 5+ messages in thread
From: Jiawei Wang @ 2020-12-15  7:49 UTC (permalink / raw)
  To: viacheslavo, matan, orika; +Cc: dev, rasland

The sampling feature introduces the scale flow group with factor,
then the scaled table value can be used for the normal path table
due to this table be created implicitly.

But if the input group value already be scaled, for example the
group value of sampling suffix flow, then use 'skip_scale" flag
to skip the scale twice in the translation action.

Consider the flow with jump action and this jump action could be
created implicitly, PMD may only scale the original flow group
value or scale the jump group value or both, so extend the
'skip_scale' flag to two bits:
If bit0 of 'skip_scale' flag is set to 1, then skip the scale the
original flow group;
If bit1 of 'skip_scale' flag is set to 1, then skip the scale the
jump flow group.

Signed-off-by: Jiawei Wang <jiaweiw@nvidia.com>
---
 drivers/net/mlx5/mlx5_flow.c    |  2 +-
 drivers/net/mlx5/mlx5_flow.h    | 21 ++++++++++++++++++---
 drivers/net/mlx5/mlx5_flow_dv.c |  9 +++++++--
 3 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 3bf4484..6095e03 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -5108,7 +5108,7 @@ struct mlx5_hlist_entry *
 		/* Suffix group level already be scaled with factor, set
 		 * skip_scale to 1 to avoid scale again in translation.
 		 */
-		flow_split_info->skip_scale = 1;
+		flow_split_info->skip_scale = 1 << MLX5_SCALE_FLOW_GROUP_BIT;
 #endif
 	}
 	/* Add the suffix subflow. */
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 0172ee5..96becd7 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -759,6 +759,9 @@ struct mlx5_flow_verbs_workspace {
 	/**< Specifications & actions buffer of verbs flow. */
 };
 
+#define MLX5_SCALE_FLOW_GROUP_BIT 0
+#define MLX5_SCALE_JUMP_FLOW_GROUP_BIT 1
+
 /** Maximal number of device sub-flows supported. */
 #define MLX5_NUM_MAX_DEV_FLOWS 32
 
@@ -772,8 +775,20 @@ struct mlx5_flow {
 	/**< Bit-fields of detected actions, see MLX5_FLOW_ACTION_*. */
 	bool external; /**< true if the flow is created external to PMD. */
 	uint8_t ingress:1; /**< 1 if the flow is ingress. */
-	uint8_t skip_scale:1;
-	/**< 1 if skip the scale the table with factor. */
+	uint8_t skip_scale:2;
+	/**
+	 * Each Bit be set to 1 if Skip the scale the flow group with factor.
+	 * If bit0 be set to 1, then skip the scale the original flow group;
+	 * If bit1 be set to 1, then skip the scale the jump flow group if
+	 * having jump action.
+	 * 00: Enable scale in a flow, default value.
+	 * 01: Skip scale the flow group with factor, enable scale the group
+	 * of jump action.
+	 * 10: Enable scale the group with factor, skip scale the group of
+	 * jump action.
+	 * 11: Skip scale the table with factor both for flow group and jump
+	 * group.
+	 */
 	union {
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
 		struct mlx5_flow_dv_workspace dv;
@@ -1240,7 +1255,7 @@ struct flow_grp_info {
 	uint64_t fdb_def_rule:1;
 	/* force standard group translation */
 	uint64_t std_tbl_fix:1;
-	uint64_t skip_scale:1;
+	uint64_t skip_scale:2;
 };
 
 static inline bool
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 4a8154f..109369e 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -9708,7 +9708,8 @@ struct mlx5_cache_entry *
 		.external = !!dev_flow->external,
 		.transfer = !!attr->transfer,
 		.fdb_def_rule = !!priv->fdb_def_rule,
-		.skip_scale = !!dev_flow->skip_scale,
+		.skip_scale = dev_flow->skip_scale &
+			(1 << MLX5_SCALE_FLOW_GROUP_BIT),
 	};
 
 	if (!wks)
@@ -10066,7 +10067,11 @@ struct mlx5_cache_entry *
 			jump_group = ((const struct rte_flow_action_jump *)
 							action->conf)->group;
 			grp_info.std_tbl_fix = 0;
-			grp_info.skip_scale = 0;
+			if (dev_flow->skip_scale &
+				(1 << MLX5_SCALE_JUMP_FLOW_GROUP_BIT))
+				grp_info.skip_scale = 1;
+			else
+				grp_info.skip_scale = 0;
 			ret = mlx5_flow_group_to_table(dev, tunnel,
 						       jump_group,
 						       &table,
-- 
1.8.3.1


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

* [dpdk-dev] [RFC 4/4] net/mlx5: supports modify one port in E-Switch mirroring
  2020-12-15  7:49 [dpdk-dev] [RFC 0/4] Add the E-Switch mirroring and jump supports Jiawei Wang
                   ` (2 preceding siblings ...)
  2020-12-15  7:49 ` [dpdk-dev] [RFC 3/4] net/mlx5: extend the skip scale flag Jiawei Wang
@ 2020-12-15  7:49 ` Jiawei Wang
  3 siblings, 0 replies; 5+ messages in thread
From: Jiawei Wang @ 2020-12-15  7:49 UTC (permalink / raw)
  To: viacheslavo, matan, orika; +Cc: dev, rasland

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, smiliar 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>
---
 drivers/net/mlx5/mlx5_flow.c    | 175 ++++++++++++++++++++++++++++------------
 drivers/net/mlx5/mlx5_flow_dv.c |  10 ---
 2 files changed, 123 insertions(+), 62 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 6095e03..aca3436 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -4465,6 +4465,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.
@@ -4474,13 +4476,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;
@@ -4489,25 +4493,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;
@@ -4542,6 +4574,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.
  *
@@ -4559,14 +4593,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)
@@ -4574,13 +4611,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;
@@ -4605,31 +4666,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)
@@ -4640,6 +4677,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,
@@ -5043,12 +5096,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)
@@ -5072,16 +5129,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,
@@ -5092,21 +5156,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 109369e..f930eaa 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -3584,8 +3584,6 @@ struct mlx5_cache_entry *
 					    (dev, &res, dev_flow, error);
 }
 
-static int fdb_mirror_limit;
-
 /**
  * Validate the modify-header actions.
  *
@@ -3613,12 +3611,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;
 }
 
@@ -4346,7 +4338,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,
@@ -4463,7 +4454,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,
-- 
1.8.3.1


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

end of thread, other threads:[~2020-12-15  7:51 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-15  7:49 [dpdk-dev] [RFC 0/4] Add the E-Switch mirroring and jump supports Jiawei Wang
2020-12-15  7:49 ` [dpdk-dev] [RFC 1/4] common/mlx5: query register c preserve capability via DevX Jiawei Wang
2020-12-15  7:49 ` [dpdk-dev] [RFC 2/4] net/mlx5: support E-Switch mirroring and jump in one flow Jiawei Wang
2020-12-15  7:49 ` [dpdk-dev] [RFC 3/4] net/mlx5: extend the skip scale flag Jiawei Wang
2020-12-15  7:49 ` [dpdk-dev] [RFC 4/4] net/mlx5: supports modify one port in E-Switch mirroring Jiawei Wang

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).