[RFC,4/5] net/mlx5: add port affinity item support

Message ID 20221221102934.13822-5-jiaweiw@nvidia.com (mailing list archive)
State Superseded, archived
Delegated to: Ferruh Yigit
Headers
Series add new port affinity item and affinity in Tx queue API |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Jiawei Wang Dec. 21, 2022, 10:29 a.m. UTC
  This patch adds the new port affinity item supports in PMD:
RTE_FLOW_ITEM_TYPE_PORT_AFFINITY.

This patch adds the validation function for the new item,
it works for NIC-RX rules on ROOT-table only.

Signed-off-by: Jiawei Wang <jiaweiw@nvidia.com>
---
 doc/guides/nics/features/mlx5.ini |  1 +
 doc/guides/nics/mlx5.rst          |  4 +-
 drivers/net/mlx5/linux/mlx5_os.c  |  2 +
 drivers/net/mlx5/mlx5.h           |  1 +
 drivers/net/mlx5/mlx5_flow.h      |  3 +
 drivers/net/mlx5/mlx5_flow_dv.c   | 95 +++++++++++++++++++++++++++++++
 drivers/net/mlx5/mlx5_flow_hw.c   | 14 +++++
 7 files changed, 119 insertions(+), 1 deletion(-)
  

Patch

diff --git a/doc/guides/nics/features/mlx5.ini b/doc/guides/nics/features/mlx5.ini
index 62fd330e2b..a7766221c9 100644
--- a/doc/guides/nics/features/mlx5.ini
+++ b/doc/guides/nics/features/mlx5.ini
@@ -87,6 +87,7 @@  vlan                 = Y
 vxlan                = Y
 vxlan_gpe            = Y
 represented_port     = Y
+port_affinity        = Y
 
 [rte_flow actions]
 age                  = I
diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst
index 85a2b422c5..fe33c2a895 100644
--- a/doc/guides/nics/mlx5.rst
+++ b/doc/guides/nics/mlx5.rst
@@ -106,6 +106,7 @@  Features
 - Sub-Function representors.
 - Sub-Function.
 - Matching on represented port.
+- Matching on port affinity.
 
 
 Limitations
@@ -595,10 +596,11 @@  Limitations
   - key
   - sequence
 
-  Matching on checksum and sequence needs MLNX_OFED 5.6+.
+- Matching on checksum and sequence needs MLNX_OFED 5.6+.
 
 - The NIC egress flow rules on representor port are not supported.
 
+- Match on port affinity is supported NIC ingress flow in group 0 only.
 
 Statistics
 ----------
diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c
index 3fea72013f..babc7d2f94 100644
--- a/drivers/net/mlx5/linux/mlx5_os.c
+++ b/drivers/net/mlx5/linux/mlx5_os.c
@@ -1406,6 +1406,8 @@  mlx5_dev_spawn(struct rte_device *dpdk_dev,
 			sh->lag_rx_port_affinity_en = 1;
 			DRV_LOG(DEBUG, "LAG Rx Port Affinity enabled");
 		}
