Skip to contentSkip to conversation

net/mlx5: fix the table flags of mirror action

PATCH Superseded Gregory Etelson 2 participants 11 messages Jun 17, 2025 – Jun 26, 2025

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/5 net/mlx5: fix the table flags of mirror action

From: Bing Zhao <[email protected]>

The HWS mirror action is created with STCs based on the flags. In the past, there was a single type of FDB domain. After introducing the unified FDB feature, there are 4 types of tables in FDB domain, including FDB, FDB_RX, FDB_TX and FDB_UNIFIED. More STCs will be allocated when the new FDB flags are set.

Without specifying the group ID, the default 0 would be used to determine the table type. Since only the old FDB type was supported on the root table. The flag was set wrongly and the STCs for other FDB sub-types were not allocated.

When using this mirror action to create a flow in the unified FDB, there are some errors:

1. If there is no other action STC allocated before, the offsets of old FDB and unified FDB will be the same. But the value of the mirror is zero. The mirror action is not really applied even if no error is observed when pulling the result.
2. If there is some other action STC allocated before, the offset 0 will reflact that action but not the mirror itself. An error will be observed for the rule insertion.

Since the mirror is only supported in HWS non-root tables, setting the group to some non-zero value will make STCs be allocated and used properly.

Fixes 8daf5794077f ("net/mlx5: support FDB unified domain")
---
 drivers/net/mlx5/mlx5_flow_hw.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/net/mlx5/mlx5_flow_hw.c +6 -1
