[18/27] net/mlx5: add meta item support in egress

Message ID 20220923144334.27736-19-suanmingm@nvidia.com (mailing list archive)
State Superseded, archived
Delegated to: Thomas Monjalon
Headers
Series net/mlx5: HW steering PMD update |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Suanming Mou Sept. 23, 2022, 2:43 p.m. UTC
  From: Dariusz Sosnowski <dsosnowski@nvidia.com>

This patch adds support for META item in HW Steering mode, in NIC TX
domain.

Due to API limitations, usage of META item requires that all mlx5
ports use the same configuration of dv_esw_en and dv_xmeta_en device
arguments in order to consistently translate META item to appropriate
register. If mlx5 ports use different configurations, then configuration
of the first probed device is used.

Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
---
 drivers/net/mlx5/linux/mlx5_os.c |  1 +
 drivers/net/mlx5/mlx5.c          |  4 ++-
 drivers/net/mlx5/mlx5_flow.h     | 22 +++++++++++-
 drivers/net/mlx5/mlx5_flow_hw.c  | 61 ++++++++++++++++++++++++++++++--
 4 files changed, 84 insertions(+), 4 deletions(-)
  

Patch

diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c
index 41940d7ce7..54e7164663 100644
--- a/drivers/net/mlx5/linux/mlx5_os.c
+++ b/drivers/net/mlx5/linux/mlx5_os.c
@@ -1563,6 +1563,7 @@  mlx5_dev_spawn(struct rte_device *dpdk_dev,
 		}
 		/* Only HWS requires this information. */
 		flow_hw_init_tags_set(eth_dev);
+		flow_hw_init_flow_metadata_config(eth_dev);
 		if (priv->sh->config.dv_esw_en &&
 		    flow_hw_create_vport_action(eth_dev)) {
 			DRV_LOG(ERR, "port %u failed to create vport action",
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 314176022a..87cbcd473d 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -1970,8 +1970,10 @@  mlx5_dev_close(struct rte_eth_dev *dev)
 	flow_hw_resource_release(dev);
 #endif
 	flow_hw_clear_port_info(dev);
-	if (priv->sh->config.dv_flow_en == 2)
+	if (priv->sh->config.dv_flow_en == 2) {
+		flow_hw_clear_flow_metadata_config();
 		flow_hw_clear_tags_set(dev);
+	}
 	if (priv->rxq_privs != NULL) {
 		/* XXX race condition if mlx5_rx_burst() is still running. */
 		rte_delay_us_sleep(1000);
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index a39dacc60a..dae2fe6b37 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -1485,6 +1485,13 @@  flow_hw_get_wire_port(struct ibv_context *ibctx)
 	return NULL;
 }
 
+extern uint32_t mlx5_flow_hw_flow_metadata_config_refcnt;
+extern uint8_t mlx5_flow_hw_flow_metadata_esw_en;
+extern uint8_t mlx5_flow_hw_flow_metadata_xmeta_en;
+
+void flow_hw_init_flow_metadata_config(struct rte_eth_dev *dev);
+void flow_hw_clear_flow_metadata_config(void);
+
 /*
  * Convert metadata or tag to the actual register.
  * META: Can only be used to match in the FDB in this stage, fixed C_1.
@@ -1496,7 +1503,20 @@  flow_hw_get_reg_id(enum rte_flow_item_type type, uint32_t id)
 {
 	switch (type) {
 	case RTE_FLOW_ITEM_TYPE_META:
-		return REG_C_1;
+		if (mlx5_flow_hw_flow_metadata_esw_en &&
+		    mlx5_flow_hw_flow_metadata_xmeta_en == MLX5_XMETA_MODE_META32_HWS) {
+			return REG_C_1;
+		}
+		/*
+		 * On root table - PMD allows only egress META matching, thus
+		 * REG_A matching is sufficient.
+		 *
+		 * On non-root tables - REG_A corresponds to general_purpose_lookup_field,
+		 * which translates to REG_A in NIC TX and to REG_B in NIC RX.
+		 * However, current FW does not implement REG_B case right now, so
+		 * REG_B case should be rejected on pattern template validation.
+		 */
+		return REG_A;
 	case RTE_FLOW_ITEM_TYPE_TAG:
 		MLX5_ASSERT(id < MLX5_FLOW_HW_TAGS_MAX);
 		return mlx5_flow_hw_avl_tags[id];
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index dfbc434d54..55a14d39eb 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -3332,7 +3332,6 @@  flow_hw_pattern_validate(struct rte_eth_dev *dev,
 		{
 			const struct rte_flow_item_tag *tag =
 				(const struct rte_flow_item_tag *)items[i].spec;
-			struct mlx5_priv *priv = dev->data->dev_private;
 			uint8_t regcs = (uint8_t)priv->sh->cdev->config.hca_attr.set_reg_c;
 
 			if (!((1 << (tag->index - REG_C_0)) & regcs))
@@ -3349,6 +3348,17 @@  flow_hw_pattern_validate(struct rte_eth_dev *dev,
 						  "represented port item cannot be used"
 						  " when transfer attribute is set");
 			break;
+		case RTE_FLOW_ITEM_TYPE_META:
+			if (!priv->sh->config.dv_esw_en ||
+			    priv->sh->config.dv_xmeta_en != MLX5_XMETA_MODE_META32_HWS) {
+				if (attr->ingress)
+					return rte_flow_error_set(error, EINVAL,
+								  RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+								  "META item is not supported"
+								  " on current FW with ingress"
+								  " attribute");
+			}
+			break;
 		case RTE_FLOW_ITEM_TYPE_VOID:
 		case RTE_FLOW_ITEM_TYPE_ETH:
 		case RTE_FLOW_ITEM_TYPE_VLAN:
@@ -3360,7 +3370,6 @@  flow_hw_pattern_validate(struct rte_eth_dev *dev,
 		case RTE_FLOW_ITEM_TYPE_GTP_PSC:
 		case RTE_FLOW_ITEM_TYPE_VXLAN:
 		case MLX5_RTE_FLOW_ITEM_TYPE_TX_QUEUE:
-		case RTE_FLOW_ITEM_TYPE_META:
 		case RTE_FLOW_ITEM_TYPE_GRE:
 		case RTE_FLOW_ITEM_TYPE_GRE_KEY:
 		case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
@@ -4938,6 +4947,54 @@  void flow_hw_clear_tags_set(struct rte_eth_dev *dev)
 		       sizeof(enum modify_reg) * MLX5_FLOW_HW_TAGS_MAX);
 }
 
+uint32_t mlx5_flow_hw_flow_metadata_config_refcnt;
+uint8_t mlx5_flow_hw_flow_metadata_esw_en;
+uint8_t mlx5_flow_hw_flow_metadata_xmeta_en;
+
+/**
+ * Initializes static configuration of META flow items.
+ *
+ * As a temporary workaround, META flow item is translated to a register,
+ * based on statically saved dv_esw_en and dv_xmeta_en device arguments.
+ * It is a workaround for flow_hw_get_reg_id() where port specific information
+ * is not available at runtime.
+ *
+ * Values of dv_esw_en and dv_xmeta_en device arguments are taken from the first opened port.
+ * This means that each mlx5 port will use the same configuration for translation
+ * of META flow items.
+ *
+ * @param[in] dev
+ *    Pointer to Ethernet device.
+ */
+void
+flow_hw_init_flow_metadata_config(struct rte_eth_dev *dev)
+{
+	uint32_t refcnt;
+
+	refcnt = __atomic_fetch_add(&mlx5_flow_hw_flow_metadata_config_refcnt, 1,
+				    __ATOMIC_RELAXED);
+	if (refcnt > 0)
+		return;
+	mlx5_flow_hw_flow_metadata_esw_en = MLX5_SH(dev)->config.dv_esw_en;
+	mlx5_flow_hw_flow_metadata_xmeta_en = MLX5_SH(dev)->config.dv_xmeta_en;
+}
+
+/**
+ * Clears statically stored configuration related to META flow items.
+ */
+void
+flow_hw_clear_flow_metadata_config(void)
+{
+	uint32_t refcnt;
+
+	refcnt = __atomic_sub_fetch(&mlx5_flow_hw_flow_metadata_config_refcnt, 1,
+				    __ATOMIC_RELAXED);
+	if (refcnt > 0)
+		return;
+	mlx5_flow_hw_flow_metadata_esw_en = 0;
+	mlx5_flow_hw_flow_metadata_xmeta_en = 0;
+}
+
 /**
  * Create shared action.
  *