+		priv->num_lag_ports = hca_attr->num_lag_ports;
+		DRV_LOG(DEBUG, "The number of lag ports is %d", priv->num_lag_ports);
 	}
 	/* Process parameters and store port configuration on priv structure. */
 	err = mlx5_port_args_config(priv, mkvlist, &priv->config);
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index dc4d1a8686..52f1592035 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -1739,6 +1739,7 @@  struct mlx5_priv {
 	unsigned int mtr_reg_share:1; /* Whether support meter REG_C share. */
 	unsigned int lb_used:1; /* Loopback queue is referred to. */
 	uint32_t mark_enabled:1; /* If mark action is enabled on rxqs. */
+	uint32_t num_lag_ports:4; /* Number of ports can be bonded. */
 	uint16_t domain_id; /* Switch domain identifier. */
 	uint16_t vport_id; /* Associated VF vport index (if any). */
 	uint32_t vport_meta_tag; /* Used for vport index match ove VF LAG. */
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 7148c10e96..13cf9b7d76 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -264,6 +264,9 @@  enum mlx5_feature_name {
 /* IPSEC syndrome item */
 #define MLX5_FLOW_ITEM_IPSEC_SYNDROME (UINT64_C(1) << 46)
 
+/* Port affinity item */
+#define MLX5_FLOW_ITEM_PORT_AFFINITY (UINT64_C(1) << 47)
+
 /* Outer Masks. */
 #define MLX5_FLOW_LAYER_OUTER_L3 \
 	(MLX5_FLOW_LAYER_OUTER_L3_IPV4 | MLX5_FLOW_LAYER_OUTER_L3_IPV6)
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 310fb7c5c3..62a6fb496d 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -3888,6 +3888,74 @@  flow_dv_validate_item_ipsec_syndrome(struct rte_eth_dev *dev,
 	return 0;
 }
 
+/**
+ * Validate Port affinity item.
+ *
+ * @param[in] dev
+ *   Pointer to the rte_eth_dev structure.
+ * @param[in] item
+ *   Item specification.
+ * @param[in] attr
+ *   Attributes of flow that includes this item.
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_validate_item_port_affinity(struct rte_eth_dev *dev,
+				    const struct rte_flow_item *item,
+				    const struct rte_flow_attr *attr,
+				    struct rte_flow_error *error)
+{
+	struct mlx5_priv *priv = dev->data->dev_private;
+	const struct rte_flow_item_port_affinity *spec = item->spec;
+	const struct rte_flow_item_port_affinity *mask = item->mask;
+	struct rte_flow_item_port_affinity nic_mask = {
+		.affinity = UINT8_MAX
+	};
+	int ret;
+
+	if (!priv->sh->lag_rx_port_affinity_en)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+					  "Unsupported port affinity with Older FW");
+	if (!attr->ingress || attr->transfer || attr->group)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
+					  item->spec,
+					  "port affinity is supported with NIC-RX on Root");
+	if (!spec)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
+					  item->spec,
+					  "data cannot be empty");
+	if (spec->affinity == 0)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
+					  item->spec,
+					  "zero affinity number not supported");
+	if (spec->affinity > priv->num_lag_ports)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
+					  item->spec,
+					  "exceed max affinity number in lag ports");
+	if (!mask)
+		mask = &rte_flow_item_port_affinity_mask;
+	if (!mask->affinity)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL,
+					  "mask cannot be zero");
+	ret = mlx5_flow_item_acceptable(item, (const uint8_t *)mask,
+				(const uint8_t *)&nic_mask,
+				sizeof(struct rte_flow_item_port_affinity),
+				MLX5_ITEM_RANGE_NOT_ACCEPTED, error);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
 int
 flow_dv_encap_decap_match_cb(void *tool_ctx __rte_unused,
 			     struct mlx5_list_entry *entry, void *cb_ctx)
@@ -7679,6 +7747,13 @@  flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 				return ret;
 			last_item = MLX5_FLOW_ITEM_IPSEC_SYNDROME;
 			break;
+		case RTE_FLOW_ITEM_TYPE_PORT_AFFINITY:
+			ret = flow_dv_validate_item_port_affinity(dev, items,
+								  attr, error);
+			if (ret < 0)
+				return ret;
+			last_item = MLX5_FLOW_ITEM_PORT_AFFINITY;
+			break;
 		default:
 			return rte_flow_error_set(error, ENOTSUP,
 						  RTE_FLOW_ERROR_TYPE_ITEM,
@@ -10978,6 +11053,22 @@  flow_dv_translate_item_ipsec_syndrome(void *key,
 		 spec->syndrome & mask->syndrome);
 }
 
+static void
+flow_dv_translate_item_port_affinity(void *key,
+				     const struct rte_flow_item *item,
+				     uint32_t key_type)
+{
+	const struct rte_flow_item_port_affinity *affinity_v;
+	const struct rte_flow_item_port_affinity *affinity_m;
+	void *misc_v;
+
+	MLX5_ITEM_UPDATE(item, key_type, affinity_v, affinity_m,
+			 &rte_flow_item_port_affinity_mask);
+	misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
+	MLX5_SET(fte_match_set_misc, misc_v, lag_rx_port_affinity,
+		 affinity_v->affinity & affinity_m->affinity);
+}
+
 static uint32_t matcher_zero[MLX5_ST_SZ_DW(fte_match_param)] = { 0 };
 
 #define HEADER_IS_ZERO(match_criteria, headers)				     \
@@ -13779,6 +13870,10 @@  flow_dv_translate_items(struct rte_eth_dev *dev,
 		flow_dv_translate_item_ipsec_syndrome(key, items, key_type);
 		last_item = MLX5_FLOW_ITEM_IPSEC_SYNDROME;
 		break;
+	case RTE_FLOW_ITEM_TYPE_PORT_AFFINITY:
+		flow_dv_translate_item_port_affinity(key, items, key_type);
+		last_item = MLX5_FLOW_ITEM_PORT_AFFINITY;
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index 0705002d99..2e93dcf801 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -5015,6 +5015,20 @@  flow_hw_pattern_validate(struct rte_eth_dev *dev,
 							  "Unsupported meter color register");
 			break;
 		}
+		case RTE_FLOW_ITEM_TYPE_PORT_AFFINITY:
+		{
+			if (!priv->sh->lag_rx_port_affinity_en)
+				return rte_flow_error_set(error, EINVAL,
+							  RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+							  "Unsupported port affinity with Older FW");
+			if (!attr->ingress || attr->transfer)
+				return rte_flow_error_set(error, EINVAL,
+							  RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+							  "Port affinity item not supported"
+							  " with egress or transfer"
+							  " attribute");
+			break;
+		}
 		case RTE_FLOW_ITEM_TYPE_VOID:
 		case RTE_FLOW_ITEM_TYPE_ETH:
 		case RTE_FLOW_ITEM_TYPE_VLAN: