DPDK-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Dariusz Sosnowski <dsosnowski@nvidia.com>
To: Viacheslav Ovsiienko <viacheslavo@nvidia.com>,
	Bing Zhao <bingz@nvidia.com>, Ori Kam <orika@nvidia.com>,
	Suanming Mou <suanmingm@nvidia.com>,
	Matan Azrad <matan@nvidia.com>
Cc: <dev@dpdk.org>, <stable@dpdk.org>
Subject: [PATCH] net/mlx5: redirect LACP traffic for legacy E-Switch
Date: Fri, 15 May 2026 14:37:00 +0200	[thread overview]
Message-ID: <20260515123700.354341-1-dsosnowski@nvidia.com> (raw)

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@dpdk.org

Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
---
 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


                 reply	other threads:[~2026-05-15 12:38 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260515123700.354341-1-dsosnowski@nvidia.com \
    --to=dsosnowski@nvidia.com \
    --cc=bingz@nvidia.com \
    --cc=dev@dpdk.org \
    --cc=matan@nvidia.com \
    --cc=orika@nvidia.com \
    --cc=stable@dpdk.org \
    --cc=suanmingm@nvidia.com \
    --cc=viacheslavo@nvidia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox