diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index ad9a2f2273..819831cff8 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -1178,6 +1178,13 @@ mlx5_flow_async_action_list_handle_query_update(struct rte_eth_dev *dev,
 						enum rte_flow_query_update_mode mode,
 						void *user_data,
 						struct rte_flow_error *error);
+static int
+mlx5_flow_calc_table_hash(struct rte_eth_dev *dev,
+			  const struct rte_flow_template_table *table,
+			  const struct rte_flow_item pattern[],
+			  uint8_t pattern_template_index,
+			  uint32_t *hash, struct rte_flow_error *error);
+
 static const struct rte_flow_ops mlx5_flow_ops = {
 	.validate = mlx5_flow_validate,
 	.create = mlx5_flow_create,
@@ -1231,6 +1238,7 @@ static const struct rte_flow_ops mlx5_flow_ops = {
 		mlx5_flow_action_list_handle_query_update,
 	.async_action_list_handle_query_update =
 		mlx5_flow_async_action_list_handle_query_update,
+	.flow_calc_table_hash = mlx5_flow_calc_table_hash,
 };
 
 /* Tunnel information. */
@@ -11058,6 +11066,30 @@ mlx5_flow_async_action_list_handle_query_update(struct rte_eth_dev *dev,
 }
 
 
+static int
+mlx5_flow_calc_table_hash(struct rte_eth_dev *dev,
+			  const struct rte_flow_template_table *table,
+			  const struct rte_flow_item pattern[],
+			  uint8_t pattern_template_index,
+			  uint32_t *hash, struct rte_flow_error *error)
+{
+	struct rte_flow_attr attr = { .transfer = 0 };
+	enum mlx5_flow_drv_type drv_type = flow_get_drv_type(dev, &attr);
+	const struct mlx5_flow_driver_ops *fops;
+
+	if (drv_type == MLX5_FLOW_TYPE_MIN || drv_type == MLX5_FLOW_TYPE_MAX)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  NULL, "invalid driver type");
+	fops = flow_get_drv_ops(drv_type);
+	if (!fops || !fops->action_query_update)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  NULL, "no query_update handler");
+	return fops->flow_calc_table_hash(dev, table, pattern, pattern_template_index,
+					  hash, error);
+}
+
 /**
  * Destroy all indirect actions (shared RSS).
  *
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index aea8b38f39..64e2fc6f04 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -2059,6 +2059,13 @@ typedef int
 			const void **update, void **query,
 			enum rte_flow_query_update_mode mode,
 			void *user_data, struct rte_flow_error *error);
+typedef int
+(*mlx5_flow_calc_table_hash_t)
+			(struct rte_eth_dev *dev,
+			 const struct rte_flow_template_table *table,
+			 const struct rte_flow_item pattern[],
+			 uint8_t pattern_template_index,
+			 uint32_t *hash, struct rte_flow_error *error);
 
 struct mlx5_flow_driver_ops {
 	mlx5_flow_validate_t validate;
@@ -2130,6 +2137,7 @@ struct mlx5_flow_driver_ops {
 		action_list_handle_query_update;
 	mlx5_flow_async_action_list_handle_query_update_t
 		async_action_list_handle_query_update;
+	mlx5_flow_calc_table_hash_t flow_calc_table_hash;
 };
 
 /* mlx5_flow.c */
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index b0ef14c14e..67ef272a2d 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -2773,7 +2773,7 @@ flow_hw_actions_construct(struct rte_eth_dev *dev,
 
 static const struct rte_flow_item *
 flow_hw_get_rule_items(struct rte_eth_dev *dev,
-		       struct rte_flow_template_table *table,
+		       const struct rte_flow_template_table *table,
 		       const struct rte_flow_item items[],
 		       uint8_t pattern_template_index,
 		       struct mlx5_hw_q_job *job)
@@ -10143,6 +10143,34 @@ flow_hw_action_list_handle_query_update(struct rte_eth_dev *dev,
 					 update, query, mode, NULL, error);
 }
 
+static int
+flow_hw_calc_table_hash(struct rte_eth_dev *dev,
+			 const struct rte_flow_template_table *table,
+			 const struct rte_flow_item pattern[],
+			 uint8_t pattern_template_index,
+			 uint32_t *hash, struct rte_flow_error *error)
+{
+	const struct rte_flow_item *items;
+	/* Temp job to allow adding missing items */
+	static struct rte_flow_item tmp_items[MLX5_HW_MAX_ITEMS];
+	static struct mlx5_hw_q_job job = {.items = tmp_items};
+	int res;
+
+	items = flow_hw_get_rule_items(dev, table, pattern,
+				       pattern_template_index,
+				       &job);
+	res = mlx5dr_rule_hash_calculate(table->matcher, items,
+					 pattern_template_index,
+					 MLX5DR_RULE_HASH_CALC_MODE_RAW,
+					 hash);
+	if (res)
+		return rte_flow_error_set(error, res,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					  NULL,
+					  "hash could not be calculated");
+	return 0;
+}
+
 const struct mlx5_flow_driver_ops mlx5_flow_hw_drv_ops = {
 	.info_get = flow_hw_info_get,
 	.configure = flow_hw_configure,
@@ -10186,6 +10214,7 @@ const struct mlx5_flow_driver_ops mlx5_flow_hw_drv_ops = {
 	.get_q_aged_flows = flow_hw_get_q_aged_flows,
 	.item_create = flow_dv_item_create,
 	.item_release = flow_dv_item_release,
+	.flow_calc_table_hash = flow_hw_calc_table_hash,
 };
 
 /**
