patch 'net/mlx5: fix job leak on indirect meter creation failure' has been queued to stable release 25.11.1
Kevin Traynor
ktraynor at redhat.com
Thu Feb 26 14:09:48 CET 2026
Hi,
FYI, your patch has been queued to stable release 25.11.1
Note it hasn't been pushed to http://dpdk.org/browse/dpdk-stable yet.
It will be pushed if I get no objections before 03/02/26. So please
shout if anyone has objections.
Also note that after the patch there's a diff of the upstream commit vs the
patch applied to the branch. This will indicate if there was any rebasing
needed to apply to the stable branch. If there were code changes for rebasing
(ie: not only metadata diffs), please double check that the rebase was
correctly done.
Queued patches are on a temporary branch at:
https://github.com/kevintraynor/dpdk-stable
This queued commit can be viewed at:
https://github.com/kevintraynor/dpdk-stable/commit/c9844e795b48cf4b0a1c711646984fefece82c27
Thanks.
Kevin
---
>From c9844e795b48cf4b0a1c711646984fefece82c27 Mon Sep 17 00:00:00 2001
From: Rongwei Liu <rongweil at nvidia.com>
Date: Mon, 8 Dec 2025 12:12:03 +0200
Subject: [PATCH] net/mlx5: fix job leak on indirect meter creation failure
[ upstream commit f5a92b70f545e830bf6baae9d15f88bb500481c4 ]
Indirect meter_mark action needs to allocate a job to track
asynchronous HW operation to create the meter object.
When meter_mark creation failed, the job may have been leaked
because there was no job cleanup code for sync API.
Add necessary code to check if meter_mark creation failed before or
after HW operation is enqueued and call job_put accordingly.
Fixes: 4359d9d1f76b ("net/mlx5: fix sync meter processing in HWS")
Signed-off-by: Rongwei Liu <rongweil at nvidia.com>
Acked-by: Dariusz Sosnowski <dsosnowski at nvidia.com>
---
drivers/net/mlx5/mlx5_flow_hw.c | 86 +++++++++++++++++++--------------
1 file changed, 49 insertions(+), 37 deletions(-)
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index bbd245ed9b..31886219b8 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -1871,8 +1871,9 @@ static rte_be32_t vlan_hdr_to_be32(const struct rte_flow_action *actions)
}
-static __rte_always_inline struct mlx5_aso_mtr *
+static __rte_always_inline int
flow_hw_meter_mark_alloc(struct rte_eth_dev *dev, uint32_t queue,
const struct rte_flow_action *action,
struct mlx5_hw_q_job *job, bool push,
+ struct mlx5_aso_mtr **aso_mtr,
struct rte_flow_error *error)
{
@@ -1880,5 +1881,4 @@ flow_hw_meter_mark_alloc(struct rte_eth_dev *dev, uint32_t queue,
struct mlx5_aso_mtr_pool *pool = priv->hws_mpool;
const struct rte_flow_action_meter_mark *meter_mark = action->conf;
- struct mlx5_aso_mtr *aso_mtr;
struct mlx5_flow_meter_info *fm;
uint32_t mtr_id = 0;
@@ -1886,47 +1886,50 @@ flow_hw_meter_mark_alloc(struct rte_eth_dev *dev, uint32_t queue,
MLX5_INDIRECT_ACTION_TYPE_OFFSET;
- if (priv->shared_host) {
- rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
- "Meter mark actions can only be created on the host port");
- return NULL;
- }
+ if (priv->shared_host)
+ return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "Meter mark actions can only be created on the host port");
+ MLX5_ASSERT(aso_mtr);
if (meter_mark->profile == NULL)
- return NULL;
- aso_mtr = mlx5_ipool_malloc(pool->idx_pool, &mtr_id);
- if (!aso_mtr) {
- rte_flow_error_set(error, ENOMEM,
- RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
- NULL,
- "failed to allocate aso meter entry");
+ return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "No Meter mark profile");
+
+ *aso_mtr = mlx5_ipool_malloc(pool->idx_pool, &mtr_id);
+ if (!*aso_mtr) {
if (mtr_id)
mlx5_ipool_free(pool->idx_pool, mtr_id);
- return NULL;
+ return rte_flow_error_set(error, ENOMEM,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL,
+ "failed to allocate aso meter entry");
}
/* Fill the flow meter parameters. */
- aso_mtr->type = ASO_METER_INDIRECT;
- fm = &aso_mtr->fm;
+ (*aso_mtr)->type = ASO_METER_INDIRECT;
+ fm = &(*aso_mtr)->fm;
fm->meter_id = mtr_id;
fm->profile = (struct mlx5_flow_meter_profile *)(meter_mark->profile);
fm->is_enable = meter_mark->state;
fm->color_aware = meter_mark->color_mode;
- aso_mtr->pool = pool;
- aso_mtr->state = (queue == MLX5_HW_INV_QUEUE) ?
+ (*aso_mtr)->pool = pool;
+ (*aso_mtr)->state = (queue == MLX5_HW_INV_QUEUE) ?
ASO_METER_WAIT : ASO_METER_WAIT_ASYNC;
- aso_mtr->offset = mtr_id - 1;
- aso_mtr->init_color = fm->color_aware ? RTE_COLORS : RTE_COLOR_GREEN;
+ (*aso_mtr)->offset = mtr_id - 1;
+ (*aso_mtr)->init_color = fm->color_aware ? RTE_COLORS : RTE_COLOR_GREEN;
job->action = (void *)(handle | mtr_id);
/* Update ASO flow meter by wqe. */
- if (mlx5_aso_meter_update_by_wqe(priv, queue, aso_mtr,
+ if (mlx5_aso_meter_update_by_wqe(priv, queue, *aso_mtr,
&priv->mtr_bulk, job, push)) {
mlx5_ipool_free(pool->idx_pool, mtr_id);
- return NULL;
+ return rte_flow_error_set(error, EBUSY,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL,
+ "Failed to enqueue ASO meter update");
}
/* Wait for ASO object completion. */
if (queue == MLX5_HW_INV_QUEUE &&
- mlx5_aso_mtr_wait(priv, aso_mtr, true)) {
+ mlx5_aso_mtr_wait(priv, *aso_mtr, true)) {
mlx5_ipool_free(pool->idx_pool, mtr_id);
- return NULL;
+ return -EIO;
}
- return aso_mtr;
+ return 0;
}
@@ -1942,18 +1945,20 @@ flow_hw_meter_mark_compile(struct rte_eth_dev *dev,
struct mlx5_priv *priv = dev->data->dev_private;
struct mlx5_aso_mtr_pool *pool = priv->hws_mpool;
- struct mlx5_aso_mtr *aso_mtr;
+ struct mlx5_aso_mtr *aso_mtr = NULL;
struct mlx5_hw_q_job *job =
flow_hw_action_job_init(priv, queue, NULL, NULL, NULL,
MLX5_HW_Q_JOB_TYPE_CREATE,
MLX5_HW_INDIRECT_TYPE_LEGACY, NULL);
+ int ret;
if (!job)
return -1;
- aso_mtr = flow_hw_meter_mark_alloc(dev, queue, action, job,
- true, error);
- if (!aso_mtr) {
- if (queue == MLX5_HW_INV_QUEUE)
- queue = CTRL_QUEUE_ID(priv);
- flow_hw_job_put(priv, job, queue);
+ ret = flow_hw_meter_mark_alloc(dev, queue, action, job, true, &aso_mtr, error);
+ if (ret) {
+ if (ret != -EIO) {
+ if (queue == MLX5_HW_INV_QUEUE)
+ queue = CTRL_QUEUE_ID(priv);
+ flow_hw_job_put(priv, job, queue);
+ }
return -1;
}
@@ -12769,5 +12774,5 @@ flow_hw_action_handle_create(struct rte_eth_dev *dev, uint32_t queue,
struct mlx5_priv *priv = dev->data->dev_private;
const struct rte_flow_action_age *age;
- struct mlx5_aso_mtr *aso_mtr;
+ struct mlx5_aso_mtr *aso_mtr = NULL;
cnt_id_t cnt_id;
uint32_t age_idx;
@@ -12775,4 +12780,5 @@ flow_hw_action_handle_create(struct rte_eth_dev *dev, uint32_t queue,
bool aso = false;
bool force_job = action->type == RTE_FLOW_ACTION_TYPE_METER_MARK;
+ int ret;
if (!mlx5_hw_ctx_validate(dev, error))
@@ -12830,7 +12836,13 @@ flow_hw_action_handle_create(struct rte_eth_dev *dev, uint32_t queue,
case RTE_FLOW_ACTION_TYPE_METER_MARK:
aso = true;
- aso_mtr = flow_hw_meter_mark_alloc(dev, queue, action, job, push, error);
- if (!aso_mtr)
+ ret = flow_hw_meter_mark_alloc(dev, queue, action, job, push, &aso_mtr, error);
+ if (ret) {
+ if (ret != -EIO) {
+ if (queue == MLX5_HW_INV_QUEUE)
+ queue = CTRL_QUEUE_ID(priv);
+ flow_hw_job_put(priv, job, queue);
+ }
break;
+ }
handle = (void *)(uintptr_t)job->action;
break;
@@ -12848,5 +12860,5 @@ flow_hw_action_handle_create(struct rte_eth_dev *dev, uint32_t queue,
break;
}
- if (job && !force_job) {
+ if (job && (!force_job || handle)) {
job->action = handle;
flow_hw_action_finalize(dev, queue, job, push, aso,
--
2.53.0
---
Diff of the applied patch vs upstream commit (please double-check if non-empty:
---
--- - 2026-02-26 10:16:51.204294961 +0000
+++ 0106-net-mlx5-fix-job-leak-on-indirect-meter-creation-fai.patch 2026-02-26 10:16:47.099459885 +0000
@@ -1 +1 @@
-From f5a92b70f545e830bf6baae9d15f88bb500481c4 Mon Sep 17 00:00:00 2001
+From c9844e795b48cf4b0a1c711646984fefece82c27 Mon Sep 17 00:00:00 2001
@@ -5,0 +6,2 @@
+[ upstream commit f5a92b70f545e830bf6baae9d15f88bb500481c4 ]
+
@@ -16 +17,0 @@
-Cc: stable at dpdk.org
@@ -25 +26 @@
-index 9cd6ae8a8d..22cc7efe65 100644
+index bbd245ed9b..31886219b8 100644
@@ -28 +29 @@
-@@ -1953,8 +1953,9 @@ static rte_be32_t vlan_hdr_to_be32(const struct rte_flow_action *actions)
+@@ -1871,8 +1871,9 @@ static rte_be32_t vlan_hdr_to_be32(const struct rte_flow_action *actions)
@@ -39 +40 @@
-@@ -1962,5 +1963,4 @@ flow_hw_meter_mark_alloc(struct rte_eth_dev *dev, uint32_t queue,
+@@ -1880,5 +1881,4 @@ flow_hw_meter_mark_alloc(struct rte_eth_dev *dev, uint32_t queue,
@@ -45 +46 @@
-@@ -1968,47 +1968,50 @@ flow_hw_meter_mark_alloc(struct rte_eth_dev *dev, uint32_t queue,
+@@ -1886,47 +1886,50 @@ flow_hw_meter_mark_alloc(struct rte_eth_dev *dev, uint32_t queue,
@@ -120 +121 @@
-@@ -2024,18 +2027,20 @@ flow_hw_meter_mark_compile(struct rte_eth_dev *dev,
+@@ -1942,18 +1945,20 @@ flow_hw_meter_mark_compile(struct rte_eth_dev *dev,
@@ -148 +149 @@
-@@ -12851,5 +12856,5 @@ flow_hw_action_handle_create(struct rte_eth_dev *dev, uint32_t queue,
+@@ -12769,5 +12774,5 @@ flow_hw_action_handle_create(struct rte_eth_dev *dev, uint32_t queue,
@@ -155 +156 @@
-@@ -12857,4 +12862,5 @@ flow_hw_action_handle_create(struct rte_eth_dev *dev, uint32_t queue,
+@@ -12775,4 +12780,5 @@ flow_hw_action_handle_create(struct rte_eth_dev *dev, uint32_t queue,
@@ -161 +162 @@
-@@ -12912,7 +12918,13 @@ flow_hw_action_handle_create(struct rte_eth_dev *dev, uint32_t queue,
+@@ -12830,7 +12836,13 @@ flow_hw_action_handle_create(struct rte_eth_dev *dev, uint32_t queue,
@@ -177 +178 @@
-@@ -12930,5 +12942,5 @@ flow_hw_action_handle_create(struct rte_eth_dev *dev, uint32_t queue,
+@@ -12848,5 +12860,5 @@ flow_hw_action_handle_create(struct rte_eth_dev *dev, uint32_t queue,
More information about the stable
mailing list