|SUCCESS| [v2] net/mlx5: prepend implicit items in sync flow creation path
dpdklab at iol.unh.edu
dpdklab at iol.unh.edu
Fri Apr 24 22:09:29 CEST 2026
Test-Label: ai-code-review
Test-Status: SUCCESS
https://dpdk.org/patch/163285
_AI Code Review_
=== Patch Review: series.patch (via Claude) ===
Review date: 2026-04-24
Reviewing patch: net/mlx5: prepend implicit items in sync flow creation path
Author: Maxime Peim <maxime.peim at gmail.com>
This patch adds implicit item prepending to the sync flow creation path
(flow_hw_list_create) to match behavior in the async template path,
ensuring flow rules are scoped to the correct representor port in eSwitch
mode. It also fixes a bug where metadata split failure incorrectly
returned a negative int cast to uintptr_t.
> diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
> index bca5b2769e..21cadcc5bd 100644
> --- a/drivers/net/mlx5/mlx5_flow_hw.c
> +++ b/drivers/net/mlx5/mlx5_flow_hw.c
[ ... ]
> @@ -14275,6 +14275,7 @@ static uintptr_t flow_hw_list_create(struct rte_eth_dev *dev,
> uint64_t item_flags = 0;
> uint64_t action_flags = mlx5_flow_hw_action_flags_get(actions, &qrss, &mark,
> &encap_idx, &actions_n, error);
> + struct mlx5_priv *priv = dev->data->dev_private;
> struct mlx5_flow_hw_split_resource resource = {
> .suffix = {
> .attr = attr,
> @@ -14282,6 +14283,28 @@ static uintptr_t flow_hw_list_create(struct rte_eth_dev *dev,
> .actions = actions,
> },
> };
> + struct rte_flow_item *prepend_items = NULL;
> + struct rte_flow_item_ethdev port_spec = {.port_id = dev->data->port_id};
> + struct rte_flow_item port = {
> + .type = RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT,
> + .spec = &port_spec,
> + .mask = &rte_flow_item_ethdev_mask,
> + };
> + struct mlx5_rte_flow_item_tag tag_v = {
> + .id = REG_C_0,
> + .data = flow_hw_tx_tag_regc_value(dev),
> + };
> + struct mlx5_rte_flow_item_tag tag_m = {
> + .id = REG_C_0,
> + .data = flow_hw_tx_tag_regc_mask(dev),
> + };
> + struct rte_flow_item tag = {
> + .type = (enum rte_flow_item_type)MLX5_RTE_FLOW_ITEM_TYPE_TAG,
> + .spec = &tag_v,
> + .mask = &tag_m,
> + .last = NULL,
> + };
> + uint32_t nb_items;
Does the declaration order comply with the reverse christmas tree style
required by the coding standards? The nb_items declaration appears after
the struct rte_flow_item tag declaration, but nb_items is a shorter
declaration.
> struct rte_flow_error shadow_error = {0, };
[ ... ]
> @@ -14296,13 +14319,48 @@ static uintptr_t flow_hw_list_create(struct rte_eth_dev *dev,
> if (ret < 0)
> return 0;
>
> + nb_items = ret;
> +
> + /*
> + * In eSwitch mode, the async (template) path automatically prepends
> + * implicit items to scope flow rules to the correct representor port:
> + * - Ingress: REPRESENTED_PORT item matching dev->data->port_id
> + * - Egress: REG_C_0 TAG item matching the port's tx tag value
> + * Mirror this behavior in the sync path so rules are not shared
> + * across all eSwitch ports.
> + */
> + if (priv->sh->config.dv_esw_en &&
> + attr->ingress && !attr->egress && !attr->transfer) {
> + prepend_items = flow_hw_prepend_item(items, nb_items,
> + &port, error);
> + if (!prepend_items)
Does this implicit NULL comparison comply with the coding style
guideline requiring explicit NULL checks? The style guide requires
"if (prepend_items == NULL)" rather than "if (!prepend_items)".
> + return 0;
> + items = prepend_items;
> + } else if (priv->sh->config.dv_esw_en &&
> + !attr->ingress && attr->egress && !attr->transfer) {
> + if (item_flags & MLX5_FLOW_ITEM_SQ) {
> + DRV_LOG(DEBUG,
> + "Port %u omitting implicit REG_C_0 match for egress "
> + "pattern template",
> + dev->data->port_id);
> + goto setup_pattern;
> + }
> + prepend_items = flow_hw_prepend_item(items, nb_items,
> + &tag, error);
> + if (!prepend_items)
Does this implicit NULL comparison comply with the coding style?
> + return 0;
> + items = prepend_items;
> + }
> +setup_pattern:
> RTE_SET_USED(encap_idx);
> if (!error)
Does this implicit NULL comparison comply with the coding style?
> error = &shadow_error;
> split = mlx5_flow_nta_split_metadata(dev, attr, actions, qrss, action_flags,
> actions_n, external, &resource, error);
> - if (split < 0)
> - return split;
> + if (split < 0) {
> + mlx5_free(prepend_items);
> + return 0;
> + }
>
> /* Update the metadata copy table - MLX5_FLOW_MREG_CP_TABLE_GROUP */
> if (((attr->ingress && attr->group != MLX5_FLOW_MREG_CP_TABLE_GROUP) ||
> @@ -14315,8 +14373,10 @@ static uintptr_t flow_hw_list_create(struct rte_eth_dev *dev,
> if (action_flags & MLX5_FLOW_ACTION_SAMPLE) {
> flow = mlx5_nta_sample_flow_list_create(dev, type, attr, items, actions,
> item_flags, action_flags, error);
> - if (flow != NULL)
> + if (flow != NULL) {
> + mlx5_free(prepend_items);
> return (uintptr_t)flow;
> + }
> goto free;
> }
> if (action_flags & MLX5_FLOW_ACTION_RSS) {
> @@ -14328,8 +14388,10 @@ static uintptr_t flow_hw_list_create(struct rte_eth_dev *dev,
> if (flow) {
Does this implicit non-NULL comparison comply with the coding style?
Should this be "if (flow != NULL)"?
> flow->nt2hws->rix_mreg_copy = cpy_idx;
> cpy_idx = 0;
> - if (!split)
> + if (!split) {
Does this implicit zero comparison comply with the coding style? The
guide requires explicit comparisons, so should this be "if (split == 0)"?
> + mlx5_free(prepend_items);
> return (uintptr_t)flow;
> + }
> goto prefix_flow;
> }
> goto free;
> @@ -14343,8 +14405,10 @@ static uintptr_t flow_hw_list_create(struct rte_eth_dev *dev,
> if (flow) {
Does this implicit non-NULL comparison comply with the coding style?
> flow->nt2hws->rix_mreg_copy = cpy_idx;
> cpy_idx = 0;
> - if (!split)
> + if (!split) {
Does this implicit zero comparison comply with the coding style?
> + mlx5_free(prepend_items);
> return (uintptr_t)flow;
> + }
> /* Fall Through to prefix flow creation. */
> }
> prefix_flow:
> @@ -14357,6 +14421,7 @@ static uintptr_t flow_hw_list_create(struct rte_eth_dev *dev,
> flow->nt2hws->chaned_flow = 1;
> SLIST_INSERT_AFTER(prfx_flow, flow, nt2hws->next);
> mlx5_flow_nta_split_resource_free(dev, &resource);
> + mlx5_free(prepend_items);
> return (uintptr_t)prfx_flow;
> }
> free:
> @@ -14368,6 +14433,7 @@ static uintptr_t flow_hw_list_create(struct rte_eth_dev *dev,
> mlx5_flow_nta_del_copy_action(dev, cpy_idx);
> if (split > 0)
> mlx5_flow_nta_split_resource_free(dev, &resource);
> + mlx5_free(prepend_items);
> return 0;
> }
Does this code leak prepend_items in the early return path when
flow_hw_list_create is called with attr->ingress or attr->egress being
true and mlx5_flow_hw_validate returns an error? The validation check at
the start of the function occurs before nb_items assignment and item
prepending, but if validation succeeds and then later
mlx5_nta_split_metadata fails, does this patch correctly free
prepend_items on all error paths after allocation?
Looking at the goto free label, does the code at the free label properly
handle prepend_items cleanup in all cases, or can prepend_items be leaked
when flow creation fails after mlx5_nta_sample_flow_list_create or
mlx5_nta_qrss_flow_list_create?
More information about the test-report
mailing list