From 1dc3e8d9866e9328fcf5c0b727226161a2729c4d Mon Sep 17 00:00:00 2001 From: Maher Sanalla Date: Tue, 8 Jul 2025 17:23:09 +0300 Subject: [PATCH 1/2] mlx5: Add support for bulk flow counters in mlx5dv_create_flow Extend the mlx5dv_create_flow API to support bulk counter operations by introducing a new action type MLX5DV_FLOW_ACTION_COUNTERS_DEVX_WITH_OFFSET. This allows users to specify an offset within DEVX counter objects for more granular bulk counter object management. The implementation removes the previous auxiliary array approach (_mlx5dv_create_flow with actions_attr_aux parameter) in favor of a cleaner design that embeds offset information directly within the flow action structure. The mlx5dv_flow_action_attr union is extended with a bulk_obj member containing both the DEVX object and an offset, allowing also external rdma-core applications to use DEVX bulk counter via the offset. Existing applications using MLX5DV_FLOW_ACTION_COUNTERS_DEVX continue to work unchanged, while new applications can use the enhanced MLX5DV_FLOW_ACTION_COUNTERS_DEVX_WITH_OFFSET for bulk counter scenarios. Note that no kernel changes needed, since DEVX bulk counter object with offset is already supported. Signed-off-by: Maher Sanalla Signed-off-by: Alex Vesker Signed-off-by: Yishai Hadas --- providers/mlx5/dr_action.c | 7 +++--- providers/mlx5/dr_rule.c | 21 ++++------------ providers/mlx5/man/mlx5dv_create_flow.3.md | 13 +++++++++- providers/mlx5/mlx5.h | 13 +++++----- providers/mlx5/mlx5dv.h | 5 ++++ providers/mlx5/mlx5dv_dr.h | 3 +-- providers/mlx5/verbs.c | 29 +++++++++++++--------- 7 files changed, 49 insertions(+), 42 deletions(-) diff --git a/providers/mlx5/dr_action.c b/providers/mlx5/dr_action.c index 4377bf8ba..8fe966eef 100644 --- a/providers/mlx5/dr_action.c +++ b/providers/mlx5/dr_action.c @@ -975,8 +975,7 @@ int dr_actions_build_ste_arr(struct mlx5dv_dr_matcher *matcher, int dr_actions_build_attr(struct mlx5dv_dr_matcher *matcher, struct mlx5dv_dr_action *actions[], size_t num_actions, - struct mlx5dv_flow_action_attr *attr, - struct mlx5_flow_action_attr_aux *attr_aux) + struct mlx5dv_flow_action_attr *attr) { struct mlx5dv_dr_domain *dmn = matcher->tbl->dmn; int i; @@ -1026,8 +1025,8 @@ int dr_actions_build_attr(struct mlx5dv_dr_matcher *matcher, attr[i].obj = actions[i]->ctr.devx_obj; if (actions[i]->ctr.offset) { - attr_aux[i].type = MLX5_FLOW_ACTION_COUNTER_OFFSET; - attr_aux[i].offset = actions[i]->ctr.offset; + attr[i].type = MLX5DV_FLOW_ACTION_COUNTERS_DEVX_WITH_OFFSET; + attr[i].bulk_obj.offset = actions[i]->ctr.offset; } break; case DR_ACTION_TYP_TAG: diff --git a/providers/mlx5/dr_rule.c b/providers/mlx5/dr_rule.c index 61bc1e469..e324e90b5 100644 --- a/providers/mlx5/dr_rule.c +++ b/providers/mlx5/dr_rule.c @@ -1552,7 +1552,6 @@ dr_rule_create_rule_root(struct mlx5dv_dr_matcher *matcher, struct mlx5dv_dr_action *actions[]) { struct mlx5dv_flow_action_attr *attr; - struct mlx5_flow_action_attr_aux *attr_aux; struct mlx5dv_dr_rule *rule; int ret; @@ -1570,37 +1569,27 @@ dr_rule_create_rule_root(struct mlx5dv_dr_matcher *matcher, goto free_rule; } - attr_aux = calloc(num_actions, sizeof(*attr_aux)); - if (!attr_aux) { - errno = ENOMEM; - goto free_attr; - } - - ret = dr_actions_build_attr(matcher, actions, num_actions, attr, attr_aux); + ret = dr_actions_build_attr(matcher, actions, num_actions, attr); if (ret) - goto free_attr_aux; + goto free_attr; ret = dr_rule_add_action_members(rule, num_actions, actions); if (ret) - goto free_attr_aux; + goto free_attr; - rule->flow = _mlx5dv_create_flow(matcher->dv_matcher, + rule->flow = mlx5dv_create_flow(matcher->dv_matcher, value, num_actions, - attr, - attr_aux); + attr); if (!rule->flow) goto remove_action_members; free(attr); - free(attr_aux); return rule; remove_action_members: dr_rule_remove_action_members(rule); -free_attr_aux: - free(attr_aux); free_attr: free(attr); free_rule: diff --git a/providers/mlx5/man/mlx5dv_create_flow.3.md b/providers/mlx5/man/mlx5dv_create_flow.3.md index 1b7622a95..7334bafc9 100644 --- a/providers/mlx5/man/mlx5dv_create_flow.3.md +++ b/providers/mlx5/man/mlx5dv_create_flow.3.md @@ -46,6 +46,10 @@ struct mlx5dv_flow_action_attr { struct ibv_flow_action *action; uint32_t tag_value; struct mlx5dv_devx_obj *obj; + struct { + struct mlx5dv_devx_obj *obj; + uint32_t offset; + } bulk_obj; }; }; ``` @@ -65,6 +69,8 @@ struct mlx5dv_flow_action_attr { Steer the packet to the default miss destination. MLX5DV_FLOW_ACTION_DROP Action is dropping the matched packet. + MLX5DV_FLOW_ACTION_COUNTERS_DEVX_WITH_OFFSET + The DEVX bulk counter object and its counter offset for the matched packets. *qp* : QP passed, to be used with *type* *MLX5DV_FLOW_ACTION_DEST_IBV_QP*. @@ -78,7 +84,12 @@ struct mlx5dv_flow_action_attr { *MLX5DV_FLOW_ACTION_TAG* see *ibv_create_cq_ex(3)*. *obj* -: DEVX object, to be used with *type* *MLX5DV_FLOW_ACTION_DEST_DEVX* or by *MLX5DV_FLOW_ACTION_COUNTERS_DEVX*. +: DEVX object, to be used with *type* *MLX5DV_FLOW_ACTION_DEST_DEVX* or by *MLX5DV_FLOW_ACTION_COUNTERS_DEVX* + or by *MLX5DV_FLOW_ACTION_COUNTERS_DEVX_WITH_OFFSET*. + +*offset* +: offset to the target counter within a bulk DEVX object, to be used with *type* + *MLX5DV_FLOW_ACTION_COUNTERS_DEVX_WITH_OFFSET* # RETURN VALUE diff --git a/providers/mlx5/mlx5.h b/providers/mlx5/mlx5.h index d98db9aa1..34c18083b 100644 --- a/providers/mlx5/mlx5.h +++ b/providers/mlx5/mlx5.h @@ -962,8 +962,7 @@ struct ibv_flow * _mlx5dv_create_flow(struct mlx5dv_flow_matcher *flow_matcher, struct mlx5dv_flow_match_parameters *match_value, size_t num_actions, - struct mlx5dv_flow_action_attr actions_attr[], - struct mlx5_flow_action_attr_aux actions_attr_aux[]); + struct mlx5dv_flow_action_attr actions_attr[]); extern int mlx5_stall_num_loop; extern int mlx5_stall_cq_poll_min; @@ -1586,11 +1585,11 @@ struct mlx5_dv_context_ops { struct mlx5dv_flow_matcher *(*create_flow_matcher)(struct ibv_context *context, struct mlx5dv_flow_matcher_attr *attr); int (*destroy_flow_matcher)(struct mlx5dv_flow_matcher *flow_matcher); - struct ibv_flow *(*create_flow)(struct mlx5dv_flow_matcher *flow_matcher, - struct mlx5dv_flow_match_parameters *match_value, - size_t num_actions, - struct mlx5dv_flow_action_attr actions_attr[], - struct mlx5_flow_action_attr_aux actions_attr_aux[]); + struct ibv_flow *(*create_flow)( + struct mlx5dv_flow_matcher *flow_matcher, + struct mlx5dv_flow_match_parameters *match_value, + size_t num_actions, + struct mlx5dv_flow_action_attr actions_attr[]); struct mlx5dv_steering_anchor *(*create_steering_anchor)(struct ibv_context *conterxt, struct mlx5dv_steering_anchor_attr *attr); diff --git a/providers/mlx5/mlx5dv.h b/providers/mlx5/mlx5dv.h index 4e8d461e7..a24940196 100644 --- a/providers/mlx5/mlx5dv.h +++ b/providers/mlx5/mlx5dv.h @@ -783,6 +783,7 @@ enum mlx5dv_flow_action_type { MLX5DV_FLOW_ACTION_DEST_DEVX, MLX5DV_FLOW_ACTION_COUNTERS_DEVX, MLX5DV_FLOW_ACTION_DEFAULT_MISS, + MLX5DV_FLOW_ACTION_COUNTERS_DEVX_WITH_OFFSET, }; struct mlx5dv_flow_action_attr { @@ -793,6 +794,10 @@ struct mlx5dv_flow_action_attr { struct ibv_flow_action *action; uint32_t tag_value; struct mlx5dv_devx_obj *obj; + struct { + struct mlx5dv_devx_obj *obj; + uint32_t offset; + } bulk_obj; }; }; diff --git a/providers/mlx5/mlx5dv_dr.h b/providers/mlx5/mlx5dv_dr.h index 36fb67e28..8639b37c5 100644 --- a/providers/mlx5/mlx5dv_dr.h +++ b/providers/mlx5/mlx5dv_dr.h @@ -691,8 +691,7 @@ int dr_actions_build_ste_arr(struct mlx5dv_dr_matcher *matcher, int dr_actions_build_attr(struct mlx5dv_dr_matcher *matcher, struct mlx5dv_dr_action *actions[], size_t num_actions, - struct mlx5dv_flow_action_attr *attr, - struct mlx5_flow_action_attr_aux *attr_aux); + struct mlx5dv_flow_action_attr *attr); uint32_t dr_actions_reformat_get_id(struct mlx5dv_dr_action *action); diff --git a/providers/mlx5/verbs.c b/providers/mlx5/verbs.c index 49894ddc9..5694194e7 100644 --- a/providers/mlx5/verbs.c +++ b/providers/mlx5/verbs.c @@ -5615,8 +5615,7 @@ struct ibv_flow * _mlx5dv_create_flow(struct mlx5dv_flow_matcher *flow_matcher, struct mlx5dv_flow_match_parameters *match_value, size_t num_actions, - struct mlx5dv_flow_action_attr actions_attr[], - struct mlx5_flow_action_attr_aux actions_attr_aux[]) + struct mlx5dv_flow_action_attr actions_attr[]) { uint32_t flow_actions[CREATE_FLOW_MAX_FLOW_ACTIONS_SUPPORTED]; struct verbs_flow_action *vaction; @@ -5626,6 +5625,7 @@ _mlx5dv_create_flow(struct mlx5dv_flow_matcher *flow_matcher, bool have_dest_devx = false; bool have_flow_tag = false; bool have_counter = false; + bool have_bulk_counter = false; bool have_default = false; bool have_drop = false; int ret; @@ -5695,20 +5695,13 @@ _mlx5dv_create_flow(struct mlx5dv_flow_matcher *flow_matcher, have_flow_tag = true; break; case MLX5DV_FLOW_ACTION_COUNTERS_DEVX: - if (have_counter) { + if (have_counter || have_bulk_counter) { errno = EOPNOTSUPP; goto err; } fill_attr_in_objs_arr(cmd, MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX, &actions_attr[i].obj->handle, 1); - - if (actions_attr_aux && - actions_attr_aux[i].type == MLX5_FLOW_ACTION_COUNTER_OFFSET) - fill_attr_in_ptr_array(cmd, - MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX_OFFSET, - &actions_attr_aux[i].offset, 1); - have_counter = true; break; case MLX5DV_FLOW_ACTION_DEFAULT_MISS: @@ -5733,6 +5726,19 @@ _mlx5dv_create_flow(struct mlx5dv_flow_matcher *flow_matcher, MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DROP); have_drop = true; break; + case MLX5DV_FLOW_ACTION_COUNTERS_DEVX_WITH_OFFSET: + if (have_counter || have_bulk_counter) { + errno = EOPNOTSUPP; + goto err; + } + fill_attr_in_objs_arr(cmd, + MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX, + &actions_attr[i].bulk_obj.obj->handle, 1); + fill_attr_in_ptr_array(cmd, + MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX_OFFSET, + &actions_attr[i].bulk_obj.offset, 1); + have_bulk_counter = true; + break; default: errno = EOPNOTSUPP; goto err; @@ -5772,8 +5778,7 @@ mlx5dv_create_flow(struct mlx5dv_flow_matcher *flow_matcher, return dvops->create_flow(flow_matcher, match_value, num_actions, - actions_attr, - NULL); + actions_attr); } static struct mlx5dv_steering_anchor * From ec3d7f5ec6a44601e4e8f2fda1750ae3dbd76c48 Mon Sep 17 00:00:00 2001 From: Maher Sanalla Date: Mon, 28 Jul 2025 14:10:29 +0300 Subject: [PATCH 2/2] mlx5: Implement UAR fallback for td allocation In mlx5_alloc_td(), check if blueflame is supported by examining ctx->bf_reg_size before attempting UAR allocation. When blueflame is not supported (bf_reg_size == 0), fallback to using the shared nc (non-cached) UAR instead of trying to allocate a dedicated UAR. This prevents unnecessary dedicated UAR allocation attempts on devices that don't support blueflame, while ensuring td allocation succeeds by using the available non-cached singleton UAR. In mlx5_dealloc_td(), only detach dedicated UARs by checking the singleton flag to avoid incorrectly freeing the shared nc_uar. Signed-off-by: Maher Sanalla Signed-off-by: Yishai Hadas --- providers/mlx5/verbs.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/providers/mlx5/verbs.c b/providers/mlx5/verbs.c index 5694194e7..06da22907 100644 --- a/providers/mlx5/verbs.c +++ b/providers/mlx5/verbs.c @@ -448,6 +448,7 @@ static void mlx5_detach_dedicated_uar(struct ibv_context *context, struct mlx5_b struct ibv_td *mlx5_alloc_td(struct ibv_context *context, struct ibv_td_init_attr *init_attr) { + struct mlx5_context *ctx = to_mctx(context); struct mlx5_td *td; if (init_attr->comp_mask) { @@ -461,7 +462,12 @@ struct ibv_td *mlx5_alloc_td(struct ibv_context *context, struct ibv_td_init_att return NULL; } - td->bf = mlx5_attach_dedicated_uar(context, 0); + /* Check whether BlueFlame is supported on the device */ + if (ctx->bf_reg_size) + td->bf = mlx5_attach_dedicated_uar(context, 0); + else + td->bf = ctx->nc_uar; + if (!td->bf) { free(td); return NULL; @@ -481,7 +487,8 @@ int mlx5_dealloc_td(struct ibv_td *ib_td) if (atomic_load(&td->refcount) > 1) return EBUSY; - mlx5_detach_dedicated_uar(ib_td->context, td->bf); + if (!td->bf->singleton) + mlx5_detach_dedicated_uar(ib_td->context, td->bf); free(td); return 0;