[PATCH 24.11] net/mlx5: redirect LACP traffic for legacy E-Switch
Dariusz Sosnowski
dsosnowski at nvidia.com
Mon Jun 15 12:36:54 CEST 2026
[ upstream commit d630c199f0a553df12d456e45c6ddaa51471efd1 ]
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: stable at dpdk.org
Signed-off-by: Dariusz Sosnowski <dsosnowski at nvidia.com>
Acked-by: Bing Zhao <bingz at nvidia.com>
---
drivers/net/mlx5/mlx5.h | 1 +
drivers/net/mlx5/mlx5_flow.h | 41 +++++++++-
drivers/net/mlx5/mlx5_flow_hw.c | 137 +++++++++++++++++++++++---------
drivers/net/mlx5/mlx5_trigger.c | 7 +-
4 files changed, 143 insertions(+), 43 deletions(-)
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 69c60c3eed..9364367d4e 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -2003,6 +2003,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;
struct rte_flow_pattern_template *hw_tx_repr_tagging_pt;
struct rte_flow_actions_template *hw_tx_repr_tagging_at;
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index af90860fb0..4abe8d9628 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -2969,6 +2969,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;
@@ -2983,9 +2990,6 @@ struct mlx5_flow_hw_ctrl_fdb {
struct rte_flow_pattern_template *tx_meta_items_tmpl;
struct rte_flow_actions_template *tx_meta_actions_tmpl;
struct rte_flow_template_table *hw_tx_meta_cpy_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;
};
#define MLX5_CTRL_PROMISCUOUS (RTE_BIT32(0))
@@ -3662,6 +3666,37 @@ mlx5_dv_modify_ipv6_traffic_class_supported(struct mlx5_priv *priv)
void
mlx5_indirect_list_handles_release(struct rte_eth_dev *dev);
+
+/**
+ * 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 2a9715a7ef..651f973901 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -10661,15 +10661,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 Tx metadata copy. */
if (hw_ctrl_fdb->hw_tx_meta_cpy_tbl)
claim_zero(flow_hw_table_destroy(dev, hw_ctrl_fdb->hw_tx_meta_cpy_tbl, NULL));
@@ -10748,6 +10739,96 @@ 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;
+
+ 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.
@@ -10878,31 +10959,6 @@ flow_hw_create_ctrl_tables(struct rte_eth_dev *dev, struct rte_flow_error *error
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:
@@ -11625,6 +11681,7 @@ __flow_hw_resource_release(struct rte_eth_dev *dev, bool ctx_close)
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_tx_repr_tagging(dev);
flow_hw_action_template_drop_release(dev);
@@ -12056,6 +12113,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;
+ }
+ }
/*
* DEFAULT_MISS action have different behaviors in different domains.
* In FDB, it will steering the packets to the E-switch manager.
@@ -16051,10 +16116,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 b299ee10c1..33d92ce09b 100644
--- a/drivers/net/mlx5/mlx5_trigger.c
+++ b/drivers/net/mlx5/mlx5_trigger.c
@@ -1558,9 +1558,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);
@@ -1679,7 +1678,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
More information about the stable
mailing list