|SUCCESS| net/mlx5: fix the eCPRI match on HWS root table
dpdklab at iol.unh.edu
dpdklab at iol.unh.edu
Thu Jun 4 11:05:37 CEST 2026
Test-Label: ai-code-review
Test-Status: SUCCESS
https://dpdk.org/patch/164963
_AI Code Review_
=== Patch Review: series.patch (via Claude) ===
Review date: 2026-06-04
commit 93c7d4c22628
Author: Bing Zhao <bingz at nvidia.com>
net/mlx5: fix the eCPRI match on HWS root table
This patch fixes eCPRI matching behavior on HWS root tables by
introducing per-table flags to track whether eCPRI type and message body
fields are masked. The patch modifies both matcher creation and rule
translation paths.
> diff --git a/drivers/net/mlx5/hws/mlx5dr_matcher.c b/drivers/net/mlx5/hws/mlx5dr_matcher.c
> index 8c07ea8882..511f394448 100644
> --- a/drivers/net/mlx5/hws/mlx5dr_matcher.c
> +++ b/drivers/net/mlx5/hws/mlx5dr_matcher.c
> @@ -1381,6 +1381,7 @@ static int mlx5dr_matcher_init_root(struct mlx5dr_matcher *matcher)
> LIST_INSERT_HEAD(&matcher->tbl->head, matcher, next);
> pthread_spin_unlock(&ctx->ctrl_lock);
>
> + matcher->hws_root_match_flags = flow_attr.hws_root_match_flags;
Does this code correctly initialize hws_root_match_flags? The
flow_attr.hws_root_match_flags field is read here but I don't see where
it's being set before this point in mlx5dr_matcher_init_root().
[ ... ]
> diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
> index c9e72a33d6..39c85eb9a4 100644
> --- a/drivers/net/mlx5/mlx5_flow.h
> +++ b/drivers/net/mlx5/mlx5_flow.h
> @@ -117,6 +117,9 @@ enum mlx5_indirect_type {
> ((struct rte_flow_action_handle *)(uintptr_t) \
> ((MLX5_INDIRECT_ACTION_TYPE_CT << MLX5_INDIRECT_ACTION_TYPE_OFFSET) | (index)))
>
> +#define MLX5_EMPTY_ECPRI_TYPE_MASK RTE_BIT32(0)
> +#define MLX5_EMPTY_ECPRI_BODY_MASK RTE_BIT32(1)
> +
> enum mlx5_indirect_list_type {
> MLX5_INDIRECT_ACTION_LIST_TYPE_ERR = 0,
> MLX5_INDIRECT_ACTION_LIST_TYPE_LEGACY = 1,
> @@ -1264,6 +1267,7 @@ struct mlx5_flow_attr {
> /* Action flags, used by priority adjustment. */
> uint32_t act_flags;
> uint32_t tbl_type; /* Flow table type. */
> + uint32_t hws_root_match_flags;
> };
[ ... ]
> @@ -1985,6 +1989,8 @@ struct mlx5_flow_workspace {
> uint32_t skip_matcher_reg:1;
> /* Indicates if need to skip matcher register in translate. */
> uint32_t mark:1; /* Indicates if flow contains mark action. */
> + uint32_t empty_ecpri_type_mask:1; /* Indicates if eCPRI type was not masked. */
> + uint32_t empty_ecpri_body_mask:1; /* Indicates if 1st DW of eCPRI payload was not masked. */
These comments exceed 79 characters. The lines should be wrapped or the
comments shortened.
[ ... ]
> diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
> index c2a2874913..307354c886 100644
> --- a/drivers/net/mlx5/mlx5_flow_dv.c
> +++ b/drivers/net/mlx5/mlx5_flow_dv.c
[ ... ]
> @@ -11401,6 +11401,20 @@ flow_dv_translate_item_gtp_psc(void *key, const struct rte_flow_item *item,
> return 0;
> }
>
> +
> +static inline void
> +flow_dv_set_ecpri_sample1(void *misc4_v,
> + const struct rte_flow_item_ecpri *ecpri_m,
> + const struct rte_flow_item_ecpri *ecpri_v,
> + uint32_t sample1)
> +{
> + void *dw_v;
> + dw_v = MLX5_ADDR_OF(fte_match_set_misc4, misc4_v, prog_sample_field_value_1);
> + *(uint32_t *)dw_v = ecpri_v->hdr.dummy[0] & ecpri_m->hdr.dummy[0];
This code violates the DPDK C11 style forbidden token policy. Direct
casts to modify pointers like *(uint32_t *)dw_v should be avoided. Can
this use MLX5_SET or similar macros instead?
> + /* Sample#1, to match message body, offset 4. */
> + MLX5_SET(fte_match_set_misc4, misc4_v, prog_sample_field_id_1, sample1);
> +}
> +
> /**
> * Add eCPRI item to matcher and to the value.
> *
[ ... ]
> @@ -11418,6 +11432,7 @@ flow_dv_translate_item_gtp_psc(void *key, const struct rte_flow_item *item,
> static void
> flow_dv_translate_item_ecpri(struct rte_eth_dev *dev, void *key,
> const struct rte_flow_item *item,
> + struct mlx5_dv_matcher_workspace *wks,
> uint64_t last_item, uint32_t key_type)
> {
> struct mlx5_priv *priv = dev->data->dev_private;
[ ... ]
> + /* HWS matcher does need a non-empty mask. */
Does this comment have a typo? Should it say "does NOT need"?
> if (MLX5_ITEM_VALID(item, key_type))
> return;
> - MLX5_ITEM_UPDATE(item, key_type, ecpri_v, ecpri_m,
> - &rte_flow_item_ecpri_mask);
> + MLX5_ITEM_UPDATE(item, key_type, ecpri_v, ecpri_m, &rte_flow_item_ecpri_mask);
[ ... ]
> + if (key_type == MLX5_SET_MATCHER_HS_M) {
> + if (!ecpri_m->hdr.common.u32) {
> + *wks->p_root_flags |= MLX5_EMPTY_ECPRI_TYPE_MASK;
> + return;
> + }
> + /* Initialized with 0, this should not hit. */
> + *wks->p_root_flags &= ~MLX5_EMPTY_ECPRI_TYPE_MASK;
> + }
> + if (key_type == MLX5_SET_MATCHER_HS_V && (*wks->p_root_flags & MLX5_EMPTY_ECPRI_TYPE_MASK))
> + return;
Does this code have proper NULL pointer checks? Can wks or
wks->p_root_flags ever be NULL when key_type is MLX5_SET_MATCHER_HS_M
or MLX5_SET_MATCHER_HS_V?
> + if ((key_type & MLX5_SET_MATCHER_SW) && !ecpri_m->hdr.common.u32)
> return;
> samples = priv->sh->ecpri_parser.ids;
> /* Need to take the whole DW as the mask to fill the entry. */
[ ... ]
> @@ -11473,27 +11502,40 @@ flow_dv_translate_item_ecpri(struct rte_eth_dev *dev, void *key,
> * Checking if message body part needs to be matched.
> * Some wildcard rules only matching type field should be supported.
> */
> - if (ecpri_m->hdr.dummy[0]) {
> - if (key_type == MLX5_SET_MATCHER_SW_M)
> - common.u32 = rte_be_to_cpu_32(ecpri_vv->hdr.common.u32);
> - else
> - common.u32 = rte_be_to_cpu_32(ecpri_v->hdr.common.u32);
> + if (key_type == MLX5_SET_MATCHER_HS_M) {
> + if (!ecpri_m->hdr.dummy[0]) {
> + *wks->p_root_flags |= MLX5_EMPTY_ECPRI_BODY_MASK;
> + return;
> + }
> + *wks->p_root_flags &= ~MLX5_EMPTY_ECPRI_BODY_MASK;
> + }
> + if (key_type == MLX5_SET_MATCHER_HS_V && (*wks->p_root_flags & MLX5_EMPTY_ECPRI_BODY_MASK))
> + return;
> + if (key_type & MLX5_SET_MATCHER_SW) {
> + if (!ecpri_m->hdr.dummy[0])
> + return;
> + common.u32 = rte_be_to_cpu_32(ecpri_vv->hdr.common.u32);
> + } else if (key_type == MLX5_SET_MATCHER_HS_V) {
> + common.u32 = rte_be_to_cpu_32(ecpri_v->hdr.common.u32);
> + }
> + if (key_type != MLX5_SET_MATCHER_HS_M) {
> switch (common.type) {
> case RTE_ECPRI_MSG_TYPE_IQ_DATA:
> case RTE_ECPRI_MSG_TYPE_RTC_CTRL:
> case RTE_ECPRI_MSG_TYPE_DLY_MSR:
> - dw_v = MLX5_ADDR_OF(fte_match_set_misc4, misc4_v,
> - prog_sample_field_value_1);
> - *(uint32_t *)dw_v = ecpri_v->hdr.dummy[0] &
> - ecpri_m->hdr.dummy[0];
> - /* Sample#1, to match message body, offset 4. */
> - MLX5_SET(fte_match_set_misc4, misc4_v,
> - prog_sample_field_id_1, samples[1]);
> + flow_dv_set_ecpri_sample1(misc4_v, ecpri_v, ecpri_m, samples[1]);
Does the function call flow_dv_set_ecpri_sample1() swap the order of
ecpri_v and ecpri_m parameters? The function signature shows ecpri_m
comes before ecpri_v, but this call passes ecpri_v first.
> break;
> default:
> /* Others, do not match any sample ID. */
> break;
> }
> + } else {
> + /* When MLX5_SET_MATCHER_HS_M on root table (default value),
> + * the sample ID and mask should be set, or else prog_sample_field_id_1 will
> + * be zero and a mismatch with the HWS rule.
These comment lines exceed 79 characters and should be wrapped.
> + * Empty body mask for a matcher returns directly in the previous lines.
> + */
> + flow_dv_set_ecpri_sample1(misc4_v, ecpri_v, ecpri_m, samples[1]);
> }
> }
[ ... ]
> @@ -14698,6 +14740,7 @@ mlx5_flow_dv_translate_items_hws_impl(const struct rte_flow_item *items,
> .attr = &rattr,
> .rss_desc = &rss_desc,
> .group = attr->group,
> + .p_root_flags = &attr->hws_root_match_flags,
> };
> int ret = 0;
>
More information about the test-report
mailing list