index af2e7a84a5..a8a3f3872a 100644
@@ -14803,7 +14803,7 @@ flow_hw_async_action_list_handle_create(struct rte_eth_dev *dev, uint32_t queue,
 	enum mlx5_indirect_list_type list_type;
 	struct rte_flow_action_list_handle *handle;
 	struct mlx5_priv *priv = dev->data->dev_private;
-	const struct mlx5_flow_template_table_cfg table_cfg = {
+	struct mlx5_flow_template_table_cfg table_cfg = {
 		.external = true,
 		.attr = {
 			.flow_attr = {
@@ -14840,6 +14840,11 @@ flow_hw_async_action_list_handle_create(struct rte_eth_dev *dev, uint32_t queue,
 	}
 	switch (list_type) {
 	case MLX5_INDIRECT_ACTION_LIST_TYPE_MIRROR:
+		/*
+		 * Mirror action is only supported in HWS group. Setting group to
+		 * non-zero will ensure that the action resources are allocated correctly.
+		 */
+		table_cfg.attr.flow_attr.group = 1;
 		handle = mlx5_hw_mirror_handle_create(dev, &table_cfg,
 						      actions, error);
 		break;
Signature · 1 line
2.48.1
#1 lore raw

PATCH 2/5 net/mlx5: add mlx5_hw_create_mirror function.

The new mlx5_hw_create_mirror() function separates existing HWS mirror functionality into mirror action creation and indirect list handle creation.

The new mirror creation function will be used in non-template SAMPLE action implementation.

---
 drivers/net/mlx5/mlx5_flow.h    | 21 +++++++++++++++++++++
 drivers/net/mlx5/mlx5_flow_hw.c | 29 ++++++++++++++++++++---------
 2 files changed, 41 insertions(+), 9 deletions(-)
drivers/net/mlx5/mlx5_flow.h +21 -0
index 9816ed9238..23c5833290 100644
@@ -201,6 +201,21 @@ enum mlx5_feature_name {
 	MLX5_SAMPLE_ID,
 };
 
+#define MLX5_MIRROR_MAX_CLONES_NUM 3
+#define MLX5_MIRROR_MAX_SAMPLE_ACTIONS_LEN 4
+
+struct mlx5_mirror_clone {
+	enum rte_flow_action_type type;
+	void *action_ctx;
+};
+
+struct mlx5_mirror {
+	struct mlx5_indirect_list indirect;
+	uint32_t clones_num;
+	struct mlx5dr_action *mirror_action;
+	struct mlx5_mirror_clone clone[MLX5_MIRROR_MAX_CLONES_NUM];
+};
+
 /* Default queue number. */
 #define MLX5_RSSQ_DEFAULT_NUM 16
 
@@ -3722,5 +3737,11 @@ mlx5_flow_nta_update_copy_table(struct rte_eth_dev *dev,
 
 struct mlx5_ecpri_parser_profile *flow_hw_get_ecpri_parser_profile(void *dr_ctx);
 
+struct mlx5_mirror *
+mlx5_hw_create_mirror(struct rte_eth_dev *dev,
+		      const struct mlx5_flow_template_table_cfg *table_cfg,
+		      const struct rte_flow_action *actions,
+		      struct rte_flow_error *error);
+
 #endif
 #endif /* RTE_PMD_MLX5_FLOW_H_ */
drivers/net/mlx5/mlx5_flow_hw.c +20 -9
index a8a3f3872a..9b3e56938a 100644
@@ -14589,11 +14589,11 @@ hw_mirror_format_clone(struct rte_eth_dev *dev,
 	return 0;
 }
 
-static struct rte_flow_action_list_handle *
-mlx5_hw_mirror_handle_create(struct rte_eth_dev *dev,
-			     const struct mlx5_flow_template_table_cfg *table_cfg,
-			     const struct rte_flow_action *actions,
-			     struct rte_flow_error *error)
+struct mlx5_mirror *
+mlx5_hw_create_mirror(struct rte_eth_dev *dev,
+		      const struct mlx5_flow_template_table_cfg *table_cfg,
+		      const struct rte_flow_action *actions,
+		      struct rte_flow_error *error)
 {
 	uint32_t hws_flags;
 	int ret = 0, i, clones_num;
@@ -14656,15 +14656,26 @@ mlx5_hw_mirror_handle_create(struct rte_eth_dev *dev,
 				   actions, "Failed to create HWS mirror action");
 		goto error;
 	}
-
-	mlx5_indirect_list_add_entry(&priv->indirect_list_head, &mirror->indirect);
-	return (struct rte_flow_action_list_handle *)mirror;
-
+	return mirror;
 error:
 	mlx5_hw_mirror_destroy(dev, mirror);
 	return NULL;
 }
 
+static struct rte_flow_action_list_handle *
+mlx5_hw_mirror_handle_create(struct rte_eth_dev *dev,
+			     const struct mlx5_flow_template_table_cfg *table_cfg,
+			     const struct rte_flow_action *actions,
+			     struct rte_flow_error *error)
+{
+	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_mirror *mirror = mlx5_hw_create_mirror(dev, table_cfg, actions, error);
+
+	if (mirror)
+		mlx5_indirect_list_add_entry(&priv->indirect_list_head, &mirror->indirect);
+	return (struct rte_flow_action_list_handle *)mirror;
+}
+
 void
 mlx5_destroy_legacy_indirect(__rte_unused struct rte_eth_dev *dev,
 			     struct mlx5_indirect_list *ptr)
Signature · 1 line
2.48.1
#2 lore raw

PATCH 3/5 net/mlx5: create utility functions for non-template sample action

In reply to Gregory Etelson

The patch initiates non-template sample action environment and adds function to create hws mirror object.

---
 drivers/net/mlx5/meson.build       |   1 +
 drivers/net/mlx5/mlx5.h            |   7 +
 drivers/net/mlx5/mlx5_flow.h       |   7 +
 drivers/net/mlx5/mlx5_flow_hw.c    |  22 +-
 drivers/net/mlx5/mlx5_nta_sample.c | 462 +++++++++++++++++++++++++++++
 5 files changed, 483 insertions(+), 16 deletions(-)
 create mode 100644 drivers/net/mlx5/mlx5_nta_sample.c
drivers/net/mlx5/meson.build +1 -0
index 6a91692759..f16fe18193 100644
@@ -53,6 +53,7 @@ if is_linux
             'mlx5_flow_verbs.c',
             'mlx5_hws_cnt.c',
             'mlx5_nta_split.c',
+            'mlx5_nta_sample.c',
     )
 endif
 
drivers/net/mlx5/mlx5.h +7 -0
index 5695d0f54a..f085656196 100644
@@ -1255,6 +1255,11 @@ struct mlx5_flow_tbl_resource {
 #define MLX5_FLOW_TABLE_PTYPE_RSS_LAST (MLX5_MAX_TABLES - 11)
 #define MLX5_FLOW_TABLE_PTYPE_RSS_BASE \
 (1 + MLX5_FLOW_TABLE_PTYPE_RSS_LAST - MLX5_FLOW_TABLE_PTYPE_RSS_NUM)
+#define MLX5_FLOW_TABLE_SAMPLE_NUM 1024
+#define MLX5_FLOW_TABLE_SAMPLE_LAST (MLX5_FLOW_TABLE_PTYPE_RSS_BASE - 1)
+#define MLX5_FLOW_TABLE_SAMPLE_BASE \
+(1 + MLX5_FLOW_TABLE_SAMPLE_LAST - MLX5_FLOW_TABLE_SAMPLE_NUM)
+
 #define MLX5_FLOW_TABLE_FACTOR 10
 
 /* ID generation structure. */
@@ -1962,6 +1967,7 @@ struct mlx5_quota_ctx {
 	struct mlx5_indexed_pool *quota_ipool; /* Manage quota objects */
 };
 
+struct mlx5_nta_sample_ctx;
 struct mlx5_priv {
 	struct rte_eth_dev_data *dev_data;  /* Pointer to device data. */
 	struct mlx5_dev_ctx_shared *sh; /* Shared device context. */
@@ -2128,6 +2134,7 @@ struct mlx5_priv {
 	 */
 	struct mlx5dr_action *action_nat64[MLX5DR_TABLE_TYPE_MAX][2];
 	struct mlx5_indexed_pool *ptype_rss_groups;
+	struct mlx5_nta_sample_ctx *nta_sample_ctx;
 #endif
 	struct rte_eth_dev *shared_host; /* Host device for HW steering. */
 	RTE_ATOMIC(uint16_t) shared_refcnt; /* HW steering host reference counter. */
drivers/net/mlx5/mlx5_flow.h +7 -0
index 23c5833290..4bce136e1f 100644
@@ -3743,5 +3743,12 @@ mlx5_hw_create_mirror(struct rte_eth_dev *dev,
 		      const struct rte_flow_action *actions,
 		      struct rte_flow_error *error);
 
+struct rte_flow_hw *
+mlx5_flow_nta_handle_sample(struct rte_eth_dev *dev,
+			    const struct rte_flow_attr *attr,
+			    const struct rte_flow_item pattern[],
+			    const struct rte_flow_action actions[],
+			    struct rte_flow_error *error);
+
 #endif
 #endif /* RTE_PMD_MLX5_FLOW_H_ */
drivers/net/mlx5/mlx5_flow_hw.c +6 -16
index 9b3e56938a..f1b90d6e56 100644
@@ -62,9 +62,6 @@ static struct rte_flow_fp_ops mlx5_flow_hw_fp_ops;
 #define MLX5_HW_VLAN_PUSH_VID_IDX 1
 #define MLX5_HW_VLAN_PUSH_PCP_IDX 2
 
-#define MLX5_MIRROR_MAX_CLONES_NUM 3
-#define MLX5_MIRROR_MAX_SAMPLE_ACTIONS_LEN 4
-
 #define MLX5_HW_PORT_IS_PROXY(priv) \
 	(!!((priv)->sh->esw_mode && (priv)->master))
 
@@ -327,18 +324,6 @@ get_mlx5dr_table_type(const struct rte_flow_attr *attr, uint32_t specialize,
 /* Non template default queue size used for inner ctrl queue. */
 #define MLX5_NT_DEFAULT_QUEUE_SIZE 32
 
-struct mlx5_mirror_clone {
-	enum rte_flow_action_type type;
-	void *action_ctx;
-};
-
-struct mlx5_mirror {
-	struct mlx5_indirect_list indirect;
-	uint32_t clones_num;
-	struct mlx5dr_action *mirror_action;
-	struct mlx5_mirror_clone clone[MLX5_MIRROR_MAX_CLONES_NUM];
-};
-
 static int flow_hw_flush_all_ctrl_flows(struct rte_eth_dev *dev);
 static int flow_hw_translate_group(struct rte_eth_dev *dev,
 				   const struct mlx5_flow_template_table_cfg *cfg,
@@ -707,6 +692,9 @@ flow_hw_action_flags_get(const struct rte_flow_action actions[],
 		case RTE_FLOW_ACTION_TYPE_JUMP_TO_TABLE_INDEX:
 			action_flags |= MLX5_FLOW_ACTION_JUMP_TO_TABLE_INDEX;
 			break;
+		case RTE_FLOW_ACTION_TYPE_SAMPLE:
+			action_flags |= MLX5_FLOW_ACTION_SAMPLE;
+			break;
 		case RTE_FLOW_ACTION_TYPE_VOID:
 		case RTE_FLOW_ACTION_TYPE_END:
 			break;
@@ -14231,7 +14219,9 @@ static uintptr_t flow_hw_list_create(struct rte_eth_dev *dev,
 		if (ret)
 			goto free;
 	}
-
+	if (action_flags & MLX5_FLOW_ACTION_SAMPLE) {
+		mlx5_flow_nta_handle_sample(dev, attr, items, actions, error);
+	}
 	if (action_flags & MLX5_FLOW_ACTION_RSS) {
 		const struct rte_flow_action_rss
 			*rss_conf = flow_nta_locate_rss(dev, actions, error);
drivers/net/mlx5/mlx5_nta_sample.c new file +462 -0

462 lines not on this page · raw message

Signature · 1 line
2.48.1
#3 lore raw

PATCH 4/5 net/mlx5: add MLX5 mirror flow action

In reply to Gregory Etelson

Add private PMD flow action MLX5_RTE_FLOW_ACTION_TYPE_MIRROR.

The new action type provides direct access to the HWS mirror action.

---
 drivers/net/mlx5/mlx5_flow.h | 5 +++++
 1 file changed, 5 insertions(+)
drivers/net/mlx5/mlx5_flow.h +5 -0
index 4bce136e1f..8186b85ae1 100644
@@ -49,6 +49,11 @@ enum mlx5_rte_flow_action_type {
 	MLX5_RTE_FLOW_ACTION_TYPE_JUMP,
 	MLX5_RTE_FLOW_ACTION_TYPE_RSS,
 	MLX5_RTE_FLOW_ACTION_TYPE_METER_MARK,
+	MLX5_RTE_FLOW_ACTION_TYPE_MIRROR,
+};
+
+struct mlx5_rte_flow_action_mirror {
+	struct mlx5_mirror *mirror;
 };
 
 /* Private (internal) Field IDs for MODIFY_FIELD action. */
Signature · 1 line
2.48.1
#4 lore raw

PATCH 5/5 net/mlx5: support non-template SAMPLE flow action

In reply to Gregory Etelson

MLX5 HWS flow engine does not support the SAMPLE flow action.

The patch adds the SAMPLE action support to the non-template API.

---
 drivers/net/mlx5/mlx5.c            |   1 +
 drivers/net/mlx5/mlx5_flow.h       |  26 +-
 drivers/net/mlx5/mlx5_flow_hw.c    |  40 ++-
 drivers/net/mlx5/mlx5_nta_sample.c | 401 ++++++++++++++++++++++++++---
 drivers/net/mlx5/mlx5_nta_sample.h |  25 ++
 5 files changed, 444 insertions(+), 49 deletions(-)
 create mode 100644 drivers/net/mlx5/mlx5_nta_sample.h
drivers/net/mlx5/mlx5.c +1 -0
index b4bd43aae2..224f70994d 100644
@@ -2368,6 +2368,7 @@ mlx5_dev_close(struct rte_eth_dev *dev)
 	mlx5_flex_item_port_cleanup(dev);
 	mlx5_indirect_list_handles_release(dev);
 #ifdef HAVE_MLX5_HWS_SUPPORT
+	mlx5_free_sample_context(dev);
 	flow_hw_destroy_vport_action(dev);
 	/* dr context will be closed after mlx5_os_free_shared_dr. */
 	flow_hw_resource_release(dev);
drivers/net/mlx5/mlx5_flow.h +20 -6
index 8186b85ae1..e9a981707d 100644
@@ -54,6 +54,8 @@ enum mlx5_rte_flow_action_type {
 
 struct mlx5_rte_flow_action_mirror {
 	struct mlx5_mirror *mirror;
+	uint32_t sample_group;
+	uint32_t suffix_group;
 };
 
 /* Private (internal) Field IDs for MODIFY_FIELD action. */
@@ -1356,6 +1358,8 @@ struct rte_flow_nt2hws {
 	struct rte_flow_hw_aux *flow_aux;
 	/** Modify header pointer. */
 	struct mlx5_flow_dv_modify_hdr_resource *modify_hdr;
+	/** Group Id used in SAMPLE flow action */
+	uint32_t sample_group;
 	/** Chain NTA flows. */
 	SLIST_ENTRY(rte_flow_hw) next;
 	/** Encap/decap index. */
@@ -3748,12 +3752,22 @@ mlx5_hw_create_mirror(struct rte_eth_dev *dev,
 		      const struct rte_flow_action *actions,
 		      struct rte_flow_error *error);
 
-struct rte_flow_hw *
-mlx5_flow_nta_handle_sample(struct rte_eth_dev *dev,
-			    const struct rte_flow_attr *attr,
-			    const struct rte_flow_item pattern[],
-			    const struct rte_flow_action actions[],
-			    struct rte_flow_error *error);
+int
+mlx5_flow_hw_group_set_miss_actions(struct rte_eth_dev *dev,
+				    uint32_t group_id,
+				    const struct rte_flow_group_attr *attr,
+				    const struct rte_flow_action actions[],
+				    struct rte_flow_error *error);
+
+uint64_t
+mlx5_flow_hw_action_flags_get(const struct rte_flow_action actions[],
+			      const struct rte_flow_action **qrss,
+			      const struct rte_flow_action **mark,
+			      int *encap_idx,
+			      int *act_cnt,
+			      struct rte_flow_error *error);
+
+#include "mlx5_nta_sample.h"
 
 #endif
 #endif /* RTE_PMD_MLX5_FLOW_H_ */
drivers/net/mlx5/mlx5_flow_hw.c +33 -7
index f1b90d6e56..db162e5a4f 100644
@@ -574,8 +574,8 @@ flow_hw_hashfields_set(struct mlx5_flow_rss_desc *rss_desc,
 	*hash_fields |= fields;
 }
 
-static uint64_t
-flow_hw_action_flags_get(const struct rte_flow_action actions[],
+uint64_t
+mlx5_flow_hw_action_flags_get(const struct rte_flow_action actions[],
 			 const struct rte_flow_action **qrss,
 			 const struct rte_flow_action **mark,
 			 int *encap_idx,
@@ -1987,6 +1987,7 @@ hws_table_tmpl_translate_indirect_mirror(struct rte_eth_dev *dev,
 			 action_src, action_dst,
 			 flow_hw_translate_indirect_mirror);
 	}
+
 	return ret;
 }
 
@@ -2903,6 +2904,12 @@ __flow_hw_translate_actions_template(struct rte_eth_dev *dev,
 				goto err;
 			}
 			break;
+		case MLX5_RTE_FLOW_ACTION_TYPE_MIRROR:
+			if (__flow_hw_act_data_general_append(priv, acts,
+							      actions->type,
+							      src_pos, dr_pos))
+				goto err;
+			break;
 		case RTE_FLOW_ACTION_TYPE_END:
 			actions_end = true;
 			break;
@@ -3743,6 +3750,12 @@ flow_hw_actions_construct(struct rte_eth_dev *dev,
 				((const struct rte_flow_action_jump_to_table_index *)
 				action->conf)->index;
 			break;
+		case MLX5_RTE_FLOW_ACTION_TYPE_MIRROR: {
+			const struct mlx5_rte_flow_action_mirror *mirror_conf = action->conf;
+
+			rule_acts[act_data->action_dst].action = mirror_conf->mirror->mirror_action;
+		}
+			break;
 		default:
 			break;
 		}
@@ -3995,6 +4008,7 @@ flow_hw_async_flow_create_generic(struct rte_eth_dev *dev,
 		aux->matcher_selector = selector;
 		flow->flags |= MLX5_FLOW_HW_FLOW_FLAG_MATCHER_SELECTOR;
 	}
+
 	if (likely(!ret)) {
 		flow_hw_q_inc_flow_ops(priv, queue);
 		return (struct rte_flow *)flow;
@@ -5694,8 +5708,8 @@ flow_hw_group_unset_miss_group(struct rte_eth_dev *dev,
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 
-static int
-flow_hw_group_set_miss_actions(struct rte_eth_dev *dev,
+int
+mlx5_flow_hw_group_set_miss_actions(struct rte_eth_dev *dev,
 			       uint32_t group_id,
 			       const struct rte_flow_group_attr *attr,
 			       const struct rte_flow_action actions[],
@@ -7623,6 +7637,10 @@ flow_hw_parse_flow_actions_to_dr_actions(struct rte_eth_dev *dev,
 			at->dr_off[i] = curr_off;
 			action_types[curr_off++] = MLX5DR_ACTION_TYP_JUMP_TO_MATCHER;
 			break;
+		case MLX5_RTE_FLOW_ACTION_TYPE_MIRROR:
+			at->dr_off[i] = curr_off;
+			action_types[curr_off++] = MLX5DR_ACTION_TYP_DEST_ARRAY;
+				break;
 		default:
 			type = mlx5_hw_dr_action_types[at->actions[i].type];
 			at->dr_off[i] = curr_off;
@@ -14107,6 +14125,8 @@ flow_hw_destroy(struct rte_eth_dev *dev, struct rte_flow_hw *flow)
 	}
 	if (flow->nt2hws->matcher)
 		flow_hw_unregister_matcher(dev, flow->nt2hws->matcher);
+	if (flow->nt2hws->sample_group != 0)
+		mlx5_nta_release_sample_group(dev, flow->nt2hws->sample_group);
 }
 
 #ifdef HAVE_MLX5_HWS_SUPPORT
@@ -14180,7 +14200,7 @@ static uintptr_t flow_hw_list_create(struct rte_eth_dev *dev,
 	const struct rte_flow_action *qrss = NULL;
 	const struct rte_flow_action *mark = NULL;
 	uint64_t item_flags = 0;
-	uint64_t action_flags = flow_hw_action_flags_get(actions, &qrss, &mark,
+	uint64_t action_flags = mlx5_flow_hw_action_flags_get(actions, &qrss, &mark,
 							 &encap_idx, &actions_n, error);
 	struct mlx5_flow_hw_split_resource resource = {
 		.suffix = {
@@ -14220,7 +14240,13 @@ static uintptr_t flow_hw_list_create(struct rte_eth_dev *dev,
 			goto free;
 	}
 	if (action_flags & MLX5_FLOW_ACTION_SAMPLE) {
-		mlx5_flow_nta_handle_sample(dev, attr, items, actions, error);
+		flow = mlx5_flow_nta_handle_sample(dev, type, attr, items,
+						   actions,
+						   item_flags, action_flags,
+						   error);
+		if (flow != NULL)
+			return (uintptr_t)flow;
+		goto free;
 	}
 	if (action_flags & MLX5_FLOW_ACTION_RSS) {
 		const struct rte_flow_action_rss
@@ -15378,7 +15404,7 @@ const struct mlx5_flow_driver_ops mlx5_flow_hw_drv_ops = {
 	.template_table_create = flow_hw_template_table_create,
 	.template_table_destroy = flow_hw_table_destroy,
 	.table_resize = flow_hw_table_resize,
-	.group_set_miss_actions = flow_hw_group_set_miss_actions,
+	.group_set_miss_actions = mlx5_flow_hw_group_set_miss_actions,
 	.async_flow_create = flow_hw_async_flow_create,
 	.async_flow_create_by_index = flow_hw_async_flow_create_by_index,
 	.async_flow_update = flow_hw_async_flow_update,
drivers/net/mlx5/mlx5_nta_sample.c +365 -36

461 lines not on this page · raw message

drivers/net/mlx5/mlx5_nta_sample.h new file +25 -0
new file mode 100644
index 0000000000..129d534b33
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2025 NVIDIA Corporation & Affiliates
+ */
+
+#ifndef MLX5_NTA_SAMPLE_H
+#define MLX5_NTA_SAMPLE_H
+
+#include <stdint.h>
+
+struct rte_flow_hw *
+mlx5_flow_nta_handle_sample(struct rte_eth_dev *dev,
+			    enum mlx5_flow_type type,
+			    const struct rte_flow_attr *attr,
+			    const struct rte_flow_item pattern[],
+			    const struct rte_flow_action actions[],
+			    uint64_t item_flags, uint64_t action_flags,
+			    struct rte_flow_error *error);
+
+void
+mlx5_nta_release_sample_group(struct rte_eth_dev *dev, uint32_t group);
+
+void
+mlx5_free_sample_context(struct rte_eth_dev *dev);
+
+#endif /* MLX5_NTA_SAMPLE_H */
Signature · 1 line
2.48.1
#5 lore raw

v2 cover net/mlx5: support non template SAMPLE flow action

In reply to Gregory Etelson

Support SAMPLE flow action in the non-template API.

Bing Zhao (1):
net/mlx5: fix the table flags of mirror action

Gregory Etelson (3):
net/mlx5: add a stand alone function for mirror creation net/mlx5: add functions for non template sample action net/mlx5: support non-template SAMPLE flow action

 drivers/net/mlx5/meson.build       |   1 +
 drivers/net/mlx5/mlx5.c            |   1 +
 drivers/net/mlx5/mlx5.h            |   7 +
 drivers/net/mlx5/mlx5_flow.h       |  46 ++
 drivers/net/mlx5/mlx5_flow_hw.c    |  96 ++--
 drivers/net/mlx5/mlx5_nta_sample.c | 857 +++++++++++++++++++++++++++++
 drivers/net/mlx5/mlx5_nta_sample.h |  25 +
 7 files changed, 1001 insertions(+), 32 deletions(-)
 create mode 100644 drivers/net/mlx5/mlx5_nta_sample.c
 create mode 100644 drivers/net/mlx5/mlx5_nta_sample.h

--
v2: Fix the action destruction.

Signature · 1 line
2.48.1
#6 lore raw

PATCH v2 1/4 net/mlx5: fix the table flags of mirror action

From: Bing Zhao <[email protected]>

The HWS mirror action is created with STCs based on the flags. In the past, there was a single type of FDB domain. After introducing the unified FDB feature, there are 4 types of tables in FDB domain, including FDB, FDB_RX, FDB_TX and FDB_UNIFIED. More STCs will be allocated when the new FDB flags are set.

Without specifying the group ID, the default 0 would be used to determine the table type. Since only the old FDB type was supported on the root table. The flag was set wrongly and the STCs for other FDB sub-types were not allocated.

When using this mirror action to create a flow in the unified FDB, there are some errors:

1. If there is no other action STC allocated before, the offsets of old FDB and unified FDB will be the same. But the value of the mirror is zero. The mirror action is not really applied even if no error is observed when pulling the result.
2. If there is some other action STC allocated before, the offset 0 will reflact that action but not the mirror itself. An error will be observed for the rule insertion.

Since the mirror is only supported in HWS non-root tables, setting the group to some non-zero value will make STCs be allocated and used properly.

Fixes ac687bb002c9 ("net/mlx5: support unified FDB domain")
---
 drivers/net/mlx5/mlx5_flow_hw.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/net/mlx5/mlx5_flow_hw.c +6 -1
index af2e7a84a5..a8a3f3872a 100644
@@ -14803,7 +14803,7 @@ flow_hw_async_action_list_handle_create(struct rte_eth_dev *dev, uint32_t queue,
 	enum mlx5_indirect_list_type list_type;
 	struct rte_flow_action_list_handle *handle;
 	struct mlx5_priv *priv = dev->data->dev_private;
-	const struct mlx5_flow_template_table_cfg table_cfg = {
+	struct mlx5_flow_template_table_cfg table_cfg = {
 		.external = true,
 		.attr = {
 			.flow_attr = {
@@ -14840,6 +14840,11 @@ flow_hw_async_action_list_handle_create(struct rte_eth_dev *dev, uint32_t queue,
 	}
 	switch (list_type) {
 	case MLX5_INDIRECT_ACTION_LIST_TYPE_MIRROR:
+		/*
+		 * Mirror action is only supported in HWS group. Setting group to
+		 * non-zero will ensure that the action resources are allocated correctly.
+		 */
+		table_cfg.attr.flow_attr.group = 1;
 		handle = mlx5_hw_mirror_handle_create(dev, &table_cfg,
 						      actions, error);
 		break;
Signature · 1 line
2.48.1
#7 lore raw

PATCH v2 2/4 net/mlx5: add a stand alone function for mirror creation

In reply to Gregory Etelson

The new mlx5_hw_create_mirror() function separates existing HWS mirror functionality into mirror action creation and indirect list handle creation.

The new mirror creation function will be used in non-template SAMPLE action implementation.

---
 drivers/net/mlx5/mlx5_flow.h    | 21 +++++++++++++++++
 drivers/net/mlx5/mlx5_flow_hw.c | 41 ++++++++++++++++-----------------
 2 files changed, 41 insertions(+), 21 deletions(-)
drivers/net/mlx5/mlx5_flow.h +21 -0
index 9816ed9238..23c5833290 100644
@@ -201,6 +201,21 @@ enum mlx5_feature_name {
 	MLX5_SAMPLE_ID,
 };
 
+#define MLX5_MIRROR_MAX_CLONES_NUM 3
+#define MLX5_MIRROR_MAX_SAMPLE_ACTIONS_LEN 4
+
+struct mlx5_mirror_clone {
+	enum rte_flow_action_type type;
+	void *action_ctx;
+};
+
+struct mlx5_mirror {
+	struct mlx5_indirect_list indirect;
+	uint32_t clones_num;
+	struct mlx5dr_action *mirror_action;
+	struct mlx5_mirror_clone clone[MLX5_MIRROR_MAX_CLONES_NUM];
+};
+
 /* Default queue number. */
 #define MLX5_RSSQ_DEFAULT_NUM 16
 
@@ -3722,5 +3737,11 @@ mlx5_flow_nta_update_copy_table(struct rte_eth_dev *dev,
 
 struct mlx5_ecpri_parser_profile *flow_hw_get_ecpri_parser_profile(void *dr_ctx);
 
+struct mlx5_mirror *
+mlx5_hw_create_mirror(struct rte_eth_dev *dev,
+		      const struct mlx5_flow_template_table_cfg *table_cfg,
+		      const struct rte_flow_action *actions,
+		      struct rte_flow_error *error);
+
 #endif
 #endif /* RTE_PMD_MLX5_FLOW_H_ */
drivers/net/mlx5/mlx5_flow_hw.c +20 -21

64 lines not on this page · raw message

Signature · 1 line
2.48.1
#8 lore raw

PATCH v2 3/4 net/mlx5: add functions for non template sample action

In reply to Gregory Etelson

The patch initiates non-template sample action environment and adds private functions to support the sample flow action.

---
 drivers/net/mlx5/meson.build       |   1 +
 drivers/net/mlx5/mlx5.h            |   7 +
 drivers/net/mlx5/mlx5_flow.h       |   2 +
 drivers/net/mlx5/mlx5_nta_sample.c | 470 +++++++++++++++++++++++++++++
 drivers/net/mlx5/mlx5_nta_sample.h |  22 ++
 5 files changed, 502 insertions(+)
 create mode 100644 drivers/net/mlx5/mlx5_nta_sample.c
 create mode 100644 drivers/net/mlx5/mlx5_nta_sample.h
drivers/net/mlx5/meson.build +1 -0
index 6a91692759..f16fe18193 100644
@@ -53,6 +53,7 @@ if is_linux
             'mlx5_flow_verbs.c',
             'mlx5_hws_cnt.c',
             'mlx5_nta_split.c',
+            'mlx5_nta_sample.c',
     )
 endif
 
drivers/net/mlx5/mlx5.h +7 -0
index 5695d0f54a..f085656196 100644
@@ -1255,6 +1255,11 @@ struct mlx5_flow_tbl_resource {
 #define MLX5_FLOW_TABLE_PTYPE_RSS_LAST (MLX5_MAX_TABLES - 11)
 #define MLX5_FLOW_TABLE_PTYPE_RSS_BASE \
 (1 + MLX5_FLOW_TABLE_PTYPE_RSS_LAST - MLX5_FLOW_TABLE_PTYPE_RSS_NUM)
+#define MLX5_FLOW_TABLE_SAMPLE_NUM 1024
+#define MLX5_FLOW_TABLE_SAMPLE_LAST (MLX5_FLOW_TABLE_PTYPE_RSS_BASE - 1)
+#define MLX5_FLOW_TABLE_SAMPLE_BASE \
+(1 + MLX5_FLOW_TABLE_SAMPLE_LAST - MLX5_FLOW_TABLE_SAMPLE_NUM)
+
 #define MLX5_FLOW_TABLE_FACTOR 10
 
 /* ID generation structure. */
@@ -1962,6 +1967,7 @@ struct mlx5_quota_ctx {
 	struct mlx5_indexed_pool *quota_ipool; /* Manage quota objects */
 };
 
+struct mlx5_nta_sample_ctx;
 struct mlx5_priv {
 	struct rte_eth_dev_data *dev_data;  /* Pointer to device data. */
 	struct mlx5_dev_ctx_shared *sh; /* Shared device context. */
@@ -2128,6 +2134,7 @@ struct mlx5_priv {
 	 */
 	struct mlx5dr_action *action_nat64[MLX5DR_TABLE_TYPE_MAX][2];
 	struct mlx5_indexed_pool *ptype_rss_groups;
+	struct mlx5_nta_sample_ctx *nta_sample_ctx;
 #endif
 	struct rte_eth_dev *shared_host; /* Host device for HW steering. */
 	RTE_ATOMIC(uint16_t) shared_refcnt; /* HW steering host reference counter. */
drivers/net/mlx5/mlx5_flow.h +2 -0
index 23c5833290..561bb05dfa 100644
@@ -3743,5 +3743,7 @@ mlx5_hw_create_mirror(struct rte_eth_dev *dev,
 		      const struct rte_flow_action *actions,
 		      struct rte_flow_error *error);
 
+#include "mlx5_nta_sample.h"
+
 #endif
 #endif /* RTE_PMD_MLX5_FLOW_H_ */
drivers/net/mlx5/mlx5_nta_sample.c new file +470 -0

470 lines not on this page · raw message

drivers/net/mlx5/mlx5_nta_sample.h new file +22 -0
new file mode 100644
index 0000000000..07b7589a75
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2025 NVIDIA Corporation & Affiliates
+ */
+
+#ifndef RTE_PMD_MLX5_NTA_SAMPLE_H_
+#define RTE_PMD_MLX5_NTA_SAMPLE_H_
+
+#include <stdint.h>
+
+struct rte_flow_hw *
+mlx5_nta_sample_flow_list_create(struct rte_eth_dev *dev,
+				 enum mlx5_flow_type type,
+				 const struct rte_flow_attr *attr,
+				 const struct rte_flow_item pattern[],
+				 const struct rte_flow_action actions[],
+				 uint64_t item_flags, uint64_t action_flags,
+				 struct rte_flow_error *error);
+
+void
+mlx5_nta_sample_context_free(struct rte_eth_dev *dev);
+
+#endif /* RTE_PMD_MLX5_NTA_SAMPLE_H_ */
Signature · 1 line
2.48.1
#9 lore raw

PATCH v2 4/4 net/mlx5: support non-template SAMPLE flow action

In reply to Gregory Etelson

MLX5 HWS flow engine does not support the SAMPLE flow action.

The patch adds the SAMPLE action support to the non-template API.

---
 drivers/net/mlx5/mlx5.c            |   1 +
 drivers/net/mlx5/mlx5_flow.h       |  23 ++
 drivers/net/mlx5/mlx5_flow_hw.c    |  48 +++-
 drivers/net/mlx5/mlx5_nta_sample.c | 411 ++++++++++++++++++++++++++++-
 drivers/net/mlx5/mlx5_nta_sample.h |   3 +
 5 files changed, 464 insertions(+), 22 deletions(-)
drivers/net/mlx5/mlx5.c +1 -0
index b4bd43aae2..09cefd5b36 100644
@@ -2368,6 +2368,7 @@ mlx5_dev_close(struct rte_eth_dev *dev)
 	mlx5_flex_item_port_cleanup(dev);
 	mlx5_indirect_list_handles_release(dev);
 #ifdef HAVE_MLX5_HWS_SUPPORT
+	mlx5_nta_sample_context_free(dev);
 	flow_hw_destroy_vport_action(dev);
 	/* dr context will be closed after mlx5_os_free_shared_dr. */
 	flow_hw_resource_release(dev);
drivers/net/mlx5/mlx5_flow.h +23 -0
index 561bb05dfa..e890e732c3 100644
@@ -49,6 +49,7 @@ enum mlx5_rte_flow_action_type {
 	MLX5_RTE_FLOW_ACTION_TYPE_JUMP,
 	MLX5_RTE_FLOW_ACTION_TYPE_RSS,
 	MLX5_RTE_FLOW_ACTION_TYPE_METER_MARK,
+	MLX5_RTE_FLOW_ACTION_TYPE_MIRROR,
 };
 
 /* Private (internal) Field IDs for MODIFY_FIELD action. */
@@ -1341,6 +1342,11 @@ enum {
 
 SLIST_HEAD(mlx5_nta_rss_flow_head, rte_flow_hw);
 
+struct mlx5_sample_release_ctx {
+	struct mlx5_list_entry *mirror_entry;
+	uint32_t sample_group;
+};
+
 /** HWS non template flow data. */
 struct rte_flow_nt2hws {
 	/** BWC rule pointer. */
@@ -1351,6 +1357,8 @@ struct rte_flow_nt2hws {
 	struct rte_flow_hw_aux *flow_aux;
 	/** Modify header pointer. */
 	struct mlx5_flow_dv_modify_hdr_resource *modify_hdr;
+	/** SAMPLE resources */
+	struct mlx5_sample_release_ctx *sample_release_ctx;
 	/** Chain NTA flows. */
 	SLIST_ENTRY(rte_flow_hw) next;
 	/** Encap/decap index. */
@@ -3743,6 +3751,21 @@ mlx5_hw_create_mirror(struct rte_eth_dev *dev,
 		      const struct rte_flow_action *actions,
 		      struct rte_flow_error *error);
 
+int
+mlx5_flow_hw_group_set_miss_actions(struct rte_eth_dev *dev,
+				    uint32_t group_id,
+				    const struct rte_flow_group_attr *attr,
+				    const struct rte_flow_action actions[],
+				    struct rte_flow_error *error);
+
+uint64_t
+mlx5_flow_hw_action_flags_get(const struct rte_flow_action actions[],
+			      const struct rte_flow_action **qrss,
+			      const struct rte_flow_action **mark,
+			      int *encap_idx,
+			      int *act_cnt,
+			      struct rte_flow_error *error);
+
 #include "mlx5_nta_sample.h"
 
 #endif
drivers/net/mlx5/mlx5_flow_hw.c +38 -10

126 lines not on this page · raw message

drivers/net/mlx5/mlx5_nta_sample.c +399 -12

475 lines not on this page · raw message

drivers/net/mlx5/mlx5_nta_sample.h +3 -0
index 07b7589a75..44d5b3b01a 100644
@@ -19,4 +19,7 @@ mlx5_nta_sample_flow_list_create(struct rte_eth_dev *dev,
 void
 mlx5_nta_sample_context_free(struct rte_eth_dev *dev);
 
+void
+mlx5_nta_sample_mirror_entry_release(struct rte_eth_dev *dev,
+				     struct mlx5_sample_release_ctx *release);
 #endif /* RTE_PMD_MLX5_NTA_SAMPLE_H_ */
Signature · 1 line
2.48.1
#10 lore raw

Re: [PATCH v2 0/4] net/mlx5: support non template SAMPLE flow action

In reply to Gregory Etelson

26/06/2025 09:59, Gregory Etelson:

Quoted 9 lines

Support SAMPLE flow action in the non-template API.

Bing Zhao (1):
net/mlx5: fix the table flags of mirror action

Gregory Etelson (3):
net/mlx5: add a stand alone function for mirror creation net/mlx5: add functions for non template sample action net/mlx5: support non-template SAMPLE flow action

Applied, thanks.

Note: UINT32_WIDTH was replaced with 32 to help with Alpine musl.