[PATCH 6/9] net/mlx5: lazily allocate HWS push VLAN action

Dariusz Sosnowski dsosnowski at nvidia.com
Wed Feb 25 12:59:14 CET 2026


HWS push_vlan action is used to implement OF_PUSH_VLAN rte_flow action.
It was allocated either on port start or on rte_flow_configure().
This could cause unnecessary FW resource usage
if user did not use any OF_PUSH_VLAN action.

This patch extends global actions internal API,
introduced in previous commits, to allow lazy allocation
of HWS push_vlan action. It will be allocated on first use
and will be allocated per domain to minimize FW resource usage.

Signed-off-by: Dariusz Sosnowski <dsosnowski at nvidia.com>
Acked-by: Ori Kam <orika at nvidia.com>
---
 drivers/net/mlx5/mlx5.h                    |  1 -
 drivers/net/mlx5/mlx5_flow_hw.c            | 78 +++-------------------
 drivers/net/mlx5/mlx5_hws_global_actions.c | 21 ++++++
 drivers/net/mlx5/mlx5_hws_global_actions.h |  5 ++
 4 files changed, 36 insertions(+), 69 deletions(-)

diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 9e46a8cee8..94b4cb0d7b 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -2110,7 +2110,6 @@ struct mlx5_priv {
 	LIST_HEAD(flow_hw_tbl, rte_flow_template_table) flow_hw_tbl;
 	/* HW steering rte flow group list header */
 	LIST_HEAD(flow_hw_grp, mlx5_flow_group) flow_hw_grp;
-	struct mlx5dr_action *hw_push_vlan[MLX5DR_TABLE_TYPE_MAX];
 	struct mlx5dr_action **hw_vport;
 	/* HWS global actions. */
 	struct mlx5_hws_global_actions hw_global_actions;
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index 21c61bce90..2ecae1b7e7 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -2737,8 +2737,16 @@ __flow_hw_translate_actions_template(struct rte_eth_dev *dev,
 			mlx5_flow_hw_rxq_flag_set(dev, true);
 			break;
 		case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
-			acts->rule_acts[dr_pos].action =
-				priv->hw_push_vlan[type];
+			dr_action = mlx5_hws_global_action_push_vlan_get(priv, type, is_root);
+			if (dr_action == NULL) {
+				DRV_LOG(ERR, "port %u failed to allocate push VLAN action",
+					priv->dev_data->port_id);
+				rte_flow_error_set(&sub_error, ENOMEM,
+						   RTE_FLOW_ERROR_TYPE_STATE, NULL,
+						   "failed to allocate push VLAN action");
+				goto err;
+			}
+			acts->rule_acts[dr_pos].action = dr_action;
 			if (is_template_masked_push_vlan(masks->conf))
 				acts->rule_acts[dr_pos].push_vlan.vlan_hdr =
 					vlan_hdr_to_be32(actions);
@@ -11378,65 +11386,6 @@ mlx5_flow_ct_init(struct rte_eth_dev *dev,
 	return ret;
 }
 
-static void
-flow_hw_destroy_vlan(struct rte_eth_dev *dev)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	enum mlx5dr_table_type i;
-
-	for (i = MLX5DR_TABLE_TYPE_NIC_RX; i < MLX5DR_TABLE_TYPE_MAX; i++) {
-		if (priv->hw_push_vlan[i]) {
-			mlx5dr_action_destroy(priv->hw_push_vlan[i]);
-			priv->hw_push_vlan[i] = NULL;
-		}
-	}
-}
-
-static int
-_create_vlan(struct mlx5_priv *priv, enum mlx5dr_table_type type)
-{
-	const enum mlx5dr_action_flags flags[MLX5DR_TABLE_TYPE_MAX] = {
-		MLX5DR_ACTION_FLAG_HWS_RX,
-		MLX5DR_ACTION_FLAG_HWS_TX,
-		MLX5DR_ACTION_FLAG_HWS_FDB,
-		MLX5DR_ACTION_FLAG_HWS_FDB_RX,
-		MLX5DR_ACTION_FLAG_HWS_FDB_TX,
-		MLX5DR_ACTION_FLAG_HWS_FDB_UNIFIED,
-	};
-
-	/* rte_errno is set in the mlx5dr_action* functions. */
-	priv->hw_push_vlan[type] =
-		mlx5dr_action_create_push_vlan(priv->dr_ctx, flags[type]);
-	if (!priv->hw_push_vlan[type])
-		return -rte_errno;
-	return 0;
-}
-
-static int
-flow_hw_create_vlan(struct rte_eth_dev *dev)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	enum mlx5dr_table_type i, from, to;
-	int rc;
-	bool unified_fdb = is_unified_fdb(priv);
-
-	for (i = MLX5DR_TABLE_TYPE_NIC_RX; i <= MLX5DR_TABLE_TYPE_NIC_TX; i++) {
-		rc = _create_vlan(priv, i);
-		if (rc)
-			return rc;
-	}
-	from = unified_fdb ? MLX5DR_TABLE_TYPE_FDB_RX : MLX5DR_TABLE_TYPE_FDB;
-	to = unified_fdb ? MLX5DR_TABLE_TYPE_FDB_UNIFIED : MLX5DR_TABLE_TYPE_FDB;
-	if (priv->sh->config.dv_esw_en && priv->master) {
-		for (i = from; i <= to; i++) {
-			rc = _create_vlan(priv, i);
-			if (rc)
-				return rc;
-		}
-	}
-	return 0;
-}
-
 void
 mlx5_flow_hw_cleanup_ctrl_rx_tables(struct rte_eth_dev *dev)
 {
@@ -11992,7 +11941,6 @@ __mlx5_flow_hw_resource_release(struct rte_eth_dev *dev, bool ctx_close)
 	if (priv->hw_def_miss)
 		mlx5dr_action_destroy(priv->hw_def_miss);
 	flow_hw_destroy_nat64_actions(priv);
-	flow_hw_destroy_vlan(dev);
 	flow_hw_destroy_send_to_kernel_action(priv);
 	flow_hw_free_vport_actions(priv);
 	if (priv->acts_ipool) {
@@ -12452,12 +12400,6 @@ __flow_hw_configure(struct rte_eth_dev *dev,
 		if (ret < 0)
 			goto err;
 	}
-	ret = flow_hw_create_vlan(dev);
-	if (ret) {
-		rte_flow_error_set(error, -ret, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				   NULL, "Failed to VLAN actions.");
-		goto err;
-	}
 	if (flow_hw_should_create_nat64_actions(priv)) {
 		if (flow_hw_create_nat64_actions(priv, error))
 			goto err;
diff --git a/drivers/net/mlx5/mlx5_hws_global_actions.c b/drivers/net/mlx5/mlx5_hws_global_actions.c
index 236e6f1d1a..2bbfa5a24c 100644
--- a/drivers/net/mlx5/mlx5_hws_global_actions.c
+++ b/drivers/net/mlx5/mlx5_hws_global_actions.c
@@ -42,6 +42,7 @@ mlx5_hws_global_actions_cleanup(struct mlx5_priv *priv)
 	global_actions_array_cleanup(priv, &priv->hw_global_actions.drop, "drop");
 	global_actions_array_cleanup(priv, &priv->hw_global_actions.tag, "tag");
 	global_actions_array_cleanup(priv, &priv->hw_global_actions.pop_vlan, "pop_vlan");
+	global_actions_array_cleanup(priv, &priv->hw_global_actions.push_vlan, "push_vlan");
 
 	rte_spinlock_unlock(&priv->hw_global_actions.lock);
 }
@@ -70,6 +71,13 @@ action_create_pop_vlan_cb(struct mlx5dr_context *ctx,
 	return mlx5dr_action_create_pop_vlan(ctx, action_flags);
 }
 
+static struct mlx5dr_action *
+action_create_push_vlan_cb(struct mlx5dr_context *ctx,
+			   uint32_t action_flags)
+{
+	return mlx5dr_action_create_push_vlan(ctx, action_flags);
+}
+
 static struct mlx5dr_action *
 global_action_get(struct mlx5_priv *priv,
 		  struct mlx5_hws_global_actions_array *array,
@@ -145,3 +153,16 @@ mlx5_hws_global_action_pop_vlan_get(struct mlx5_priv *priv,
 				 is_root,
 				 action_create_pop_vlan_cb);
 }
+
+struct mlx5dr_action *
+mlx5_hws_global_action_push_vlan_get(struct mlx5_priv *priv,
+				     enum mlx5dr_table_type table_type,
+				     bool is_root)
+{
+	return global_action_get(priv,
+				 &priv->hw_global_actions.push_vlan,
+				 "push_vlan",
+				 table_type,
+				 is_root,
+				 action_create_push_vlan_cb);
+}
diff --git a/drivers/net/mlx5/mlx5_hws_global_actions.h b/drivers/net/mlx5/mlx5_hws_global_actions.h
index d04ebc42be..4281ba701c 100644
--- a/drivers/net/mlx5/mlx5_hws_global_actions.h
+++ b/drivers/net/mlx5/mlx5_hws_global_actions.h
@@ -27,6 +27,7 @@ struct mlx5_hws_global_actions {
 	struct mlx5_hws_global_actions_array drop;
 	struct mlx5_hws_global_actions_array tag;
 	struct mlx5_hws_global_actions_array pop_vlan;
+	struct mlx5_hws_global_actions_array push_vlan;
 	rte_spinlock_t lock;
 };
 
@@ -46,4 +47,8 @@ struct mlx5dr_action *mlx5_hws_global_action_pop_vlan_get(struct mlx5_priv *priv
 							  enum mlx5dr_table_type table_type,
 							  bool is_root);
 
+struct mlx5dr_action *mlx5_hws_global_action_push_vlan_get(struct mlx5_priv *priv,
+							   enum mlx5dr_table_type table_type,
+							   bool is_root);
+
 #endif /* !RTE_PMD_MLX5_HWS_GLOBAL_ACTIONS_H_ */
-- 
2.47.3



More information about the dev mailing list