Hi, > -----Original Message----- > From: Dariusz Sosnowski <[email protected]> > Sent: Friday, May 15, 2026 8:37 PM > To: Slava Ovsiienko <[email protected]>; Bing Zhao > <[email protected]>; Ori Kam <[email protected]>; Suanming Mou > <[email protected]>; Matan Azrad <[email protected]> > Cc: [email protected]; [email protected] > Subject: [PATCH] net/mlx5: redirect LACP traffic for legacy E-Switch > > Offending patch fixed the LACP miss rule logic for NICs where switchdev is > enabled. In this case, LACP miss rules should be inserted if and only if > started port is a main port on the embedded switch. > Side effect of that change was that LACP miss rules are not inserted when > switchdev is disabled and legacy SR-IOV switch mode is used. > > This patch addresses that: > > - Fix the LACP rule insertion condition. > - Move HWS table for LACP rule creation out of FDB rules, > so they can be created separately. > > Fixes: 87e4384d2662 ("net/mlx5: fix condition of LACP miss flow") > Cc: [email protected] > > Signed-off-by: Dariusz Sosnowski <[email protected]> > --- > drivers/net/mlx5/mlx5.h | 1 + > drivers/net/mlx5/mlx5_flow.h | 40 ++++++++- > drivers/net/mlx5/mlx5_flow_hw.c | 140 ++++++++++++++++++++++++-------- > drivers/net/mlx5/mlx5_trigger.c | 7 +- > 4 files changed, 145 insertions(+), 43 deletions(-) > > diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index > 49a0c03544..ab5c76bfc4 100644 > --- a/drivers/net/mlx5/mlx5.h > +++ b/drivers/net/mlx5/mlx5.h > @@ -2040,6 +2040,7 @@ struct mlx5_priv { > rte_spinlock_t hw_ctrl_lock; > LIST_HEAD(hw_ctrl_flow, mlx5_ctrl_flow_entry) hw_ctrl_flows; > LIST_HEAD(hw_ext_ctrl_flow, mlx5_ctrl_flow_entry) hw_ext_ctrl_flows; > + struct mlx5_flow_hw_lacp_miss *hw_lacp_miss; /* HWS LACP miss flow > +tables */ > struct mlx5_flow_hw_ctrl_fdb *hw_ctrl_fdb; /* FDB control flow > context */ > struct mlx5_flow_hw_ctrl_nic *hw_ctrl_nic; /* NIC control flow > context */ > struct rte_flow_pattern_template *hw_tx_repr_tagging_pt; diff --git > a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h index > c9e72a33d6..3f5ba55bf9 100644 > --- a/drivers/net/mlx5/mlx5_flow.h > +++ b/drivers/net/mlx5/mlx5_flow.h > @@ -3031,6 +3031,13 @@ struct mlx5_flow_hw_ctrl_rx { > > [MLX5_FLOW_HW_CTRL_RX_EXPANDED_RSS_MAX]; > }; > > +/* Contains all templates and table required for redirecting LACP > +traffic with HWS. */ struct mlx5_flow_hw_lacp_miss { > + struct rte_flow_pattern_template *lacp_rx_items_tmpl; > + struct rte_flow_actions_template *lacp_rx_actions_tmpl; > + struct rte_flow_template_table *hw_lacp_rx_tbl; }; > + > /* Contains all templates required for control flow rules in FDB with > HWS. */ struct mlx5_flow_hw_ctrl_fdb { > struct rte_flow_pattern_template *esw_mgr_items_tmpl; @@ -3042,9 > +3049,6 @@ struct mlx5_flow_hw_ctrl_fdb { > struct rte_flow_pattern_template *port_items_tmpl; > struct rte_flow_actions_template *jump_one_actions_tmpl; > struct rte_flow_template_table *hw_esw_zero_tbl; > - struct rte_flow_pattern_template *lacp_rx_items_tmpl; > - struct rte_flow_actions_template *lacp_rx_actions_tmpl; > - struct rte_flow_template_table *hw_lacp_rx_tbl; > }; > > struct mlx5_flow_hw_ctrl_nic { > @@ -3735,6 +3739,36 @@ mlx5_indirect_list_handles_release(struct > rte_eth_dev *dev); > > bool mlx5_flow_is_steering_disabled(void); > > +/** > + * Returns true if Rx control rule for LACP traffic is needed. > + * > + * mlx5 PMD needs to create a rule matching LACP traffic and forwarding > it back to kernel if: > + * > + * - Underlying device is a bond interface. > + * - User did not request to handle LACP traffic in user space. > + * > + * Creation of this rule is also controlled by the E-Switch mode: > + * > + * - It must be created in legacy mode. > + * - It must be created only on proxy port in switchdev mode. > + * > + * @param[in] priv > + * Pointer to Ethernet device structure. > + * > + * @return > + * True if LACP rules must be created. > + * False otherwise. > + */ > +static inline bool > +mlx5_flow_lacp_miss_needed(struct rte_eth_dev *dev) { > + struct mlx5_priv *priv = dev->data->dev_private; > + > + return !priv->sh->config.lacp_by_user && > + priv->pf_bond >= 0 && > + (!priv->sh->esw_mode || (priv->sh->esw_mode && priv->master)); } > + > #ifdef HAVE_MLX5_HWS_SUPPORT > > #define MLX5_REPR_STC_MEMORY_LOG 11 > diff --git a/drivers/net/mlx5/mlx5_flow_hw.c > b/drivers/net/mlx5/mlx5_flow_hw.c index b6bb9f12a6..c133230cb7 100644 > --- a/drivers/net/mlx5/mlx5_flow_hw.c > +++ b/drivers/net/mlx5/mlx5_flow_hw.c > @@ -10820,15 +10820,6 @@ flow_hw_cleanup_ctrl_fdb_tables(struct > rte_eth_dev *dev) > if (!priv->hw_ctrl_fdb) > return; > hw_ctrl_fdb = priv->hw_ctrl_fdb; > - /* Clean up templates used for LACP default miss table. */ > - if (hw_ctrl_fdb->hw_lacp_rx_tbl) > - claim_zero(flow_hw_table_destroy(dev, hw_ctrl_fdb- > >hw_lacp_rx_tbl, NULL)); > - if (hw_ctrl_fdb->lacp_rx_actions_tmpl) > - claim_zero(flow_hw_actions_template_destroy(dev, hw_ctrl_fdb- > >lacp_rx_actions_tmpl, > - NULL)); > - if (hw_ctrl_fdb->lacp_rx_items_tmpl) > - claim_zero(flow_hw_pattern_template_destroy(dev, hw_ctrl_fdb- > >lacp_rx_items_tmpl, > - NULL)); > /* Clean up templates used for default FDB jump rule. */ > if (hw_ctrl_fdb->hw_esw_zero_tbl) > claim_zero(flow_hw_table_destroy(dev, hw_ctrl_fdb- > >hw_esw_zero_tbl, NULL)); @@ -10898,6 +10889,99 @@ > flow_hw_create_lacp_rx_table(struct rte_eth_dev *dev, > return flow_hw_table_create(dev, &cfg, &it, 1, &at, 1, error); } > > +/* > + * Clean up templates and table used for redirecting LACP traffic to > kernel. > + * > + * @param dev > + * Pointer to Ethernet device. > + */ > +static void > +flow_hw_cleanup_lacp_miss_tables(struct rte_eth_dev *dev) { > + struct mlx5_priv *priv = dev->data->dev_private; > + struct mlx5_flow_hw_lacp_miss *hw_lacp_miss; > + > + if (priv->hw_lacp_miss == NULL) > + return; > + > + hw_lacp_miss = priv->hw_lacp_miss; > + > + if (hw_lacp_miss->hw_lacp_rx_tbl) > + claim_zero(flow_hw_table_destroy(dev, hw_lacp_miss- > >hw_lacp_rx_tbl, NULL)); > + if (hw_lacp_miss->lacp_rx_actions_tmpl) > + claim_zero(flow_hw_actions_template_destroy(dev, > + hw_lacp_miss- > >lacp_rx_actions_tmpl, > + NULL)); > + if (hw_lacp_miss->lacp_rx_items_tmpl) > + claim_zero(flow_hw_pattern_template_destroy(dev, > + hw_lacp_miss- > >lacp_rx_items_tmpl, > + NULL)); > + > + mlx5_free(hw_lacp_miss); > + priv->hw_lacp_miss = NULL; > +} > + > +/* > + * Create templates and table for redirecting LACP traffic to kernel. > + * > + * LACP traffic redirection is needed whenever LACP bond is managed by > the kernel. > + * Required rule has a following structure: > + * > + * - ingress rule on root table > + * - match EtherType 0x8809 > + * - action DEFAULT_MISS > + * > + * @param dev > + * Pointer to Ethernet device. > + * > + * @return > + * 0 on success. Negative errno otherwise. > + */ > +static int > +flow_hw_create_lacp_miss_tables(struct rte_eth_dev *dev) { > + struct mlx5_priv *priv = dev->data->dev_private; > + struct mlx5_flow_hw_lacp_miss *hw_lacp_miss; > + > + if (mlx5_flow_is_steering_disabled()) > + return 0; > + > + hw_lacp_miss = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*hw_lacp_miss), 0, > SOCKET_ID_ANY); > + if (!hw_lacp_miss) { > + DRV_LOG(ERR, "port %u Failed to allocate memory for LACP miss > tables", > + dev->data->port_id); > + return -ENOMEM; > + } > + priv->hw_lacp_miss = hw_lacp_miss; > + > + hw_lacp_miss->lacp_rx_items_tmpl = > flow_hw_create_lacp_rx_pattern_template(dev, NULL); > + if (!hw_lacp_miss->lacp_rx_items_tmpl) { > + DRV_LOG(ERR, "port %u Failed to create pattern template for > LACP Rx traffic", > + dev->data->port_id); > + goto error; > + } > + hw_lacp_miss->lacp_rx_actions_tmpl = > flow_hw_create_lacp_rx_actions_template(dev, NULL); > + if (!hw_lacp_miss->lacp_rx_actions_tmpl) { > + DRV_LOG(ERR, "port %u Failed to create actions template for > LACP Rx traffic", > + dev->data->port_id); > + goto error; > + } > + hw_lacp_miss->hw_lacp_rx_tbl = > + flow_hw_create_lacp_rx_table(dev, hw_lacp_miss- > >lacp_rx_items_tmpl, > + hw_lacp_miss->lacp_rx_actions_tmpl, > NULL); > + if (!hw_lacp_miss->hw_lacp_rx_tbl) { > + DRV_LOG(ERR, "port %u Failed to create template table for LACP > Rx traffic", > + dev->data->port_id); > + goto error; > + } > + > + return 0; > + > +error: > + flow_hw_cleanup_lacp_miss_tables(dev); > + return -EINVAL; > +} > + > /** > * Creates a set of flow tables used to create control flows used > * when E-Switch is engaged. > @@ -11000,31 +11084,6 @@ flow_hw_create_fdb_ctrl_tables(struct rte_eth_dev > *dev, struct rte_flow_error *e > goto err; > } > } > - /* Create LACP default miss table. */ > - if (!priv->sh->config.lacp_by_user && priv->pf_bond >= 0 && priv- > >master) { > - hw_ctrl_fdb->lacp_rx_items_tmpl = > - flow_hw_create_lacp_rx_pattern_template(dev, > error); > - if (!hw_ctrl_fdb->lacp_rx_items_tmpl) { > - DRV_LOG(ERR, "port %u failed to create pattern template" > - " for LACP Rx traffic", dev->data->port_id); > - goto err; > - } > - hw_ctrl_fdb->lacp_rx_actions_tmpl = > - flow_hw_create_lacp_rx_actions_template(dev, > error); > - if (!hw_ctrl_fdb->lacp_rx_actions_tmpl) { > - DRV_LOG(ERR, "port %u failed to create actions template" > - " for LACP Rx traffic", dev->data->port_id); > - goto err; > - } > - hw_ctrl_fdb->hw_lacp_rx_tbl = flow_hw_create_lacp_rx_table > - (dev, hw_ctrl_fdb->lacp_rx_items_tmpl, > - hw_ctrl_fdb->lacp_rx_actions_tmpl, error); > - if (!hw_ctrl_fdb->hw_lacp_rx_tbl) { > - DRV_LOG(ERR, "port %u failed to create template table > for" > - " for LACP Rx traffic", dev->data->port_id); > - goto err; > - } > - } > return 0; > > err: > @@ -11754,6 +11813,7 @@ __mlx5_flow_hw_resource_release(struct rte_eth_dev > *dev, bool ctx_close) > > mlx5_flow_hw_rxq_flag_set(dev, false); > flow_hw_flush_all_ctrl_flows(dev); > + flow_hw_cleanup_lacp_miss_tables(dev); > flow_hw_cleanup_ctrl_fdb_tables(dev); > flow_hw_cleanup_ctrl_nic_tables(dev); > flow_hw_cleanup_tx_repr_tagging(dev); > @@ -12160,6 +12220,14 @@ __flow_hw_configure(struct rte_eth_dev *dev, > if (ret) > goto err; > } > + if (mlx5_flow_lacp_miss_needed(dev)) { > + ret = flow_hw_create_lacp_miss_tables(dev); > + if (ret) { > + rte_flow_error_set(error, -ret, > RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, > + "Unable to create LACP miss flow > tables"); > + goto err; > + } > + } > if (is_proxy) { > ret = flow_hw_create_vport_actions(priv); > if (ret) { > @@ -16234,10 +16302,10 @@ mlx5_flow_hw_lacp_rx_flow(struct rte_eth_dev > *dev) > .type = MLX5_CTRL_FLOW_TYPE_LACP_RX, > }; > > - if (!priv->dr_ctx || !priv->hw_ctrl_fdb || !priv->hw_ctrl_fdb- > >hw_lacp_rx_tbl) > + if (!priv->dr_ctx || !priv->hw_lacp_miss || > +!priv->hw_lacp_miss->hw_lacp_rx_tbl) > return 0; > return flow_hw_create_ctrl_flow(dev, dev, > - priv->hw_ctrl_fdb->hw_lacp_rx_tbl, > + priv->hw_lacp_miss->hw_lacp_rx_tbl, > eth_lacp, 0, miss_action, 0, &flow_info, > false); } > > diff --git a/drivers/net/mlx5/mlx5_trigger.c > b/drivers/net/mlx5/mlx5_trigger.c index a070aaecfd..32cd18717d 100644 > --- a/drivers/net/mlx5/mlx5_trigger.c > +++ b/drivers/net/mlx5/mlx5_trigger.c > @@ -1672,9 +1672,8 @@ mlx5_traffic_enable_hws(struct rte_eth_dev *dev) > } else { > DRV_LOG(INFO, "port %u FDB default rule is disabled", dev- > >data->port_id); > } > - if (!priv->sh->config.lacp_by_user && priv->pf_bond >= 0 && priv- > >master) > - if (mlx5_flow_hw_lacp_rx_flow(dev)) > - goto error; > + if (mlx5_flow_lacp_miss_needed(dev) && > mlx5_flow_hw_lacp_rx_flow(dev) != 0) > + goto error; > if (priv->isolated) > return 0; > ret = mlx5_flow_hw_create_ctrl_rx_tables(dev); > @@ -1796,7 +1795,7 @@ mlx5_traffic_enable(struct rte_eth_dev *dev) > DRV_LOG(INFO, "port %u FDB default rule is disabled", > dev->data->port_id); > } > - if (!priv->sh->config.lacp_by_user && priv->pf_bond >= 0 && priv- > >master) { > + if (mlx5_flow_lacp_miss_needed(dev)) { > ret = mlx5_flow_lacp_miss(dev); > if (ret) > DRV_LOG(INFO, "port %u LACP rule cannot be created - " > -- > 2.47.3
Acked-by: Bing Zhao <[email protected]>

