DPDK patches and discussions
 help / color / mirror / Atom feed
* [PATCH 0/5] net/mlx5: support count and age actions on root group
@ 2025-11-04 17:46 Dariusz Sosnowski
  2025-11-04 17:46 ` [PATCH 1/5] common/mlx5: detect DevX counters support in rdma-core Dariusz Sosnowski
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Dariusz Sosnowski @ 2025-11-04 17:46 UTC (permalink / raw)
  To: Viacheslav Ovsiienko, Bing Zhao, Ori Kam, Suanming Mou, Matan Azrad
  Cc: dev, Raslan Darawsheh

When working with HW Steering flow engine (HWS, dv_flow_en=2),
mlx5 PMD does not support using count and age flow actions
on flow group 0 i.e., root table.
Flow rules on root table are special in a sense that
they are created through mlx5 kernel driver using rdma-core mlx5dv_create_flow() API.
This API however does not support using counters from FW-allocated counter bulks
which contain more than 1 counter (extensively used with HWS to optimize allocations).
This affects age flow action as well, because it's implementation in mlx5 PMD
relies on counters.

rdma-core version v60.0 added a new flow action type to mlx5dv_create_flow() API -
MLX5DV_FLOW_ACTION_COUNTERS_DEVX_WITH_OFFSET - which allows the use of counters
from bigger FW-allocated counter bulks. This in turn allows mlx5 PMD to extend
count and age flow action support to group 0.

This patchset implements that support. Patchset contains:

- Patch 1 - Adds detection of MLX5DV_FLOW_ACTION_COUNTERS_DEVX_WITH_OFFSET in rdma-core at build time.
- Patch 2 - Adds support for counter action in HWS layer whenever MLX5DV_FLOW_ACTION_COUNTERS_DEVX_WITH_OFFSET is available.
- Patch 3-4 - Small reworks and fixes which allow cleaner implementation of count/age support.
- Patch 5 - Enables support of count and age flow action in group 0, in flow API implementation with HWS.

Dariusz Sosnowski (5):
  common/mlx5: detect DevX counters support in rdma-core
  net/mlx5/hws: support counter from DevX bulk on root
  net/mlx5: rework root group checks in table create
  net/mlx5: improve error reporting on masked indirect actions
  net/mlx5: support count and age on root group

 doc/guides/nics/mlx5.rst               |  34 +++++--
 doc/guides/rel_notes/release_25_11.rst |   4 +
 drivers/common/mlx5/linux/meson.build  |   2 +
 drivers/net/mlx5/hws/mlx5dr.h          |  14 +++
 drivers/net/mlx5/hws/mlx5dr_action.c   |  19 ++--
 drivers/net/mlx5/mlx5_flow.h           |  17 ++++
 drivers/net/mlx5/mlx5_flow_hw.c        | 136 ++++++++++++++-----------
 drivers/net/mlx5/mlx5_hws_cnt.c        |  43 ++++++--
 drivers/net/mlx5/mlx5_hws_cnt.h        |  17 +++-
 9 files changed, 196 insertions(+), 90 deletions(-)

--
2.39.5


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

* [PATCH 1/5] common/mlx5: detect DevX counters support in rdma-core
  2025-11-04 17:46 [PATCH 0/5] net/mlx5: support count and age actions on root group Dariusz Sosnowski
@ 2025-11-04 17:46 ` Dariusz Sosnowski
  2025-11-04 17:46 ` [PATCH 2/5] net/mlx5/hws: support counter from DevX bulk on root Dariusz Sosnowski
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Dariusz Sosnowski @ 2025-11-04 17:46 UTC (permalink / raw)
  To: Viacheslav Ovsiienko, Bing Zhao, Ori Kam, Suanming Mou, Matan Azrad
  Cc: dev, Raslan Darawsheh

Starting with rdma-core version v60.0, there's a new action type
for mlx5dv_create_flow() which is used to create flow rules
in root table.
This new type allows mlx5 PMD to attach flow counters
from DevX bulks to flow rules in root table.

This patch adds compile time detection of this new action type,
which is used in follow up patches to enable counters
on group 0 support if and only if rdma-core supports that.

Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
---
 drivers/common/mlx5/linux/meson.build | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/common/mlx5/linux/meson.build b/drivers/common/mlx5/linux/meson.build
index 3fe7db7ec4..3767e7a69b 100644
--- a/drivers/common/mlx5/linux/meson.build
+++ b/drivers/common/mlx5/linux/meson.build
@@ -213,6 +213,8 @@ has_sym_args = [
             'ibv_is_fork_initialized'],
         [ 'HAVE_IBV_DEVICE_ATTR_ESW_MGR_REG_C0', 'infiniband/mlx5dv.h',
             'MLX5DV_CONTEXT_MASK_REG_C0' ],
+        [ 'HAVE_MLX5DV_FLOW_ACTION_COUNTERS_DEVX_WITH_OFFSET', 'infiniband/mlx5dv.h',
+            'MLX5DV_FLOW_ACTION_COUNTERS_DEVX_WITH_OFFSET' ],
 ]
 if  libmtcr_ul_found
     has_sym_args += [
-- 
2.39.5


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

* [PATCH 2/5] net/mlx5/hws: support counter from DevX bulk on root
  2025-11-04 17:46 [PATCH 0/5] net/mlx5: support count and age actions on root group Dariusz Sosnowski
  2025-11-04 17:46 ` [PATCH 1/5] common/mlx5: detect DevX counters support in rdma-core Dariusz Sosnowski
@ 2025-11-04 17:46 ` Dariusz Sosnowski
  2025-11-04 17:46 ` [PATCH 3/5] net/mlx5: rework root group checks in table create Dariusz Sosnowski
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Dariusz Sosnowski @ 2025-11-04 17:46 UTC (permalink / raw)
  To: Viacheslav Ovsiienko, Bing Zhao, Ori Kam, Suanming Mou, Matan Azrad
  Cc: dev, Raslan Darawsheh

This patch adds support for using flow counters with offsets
within a DevX bulk, in flow rules on root table, in HWS layer.

Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
---
 drivers/net/mlx5/hws/mlx5dr.h        | 14 ++++++++++++++
 drivers/net/mlx5/hws/mlx5dr_action.c | 19 ++++++++++---------
 2 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/drivers/net/mlx5/hws/mlx5dr.h b/drivers/net/mlx5/hws/mlx5dr.h
index 58526fc08e..c13316305f 100644
--- a/drivers/net/mlx5/hws/mlx5dr.h
+++ b/drivers/net/mlx5/hws/mlx5dr.h
@@ -738,6 +738,20 @@ mlx5dr_action_create_counter(struct mlx5dr_context *ctx,
 			     struct mlx5dr_devx_obj *obj,
 			     uint32_t flags);
 
