[04/10] net/mlx5: split sample flow into two sub flows
diff mbox series

Message ID 1602251436-269694-5-git-send-email-jiaweiw@nvidia.com
State Superseded, archived
Delegated to: Raslan Darawsheh
Headers show
Series
  • Add sampling and mirroring support in MLX5 PMD
Related show

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Jiawei(Jonny) Wang Oct. 9, 2020, 1:50 p.m. UTC
The flow with sample action will be splited into two sub flows:
the prefix sub flow with the all actions preceding the sample
action and sample action itself, and the suffix sub flow with
the actions following the sample action.

The original items remain in the prefix sub flow, add the
implicit tag action with unique id to set in metadata register,
and suffix sub flow uses the tag item to match with that unique id.

The flow split as below:

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

Signed-off-by: Jiawei Wang <jiaweiw@nvidia.com>
Acked-by: Viacheslav Ovsiienko <viacheslavo@nvidia.com>
---
 drivers/net/mlx5/mlx5.c      |  11 ++
 drivers/net/mlx5/mlx5.h      |   3 +
 drivers/net/mlx5/mlx5_flow.c | 360 +++++++++++++++++++++++++++++++++++++++++--
 drivers/net/mlx5/mlx5_flow.h |  37 +++++
 4 files changed, 394 insertions(+), 17 deletions(-)

Patch
diff mbox series

diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index e5ca392..2613c78 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -241,6 +241,17 @@  static LIST_HEAD(, mlx5_dev_ctx_shared) mlx5_dev_ctx_list =
 		.free = mlx5_free,
 		.type = "mlx5_jump_ipool",
 	},