+/* Check if counter action on root table is supported.
+ *
+ * @return true if counter action on root table is supported.
+ */
+static inline bool
+mlx5dr_action_counter_root_is_supported(void)
+{
+#ifdef HAVE_MLX5DV_FLOW_ACTION_COUNTERS_DEVX_WITH_OFFSET
+	return true;
+#else
+	return false;
+#endif
+}
+
 /* Create direct rule reformat action.
  *
  * @param[in] ctx
diff --git a/drivers/net/mlx5/hws/mlx5dr_action.c b/drivers/net/mlx5/hws/mlx5dr_action.c
index d765d57a8f..1be66629e5 100644
--- a/drivers/net/mlx5/hws/mlx5dr_action.c
+++ b/drivers/net/mlx5/hws/mlx5dr_action.c
@@ -832,16 +832,11 @@ int mlx5dr_action_root_build_attr(struct mlx5dr_rule_action rule_actions[],
 			attr[i].type = MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION;
 			attr[i].action = action->flow_action;
 			break;
-#ifdef HAVE_IBV_FLOW_DEVX_COUNTERS
+#ifdef HAVE_MLX5DV_FLOW_ACTION_COUNTERS_DEVX_WITH_OFFSET
 		case MLX5DR_ACTION_TYP_CTR:
-			attr[i].type = MLX5DV_FLOW_ACTION_COUNTERS_DEVX;
-			attr[i].obj = action->devx_obj;
-
-			if (rule_actions[i].counter.offset) {
-				DR_LOG(ERR, "Counter offset not supported over root");
-				rte_errno = ENOTSUP;
-				return rte_errno;
-			}
+			attr[i].type = MLX5DV_FLOW_ACTION_COUNTERS_DEVX_WITH_OFFSET;
+			attr[i].bulk_obj.obj = action->devx_obj;
+			attr[i].bulk_obj.offset = rule_actions[i].counter.offset;
 			break;
 #endif
 		default:
@@ -1712,6 +1707,12 @@ mlx5dr_action_create_counter(struct mlx5dr_context *ctx,
 		return NULL;
 	}
 
+	if (mlx5dr_action_is_root_flags(flags) &&
+	    !mlx5dr_action_counter_root_is_supported()) {
+		rte_errno = ENOTSUP;
+		return NULL;
+	}
+
 	action = mlx5dr_action_create_generic(ctx, flags, MLX5DR_ACTION_TYP_CTR);
 	if (!action)
 		return NULL;
-- 
2.39.5


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

* [PATCH 3/5] net/mlx5: rework root group checks in table create
  2025-11-04 17:46 [PATCH 0/5] net/mlx5: support count and age actions on root group Dariusz Sosnowski
  2025-11-04 17:46 ` [PATCH 1/5] common/mlx5: detect DevX counters support in rdma-core Dariusz Sosnowski
  2025-11-04 17:46 ` [PATCH 2/5] net/mlx5/hws: support counter from DevX bulk on root Dariusz Sosnowski
@ 2025-11-04 17:46 ` Dariusz Sosnowski
  2025-11-04 17:46 ` [PATCH 4/5] net/mlx5: improve error reporting on masked indirect actions Dariusz Sosnowski
  2025-11-04 17:46 ` [PATCH 5/5] net/mlx5: support count and age on root group Dariusz Sosnowski
  4 siblings, 0 replies; 6+ messages in thread
From: Dariusz Sosnowski @ 2025-11-04 17:46 UTC (permalink / raw)
  To: Viacheslav Ovsiienko, Bing Zhao, Ori Kam, Suanming Mou, Matan Azrad
  Cc: dev, Raslan Darawsheh

Before this patch, during flow actions translation done in template
table create, there were a lot of checks for group with index 0.
This group is special, because flow rules in that group are created
through mlx5 kernel driver.
For this reason, this group is referred to as root group or root table.

This patch reworks these group index checks for clarity:

- A dedicated function for checking if group index refers to
  root group is added.
- All direct group index checks in actions translation are replaced
  with a check for result of that function.
- Redundant group translation checks in actions translation is removed.
  Group indexes are already translated at that point.
- Root group check for internal default miss action is removed.
  This action is supported on root group assuming rdma-core supports it.
  If rdma-core core does not support it, then HWS layer will reject
  accordingly.

Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
---
 drivers/net/mlx5/mlx5_flow.h    | 17 +++++++++++++++++
 drivers/net/mlx5/mlx5_flow_hw.c | 34 ++++++---------------------------
 2 files changed, 23 insertions(+), 28 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index cfdd47ef50..9b0afa427e 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -1658,6 +1658,23 @@ struct mlx5_flow_group {
 	struct mlx5_list *matchers;
 };
 
+/**
+ * Returns true if a group with the given index is a root group.
+ *
+ * @param group_id
+ *   Group index.
+ *   It is assumed that provided index is already translated from user index to PMD index
+ *   (as is for transfer groups for example).
+ *
+ * @returns
+ *   True if group is a root group.
+ *   False otherwise.
+ */
+static inline bool
+mlx5_group_id_is_root(uint32_t group_id)
+{
+	return group_id == 0;
+}
 
 #define MLX5_HW_TBL_MAX_ITEM_TEMPLATE 32
 #define MLX5_HW_TBL_MAX_ACTION_TEMPLATE 32
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index ff68483a40..de004f8c1c 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -2507,7 +2507,7 @@ __flow_hw_translate_actions_template(struct rte_eth_dev *dev,
 	unsigned int of_vlan_offset;
 	uint32_t ct_idx;
 	int ret, err;
-	uint32_t target_grp = 0;
+	bool is_root = mlx5_group_id_is_root(cfg->attr.flow_attr.group);
 	bool unified_fdb = is_unified_fdb(priv);
 
 	flow_hw_modify_field_init(&mhdr, at);
@@ -2519,7 +2519,7 @@ __flow_hw_translate_actions_template(struct rte_eth_dev *dev,
 
 		switch ((int)actions->type) {
 		case RTE_FLOW_ACTION_TYPE_INDIRECT_LIST:
-			if (!attr->group) {
+			if (is_root) {
 				DRV_LOG(ERR, "Indirect action is not supported in root table.");
 				goto err;
 			}
@@ -2529,7 +2529,7 @@ __flow_hw_translate_actions_template(struct rte_eth_dev *dev,
 				goto err;
 			break;
 		case RTE_FLOW_ACTION_TYPE_INDIRECT:
-			if (!attr->group) {
+			if (is_root) {
 				DRV_LOG(ERR, "Indirect action is not supported in root table.");
 				goto err;
 			}
@@ -2550,10 +2550,6 @@ __flow_hw_translate_actions_template(struct rte_eth_dev *dev,
 				priv->hw_drop[!!attr->group];
 			break;
 		case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
-			if (!attr->group) {
-				DRV_LOG(ERR, "Port representor is not supported in root table.");
-				goto err;
-			}
 			acts->rule_acts[dr_pos].action = priv->hw_def_miss;
 			break;
 		case RTE_FLOW_ACTION_TYPE_FLAG:
@@ -2745,11 +2741,7 @@ __flow_hw_translate_actions_template(struct rte_eth_dev *dev,
 			recom_type = MLX5DR_ACTION_TYP_POP_IPV6_ROUTE_EXT;
 			break;
 		case RTE_FLOW_ACTION_TYPE_SEND_TO_KERNEL:
-			ret = flow_hw_translate_group(dev, cfg, attr->group,
-						&target_grp, &sub_error);
-			if (ret)
-				goto err;
-			if (target_grp == 0) {
+			if (is_root) {
 				__flow_hw_action_template_destroy(dev, acts);
 				rte_flow_error_set(&sub_error, ENOTSUP,
 					RTE_FLOW_ERROR_TYPE_ACTION,
@@ -2773,11 +2765,7 @@ __flow_hw_translate_actions_template(struct rte_eth_dev *dev,
 				goto err;
 			break;
 		case RTE_FLOW_ACTION_TYPE_AGE:
-			ret = flow_hw_translate_group(dev, cfg, attr->group,
-						&target_grp, &sub_error);
-			if (ret)
-				goto err;
-			if (target_grp == 0) {
+			if (is_root) {
 				__flow_hw_action_template_destroy(dev, acts);
 				rte_flow_error_set(&sub_error, ENOTSUP,
 					RTE_FLOW_ERROR_TYPE_ACTION,
@@ -2792,11 +2780,7 @@ __flow_hw_translate_actions_template(struct rte_eth_dev *dev,
 				goto err;
 			break;
 		case RTE_FLOW_ACTION_TYPE_COUNT:
-			ret = flow_hw_translate_group(dev, cfg, attr->group,
-						&target_grp, &sub_error);
-			if (ret)
-				goto err;
-			if (target_grp == 0) {
+			if (is_root) {
 				__flow_hw_action_template_destroy(dev, acts);
 				rte_flow_error_set(&sub_error, ENOTSUP,
 					RTE_FLOW_ERROR_TYPE_ACTION,
@@ -2855,12 +2839,6 @@ __flow_hw_translate_actions_template(struct rte_eth_dev *dev,
 				goto err;
 			break;
 		case MLX5_RTE_FLOW_ACTION_TYPE_DEFAULT_MISS:
-			/* Internal, can be skipped. */
-			if (!!attr->group) {
-				DRV_LOG(ERR, "DEFAULT MISS action is only"
-					" supported in root table.");
-				goto err;
-			}
 			acts->rule_acts[dr_pos].action = priv->hw_def_miss;
 			break;
 		case RTE_FLOW_ACTION_TYPE_NAT64:
-- 
2.39.5


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

* [PATCH 4/5] net/mlx5: improve error reporting on masked indirect actions
  2025-11-04 17:46 [PATCH 0/5] net/mlx5: support count and age actions on root group Dariusz Sosnowski
                   ` (2 preceding siblings ...)
  2025-11-04 17:46 ` [PATCH 3/5] net/mlx5: rework root group checks in table create Dariusz Sosnowski
@ 2025-11-04 17:46 ` Dariusz Sosnowski
  2025-11-04 17:46 ` [PATCH 5/5] net/mlx5: support count and age on root group Dariusz Sosnowski
  4 siblings, 0 replies; 6+ messages in thread
From: Dariusz Sosnowski @ 2025-11-04 17:46 UTC (permalink / raw)
  To: Viacheslav Ovsiienko, Bing Zhao, Ori Kam, Suanming Mou, Matan Azrad
  Cc: dev, Raslan Darawsheh

This patch improves error reporting for masked indirect actions,
during flow actions translation done in HWS mode:

- Replace "return -1" with error reporting through rte_flow_error.
- Change log level from WARNING to ERR.
- Add more information to log messages (port index
  and action handle).

Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
---
 drivers/net/mlx5/mlx5_flow_hw.c | 42 +++++++++++++++++++++++----------
 1 file changed, 29 insertions(+), 13 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index de004f8c1c..4aa0a01b5e 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -1321,7 +1321,8 @@ flow_hw_shared_action_translate(struct rte_eth_dev *dev,
 				const struct rte_flow_action *action,
 				struct mlx5_hw_actions *acts,
 				uint16_t action_src,
-				uint16_t action_dst)
+				uint16_t action_dst,
+				struct rte_flow_error *error)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_shared_action_rss *shared_rss;
@@ -1338,8 +1339,10 @@ flow_hw_shared_action_translate(struct rte_eth_dev *dev,
 		    (priv, acts,
 		    (enum rte_flow_action_type)MLX5_RTE_FLOW_ACTION_TYPE_RSS,
 		    action_src, action_dst, idx, shared_rss)) {
-			DRV_LOG(WARNING, "Indirect RSS action index %d translate failed", act_idx);
-			return -1;
+			DRV_LOG(ERR, "port %u Indirect RSS action (handle %p) translate failed",
+				dev->data->port_id, action->conf);
+			return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+						  action, "Indirect RSS action translate failed");
 		}
 		break;
 	case MLX5_INDIRECT_ACTION_TYPE_COUNT:
@@ -1347,15 +1350,22 @@ flow_hw_shared_action_translate(struct rte_eth_dev *dev,
 			(enum rte_flow_action_type)
 			MLX5_RTE_FLOW_ACTION_TYPE_COUNT,
 			action_src, action_dst, act_idx)) {
-			DRV_LOG(WARNING, "Indirect count action translate failed");
-			return -1;
+			DRV_LOG(ERR,
+				"port %u Indirect count action (handle %p) "
+				"translate failed",
+				dev->data->port_id, action->conf);
+			return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+						  action,
+						  "Indirect count action translate failed");
 		}
 		break;
 	case MLX5_INDIRECT_ACTION_TYPE_CT:
 		if (flow_hw_ct_compile(dev, MLX5_HW_INV_QUEUE,
 				       idx, &acts->rule_acts[action_dst])) {
-			DRV_LOG(WARNING, "Indirect CT action translate failed");
-			return -1;
+			DRV_LOG(ERR, "port %u Indirect CT action (handle %p) translate failed",
+				dev->data->port_id, action->conf);
+			return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+						  action, "Indirect CT action translate failed");
 		}
 		break;
 	case MLX5_INDIRECT_ACTION_TYPE_METER_MARK:
@@ -1363,16 +1373,22 @@ flow_hw_shared_action_translate(struct rte_eth_dev *dev,
 			(enum rte_flow_action_type)
 			MLX5_RTE_FLOW_ACTION_TYPE_METER_MARK,
 			action_src, action_dst, idx)) {
-			DRV_LOG(WARNING, "Indirect meter mark action translate failed");
-			return -1;
+			DRV_LOG(ERR,
+				"port %u Indirect meter mark action (handle %p) "
+				"translate failed",
+				dev->data->port_id, action->conf);
+			return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+						  action,
+						  "Indirect meter mark action translate failed");
 		}
 		break;
 	case MLX5_INDIRECT_ACTION_TYPE_QUOTA:
 		flow_hw_construct_quota(priv, &acts->rule_acts[action_dst], idx);
 		break;
 	default:
-		DRV_LOG(WARNING, "Unsupported shared action type:%d", type);
-		break;
+		DRV_LOG(ERR, "Unsupported shared action type: %d", type);
+		return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, action,
+					  "Unsupported shared action type");
 	}
 	return 0;
 }
@@ -2534,8 +2550,8 @@ __flow_hw_translate_actions_template(struct rte_eth_dev *dev,
 				goto err;
 			}
 			if (actions->conf && masks->conf) {
-				if (flow_hw_shared_action_translate
-				(dev, actions, acts, src_pos, dr_pos))
+				if (flow_hw_shared_action_translate(dev, actions, acts,
+								    src_pos, dr_pos, &sub_error))
 					goto err;
 			} else if (__flow_hw_act_data_indirect_append
 					(priv, acts, RTE_FLOW_ACTION_TYPE_INDIRECT,
-- 
2.39.5


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

* [PATCH 5/5] net/mlx5: support count and age on root group
  2025-11-04 17:46 [PATCH 0/5] net/mlx5: support count and age actions on root group Dariusz Sosnowski
                   ` (3 preceding siblings ...)
  2025-11-04 17:46 ` [PATCH 4/5] net/mlx5: improve error reporting on masked indirect actions Dariusz Sosnowski
@ 2025-11-04 17:46 ` Dariusz Sosnowski
  4 siblings, 0 replies; 6+ messages in thread
From: Dariusz Sosnowski @ 2025-11-04 17:46 UTC (permalink / raw)
  To: Viacheslav Ovsiienko, Bing Zhao, Ori Kam, Suanming Mou, Matan Azrad
  Cc: dev, Raslan Darawsheh

This patch enables support for count and age flow actions
in root table i.e. flow group 0, when working
with HW Steering flow engine (dv_flow_en = 2).
It depends on support in HWS layer introduced in previous patches.

Specifically this patch:

- Adjusts action validation during flow actions translation
  to allow count and age on root group.
- Adds creation and destruction of mlx5dr count action
  for use on root group.
- Adjusts count action construction (done during rule create)
  to select correct action variant based on the group
  where the rule is created.

Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
---
 doc/guides/nics/mlx5.rst               | 34 ++++++++-----
 doc/guides/rel_notes/release_25_11.rst |  4 ++
 drivers/net/mlx5/mlx5_flow_hw.c        | 66 ++++++++++++++++++--------
 drivers/net/mlx5/mlx5_hws_cnt.c        | 43 +++++++++++++----
 drivers/net/mlx5/mlx5_hws_cnt.h        | 17 +++++--
 5 files changed, 121 insertions(+), 43 deletions(-)

diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst
index fde98ae993..1ddd82b5d6 100644
--- a/doc/guides/nics/mlx5.rst
+++ b/doc/guides/nics/mlx5.rst
@@ -2698,19 +2698,26 @@ DPDK       19.05         19.02          21.05                    21.05
 Limitations
 ^^^^^^^^^^^
 
-Because freeing a counter (by destroying a flow rule or destroying indirect action)
-does not immediately make it available for the application,
-the PMD might return:
+With :ref:`HW steering <mlx5_hws>`:
 
-- ``ENOENT`` if no counter is available in ``free``, ``reuse``
-  or ``wait_reset`` rings.
-  No counter will be available until the application releases some of them.
-- ``EAGAIN`` if no counter is available in ``free`` and ``reuse`` rings,
-  but there are counters in ``wait_reset`` ring.
-  This means that after the next service thread cycle new counters will be available.
+#. Because freeing a counter (by destroying a flow rule or destroying indirect action)
+   does not immediately make it available for the application,
+   the PMD might return:
 
-The application has to be aware that flow rule create or indirect action create
-might need be retried.
+      - ``ENOENT`` if no counter is available in ``free``, ``reuse``
+        or ``wait_reset`` rings.
+        No counter will be available until the application releases some of them.
+      - ``EAGAIN`` if no counter is available in ``free`` and ``reuse`` rings,
+        but there are counters in ``wait_reset`` ring.
+        This means that after the next service thread cycle new counters will be available.
+
+      The application has to be aware that flow rule create or indirect action create
+      might need be retried.
+
+#. Using count action on root tables requires:
+
+   - Linux kernel >= v6.4
+   - rdma-core >= v60.0
 
 
 .. _mlx5_age:
@@ -2754,6 +2761,11 @@ With :ref:`HW steering <mlx5_hws>`,
    (``RTE_FLOW_PORT_FLAG_STRICT_QUEUE`` passed to ``rte_flow_configure()``),
    indirect age actions can be created only through asynchronous flow API.
 
+#. Using age action on root tables requires:
+
+   - Linux kernel >= v6.4
+   - rdma-core >= v60.0
+
 
 .. _mlx5_quota:
 
diff --git a/doc/guides/rel_notes/release_25_11.rst b/doc/guides/rel_notes/release_25_11.rst
index c5ba335cfc..40c6f30ae2 100644
--- a/doc/guides/rel_notes/release_25_11.rst
+++ b/doc/guides/rel_notes/release_25_11.rst
@@ -147,6 +147,10 @@ New Features
   * Added multi-process per port.
   * Optimized code.
 
+* **Updated NVIDIA mlx5 driver.**
+
+  * Support count and age flow actions on root tables with HW Steering flow engine.
+
 * **Added PQC ML algorithms in cryptodev.**
 
   * Added PQC ML-KEM support with reference to FIPS203.
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index 4aa0a01b5e..cca8fe6f46 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -1801,7 +1801,7 @@ flow_hw_represented_port_compile(struct rte_eth_dev *dev,
 
 static __rte_always_inline int
 flow_hw_cnt_compile(struct rte_eth_dev *dev, uint32_t  start_pos,
-		      struct mlx5_hw_actions *acts)
+		      struct mlx5_hw_actions *acts, bool is_root)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	uint32_t pos = start_pos;
@@ -1815,7 +1815,8 @@ flow_hw_cnt_compile(struct rte_eth_dev *dev, uint32_t  start_pos,
 				(priv->hws_cpool,
 				 cnt_id,
 				 &acts->rule_acts[pos].action,
-				 &acts->rule_acts[pos].counter.offset);
+				 &acts->rule_acts[pos].counter.offset,
+				 is_root);
 	if (ret != 0)
 		return ret;
 	acts->cnt_id = cnt_id;
@@ -2461,6 +2462,28 @@ mlx5_create_ipv6_ext_reformat(struct rte_eth_dev *dev,
 	return -EINVAL;
 }
 
+static bool
+is_counter_supported_root(struct rte_eth_dev *dev)
+{
+	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_hws_cnt_pool *pool = mlx5_hws_cnt_host_pool(priv->hws_cpool);
+
+	return pool->is_root_supported;
+}
+
+static bool
+is_indirect_action_type_supported_root(struct rte_eth_dev *dev,
+				       const enum rte_flow_action_type type)
+{
+	switch (type) {
+	case RTE_FLOW_ACTION_TYPE_COUNT:
+	case RTE_FLOW_ACTION_TYPE_AGE:
+		return is_counter_supported_root(dev);
+	default:
+		return false;
+	}
+}
+
 /**
  * Translate rte_flow actions to DR action.
  *
@@ -2545,8 +2568,10 @@ __flow_hw_translate_actions_template(struct rte_eth_dev *dev,
 				goto err;
 			break;
 		case RTE_FLOW_ACTION_TYPE_INDIRECT:
-			if (is_root) {
-				DRV_LOG(ERR, "Indirect action is not supported in root table.");
+			if (is_root && !is_indirect_action_type_supported_root(dev, masks->type)) {
+				DRV_LOG(ERR, "Indirect action type (%d) is not supported on "
+					     "root table.",
+					masks->type);
 				goto err;
 			}
 			if (actions->conf && masks->conf) {
@@ -2781,12 +2806,10 @@ __flow_hw_translate_actions_template(struct rte_eth_dev *dev,
 				goto err;
 			break;
 		case RTE_FLOW_ACTION_TYPE_AGE:
-			if (is_root) {
-				__flow_hw_action_template_destroy(dev, acts);
+			if (is_root && !is_counter_supported_root(dev)) {
 				rte_flow_error_set(&sub_error, ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					NULL,
-					"Age action on root table is not supported in HW steering mode");
+					RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					"Age action is not supported on group 0");
 				goto err;
 			}
 			if (__flow_hw_act_data_general_append(priv, acts,
@@ -2796,12 +2819,10 @@ __flow_hw_translate_actions_template(struct rte_eth_dev *dev,
 				goto err;
 			break;
 		case RTE_FLOW_ACTION_TYPE_COUNT:
-			if (is_root) {
-				__flow_hw_action_template_destroy(dev, acts);
+			if (is_root && !is_counter_supported_root(dev)) {
 				rte_flow_error_set(&sub_error, ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					NULL,
-					"Counter action on root table is not supported in HW steering mode");
+					RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					"Count action is not supported on group 0");
 				goto err;
 			}
 			if ((at->action_flags & MLX5_FLOW_ACTION_AGE) ||
@@ -2815,7 +2836,7 @@ __flow_hw_translate_actions_template(struct rte_eth_dev *dev,
 			if (masks->conf &&
 			    ((const struct rte_flow_action_count *)
 			     masks->conf)->id) {
-				err = flow_hw_cnt_compile(dev, dr_pos, acts);
+				err = flow_hw_cnt_compile(dev, dr_pos, acts, is_root);
 				if (err)
 					goto err;
 			} else if (__flow_hw_act_data_general_append
@@ -3157,7 +3178,7 @@ flow_hw_construct_quota(struct mlx5_priv *priv,
 static __rte_always_inline int
 flow_hw_shared_action_construct(struct rte_eth_dev *dev, uint32_t queue,
 				const struct rte_flow_action *action,
-				struct rte_flow_template_table *table __rte_unused,
+				struct rte_flow_template_table *table,
 				const uint64_t item_flags, uint64_t action_flags,
 				struct rte_flow_hw *flow,
 				struct mlx5dr_rule_action *rule_act)
@@ -3176,6 +3197,7 @@ flow_hw_shared_action_construct(struct rte_eth_dev *dev, uint32_t queue,
 		       ((1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET) - 1);
 	uint32_t *cnt_queue;
 	cnt_id_t age_cnt;
+	bool is_root = mlx5_group_id_is_root(table->grp->group_id);
 
 	memset(&act_data, 0, sizeof(act_data));
 	switch (type) {
@@ -3201,7 +3223,8 @@ flow_hw_shared_action_construct(struct rte_eth_dev *dev, uint32_t queue,
 		if (mlx5_hws_cnt_pool_get_action_offset(priv->hws_cpool,
 				act_idx,
 				&rule_act->action,
-				&rule_act->counter.offset))
+				&rule_act->counter.offset,
+				is_root))
 			return -1;
 		flow->flags |= MLX5_FLOW_HW_FLOW_FLAG_CNT_ID;
 		flow->cnt_id = act_idx;
@@ -3242,7 +3265,7 @@ flow_hw_shared_action_construct(struct rte_eth_dev *dev, uint32_t queue,
 		}
 		if (mlx5_hws_cnt_pool_get_action_offset(priv->hws_cpool,
 						     age_cnt, &rule_act->action,
-						     &rule_act->counter.offset))
+						     &rule_act->counter.offset, is_root))
 			return -1;
 		break;
 	case MLX5_INDIRECT_ACTION_TYPE_CT:
@@ -3476,6 +3499,7 @@ flow_hw_actions_construct(struct rte_eth_dev *dev,
 	struct mlx5_aso_mtr *aso_mtr;
 	struct mlx5_multi_pattern_segment *mp_segment = NULL;
 	struct rte_flow_hw_aux *aux;
+	bool is_root = mlx5_group_id_is_root(table->grp->group_id);
 
 	attr.group = table->grp->group_id;
 	ft_flag = mlx5_hw_act_flag[!!table->grp->group_id][table->type];
@@ -3673,7 +3697,8 @@ flow_hw_actions_construct(struct rte_eth_dev *dev,
 				(priv->hws_cpool,
 				 cnt_id,
 				 &rule_acts[act_data->action_dst].action,
-				 &rule_acts[act_data->action_dst].counter.offset
+				 &rule_acts[act_data->action_dst].counter.offset,
+				 is_root
 				 );
 			if (ret != 0)
 				goto error;
@@ -3685,7 +3710,8 @@ flow_hw_actions_construct(struct rte_eth_dev *dev,
 				(priv->hws_cpool,
 				 act_data->shared_counter.id,
 				 &rule_acts[act_data->action_dst].action,
-				 &rule_acts[act_data->action_dst].counter.offset
+				 &rule_acts[act_data->action_dst].counter.offset,
+				 is_root
 				 );
 			if (ret != 0)
 				goto error;
diff --git a/drivers/net/mlx5/mlx5_hws_cnt.c b/drivers/net/mlx5/mlx5_hws_cnt.c
index fb01fce4e5..7a2bb6fec4 100644
--- a/drivers/net/mlx5/mlx5_hws_cnt.c
+++ b/drivers/net/mlx5/mlx5_hws_cnt.c
@@ -439,6 +439,10 @@ mlx5_hws_cnt_pool_init(struct mlx5_dev_ctx_shared *sh,
 	}
 
 	cntp->cfg = *pcfg;
+	cntp->is_root_supported = mlx5dr_action_counter_root_is_supported();
+	DRV_LOG(DEBUG, "ibdev %s counter and age action %s supported on group 0",
+		sh->ibdev_name,
+		cntp->is_root_supported ? "is" : "is not");
 	if (cntp->cfg.host_cpool)
 		return cntp;
 	if (pcfg->request_num > sh->hws_max_nb_counters) {
@@ -659,9 +663,13 @@ mlx5_hws_cnt_pool_action_destroy(struct mlx5_hws_cnt_pool *cpool)
 	for (idx = 0; idx < cpool->dcs_mng.batch_total; idx++) {
 		struct mlx5_hws_cnt_dcs *dcs = &cpool->dcs_mng.dcs[idx];
 
-		if (dcs->dr_action != NULL) {
-			mlx5dr_action_destroy(dcs->dr_action);
-			dcs->dr_action = NULL;
+		if (dcs->root_action != NULL) {
+			mlx5dr_action_destroy(dcs->root_action);
+			dcs->root_action = NULL;
+		}
+		if (dcs->hws_action != NULL) {
+			mlx5dr_action_destroy(dcs->hws_action);
+			dcs->hws_action = NULL;
 		}
 	}
 }
@@ -673,11 +681,14 @@ mlx5_hws_cnt_pool_action_create(struct mlx5_priv *priv,
 	struct mlx5_hws_cnt_pool *hpool = mlx5_hws_cnt_host_pool(cpool);
 	uint32_t idx;
 	int ret = 0;
-	uint32_t flags;
+	uint32_t root_flags;
+	uint32_t hws_flags;
 
-	flags = MLX5DR_ACTION_FLAG_HWS_RX | MLX5DR_ACTION_FLAG_HWS_TX;
+	root_flags = MLX5DR_ACTION_FLAG_ROOT_RX | MLX5DR_ACTION_FLAG_ROOT_TX;
+	hws_flags = MLX5DR_ACTION_FLAG_HWS_RX | MLX5DR_ACTION_FLAG_HWS_TX;
 	if (priv->sh->config.dv_esw_en && priv->master) {
-		flags |= (is_unified_fdb(priv) ?
+		root_flags |= MLX5DR_ACTION_FLAG_ROOT_FDB;
+		hws_flags |= (is_unified_fdb(priv) ?
 				(MLX5DR_ACTION_FLAG_HWS_FDB_RX |
 				 MLX5DR_ACTION_FLAG_HWS_FDB_TX |
 				 MLX5DR_ACTION_FLAG_HWS_FDB_UNIFIED) :
@@ -687,10 +698,24 @@ mlx5_hws_cnt_pool_action_create(struct mlx5_priv *priv,
 		struct mlx5_hws_cnt_dcs *hdcs = &hpool->dcs_mng.dcs[idx];
 		struct mlx5_hws_cnt_dcs *dcs = &cpool->dcs_mng.dcs[idx];
 
-		dcs->dr_action = mlx5dr_action_create_counter(priv->dr_ctx,
+		dcs->hws_action = mlx5dr_action_create_counter(priv->dr_ctx,
+					(struct mlx5dr_devx_obj *)hdcs->obj,
+					hws_flags);
+		if (dcs->hws_action == NULL) {
+			mlx5_hws_cnt_pool_action_destroy(cpool);
+			ret = -ENOSYS;
+			break;
+		}
+
+		if (!cpool->is_root_supported) {
+			dcs->root_action = NULL;
+			continue;
+		}
+
+		dcs->root_action = mlx5dr_action_create_counter(priv->dr_ctx,
 					(struct mlx5dr_devx_obj *)hdcs->obj,
-					flags);
-		if (dcs->dr_action == NULL) {
+					root_flags);
+		if (dcs->root_action == NULL) {
 			mlx5_hws_cnt_pool_action_destroy(cpool);
 			ret = -ENOSYS;
 			break;
diff --git a/drivers/net/mlx5/mlx5_hws_cnt.h b/drivers/net/mlx5/mlx5_hws_cnt.h
index 8d7a9d34df..7d65ae82a0 100644
--- a/drivers/net/mlx5/mlx5_hws_cnt.h
+++ b/drivers/net/mlx5/mlx5_hws_cnt.h
@@ -31,7 +31,8 @@
 #define MLX5_HWS_AGE_IDX_MASK (RTE_BIT32(MLX5_INDIRECT_ACTION_TYPE_OFFSET) - 1)
 
 struct mlx5_hws_cnt_dcs {
-	void *dr_action;
+	struct mlx5dr_action *root_action; /* mlx5dr action used on root groups. */
+	struct mlx5dr_action *hws_action; /* mlx5dr action used on non-root groups. */
 	uint32_t batch_sz;
 	uint32_t iidx; /* internal index of first counter in this bulk. */
 	struct mlx5_devx_obj *obj;
@@ -113,6 +114,7 @@ struct __rte_cache_aligned mlx5_hws_cnt_pool {
 	struct mlx5_hws_cnt_pool_caches *cache;
 	uint64_t time_of_last_age_check;
 	struct mlx5_priv *priv;
+	uint32_t is_root_supported:1;
 };
 
 /* HWS AGE status. */
@@ -632,12 +634,21 @@ mlx5_hws_cnt_pool_get_size(struct mlx5_hws_cnt_pool *cpool)
 static __rte_always_inline int
 mlx5_hws_cnt_pool_get_action_offset(struct mlx5_hws_cnt_pool *cpool,
 		cnt_id_t cnt_id, struct mlx5dr_action **action,
-		uint32_t *offset)
+		uint32_t *offset, bool is_root)
 {
 	uint8_t idx = cnt_id >> MLX5_HWS_CNT_DCS_IDX_OFFSET;
 
 	idx &= MLX5_HWS_CNT_DCS_IDX_MASK;
-	*action = cpool->dcs_mng.dcs[idx].dr_action;
+	if (likely(!is_root)) {
+		*action = cpool->dcs_mng.dcs[idx].hws_action;
+	} else {
+		/*
+		 * Any table using counter on root group should be rejected on validation
+		 * when counter on root is not supported.
+		 */
+		MLX5_ASSERT(cpool->dcs_mng.dcs[idx].root_action != NULL);
+		*action = cpool->dcs_mng.dcs[idx].root_action;
+	}
 	*offset = cnt_id & MLX5_HWS_CNT_IDX_MASK;
 	return 0;
 }
-- 
2.39.5


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

end of thread, other threads:[~2025-11-04 17:48 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-11-04 17:46 [PATCH 0/5] net/mlx5: support count and age actions on root group Dariusz Sosnowski
2025-11-04 17:46 ` [PATCH 1/5] common/mlx5: detect DevX counters support in rdma-core Dariusz Sosnowski
2025-11-04 17:46 ` [PATCH 2/5] net/mlx5/hws: support counter from DevX bulk on root Dariusz Sosnowski
2025-11-04 17:46 ` [PATCH 3/5] net/mlx5: rework root group checks in table create Dariusz Sosnowski
2025-11-04 17:46 ` [PATCH 4/5] net/mlx5: improve error reporting on masked indirect actions Dariusz Sosnowski
2025-11-04 17:46 ` [PATCH 5/5] net/mlx5: support count and age on root group Dariusz Sosnowski

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