+	{
+		.size = sizeof(struct mlx5_flow_dv_sample_resource),
+		.trunk_size = 64,
+		.grow_trunk = 3,
+		.grow_shift = 2,
+		.need_lock = 0,
+		.release_mem_en = 1,
+		.malloc = mlx5_malloc,
+		.free = mlx5_free,
+		.type = "mlx5_sample_ipool",
+	},
 #endif
 	{
 		.size = sizeof(struct mlx5_flow_meter),
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 375c86e..391f6f3 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -39,6 +39,7 @@  enum mlx5_ipool_index {
 	MLX5_IPOOL_TAG, /* Pool for tag resource. */
 	MLX5_IPOOL_PORT_ID, /* Pool for port id resource. */
 	MLX5_IPOOL_JUMP, /* Pool for jump resource. */
+	MLX5_IPOOL_SAMPLE, /* Pool for sample resource. */
 #endif
 	MLX5_IPOOL_MTR, /* Pool for meter resource. */
 	MLX5_IPOOL_MCP, /* Pool for metadata resource. */
@@ -512,6 +513,7 @@  struct mlx5_flow_tbl_resource {
 #define MLX5_FLOW_TABLE_LEVEL_METER (MLX5_MAX_TABLES - 4)
 #define MLX5_FLOW_TABLE_LEVEL_SUFFIX (MLX5_MAX_TABLES - 3)
 #define MLX5_MAX_TABLES_FDB UINT16_MAX
+#define MLX5_FLOW_TABLE_FACTOR 10
 
 /* ID generation structure. */
 struct mlx5_flow_id_pool {
@@ -640,6 +642,7 @@  struct mlx5_dev_ctx_shared {
 	struct mlx5_hlist *tag_table;
 	uint32_t port_id_action_list; /* List of port ID actions. */
 	uint32_t push_vlan_action_list; /* List of push VLAN actions. */
+	uint32_t sample_action_list; /* List of sample actions. */
 	struct mlx5_flow_counter_mng cmng; /* Counters management structure. */
 	struct mlx5_flow_default_miss_resource default_miss;
 	/* Default miss action resource structure. */
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 691eb9a..803591c 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -3862,6 +3862,8 @@  struct mlx5_flow_tunnel_info {
  *   Pointer to return the created subflow, may be NULL.
  * @param[in] prefix_layers
  *   Prefix subflow layers, may be 0.
+ * @param[in] prefix_mark
+ *   Prefix subflow mark flag, may be 0.
  * @param[in] attr
  *   Flow rule attributes.
  * @param[in] items
@@ -3882,6 +3884,7 @@  struct mlx5_flow_tunnel_info {
 			struct rte_flow *flow,
 			struct mlx5_flow **sub_flow,
 			uint64_t prefix_layers,
+			uint32_t prefix_mark,
 			const struct rte_flow_attr *attr,
 			const struct rte_flow_item items[],
 			const struct rte_flow_action actions[],
@@ -3901,10 +3904,13 @@  struct mlx5_flow_tunnel_info {
 		      dev_flow->handle, next);
 	/*
 	 * If dev_flow is as one of the suffix flow, some actions in suffix
-	 * flow may need some user defined item layer flags.
+	 * flow may need some user defined item layer flags, and pass the
+	 * Metadate rxq mark flag to suffix flow as well.
 	 */
 	if (prefix_layers)
 		dev_flow->handle->layers = prefix_layers;
+	if (prefix_mark)
+		dev_flow->handle->mark = 1;
 	if (sub_flow)
 		*sub_flow = dev_flow;
 	return flow_drv_translate(dev, dev_flow, attr, items, actions, error);
@@ -4235,6 +4241,179 @@  struct mlx5_flow_tunnel_info {
 }
 
 /**
+ * Check the match action from the action list.
+ *
+ * @param[in] actions
+ *   Pointer to the list of actions.
+ * @param[in] action
+ *   The action to be check if exist.
+ * @param[out] match_action_pos
+ *   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.
+ *
+ * @return
+ *   > 0 the total number of actions.
+ *   0 if not found match action in action list.
+ */
+static int
+flow_check_match_action(const struct rte_flow_action actions[],
+			enum rte_flow_action_type action,
+			int *match_action_pos, int *qrss_action_pos)
+{
+	int actions_n = 0;
+	int flag = 0;
+
+	*match_action_pos = -1;
+	*qrss_action_pos = -1;
+	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
+		if (actions->type == action) {
+			flag = 1;
+			*match_action_pos = actions_n;
+		}
+		if (actions->type == RTE_FLOW_ACTION_TYPE_QUEUE ||
+		    actions->type == RTE_FLOW_ACTION_TYPE_RSS)
+			*qrss_action_pos = actions_n;
+		actions_n++;
+	}
+	/* Count RTE_FLOW_ACTION_TYPE_END. */
+	return flag ? actions_n + 1 : 0;
+}
+
+#define SAMPLE_SUFFIX_ITEM 2
+
+/**
+ * Split the sample flow.
+ *
+ * As sample flow will split to two sub flow, sample flow with
+ * sample action, the other actions will move to new suffix flow.
+ *
+ * Also add unique tag id with tag action in the sample flow,
+ * the same tag id will be as match in the suffix flow.
+ *
+ * @param dev
+ *   Pointer to Ethernet device.
+ * @param[in] fdb_tx
+ *   FDB egress flow flag.
+ * @param[out] sfx_items
+ *   Suffix flow match items (list terminated by the END pattern item).
+ * @param[in] actions
+ *   Associated actions (list terminated by the END action).
+ * @param[out] actions_sfx
+ *   Suffix flow actions.
+ * @param[out] actions_pre
+ *   Prefix flow actions.
+ * @param[in] actions_n
+ *  The total number of actions.
+ * @param[in] sample_action_pos
+ *   The sample action position.
+ * @param[in] qrss_action_pos
+ *   The Queue/RSS action position.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL.
+ *
+ * @return
+ *   0 on success, or unique flow_id, a negative errno value
+ *   otherwise and rte_errno is set.
+ */
+static int
+flow_sample_split_prep(struct rte_eth_dev *dev,
+		       uint32_t fdb_tx,
+		       struct rte_flow_item sfx_items[],
+		       const struct rte_flow_action actions[],
+		       struct rte_flow_action actions_sfx[],
+		       struct rte_flow_action actions_pre[],
+		       int actions_n,
+		       int sample_action_pos,
+		       int qrss_action_pos,
+		       struct rte_flow_error *error)
+{
+	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;
+	uint32_t tag_id = 0;
+	int index;
+	int ret;
+
+	if (sample_action_pos < 0)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  NULL, "invalid position of sample "
+					  "action in list");
+	if (!fdb_tx) {
+		/* 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);
+		if (ret < 0)
+			return ret;
+		set_tag->id = ret;
+		tag_id = flow_qrss_get_id(dev);
+		set_tag->data = tag_id;
+		/* Prepare the suffix subflow items. */
+		tag_spec = (void *)(sfx_items + SAMPLE_SUFFIX_ITEM);
+		tag_spec->data = tag_id;
+		tag_spec->id = set_tag->id;
+		tag_mask = tag_spec + 1;
+		tag_mask->data = UINT32_MAX;
+		sfx_items[0] = (struct rte_flow_item){
+			.type = (enum rte_flow_item_type)
+				MLX5_RTE_FLOW_ITEM_TYPE_TAG,
+			.spec = tag_spec,
+			.last = NULL,
+			.mask = tag_mask,
+		};
+		sfx_items[1] = (struct rte_flow_item){
+			.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);
+	}
+	/* Add the extra tag action for NIC-RX and E-Switch ingress. */
+	if (!fdb_tx) {
+		actions_pre[index++] =
+			(struct rte_flow_action){
+			.type = (enum rte_flow_action_type)
+				MLX5_RTE_FLOW_ACTION_TYPE_TAG,
+			.conf = set_tag,
+		};
+	}
+	memcpy(actions_pre + index, actions + sample_action_pos,
+	       sizeof(struct rte_flow_action));
+	index += 1;
+	actions_pre[index] = (struct rte_flow_action){
+		.type = (enum rte_flow_action_type)
+			RTE_FLOW_ACTION_TYPE_END,
+	};
+	/* Put the actions after sample into Suffix flow. */
+	memcpy(actions_sfx, actions + sample_action_pos + 1,
+	       sizeof(struct rte_flow_action) *
+	       (actions_n - sample_action_pos - 1));
+	return tag_id;
+}
+
+/**
  * The splitting for metadata feature.
  *
  * - Q/RSS action on NIC Rx should be split in order to pass by
@@ -4250,6 +4429,8 @@  struct mlx5_flow_tunnel_info {
  *   Parent flow structure pointer.
  * @param[in] prefix_layers
  *   Prefix flow layer flags.
+ * @param[in] prefix_mark
+ *   Prefix subflow mark flag, may be 0.
  * @param[in] attr
  *   Flow rule attributes.
  * @param[in] items
@@ -4269,6 +4450,7 @@  struct mlx5_flow_tunnel_info {
 flow_create_split_metadata(struct rte_eth_dev *dev,
 			   struct rte_flow *flow,
 			   uint64_t prefix_layers,
+			   uint32_t prefix_mark,
 			   const struct rte_flow_attr *attr,
 			   const struct rte_flow_item items[],
 			   const struct rte_flow_action actions[],
@@ -4292,8 +4474,9 @@  struct mlx5_flow_tunnel_info {
 	    config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY ||
 	    !mlx5_flow_ext_mreg_supported(dev))
 		return flow_create_split_inner(dev, flow, NULL, prefix_layers,
-					       attr, items, actions, external,
-					       flow_idx, error);
+					       prefix_mark, attr, items,
+					       actions, external, flow_idx,
+					       error);
 	actions_n = flow_parse_metadata_split_actions_info(actions, &qrss,
 							   &encap_idx);
 	if (qrss) {
@@ -4378,7 +4561,8 @@  struct mlx5_flow_tunnel_info {
 			goto exit;
 	}
 	/* Add the unmodified original or prefix subflow. */
-	ret = flow_create_split_inner(dev, flow, &dev_flow, prefix_layers, attr,
+	ret = flow_create_split_inner(dev, flow, &dev_flow, prefix_layers,
+				      prefix_mark, attr,
 				      items, ext_actions ? ext_actions :
 				      actions, external, flow_idx, error);
 	if (ret < 0)
@@ -4441,7 +4625,7 @@  struct mlx5_flow_tunnel_info {
 		}
 		dev_flow = NULL;
 		/* Add suffix subflow to execute Q/RSS. */
-		ret = flow_create_split_inner(dev, flow, &dev_flow, layers,
+		ret = flow_create_split_inner(dev, flow, &dev_flow, layers, 0,
 					      &q_attr, mtr_sfx ? items :
 					      q_items, q_actions,
 					      external, flow_idx, error);
@@ -4477,6 +4661,10 @@  struct mlx5_flow_tunnel_info {
  *   Pointer to Ethernet device.
  * @param[in] flow
  *   Parent flow structure pointer.
+ * @param[in] prefix_layers
+ *   Prefix subflow layers, may be 0.
+ * @param[in] prefix_mark
+ *   Prefix subflow mark flag, may be 0.
  * @param[in] attr
  *   Flow rule attributes.
  * @param[in] items
@@ -4494,12 +4682,14 @@  struct mlx5_flow_tunnel_info {
  */
 static int
 flow_create_split_meter(struct rte_eth_dev *dev,
-			   struct rte_flow *flow,
-			   const struct rte_flow_attr *attr,
-			   const struct rte_flow_item items[],
-			   const struct rte_flow_action actions[],
-			   bool external, uint32_t flow_idx,
-			   struct rte_flow_error *error)
+			struct rte_flow *flow,
+			uint64_t prefix_layers,
+			uint32_t prefix_mark,
+			const struct rte_flow_attr *attr,
+			const struct rte_flow_item items[],
+			const struct rte_flow_action actions[],
+			bool external, uint32_t flow_idx,
+			struct rte_flow_error *error)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct rte_flow_action *sfx_actions = NULL;
@@ -4542,8 +4732,10 @@  struct mlx5_flow_tunnel_info {
 			goto exit;
 		}
 		/* Add the prefix subflow. */
-		ret = flow_create_split_inner(dev, flow, &dev_flow, 0, attr,
-					      items, pre_actions, external,
+		ret = flow_create_split_inner(dev, flow, &dev_flow,
+					      prefix_layers, 0,
+					      attr, items,
+					      pre_actions, external,
 					      flow_idx, error);
 		if (ret) {
 			ret = -rte_errno;
@@ -4558,8 +4750,10 @@  struct mlx5_flow_tunnel_info {
 	/* Add the prefix subflow. */
 	ret = flow_create_split_metadata(dev, flow, dev_flow ?
 					 flow_get_prefix_layer_flags(dev_flow) :
-					 0, &sfx_attr,
-					 sfx_items ? sfx_items : items,
+					 prefix_layers, dev_flow ?
+					 dev_flow->handle->mark : prefix_mark,
+					 &sfx_attr, sfx_items ?
+					 sfx_items : items,
 					 sfx_actions ? sfx_actions : actions,
 					 external, flow_idx, error);
 exit:
@@ -4569,6 +4763,138 @@  struct mlx5_flow_tunnel_info {
 }
 
 /**
+ * The splitting for sample feature.
+ *
+ * Once Sample action is detected in the action list, the flow actions should
+ * be split into prefix sub flow and suffix sub flow.
+ *
+ * The original items remain in the prefix sub flow, all actions preceding the
+ * sample action and the sample action itself will be copied to the prefix
+ * sub flow, the actions following the sample action will be copied to the
+ * suffix sub flow, Queue action always be located in the suffix sub flow.
+ *
+ * In order to make the packet from prefix sub flow matches with suffix sub
+ * flow, an extra tag action be added into prefix sub flow, and the suffix sub
+ * flow uses tag item with the unique flow id.
+ *
+ * @param dev
+ *   Pointer to Ethernet device.
+ * @param[in] flow
+ *   Parent flow structure pointer.
+ * @param[in] attr
+ *   Flow rule attributes.
+ * @param[in] items
+ *   Pattern specification (list terminated by the END pattern item).
+ * @param[in] actions
+ *   Associated actions (list terminated by the END action).
+ * @param[in] external
+ *   This flow rule is created by request external to PMD.
+ * @param[in] flow_idx
+ *   This memory pool index to the flow.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL.
+ * @return
+ *   0 on success, negative value otherwise
+ */
+static int
+flow_create_split_sample(struct rte_eth_dev *dev,
+			 struct rte_flow *flow,
+			 const struct rte_flow_attr *attr,
+			 const struct rte_flow_item items[],
+			 const struct rte_flow_action actions[],
+			 bool external, uint32_t flow_idx,
+			 struct rte_flow_error *error)
+{
+	struct mlx5_priv *priv = dev->data->dev_private;
+	struct rte_flow_action *sfx_actions = NULL;
+	struct rte_flow_action *pre_actions = NULL;
+	struct rte_flow_item *sfx_items = NULL;
+	struct mlx5_flow *dev_flow = NULL;
+	struct rte_flow_attr sfx_attr = *attr;
+#ifdef HAVE_IBV_FLOW_DV_SUPPORT
+	struct mlx5_flow_dv_sample_resource *sample_res;
+	struct mlx5_flow_tbl_data_entry *sfx_tbl_data;
+	struct mlx5_flow_tbl_resource *sfx_tbl;
+	union mlx5_flow_tbl_key sfx_table_key;
+#endif
+	size_t act_size;
+	size_t item_size;
+	uint32_t fdb_tx = 0;
+	int32_t tag_id = 0;
+	int actions_n = 0;
+	int sample_action_pos;
+	int qrss_action_pos;
+	int ret = 0;
+
+	if (priv->sampler_en)
+		actions_n = flow_check_match_action(actions,
+					RTE_FLOW_ACTION_TYPE_SAMPLE,
+					&sample_action_pos, &qrss_action_pos);
+	if (actions_n) {
+		/* The prefix actions must includes sample, tag, end. */
+		act_size = sizeof(struct rte_flow_action) * (actions_n * 2 + 1)
+			   + sizeof(struct mlx5_rte_flow_action_set_tag);
+		item_size = sizeof(struct rte_flow_item) * SAMPLE_SUFFIX_ITEM +
+			    sizeof(struct mlx5_rte_flow_item_tag) * 2;
+		sfx_actions = mlx5_malloc(MLX5_MEM_ZERO, (act_size +
+					  item_size), 0, SOCKET_ID_ANY);
+		if (!sfx_actions)
+			return rte_flow_error_set(error, ENOMEM,
+						  RTE_FLOW_ERROR_TYPE_ACTION,
+						  NULL, "no memory to split "
+						  "sample flow");
+		if (!fdb_tx)
+			sfx_items = (struct rte_flow_item *)((char *)sfx_actions
+					+ act_size);
+		pre_actions = sfx_actions + actions_n;
+		/* For uplink, its vport num is 0xffff. */
+		fdb_tx = (attr->transfer && priv->vport_id != 0xffff);
+		tag_id = flow_sample_split_prep(dev, fdb_tx, sfx_items,
+						actions, sfx_actions,
+						pre_actions, actions_n,
+						sample_action_pos,
+						qrss_action_pos, error);
+		if (tag_id < 0 || (!fdb_tx && !tag_id)) {
+			ret = -rte_errno;
+			goto exit;
+		}
+		/* Add the prefix subflow. */
+		ret = flow_create_split_inner(dev, flow, &dev_flow, 0, 0, attr,
+					      items, pre_actions, external,
+					      flow_idx, error);
+		if (ret) {
+			ret = -rte_errno;
+			goto exit;
+		}
+		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_table_key.v64 = sfx_tbl_data->entry.key;
+		sfx_attr.group = sfx_attr.transfer ?
+					(sfx_table_key.table_id - 1) :
+					 sfx_table_key.table_id;
+#endif
+	}
+	/* Add the suffix subflow. */
+	ret = flow_create_split_meter(dev, flow, dev_flow ?
+				 flow_get_prefix_layer_flags(dev_flow) : 0,
+				 dev_flow ? dev_flow->handle->mark : 0,
+				 &sfx_attr, sfx_items ? sfx_items : items,
+				 sfx_actions ? sfx_actions : actions,
+				 external, flow_idx, error);
+exit:
+	if (sfx_actions)
+		mlx5_free(sfx_actions);
+	return ret;
+}
+
+/**
  * Split the flow to subflow set. The splitters might be linked
  * in the chain, like this:
  * flow_create_split_outer() calls:
@@ -4616,8 +4942,8 @@  struct mlx5_flow_tunnel_info {
 {
 	int ret;
 
-	ret = flow_create_split_meter(dev, flow, attr, items,
-					 actions, external, flow_idx, error);
+	ret = flow_create_split_sample(dev, flow, attr, items,
+				       actions, external, flow_idx, error);
 	MLX5_ASSERT(ret <= 0);
 	return ret;
 }
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index f47170d..85f9f45 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -520,6 +520,39 @@  struct mlx5_flow_tbl_data_entry {
 	uint32_t idx; /**< index for the indexed mempool. */
 };
 
+/* Sub rdma-core actions list. */
+struct mlx5_flow_sub_actions_list {
+	uint32_t actions_num; /**< Number of sample actions. */
+	uint64_t action_flags;
+	void *dr_queue_action;
+	void *dr_tag_action;
+	void *dr_cnt_action;
+};
+
+/* Sample sub-actions resource list. */
+struct mlx5_flow_sub_actions_idx {
+	uint32_t rix_hrxq; /**< Hash Rx queue object index. */
+	uint32_t rix_tag; /**< Index to the tag action. */
+	uint32_t cnt;
+};
+
+/* Sample action resource structure. */
+struct mlx5_flow_dv_sample_resource {
+	ILIST_ENTRY(uint32_t)next; /**< Pointer to next element. */
+	rte_atomic32_t refcnt; /**< Reference counter. */
+	void *verbs_action; /**< Verbs sample action object. */
+	uint8_t ft_type; /** Flow Table Type */
+	uint32_t ft_id; /** Flow Table Level */
+	uint32_t ratio;   /** Sample Ratio */
+	uint64_t set_action; /** Restore reg_c0 value */
+	void *normal_path_tbl; /** Flow Table pointer */
+	void *default_miss; /** default_miss dr_action. */
+	struct mlx5_flow_sub_actions_idx sample_idx;
+	/**< Action index resources. */
+	struct mlx5_flow_sub_actions_list sample_act;
+	/**< Action resources. */
+};
+
 /* Verbs specification header. */
 struct ibv_spec_header {
 	enum ibv_flow_spec_type type;
@@ -552,6 +585,8 @@  struct mlx5_flow_handle_dv {
 	/**< Index to push VLAN action resource in cache. */
 	uint32_t rix_tag;
 	/**< Index to the tag action. */
+	uint32_t rix_sample;
+	/**< Index to sample action resource in cache. */
 } __rte_packed;
 
 /** Device flow handle structure: used both for creating & destroying. */
@@ -617,6 +652,8 @@  struct mlx5_flow_dv_workspace {
 	/**< Pointer to the jump action resource. */
 	struct mlx5_flow_dv_match_params value;
 	/**< Holds the value that the packet is compared to. */
+	struct mlx5_flow_dv_sample_resource *sample_res;
+	/**< Pointer to the sample action resource. */
 };
 
 /*