DPDK patches and discussions
 help / color / mirror / Atom feed
* [PATCH] net/mlx5: support ESP SPI match and RSS hash
@ 2022-04-04 13:04 Raja Zidane
  2022-04-17  7:12 ` Raslan Darawsheh
  2022-04-18 10:57 ` [PATCH V2] " Raja Zidane
  0 siblings, 2 replies; 9+ messages in thread
From: Raja Zidane @ 2022-04-04 13:04 UTC (permalink / raw)
  To: dev; +Cc: matan

In packets with ESP header, The Inner IP will be encrypted, and
its fields cannot be used for RSS hashing. So, ESP packets
can be hashed only by the outer IP layer.
So, when using RSS on ESP packets, hashing may not be efficient,
because the fields used by the hash functions are only the Outer IPs,
causing all traffic belonging to all tunnels between a given
pair of GWs to land on one core.
Adding the SPI hash field can extend the spreading of IPSec packets.

support matching on ESP SPI.
Support RSS on ESP header by hashing SPI field.

Signed-off-by: Raja Zidane <rzidane@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
---
 drivers/common/mlx5/linux/meson.build |  2 +
 drivers/common/mlx5/mlx5_prm.h        |  5 +-
 drivers/net/mlx5/mlx5_defs.h          |  2 +-
 drivers/net/mlx5/mlx5_devx.c          |  4 +-
 drivers/net/mlx5/mlx5_flow.c          | 84 ++++++++++++++++++++++++-
 drivers/net/mlx5/mlx5_flow.h          | 20 ++++++
 drivers/net/mlx5/mlx5_flow_dv.c       | 88 ++++++++++++++++++++++++++-
 7 files changed, 200 insertions(+), 5 deletions(-)

diff --git a/drivers/common/mlx5/linux/meson.build b/drivers/common/mlx5/linux/meson.build
index ed48245c67..5335f5b027 100644
--- a/drivers/common/mlx5/linux/meson.build
+++ b/drivers/common/mlx5/linux/meson.build
@@ -72,6 +72,8 @@ has_member_args = [
 # [ "MACRO to define if found", "header for the search",
 #   "symbol to search" ]
 has_sym_args = [
+        [ 'HAVE_IBV_RX_HASH_IPSEC_SPI', 'infiniband/verbs.h',
+            'IBV_RX_HASH_IPSEC_SPI' ],
         [ 'HAVE_IBV_RELAXED_ORDERING', 'infiniband/verbs.h',
             'IBV_ACCESS_RELAXED_ORDERING ' ],
         [ 'HAVE_IBV_DEVICE_STRIDING_RQ_SUPPORT', 'infiniband/mlx5dv.h',
diff --git a/drivers/common/mlx5/mlx5_prm.h b/drivers/common/mlx5/mlx5_prm.h
index 44b18225f6..630b2c5100 100644
--- a/drivers/common/mlx5/mlx5_prm.h
+++ b/drivers/common/mlx5/mlx5_prm.h
@@ -899,7 +899,10 @@ struct mlx5_ifc_fte_match_set_misc_bits {
 	u8 reserved_at_120[0xa];
 	u8 geneve_opt_len[0x6];
 	u8 geneve_protocol_type[0x10];
-	u8 reserved_at_140[0xc0];
+	u8 reserved_at_140[0x20];
+	u8 inner_esp_spi[0x20];
+	u8 outer_esp_spi[0x20];
+	u8 reserved_at_1a0[0x60];
 };
 
 struct mlx5_ifc_ipv4_layout_bits {
diff --git a/drivers/net/mlx5/mlx5_defs.h b/drivers/net/mlx5/mlx5_defs.h
index 15728fb41f..f5c6f23d56 100644
--- a/drivers/net/mlx5/mlx5_defs.h
+++ b/drivers/net/mlx5/mlx5_defs.h
@@ -90,7 +90,7 @@
 
 /* Supported RSS */
 #define MLX5_RSS_HF_MASK (~(RTE_ETH_RSS_IP | RTE_ETH_RSS_UDP | RTE_ETH_RSS_TCP | \
-			    MLX5_RSS_SRC_DST_ONLY))
+			    MLX5_RSS_SRC_DST_ONLY | RTE_ETH_RSS_ESP))
 
 /* Timeout in seconds to get a valid link status. */
 #define MLX5_LINK_STATUS_TIMEOUT 10
diff --git a/drivers/net/mlx5/mlx5_devx.c b/drivers/net/mlx5/mlx5_devx.c
index 5ab092a259..7ae389dc10 100644
--- a/drivers/net/mlx5/mlx5_devx.c
+++ b/drivers/net/mlx5/mlx5_devx.c
@@ -765,7 +765,9 @@ mlx5_devx_tir_attr_set(struct rte_eth_dev *dev, const uint8_t *rss_key,
 			(!!(hash_fields & MLX5_L4_SRC_IBV_RX_HASH)) <<
 			 MLX5_RX_HASH_FIELD_SELECT_SELECTED_FIELDS_L4_SPORT |
 			(!!(hash_fields & MLX5_L4_DST_IBV_RX_HASH)) <<
-			 MLX5_RX_HASH_FIELD_SELECT_SELECTED_FIELDS_L4_DPORT;
+			 MLX5_RX_HASH_FIELD_SELECT_SELECTED_FIELDS_L4_DPORT |
+			(!!(hash_fields & IBV_RX_HASH_IPSEC_SPI)) <<
+			 MLX5_RX_HASH_FIELD_SELECT_SELECTED_FIELDS_IPSEC_SPI;
 	}
 	if (is_hairpin)
 		tir_attr->transport_domain = priv->sh->td->id;
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 78cb38d42b..ea7369bd7e 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -149,6 +149,7 @@ mlx5_flow_is_rss_expandable_item(const struct rte_flow_item *item)
 	case RTE_FLOW_ITEM_TYPE_IPV6:
 	case RTE_FLOW_ITEM_TYPE_UDP:
 	case RTE_FLOW_ITEM_TYPE_TCP:
+	case RTE_FLOW_ITEM_TYPE_ESP:
 	case RTE_FLOW_ITEM_TYPE_VXLAN:
 	case RTE_FLOW_ITEM_TYPE_NVGRE:
 	case RTE_FLOW_ITEM_TYPE_GRE:
@@ -214,6 +215,9 @@ mlx5_inet_proto_to_item_type(uint8_t proto_spec, uint8_t proto_mask)
 	case IPPROTO_IPV6:
 		type = RTE_FLOW_ITEM_TYPE_IPV6;
 		break;
+	case IPPROTO_ESP:
+		type = RTE_FLOW_ITEM_TYPE_ESP;
+		break;
 	default:
 		type = RTE_FLOW_ITEM_TYPE_END;
 	}
@@ -558,9 +562,11 @@ enum mlx5_expansion {
 	MLX5_EXPANSION_OUTER_IPV4,
 	MLX5_EXPANSION_OUTER_IPV4_UDP,
 	MLX5_EXPANSION_OUTER_IPV4_TCP,
+	MLX5_EXPANSION_OUTER_IPV4_ESP,
 	MLX5_EXPANSION_OUTER_IPV6,
 	MLX5_EXPANSION_OUTER_IPV6_UDP,
 	MLX5_EXPANSION_OUTER_IPV6_TCP,
+	MLX5_EXPANSION_OUTER_IPV6_ESP,
 	MLX5_EXPANSION_VXLAN,
 	MLX5_EXPANSION_STD_VXLAN,
 	MLX5_EXPANSION_L3_VXLAN,
@@ -574,9 +580,11 @@ enum mlx5_expansion {
 	MLX5_EXPANSION_IPV4,
 	MLX5_EXPANSION_IPV4_UDP,
 	MLX5_EXPANSION_IPV4_TCP,
+	MLX5_EXPANSION_IPV4_ESP,
 	MLX5_EXPANSION_IPV6,
 	MLX5_EXPANSION_IPV6_UDP,
 	MLX5_EXPANSION_IPV6_TCP,
+	MLX5_EXPANSION_IPV6_ESP,
 	MLX5_EXPANSION_IPV6_FRAG_EXT,
 	MLX5_EXPANSION_GTP,
 	MLX5_EXPANSION_GENEVE,
@@ -611,6 +619,7 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 		.next = MLX5_FLOW_EXPAND_RSS_NEXT
 			(MLX5_EXPANSION_OUTER_IPV4_UDP,
 			 MLX5_EXPANSION_OUTER_IPV4_TCP,
+			 MLX5_EXPANSION_OUTER_IPV4_ESP,
 			 MLX5_EXPANSION_GRE,
 			 MLX5_EXPANSION_NVGRE,
 			 MLX5_EXPANSION_IPV4,
@@ -632,10 +641,15 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 		.type = RTE_FLOW_ITEM_TYPE_TCP,
 		.rss_types = RTE_ETH_RSS_NONFRAG_IPV4_TCP,
 	},
+	[MLX5_EXPANSION_OUTER_IPV4_ESP] = {
+		.type = RTE_FLOW_ITEM_TYPE_ESP,
+		.rss_types = RTE_ETH_RSS_ESP,
+	},
 	[MLX5_EXPANSION_OUTER_IPV6] = {
 		.next = MLX5_FLOW_EXPAND_RSS_NEXT
 			(MLX5_EXPANSION_OUTER_IPV6_UDP,
 			 MLX5_EXPANSION_OUTER_IPV6_TCP,
+			 MLX5_EXPANSION_OUTER_IPV6_ESP,
 			 MLX5_EXPANSION_IPV4,
 			 MLX5_EXPANSION_IPV6,
 			 MLX5_EXPANSION_GRE,
@@ -657,6 +671,10 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 		.type = RTE_FLOW_ITEM_TYPE_TCP,
 		.rss_types = RTE_ETH_RSS_NONFRAG_IPV6_TCP,
 	},
+	[MLX5_EXPANSION_OUTER_IPV6_ESP] = {
+		.type = RTE_FLOW_ITEM_TYPE_ESP,
+		.rss_types = RTE_ETH_RSS_ESP,
+	},
 	[MLX5_EXPANSION_VXLAN] = {
 		.next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH,
 						  MLX5_EXPANSION_IPV4,
@@ -716,7 +734,8 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 	},
 	[MLX5_EXPANSION_IPV4] = {
 		.next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4_UDP,
-						  MLX5_EXPANSION_IPV4_TCP),
+						  MLX5_EXPANSION_IPV4_TCP,
+						  MLX5_EXPANSION_IPV4_ESP),
 		.type = RTE_FLOW_ITEM_TYPE_IPV4,
 		.rss_types = RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4 |
 			RTE_ETH_RSS_NONFRAG_IPV4_OTHER,
@@ -729,9 +748,14 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 		.type = RTE_FLOW_ITEM_TYPE_TCP,
 		.rss_types = RTE_ETH_RSS_NONFRAG_IPV4_TCP,
 	},
+	[MLX5_EXPANSION_IPV4_ESP] = {
+		.type = RTE_FLOW_ITEM_TYPE_ESP,
+		.rss_types = RTE_ETH_RSS_ESP,
+	},
 	[MLX5_EXPANSION_IPV6] = {
 		.next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV6_UDP,
 						  MLX5_EXPANSION_IPV6_TCP,
+						  MLX5_EXPANSION_IPV6_ESP,
 						  MLX5_EXPANSION_IPV6_FRAG_EXT),
 		.type = RTE_FLOW_ITEM_TYPE_IPV6,
 		.rss_types = RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6 |
@@ -745,6 +769,10 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 		.type = RTE_FLOW_ITEM_TYPE_TCP,
 		.rss_types = RTE_ETH_RSS_NONFRAG_IPV6_TCP,
 	},
+	[MLX5_EXPANSION_IPV6_ESP] = {
+		.type = RTE_FLOW_ITEM_TYPE_ESP,
+		.rss_types = RTE_ETH_RSS_ESP,
+	},
 	[MLX5_EXPANSION_IPV6_FRAG_EXT] = {
 		.type = RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT,
 	},
@@ -2612,6 +2640,60 @@ mlx5_flow_validate_item_ipv6(const struct rte_flow_item *item,
 	return 0;
 }
 
+/**
+ * Validate ESP item.
+ *
+ * @param[in] item
+ *   Item specification.
+ * @param[in] item_flags
+ *   Bit-fields that holds the items detected until now.
+ * @param[in] target_protocol
+ *   The next protocol in the previous item.
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_flow_validate_item_esp(const struct rte_flow_item *item,
+			    uint64_t item_flags,
+			    uint8_t target_protocol,
+			    struct rte_flow_error *error)
+{
+	const struct rte_flow_item_esp *mask = item->mask;
+	const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
+	const uint64_t l3m = tunnel ? MLX5_FLOW_LAYER_INNER_L3 :
+				      MLX5_FLOW_LAYER_OUTER_L3;
+	const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 :
+				      MLX5_FLOW_LAYER_OUTER_L4;
+	int ret;
+
+	if (!(item_flags & l3m))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  "L3 is mandatory to filter on L4");
+	if (item_flags & l4m)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  "multiple L4 layers not supported");
+	if (target_protocol != 0xff && target_protocol != IPPROTO_ESP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  "protocol filtering not compatible"
+					  " with ESP layer");
+	if (!mask)
+		mask = &rte_flow_item_esp_mask;
+	ret = mlx5_flow_item_acceptable
+		(item, (const uint8_t *)mask,
+		 (const uint8_t *)&rte_flow_item_esp_mask,
+		 sizeof(struct rte_flow_item_esp), MLX5_ITEM_RANGE_NOT_ACCEPTED,
+		 error);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
 /**
  * Validate UDP item.
  *
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index f56115dd11..fcb05abced 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -186,6 +186,9 @@ enum mlx5_feature_name {
 #define MLX5_FLOW_ITEM_INNER_FLEX (UINT64_C(1) << 38)
 #define MLX5_FLOW_ITEM_FLEX_TUNNEL (UINT64_C(1) << 39)
 
+/* ESP item */
+#define MLX5_FLOW_ITEM_ESP (UINT64_C(1) << 40)
+
 /* Outer Masks. */
 #define MLX5_FLOW_LAYER_OUTER_L3 \
 	(MLX5_FLOW_LAYER_OUTER_L3_IPV4 | MLX5_FLOW_LAYER_OUTER_L3_IPV6)
@@ -1185,6 +1188,16 @@ struct rte_flow_template_table {
 	(MLX5_RSS_HASH_IPV6 | IBV_RX_HASH_SRC_PORT_TCP)
 #define MLX5_RSS_HASH_IPV6_TCP_DST_ONLY \
 	(MLX5_RSS_HASH_IPV6 | IBV_RX_HASH_DST_PORT_TCP)
+
+#ifndef HAVE_IBV_RX_HASH_IPSEC_SPI
+#define IBV_RX_HASH_IPSEC_SPI (1U << 8)
+#endif
+
+#define MLX5_RSS_HASH_ESP_SPI IBV_RX_HASH_IPSEC_SPI
+#define MLX5_RSS_HASH_IPV4_ESP (MLX5_RSS_HASH_IPV4 | \
+				MLX5_RSS_HASH_ESP_SPI)
+#define MLX5_RSS_HASH_IPV6_ESP (MLX5_RSS_HASH_IPV6 | \
+				MLX5_RSS_HASH_ESP_SPI)
 #define MLX5_RSS_HASH_NONE 0ULL
 
 
@@ -1200,9 +1213,12 @@ static const uint64_t mlx5_rss_hash_fields[] = {
 	MLX5_RSS_HASH_IPV4,
 	MLX5_RSS_HASH_IPV4_TCP,
 	MLX5_RSS_HASH_IPV4_UDP,
+	MLX5_RSS_HASH_IPV4_ESP,
 	MLX5_RSS_HASH_IPV6,
 	MLX5_RSS_HASH_IPV6_TCP,
 	MLX5_RSS_HASH_IPV6_UDP,
+	MLX5_RSS_HASH_IPV6_ESP,
+	MLX5_RSS_HASH_ESP_SPI,
 	MLX5_RSS_HASH_NONE,
 };
 
@@ -1812,6 +1828,10 @@ int mlx5_flow_validate_item_tcp(const struct rte_flow_item *item,
 				uint8_t target_protocol,
 				const struct rte_flow_item_tcp *flow_mask,
 				struct rte_flow_error *error);
+int mlx5_flow_validate_item_esp(const struct rte_flow_item *item,
+				uint64_t item_flags,
+				uint8_t target_protocol,
+				struct rte_flow_error *error);
 int mlx5_flow_validate_item_udp(const struct rte_flow_item *item,
 				uint64_t item_flags,
 				uint8_t target_protocol,
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 1e9bd63635..15097e340a 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -6955,6 +6955,14 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 		switch (type) {
 		case RTE_FLOW_ITEM_TYPE_VOID:
 			break;
+		case RTE_FLOW_ITEM_TYPE_ESP:
+			ret = mlx5_flow_validate_item_esp(items, item_flags,
+							  next_protocol,
+							  error);
+			if (ret < 0)
+				return ret;
+			last_item = MLX5_FLOW_ITEM_ESP;
+			break;
 		case RTE_FLOW_ITEM_TYPE_PORT_ID:
 			ret = flow_dv_validate_item_port_id
 					(dev, items, attr, item_flags, error);
@@ -8729,6 +8737,58 @@ flow_dv_translate_item_tcp(void *matcher, void *key,
 		 (tcp_v->hdr.tcp_flags & tcp_m->hdr.tcp_flags));
 }
 
+/**
+ * Add ESP item to matcher and to the value.
+ *
+ * @param[in, out] matcher
+ *   Flow matcher.
+ * @param[in, out] key
+ *   Flow matcher value.
+ * @param[in] item
+ *   Flow pattern to translate.
+ * @param[in] inner
+ *   Item is inner pattern.
+ */
+static void
+flow_dv_translate_item_esp(void *matcher, void *key,
+			   const struct rte_flow_item *item,
+			   int inner)
+{
+	const struct rte_flow_item_esp *esp_m = item->mask;
+	const struct rte_flow_item_esp *esp_v = item->spec;
+	void *headers_m;
+	void *headers_v;
+	char *spi_m;
+	char *spi_v;
+
+	if (inner) {
+		headers_m = MLX5_ADDR_OF(fte_match_param, matcher,
+					 inner_headers);
+		headers_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers);
+	} else {
+		headers_m = MLX5_ADDR_OF(fte_match_param, matcher,
+					 outer_headers);
+		headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
+	}
+	MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_protocol, 0xff);
+	MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, IPPROTO_ESP);
+	if (!esp_v)
+		return;
+	if (!esp_m)
+		esp_m = &rte_flow_item_esp_mask;
+	headers_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters);
+	headers_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
+	if (inner) {
+		spi_m = MLX5_ADDR_OF(fte_match_set_misc, headers_m, inner_esp_spi);
+		spi_v = MLX5_ADDR_OF(fte_match_set_misc, headers_v, inner_esp_spi);
+	} else {
+		spi_m = MLX5_ADDR_OF(fte_match_set_misc, headers_m, outer_esp_spi);
+		spi_v = MLX5_ADDR_OF(fte_match_set_misc, headers_v, outer_esp_spi);
+	}
+	*(uint32_t *)spi_m = esp_m->hdr.spi;
+	*(uint32_t *)spi_v = esp_m->hdr.spi & esp_v->hdr.spi;
+}
+
 /**
  * Add UDP item to matcher and to the value.
  *
@@ -11188,12 +11248,18 @@ flow_dv_hashfields_set(uint64_t item_flags,
 				fields |= MLX5_IPV6_IBV_RX_HASH;
 		}
 	}
-	if (fields == 0)
+	if (items & MLX5_FLOW_ITEM_ESP) {
+		if (rss_types & RTE_ETH_RSS_ESP)
+			fields |= IBV_RX_HASH_IPSEC_SPI;
+	}
+	if ((fields & ~IBV_RX_HASH_IPSEC_SPI) == 0) {
+		*hash_fields = fields;
 		/*
 		 * There is no match between the RSS types and the
 		 * L3 protocol (IPv4/IPv6) defined in the flow rule.
 		 */
 		return;
+	}
 	if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L4_UDP)) ||
 	    (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L4_UDP)) ||
 	    !items) {
@@ -13538,6 +13604,11 @@ flow_dv_translate(struct rte_eth_dev *dev,
 						  RTE_FLOW_ERROR_TYPE_ITEM,
 						  NULL, "item not supported");
 		switch (item_type) {
+		case RTE_FLOW_ITEM_TYPE_ESP:
+			flow_dv_translate_item_esp(match_mask, match_value,
+						   items, tunnel);
+			last_item = MLX5_FLOW_ITEM_ESP;
+			break;
 		case RTE_FLOW_ITEM_TYPE_PORT_ID:
 			flow_dv_translate_item_port_id
 				(dev, match_mask, match_value, items, attr);
@@ -14007,6 +14078,15 @@ __flow_dv_action_rss_hrxq_set(struct mlx5_shared_action_rss *action,
 	case MLX5_RSS_HASH_NONE:
 		hrxqs[6] = hrxq_idx;
 		return 0;
+	case MLX5_RSS_HASH_IPV4_ESP:
+		hrxqs[7] = hrxq_idx;
+		return 0;
+	case MLX5_RSS_HASH_IPV6_ESP:
+		hrxqs[8] = hrxq_idx;
+		return 0;
+	case MLX5_RSS_HASH_ESP_SPI:
+		hrxqs[9] = hrxq_idx;
+		return 0;
 	default:
 		return -1;
 	}
@@ -14076,6 +14156,12 @@ flow_dv_action_rss_hrxq_lookup(struct rte_eth_dev *dev, uint32_t idx,
 		return hrxqs[5];
 	case MLX5_RSS_HASH_NONE:
 		return hrxqs[6];
+	case MLX5_RSS_HASH_IPV4_ESP:
+		return hrxqs[7];
+	case MLX5_RSS_HASH_IPV6_ESP:
+		return hrxqs[8];
+	case MLX5_RSS_HASH_ESP_SPI:
+		return hrxqs[9];
 	default:
 		return 0;
 	}
-- 
2.21.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [PATCH] net/mlx5: support ESP SPI match and RSS hash
  2022-04-04 13:04 [PATCH] net/mlx5: support ESP SPI match and RSS hash Raja Zidane
@ 2022-04-17  7:12 ` Raslan Darawsheh
  2022-04-18 10:57 ` [PATCH V2] " Raja Zidane
  1 sibling, 0 replies; 9+ messages in thread
From: Raslan Darawsheh @ 2022-04-17  7:12 UTC (permalink / raw)
  To: Raja Zidane, dev; +Cc: Matan Azrad

Hi Raja,

> -----Original Message-----
> From: Raja Zidane <rzidane@nvidia.com>
> Sent: Monday, April 4, 2022 4:04 PM
> To: dev@dpdk.org
> Cc: Matan Azrad <matan@nvidia.com>
> Subject: [PATCH] net/mlx5: support ESP SPI match and RSS hash
> 
> In packets with ESP header, The Inner IP will be encrypted, and
> its fields cannot be used for RSS hashing. So, ESP packets
> can be hashed only by the outer IP layer.
> So, when using RSS on ESP packets, hashing may not be efficient,
> because the fields used by the hash functions are only the Outer IPs,
> causing all traffic belonging to all tunnels between a given
> pair of GWs to land on one core.
> Adding the SPI hash field can extend the spreading of IPSec packets.
> 
> support matching on ESP SPI.
> Support RSS on ESP header by hashing SPI field.
> 
> Signed-off-by: Raja Zidane <rzidane@nvidia.com>
> Acked-by: Matan Azrad <matan@nvidia.com>
> ---
>  drivers/common/mlx5/linux/meson.build |  2 +
>  drivers/common/mlx5/mlx5_prm.h        |  5 +-
>  drivers/net/mlx5/mlx5_defs.h          |  2 +-
>  drivers/net/mlx5/mlx5_devx.c          |  4 +-
>  drivers/net/mlx5/mlx5_flow.c          | 84 ++++++++++++++++++++++++-
>  drivers/net/mlx5/mlx5_flow.h          | 20 ++++++
>  drivers/net/mlx5/mlx5_flow_dv.c       | 88
> ++++++++++++++++++++++++++-
>  7 files changed, 200 insertions(+), 5 deletions(-)


It seems that you missed updating two parts,
1- release notes as it's a new feature being added.
2-  features list in mlx5.ini 

devtools/check-doc-vs-code.sh
rte_flow doc out of sync for mlx5
        item esp

Kindest regards,
Raslan Darawsheh

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH V2] net/mlx5: support ESP SPI match and RSS hash
  2022-04-04 13:04 [PATCH] net/mlx5: support ESP SPI match and RSS hash Raja Zidane
  2022-04-17  7:12 ` Raslan Darawsheh
@ 2022-04-18 10:57 ` Raja Zidane
  2022-04-18 11:01   ` [PATCH V3] " Raja Zidane
  1 sibling, 1 reply; 9+ messages in thread
From: Raja Zidane @ 2022-04-18 10:57 UTC (permalink / raw)
  To: dev; +Cc: matan

In packets with ESP header, The Inner IP will be encrypted, and
its fields cannot be used for RSS hashing. So, ESP packets
can be hashed only by the outer IP layer.
So, when using RSS on ESP packets, hashing may not be efficient,
because the fields used by the hash functions are only the Outer IPs,
causing all traffic belonging to all tunnels between a given
pair of GWs to land on one core.
Adding the SPI hash field can extend the spreading of IPSec packets.

support matching on ESP SPI.
Support RSS on ESP header by hashing SPI field.

Signed-off-by: Raja Zidane <rzidane@nvidia.com>
---
V2: added doc.
 doc/guides/nics/features/mlx5.ini      |  1 +
 doc/guides/rel_notes/release_22_07.rst |  2 +
 drivers/common/mlx5/linux/meson.build  |  2 +
 drivers/common/mlx5/mlx5_prm.h         |  5 +-
 drivers/net/mlx5/mlx5_defs.h           |  2 +-
 drivers/net/mlx5/mlx5_devx.c           |  4 +-
 drivers/net/mlx5/mlx5_flow.c           | 84 +++++++++++++++++++++++-
 drivers/net/mlx5/mlx5_flow.h           | 20 ++++++
 drivers/net/mlx5/mlx5_flow_dv.c        | 88 +++++++++++++++++++++++++-
 9 files changed, 203 insertions(+), 5 deletions(-)

diff --git a/doc/guides/nics/features/mlx5.ini b/doc/guides/nics/features/mlx5.ini
index fb5993124d..5738f35324 100644
--- a/doc/guides/nics/features/mlx5.ini
+++ b/doc/guides/nics/features/mlx5.ini
@@ -56,6 +56,7 @@ Usage doc            = Y
 [rte_flow items]
 conntrack            = Y
 ecpri                = Y
+esp                  = Y
 eth                  = Y
 flex                 = Y
 geneve               = Y
diff --git a/doc/guides/rel_notes/release_22_07.rst b/doc/guides/rel_notes/release_22_07.rst
index 49b7b33f87..0179c9dcb8 100644
--- a/doc/guides/rel_notes/release_22_07.rst
+++ b/doc/guides/rel_notes/release_22_07.rst
@@ -59,6 +59,8 @@ New Features
 
   * Added support for set promiscuous mode in Windows.
   * Added support for set and get MTU in Windows.
+  * Added new item (ESP).
+  * Added RSS for ESP. 
 
 Removed Items
 -------------
diff --git a/drivers/common/mlx5/linux/meson.build b/drivers/common/mlx5/linux/meson.build
index ed48245c67..5335f5b027 100644
--- a/drivers/common/mlx5/linux/meson.build
+++ b/drivers/common/mlx5/linux/meson.build
@@ -72,6 +72,8 @@ has_member_args = [
 # [ "MACRO to define if found", "header for the search",
 #   "symbol to search" ]
 has_sym_args = [
+        [ 'HAVE_IBV_RX_HASH_IPSEC_SPI', 'infiniband/verbs.h',
+            'IBV_RX_HASH_IPSEC_SPI' ],
         [ 'HAVE_IBV_RELAXED_ORDERING', 'infiniband/verbs.h',
             'IBV_ACCESS_RELAXED_ORDERING ' ],
         [ 'HAVE_IBV_DEVICE_STRIDING_RQ_SUPPORT', 'infiniband/mlx5dv.h',
diff --git a/drivers/common/mlx5/mlx5_prm.h b/drivers/common/mlx5/mlx5_prm.h
index 44b18225f6..630b2c5100 100644
--- a/drivers/common/mlx5/mlx5_prm.h
+++ b/drivers/common/mlx5/mlx5_prm.h
@@ -899,7 +899,10 @@ struct mlx5_ifc_fte_match_set_misc_bits {
 	u8 reserved_at_120[0xa];
 	u8 geneve_opt_len[0x6];
 	u8 geneve_protocol_type[0x10];
-	u8 reserved_at_140[0xc0];
+	u8 reserved_at_140[0x20];
+	u8 inner_esp_spi[0x20];
+	u8 outer_esp_spi[0x20];
+	u8 reserved_at_1a0[0x60];
 };
 
 struct mlx5_ifc_ipv4_layout_bits {
diff --git a/drivers/net/mlx5/mlx5_defs.h b/drivers/net/mlx5/mlx5_defs.h
index 15728fb41f..f5c6f23d56 100644
--- a/drivers/net/mlx5/mlx5_defs.h
+++ b/drivers/net/mlx5/mlx5_defs.h
@@ -90,7 +90,7 @@
 
 /* Supported RSS */
 #define MLX5_RSS_HF_MASK (~(RTE_ETH_RSS_IP | RTE_ETH_RSS_UDP | RTE_ETH_RSS_TCP | \
-			    MLX5_RSS_SRC_DST_ONLY))
+			    MLX5_RSS_SRC_DST_ONLY | RTE_ETH_RSS_ESP))
 
 /* Timeout in seconds to get a valid link status. */
 #define MLX5_LINK_STATUS_TIMEOUT 10
diff --git a/drivers/net/mlx5/mlx5_devx.c b/drivers/net/mlx5/mlx5_devx.c
index 5ab092a259..7ae389dc10 100644
--- a/drivers/net/mlx5/mlx5_devx.c
+++ b/drivers/net/mlx5/mlx5_devx.c
@@ -765,7 +765,9 @@ mlx5_devx_tir_attr_set(struct rte_eth_dev *dev, const uint8_t *rss_key,
 			(!!(hash_fields & MLX5_L4_SRC_IBV_RX_HASH)) <<
 			 MLX5_RX_HASH_FIELD_SELECT_SELECTED_FIELDS_L4_SPORT |
 			(!!(hash_fields & MLX5_L4_DST_IBV_RX_HASH)) <<
-			 MLX5_RX_HASH_FIELD_SELECT_SELECTED_FIELDS_L4_DPORT;
+			 MLX5_RX_HASH_FIELD_SELECT_SELECTED_FIELDS_L4_DPORT |
+			(!!(hash_fields & IBV_RX_HASH_IPSEC_SPI)) <<
+			 MLX5_RX_HASH_FIELD_SELECT_SELECTED_FIELDS_IPSEC_SPI;
 	}
 	if (is_hairpin)
 		tir_attr->transport_domain = priv->sh->td->id;
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index f5bdf661b0..de0c15fef6 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -149,6 +149,7 @@ mlx5_flow_is_rss_expandable_item(const struct rte_flow_item *item)
 	case RTE_FLOW_ITEM_TYPE_IPV6:
 	case RTE_FLOW_ITEM_TYPE_UDP:
 	case RTE_FLOW_ITEM_TYPE_TCP:
+	case RTE_FLOW_ITEM_TYPE_ESP:
 	case RTE_FLOW_ITEM_TYPE_VXLAN:
 	case RTE_FLOW_ITEM_TYPE_NVGRE:
 	case RTE_FLOW_ITEM_TYPE_GRE:
@@ -214,6 +215,9 @@ mlx5_inet_proto_to_item_type(uint8_t proto_spec, uint8_t proto_mask)
 	case IPPROTO_IPV6:
 		type = RTE_FLOW_ITEM_TYPE_IPV6;
 		break;
+	case IPPROTO_ESP:
+		type = RTE_FLOW_ITEM_TYPE_ESP;
+		break;
 	default:
 		type = RTE_FLOW_ITEM_TYPE_END;
 	}
@@ -558,9 +562,11 @@ enum mlx5_expansion {
 	MLX5_EXPANSION_OUTER_IPV4,
 	MLX5_EXPANSION_OUTER_IPV4_UDP,
 	MLX5_EXPANSION_OUTER_IPV4_TCP,
+	MLX5_EXPANSION_OUTER_IPV4_ESP,
 	MLX5_EXPANSION_OUTER_IPV6,
 	MLX5_EXPANSION_OUTER_IPV6_UDP,
 	MLX5_EXPANSION_OUTER_IPV6_TCP,
+	MLX5_EXPANSION_OUTER_IPV6_ESP,
 	MLX5_EXPANSION_VXLAN,
 	MLX5_EXPANSION_STD_VXLAN,
 	MLX5_EXPANSION_L3_VXLAN,
@@ -574,9 +580,11 @@ enum mlx5_expansion {
 	MLX5_EXPANSION_IPV4,
 	MLX5_EXPANSION_IPV4_UDP,
 	MLX5_EXPANSION_IPV4_TCP,
+	MLX5_EXPANSION_IPV4_ESP,
 	MLX5_EXPANSION_IPV6,
 	MLX5_EXPANSION_IPV6_UDP,
 	MLX5_EXPANSION_IPV6_TCP,
+	MLX5_EXPANSION_IPV6_ESP,
 	MLX5_EXPANSION_IPV6_FRAG_EXT,
 	MLX5_EXPANSION_GTP,
 	MLX5_EXPANSION_GENEVE,
@@ -611,6 +619,7 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 		.next = MLX5_FLOW_EXPAND_RSS_NEXT
 			(MLX5_EXPANSION_OUTER_IPV4_UDP,
 			 MLX5_EXPANSION_OUTER_IPV4_TCP,
+			 MLX5_EXPANSION_OUTER_IPV4_ESP,
 			 MLX5_EXPANSION_GRE,
 			 MLX5_EXPANSION_NVGRE,
 			 MLX5_EXPANSION_IPV4,
@@ -632,10 +641,15 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 		.type = RTE_FLOW_ITEM_TYPE_TCP,
 		.rss_types = RTE_ETH_RSS_NONFRAG_IPV4_TCP,
 	},
+	[MLX5_EXPANSION_OUTER_IPV4_ESP] = {
+		.type = RTE_FLOW_ITEM_TYPE_ESP,
+		.rss_types = RTE_ETH_RSS_ESP,
+	},
 	[MLX5_EXPANSION_OUTER_IPV6] = {
 		.next = MLX5_FLOW_EXPAND_RSS_NEXT
 			(MLX5_EXPANSION_OUTER_IPV6_UDP,
 			 MLX5_EXPANSION_OUTER_IPV6_TCP,
+			 MLX5_EXPANSION_OUTER_IPV6_ESP,
 			 MLX5_EXPANSION_IPV4,
 			 MLX5_EXPANSION_IPV6,
 			 MLX5_EXPANSION_GRE,
@@ -657,6 +671,10 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 		.type = RTE_FLOW_ITEM_TYPE_TCP,
 		.rss_types = RTE_ETH_RSS_NONFRAG_IPV6_TCP,
 	},
+	[MLX5_EXPANSION_OUTER_IPV6_ESP] = {
+		.type = RTE_FLOW_ITEM_TYPE_ESP,
+		.rss_types = RTE_ETH_RSS_ESP,
+	},
 	[MLX5_EXPANSION_VXLAN] = {
 		.next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH,
 						  MLX5_EXPANSION_IPV4,
@@ -716,7 +734,8 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 	},
 	[MLX5_EXPANSION_IPV4] = {
 		.next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4_UDP,
-						  MLX5_EXPANSION_IPV4_TCP),
+						  MLX5_EXPANSION_IPV4_TCP,
+						  MLX5_EXPANSION_IPV4_ESP),
 		.type = RTE_FLOW_ITEM_TYPE_IPV4,
 		.rss_types = RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4 |
 			RTE_ETH_RSS_NONFRAG_IPV4_OTHER,
@@ -729,9 +748,14 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 		.type = RTE_FLOW_ITEM_TYPE_TCP,
 		.rss_types = RTE_ETH_RSS_NONFRAG_IPV4_TCP,
 	},
+	[MLX5_EXPANSION_IPV4_ESP] = {
+		.type = RTE_FLOW_ITEM_TYPE_ESP,
+		.rss_types = RTE_ETH_RSS_ESP,
+	},
 	[MLX5_EXPANSION_IPV6] = {
 		.next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV6_UDP,
 						  MLX5_EXPANSION_IPV6_TCP,
+						  MLX5_EXPANSION_IPV6_ESP,
 						  MLX5_EXPANSION_IPV6_FRAG_EXT),
 		.type = RTE_FLOW_ITEM_TYPE_IPV6,
 		.rss_types = RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6 |
@@ -745,6 +769,10 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 		.type = RTE_FLOW_ITEM_TYPE_TCP,
 		.rss_types = RTE_ETH_RSS_NONFRAG_IPV6_TCP,
 	},
+	[MLX5_EXPANSION_IPV6_ESP] = {
+		.type = RTE_FLOW_ITEM_TYPE_ESP,
+		.rss_types = RTE_ETH_RSS_ESP,
+	},
 	[MLX5_EXPANSION_IPV6_FRAG_EXT] = {
 		.type = RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT,
 	},
@@ -2618,6 +2646,60 @@ mlx5_flow_validate_item_ipv6(const struct rte_flow_item *item,
 	return 0;
 }
 
+/**
+ * Validate ESP item.
+ *
+ * @param[in] item
+ *   Item specification.
+ * @param[in] item_flags
+ *   Bit-fields that holds the items detected until now.
+ * @param[in] target_protocol
+ *   The next protocol in the previous item.
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_flow_validate_item_esp(const struct rte_flow_item *item,
+			    uint64_t item_flags,
+			    uint8_t target_protocol,
+			    struct rte_flow_error *error)
+{
+	const struct rte_flow_item_esp *mask = item->mask;
+	const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
+	const uint64_t l3m = tunnel ? MLX5_FLOW_LAYER_INNER_L3 :
+				      MLX5_FLOW_LAYER_OUTER_L3;
+	const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 :
+				      MLX5_FLOW_LAYER_OUTER_L4;
+	int ret;
+
+	if (!(item_flags & l3m))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  "L3 is mandatory to filter on L4");
+	if (item_flags & l4m)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  "multiple L4 layers not supported");
+	if (target_protocol != 0xff && target_protocol != IPPROTO_ESP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  "protocol filtering not compatible"
+					  " with ESP layer");
+	if (!mask)
+		mask = &rte_flow_item_esp_mask;
+	ret = mlx5_flow_item_acceptable
+		(item, (const uint8_t *)mask,
+		 (const uint8_t *)&rte_flow_item_esp_mask,
+		 sizeof(struct rte_flow_item_esp), MLX5_ITEM_RANGE_NOT_ACCEPTED,
+		 error);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
 /**
  * Validate UDP item.
  *
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index f56115dd11..fcb05abced 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -186,6 +186,9 @@ enum mlx5_feature_name {
 #define MLX5_FLOW_ITEM_INNER_FLEX (UINT64_C(1) << 38)
 #define MLX5_FLOW_ITEM_FLEX_TUNNEL (UINT64_C(1) << 39)
 
+/* ESP item */
+#define MLX5_FLOW_ITEM_ESP (UINT64_C(1) << 40)
+
 /* Outer Masks. */
 #define MLX5_FLOW_LAYER_OUTER_L3 \
 	(MLX5_FLOW_LAYER_OUTER_L3_IPV4 | MLX5_FLOW_LAYER_OUTER_L3_IPV6)
@@ -1185,6 +1188,16 @@ struct rte_flow_template_table {
 	(MLX5_RSS_HASH_IPV6 | IBV_RX_HASH_SRC_PORT_TCP)
 #define MLX5_RSS_HASH_IPV6_TCP_DST_ONLY \
 	(MLX5_RSS_HASH_IPV6 | IBV_RX_HASH_DST_PORT_TCP)
+
+#ifndef HAVE_IBV_RX_HASH_IPSEC_SPI
+#define IBV_RX_HASH_IPSEC_SPI (1U << 8)
+#endif
+
+#define MLX5_RSS_HASH_ESP_SPI IBV_RX_HASH_IPSEC_SPI
+#define MLX5_RSS_HASH_IPV4_ESP (MLX5_RSS_HASH_IPV4 | \
+				MLX5_RSS_HASH_ESP_SPI)
+#define MLX5_RSS_HASH_IPV6_ESP (MLX5_RSS_HASH_IPV6 | \
+				MLX5_RSS_HASH_ESP_SPI)
 #define MLX5_RSS_HASH_NONE 0ULL
 
 
@@ -1200,9 +1213,12 @@ static const uint64_t mlx5_rss_hash_fields[] = {
 	MLX5_RSS_HASH_IPV4,
 	MLX5_RSS_HASH_IPV4_TCP,
 	MLX5_RSS_HASH_IPV4_UDP,
+	MLX5_RSS_HASH_IPV4_ESP,
 	MLX5_RSS_HASH_IPV6,
 	MLX5_RSS_HASH_IPV6_TCP,
 	MLX5_RSS_HASH_IPV6_UDP,
+	MLX5_RSS_HASH_IPV6_ESP,
+	MLX5_RSS_HASH_ESP_SPI,
 	MLX5_RSS_HASH_NONE,
 };
 
@@ -1812,6 +1828,10 @@ int mlx5_flow_validate_item_tcp(const struct rte_flow_item *item,
 				uint8_t target_protocol,
 				const struct rte_flow_item_tcp *flow_mask,
 				struct rte_flow_error *error);
+int mlx5_flow_validate_item_esp(const struct rte_flow_item *item,
+				uint64_t item_flags,
+				uint8_t target_protocol,
+				struct rte_flow_error *error);
 int mlx5_flow_validate_item_udp(const struct rte_flow_item *item,
 				uint64_t item_flags,
 				uint8_t target_protocol,
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 1e9bd63635..15097e340a 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -6955,6 +6955,14 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 		switch (type) {
 		case RTE_FLOW_ITEM_TYPE_VOID:
 			break;
+		case RTE_FLOW_ITEM_TYPE_ESP:
+			ret = mlx5_flow_validate_item_esp(items, item_flags,
+							  next_protocol,
+							  error);
+			if (ret < 0)
+				return ret;
+			last_item = MLX5_FLOW_ITEM_ESP;
+			break;
 		case RTE_FLOW_ITEM_TYPE_PORT_ID:
 			ret = flow_dv_validate_item_port_id
 					(dev, items, attr, item_flags, error);
@@ -8729,6 +8737,58 @@ flow_dv_translate_item_tcp(void *matcher, void *key,
 		 (tcp_v->hdr.tcp_flags & tcp_m->hdr.tcp_flags));
 }
 
+/**
+ * Add ESP item to matcher and to the value.
+ *
+ * @param[in, out] matcher
+ *   Flow matcher.
+ * @param[in, out] key
+ *   Flow matcher value.
+ * @param[in] item
+ *   Flow pattern to translate.
+ * @param[in] inner
+ *   Item is inner pattern.
+ */
+static void
+flow_dv_translate_item_esp(void *matcher, void *key,
+			   const struct rte_flow_item *item,
+			   int inner)
+{
+	const struct rte_flow_item_esp *esp_m = item->mask;
+	const struct rte_flow_item_esp *esp_v = item->spec;
+	void *headers_m;
+	void *headers_v;
+	char *spi_m;
+	char *spi_v;
+
+	if (inner) {
+		headers_m = MLX5_ADDR_OF(fte_match_param, matcher,
+					 inner_headers);
+		headers_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers);
+	} else {
+		headers_m = MLX5_ADDR_OF(fte_match_param, matcher,
+					 outer_headers);
+		headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
+	}
+	MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_protocol, 0xff);
+	MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, IPPROTO_ESP);
+	if (!esp_v)
+		return;
+	if (!esp_m)
+		esp_m = &rte_flow_item_esp_mask;
+	headers_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters);
+	headers_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
+	if (inner) {
+		spi_m = MLX5_ADDR_OF(fte_match_set_misc, headers_m, inner_esp_spi);
+		spi_v = MLX5_ADDR_OF(fte_match_set_misc, headers_v, inner_esp_spi);
+	} else {
+		spi_m = MLX5_ADDR_OF(fte_match_set_misc, headers_m, outer_esp_spi);
+		spi_v = MLX5_ADDR_OF(fte_match_set_misc, headers_v, outer_esp_spi);
+	}
+	*(uint32_t *)spi_m = esp_m->hdr.spi;
+	*(uint32_t *)spi_v = esp_m->hdr.spi & esp_v->hdr.spi;
+}
+
 /**
  * Add UDP item to matcher and to the value.
  *
@@ -11188,12 +11248,18 @@ flow_dv_hashfields_set(uint64_t item_flags,
 				fields |= MLX5_IPV6_IBV_RX_HASH;
 		}
 	}
-	if (fields == 0)
+	if (items & MLX5_FLOW_ITEM_ESP) {
+		if (rss_types & RTE_ETH_RSS_ESP)
+			fields |= IBV_RX_HASH_IPSEC_SPI;
+	}
+	if ((fields & ~IBV_RX_HASH_IPSEC_SPI) == 0) {
+		*hash_fields = fields;
 		/*
 		 * There is no match between the RSS types and the
 		 * L3 protocol (IPv4/IPv6) defined in the flow rule.
 		 */
 		return;
+	}
 	if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L4_UDP)) ||
 	    (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L4_UDP)) ||
 	    !items) {
@@ -13538,6 +13604,11 @@ flow_dv_translate(struct rte_eth_dev *dev,
 						  RTE_FLOW_ERROR_TYPE_ITEM,
 						  NULL, "item not supported");
 		switch (item_type) {
+		case RTE_FLOW_ITEM_TYPE_ESP:
+			flow_dv_translate_item_esp(match_mask, match_value,
+						   items, tunnel);
+			last_item = MLX5_FLOW_ITEM_ESP;
+			break;
 		case RTE_FLOW_ITEM_TYPE_PORT_ID:
 			flow_dv_translate_item_port_id
 				(dev, match_mask, match_value, items, attr);
@@ -14007,6 +14078,15 @@ __flow_dv_action_rss_hrxq_set(struct mlx5_shared_action_rss *action,
 	case MLX5_RSS_HASH_NONE:
 		hrxqs[6] = hrxq_idx;
 		return 0;
+	case MLX5_RSS_HASH_IPV4_ESP:
+		hrxqs[7] = hrxq_idx;
+		return 0;
+	case MLX5_RSS_HASH_IPV6_ESP:
+		hrxqs[8] = hrxq_idx;
+		return 0;
+	case MLX5_RSS_HASH_ESP_SPI:
+		hrxqs[9] = hrxq_idx;
+		return 0;
 	default:
 		return -1;
 	}
@@ -14076,6 +14156,12 @@ flow_dv_action_rss_hrxq_lookup(struct rte_eth_dev *dev, uint32_t idx,
 		return hrxqs[5];
 	case MLX5_RSS_HASH_NONE:
 		return hrxqs[6];
+	case MLX5_RSS_HASH_IPV4_ESP:
+		return hrxqs[7];
+	case MLX5_RSS_HASH_IPV6_ESP:
+		return hrxqs[8];
+	case MLX5_RSS_HASH_ESP_SPI:
+		return hrxqs[9];
 	default:
 		return 0;
 	}
-- 
2.21.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH V3] net/mlx5: support ESP SPI match and RSS hash
  2022-04-18 10:57 ` [PATCH V2] " Raja Zidane
@ 2022-04-18 11:01   ` Raja Zidane
  2022-04-28 15:43     ` [PATCH V4] " Raja Zidane
  0 siblings, 1 reply; 9+ messages in thread
From: Raja Zidane @ 2022-04-18 11:01 UTC (permalink / raw)
  To: dev; +Cc: matan

In packets with ESP header, The Inner IP will be encrypted, and
its fields cannot be used for RSS hashing. So, ESP packets
can be hashed only by the outer IP layer.
So, when using RSS on ESP packets, hashing may not be efficient,
because the fields used by the hash functions are only the Outer IPs,
causing all traffic belonging to all tunnels between a given
pair of GWs to land on one core.
Adding the SPI hash field can extend the spreading of IPSec packets.

support matching on ESP SPI.
Support RSS on ESP header by hashing SPI field.

Signed-off-by: Raja Zidane <rzidane@nvidia.com>
---
V2: added doc.
V3: fixed checkpatch.
 doc/guides/nics/features/mlx5.ini      |  1 +
 doc/guides/rel_notes/release_22_07.rst |  2 +
 drivers/common/mlx5/linux/meson.build  |  2 +
 drivers/common/mlx5/mlx5_prm.h         |  5 +-
 drivers/net/mlx5/mlx5_defs.h           |  2 +-
 drivers/net/mlx5/mlx5_devx.c           |  4 +-
 drivers/net/mlx5/mlx5_flow.c           | 84 +++++++++++++++++++++++-
 drivers/net/mlx5/mlx5_flow.h           | 20 ++++++
 drivers/net/mlx5/mlx5_flow_dv.c        | 88 +++++++++++++++++++++++++-
 9 files changed, 203 insertions(+), 5 deletions(-)

diff --git a/doc/guides/nics/features/mlx5.ini b/doc/guides/nics/features/mlx5.ini
index fb5993124d..5738f35324 100644
--- a/doc/guides/nics/features/mlx5.ini
+++ b/doc/guides/nics/features/mlx5.ini
@@ -56,6 +56,7 @@ Usage doc            = Y
 [rte_flow items]
 conntrack            = Y
 ecpri                = Y
+esp                  = Y
 eth                  = Y
 flex                 = Y
 geneve               = Y
diff --git a/doc/guides/rel_notes/release_22_07.rst b/doc/guides/rel_notes/release_22_07.rst
index 49b7b33f87..824ef08ea0 100644
--- a/doc/guides/rel_notes/release_22_07.rst
+++ b/doc/guides/rel_notes/release_22_07.rst
@@ -59,6 +59,8 @@ New Features
 
   * Added support for set promiscuous mode in Windows.
   * Added support for set and get MTU in Windows.
+  * Added new item (ESP).
+  * Added RSS for ESP.
 
 Removed Items
 -------------
diff --git a/drivers/common/mlx5/linux/meson.build b/drivers/common/mlx5/linux/meson.build
index ed48245c67..5335f5b027 100644
--- a/drivers/common/mlx5/linux/meson.build
+++ b/drivers/common/mlx5/linux/meson.build
@@ -72,6 +72,8 @@ has_member_args = [
 # [ "MACRO to define if found", "header for the search",
 #   "symbol to search" ]
 has_sym_args = [
+        [ 'HAVE_IBV_RX_HASH_IPSEC_SPI', 'infiniband/verbs.h',
+            'IBV_RX_HASH_IPSEC_SPI' ],
         [ 'HAVE_IBV_RELAXED_ORDERING', 'infiniband/verbs.h',
             'IBV_ACCESS_RELAXED_ORDERING ' ],
         [ 'HAVE_IBV_DEVICE_STRIDING_RQ_SUPPORT', 'infiniband/mlx5dv.h',
diff --git a/drivers/common/mlx5/mlx5_prm.h b/drivers/common/mlx5/mlx5_prm.h
index 44b18225f6..630b2c5100 100644
--- a/drivers/common/mlx5/mlx5_prm.h
+++ b/drivers/common/mlx5/mlx5_prm.h
@@ -899,7 +899,10 @@ struct mlx5_ifc_fte_match_set_misc_bits {
 	u8 reserved_at_120[0xa];
 	u8 geneve_opt_len[0x6];
 	u8 geneve_protocol_type[0x10];
-	u8 reserved_at_140[0xc0];
+	u8 reserved_at_140[0x20];
+	u8 inner_esp_spi[0x20];
+	u8 outer_esp_spi[0x20];
+	u8 reserved_at_1a0[0x60];
 };
 
 struct mlx5_ifc_ipv4_layout_bits {
diff --git a/drivers/net/mlx5/mlx5_defs.h b/drivers/net/mlx5/mlx5_defs.h
index 15728fb41f..f5c6f23d56 100644
--- a/drivers/net/mlx5/mlx5_defs.h
+++ b/drivers/net/mlx5/mlx5_defs.h
@@ -90,7 +90,7 @@
 
 /* Supported RSS */
 #define MLX5_RSS_HF_MASK (~(RTE_ETH_RSS_IP | RTE_ETH_RSS_UDP | RTE_ETH_RSS_TCP | \
-			    MLX5_RSS_SRC_DST_ONLY))
+			    MLX5_RSS_SRC_DST_ONLY | RTE_ETH_RSS_ESP))
 
 /* Timeout in seconds to get a valid link status. */
 #define MLX5_LINK_STATUS_TIMEOUT 10
diff --git a/drivers/net/mlx5/mlx5_devx.c b/drivers/net/mlx5/mlx5_devx.c
index 5ab092a259..7ae389dc10 100644
--- a/drivers/net/mlx5/mlx5_devx.c
+++ b/drivers/net/mlx5/mlx5_devx.c
@@ -765,7 +765,9 @@ mlx5_devx_tir_attr_set(struct rte_eth_dev *dev, const uint8_t *rss_key,
 			(!!(hash_fields & MLX5_L4_SRC_IBV_RX_HASH)) <<
 			 MLX5_RX_HASH_FIELD_SELECT_SELECTED_FIELDS_L4_SPORT |
 			(!!(hash_fields & MLX5_L4_DST_IBV_RX_HASH)) <<
-			 MLX5_RX_HASH_FIELD_SELECT_SELECTED_FIELDS_L4_DPORT;
+			 MLX5_RX_HASH_FIELD_SELECT_SELECTED_FIELDS_L4_DPORT |
+			(!!(hash_fields & IBV_RX_HASH_IPSEC_SPI)) <<
+			 MLX5_RX_HASH_FIELD_SELECT_SELECTED_FIELDS_IPSEC_SPI;
 	}
 	if (is_hairpin)
 		tir_attr->transport_domain = priv->sh->td->id;
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index f5bdf661b0..de0c15fef6 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -149,6 +149,7 @@ mlx5_flow_is_rss_expandable_item(const struct rte_flow_item *item)
 	case RTE_FLOW_ITEM_TYPE_IPV6:
 	case RTE_FLOW_ITEM_TYPE_UDP:
 	case RTE_FLOW_ITEM_TYPE_TCP:
+	case RTE_FLOW_ITEM_TYPE_ESP:
 	case RTE_FLOW_ITEM_TYPE_VXLAN:
 	case RTE_FLOW_ITEM_TYPE_NVGRE:
 	case RTE_FLOW_ITEM_TYPE_GRE:
@@ -214,6 +215,9 @@ mlx5_inet_proto_to_item_type(uint8_t proto_spec, uint8_t proto_mask)
 	case IPPROTO_IPV6:
 		type = RTE_FLOW_ITEM_TYPE_IPV6;
 		break;
+	case IPPROTO_ESP:
+		type = RTE_FLOW_ITEM_TYPE_ESP;
+		break;
 	default:
 		type = RTE_FLOW_ITEM_TYPE_END;
 	}
@@ -558,9 +562,11 @@ enum mlx5_expansion {
 	MLX5_EXPANSION_OUTER_IPV4,
 	MLX5_EXPANSION_OUTER_IPV4_UDP,
 	MLX5_EXPANSION_OUTER_IPV4_TCP,
+	MLX5_EXPANSION_OUTER_IPV4_ESP,
 	MLX5_EXPANSION_OUTER_IPV6,
 	MLX5_EXPANSION_OUTER_IPV6_UDP,
 	MLX5_EXPANSION_OUTER_IPV6_TCP,
+	MLX5_EXPANSION_OUTER_IPV6_ESP,
 	MLX5_EXPANSION_VXLAN,
 	MLX5_EXPANSION_STD_VXLAN,
 	MLX5_EXPANSION_L3_VXLAN,
@@ -574,9 +580,11 @@ enum mlx5_expansion {
 	MLX5_EXPANSION_IPV4,
 	MLX5_EXPANSION_IPV4_UDP,
 	MLX5_EXPANSION_IPV4_TCP,
+	MLX5_EXPANSION_IPV4_ESP,
 	MLX5_EXPANSION_IPV6,
 	MLX5_EXPANSION_IPV6_UDP,
 	MLX5_EXPANSION_IPV6_TCP,
+	MLX5_EXPANSION_IPV6_ESP,
 	MLX5_EXPANSION_IPV6_FRAG_EXT,
 	MLX5_EXPANSION_GTP,
 	MLX5_EXPANSION_GENEVE,
@@ -611,6 +619,7 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 		.next = MLX5_FLOW_EXPAND_RSS_NEXT
 			(MLX5_EXPANSION_OUTER_IPV4_UDP,
 			 MLX5_EXPANSION_OUTER_IPV4_TCP,
+			 MLX5_EXPANSION_OUTER_IPV4_ESP,
 			 MLX5_EXPANSION_GRE,
 			 MLX5_EXPANSION_NVGRE,
 			 MLX5_EXPANSION_IPV4,
@@ -632,10 +641,15 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 		.type = RTE_FLOW_ITEM_TYPE_TCP,
 		.rss_types = RTE_ETH_RSS_NONFRAG_IPV4_TCP,
 	},
+	[MLX5_EXPANSION_OUTER_IPV4_ESP] = {
+		.type = RTE_FLOW_ITEM_TYPE_ESP,
+		.rss_types = RTE_ETH_RSS_ESP,
+	},
 	[MLX5_EXPANSION_OUTER_IPV6] = {
 		.next = MLX5_FLOW_EXPAND_RSS_NEXT
 			(MLX5_EXPANSION_OUTER_IPV6_UDP,
 			 MLX5_EXPANSION_OUTER_IPV6_TCP,
+			 MLX5_EXPANSION_OUTER_IPV6_ESP,
 			 MLX5_EXPANSION_IPV4,
 			 MLX5_EXPANSION_IPV6,
 			 MLX5_EXPANSION_GRE,
@@ -657,6 +671,10 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 		.type = RTE_FLOW_ITEM_TYPE_TCP,
 		.rss_types = RTE_ETH_RSS_NONFRAG_IPV6_TCP,
 	},
+	[MLX5_EXPANSION_OUTER_IPV6_ESP] = {
+		.type = RTE_FLOW_ITEM_TYPE_ESP,
+		.rss_types = RTE_ETH_RSS_ESP,
+	},
 	[MLX5_EXPANSION_VXLAN] = {
 		.next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH,
 						  MLX5_EXPANSION_IPV4,
@@ -716,7 +734,8 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 	},
 	[MLX5_EXPANSION_IPV4] = {
 		.next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4_UDP,
-						  MLX5_EXPANSION_IPV4_TCP),
+						  MLX5_EXPANSION_IPV4_TCP,
+						  MLX5_EXPANSION_IPV4_ESP),
 		.type = RTE_FLOW_ITEM_TYPE_IPV4,
 		.rss_types = RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4 |
 			RTE_ETH_RSS_NONFRAG_IPV4_OTHER,
@@ -729,9 +748,14 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 		.type = RTE_FLOW_ITEM_TYPE_TCP,
 		.rss_types = RTE_ETH_RSS_NONFRAG_IPV4_TCP,
 	},
+	[MLX5_EXPANSION_IPV4_ESP] = {
+		.type = RTE_FLOW_ITEM_TYPE_ESP,
+		.rss_types = RTE_ETH_RSS_ESP,
+	},
 	[MLX5_EXPANSION_IPV6] = {
 		.next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV6_UDP,
 						  MLX5_EXPANSION_IPV6_TCP,
+						  MLX5_EXPANSION_IPV6_ESP,
 						  MLX5_EXPANSION_IPV6_FRAG_EXT),
 		.type = RTE_FLOW_ITEM_TYPE_IPV6,
 		.rss_types = RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6 |
@@ -745,6 +769,10 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 		.type = RTE_FLOW_ITEM_TYPE_TCP,
 		.rss_types = RTE_ETH_RSS_NONFRAG_IPV6_TCP,
 	},
+	[MLX5_EXPANSION_IPV6_ESP] = {
+		.type = RTE_FLOW_ITEM_TYPE_ESP,
+		.rss_types = RTE_ETH_RSS_ESP,
+	},
 	[MLX5_EXPANSION_IPV6_FRAG_EXT] = {
 		.type = RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT,
 	},
@@ -2618,6 +2646,60 @@ mlx5_flow_validate_item_ipv6(const struct rte_flow_item *item,
 	return 0;
 }
 
+/**
+ * Validate ESP item.
+ *
+ * @param[in] item
+ *   Item specification.
+ * @param[in] item_flags
+ *   Bit-fields that holds the items detected until now.
+ * @param[in] target_protocol
+ *   The next protocol in the previous item.
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_flow_validate_item_esp(const struct rte_flow_item *item,
+			    uint64_t item_flags,
+			    uint8_t target_protocol,
+			    struct rte_flow_error *error)
+{
+	const struct rte_flow_item_esp *mask = item->mask;
+	const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
+	const uint64_t l3m = tunnel ? MLX5_FLOW_LAYER_INNER_L3 :
+				      MLX5_FLOW_LAYER_OUTER_L3;
+	const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 :
+				      MLX5_FLOW_LAYER_OUTER_L4;
+	int ret;
+
+	if (!(item_flags & l3m))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  "L3 is mandatory to filter on L4");
+	if (item_flags & l4m)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  "multiple L4 layers not supported");
+	if (target_protocol != 0xff && target_protocol != IPPROTO_ESP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  "protocol filtering not compatible"
+					  " with ESP layer");
+	if (!mask)
+		mask = &rte_flow_item_esp_mask;
+	ret = mlx5_flow_item_acceptable
+		(item, (const uint8_t *)mask,
+		 (const uint8_t *)&rte_flow_item_esp_mask,
+		 sizeof(struct rte_flow_item_esp), MLX5_ITEM_RANGE_NOT_ACCEPTED,
+		 error);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
 /**
  * Validate UDP item.
  *
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index f56115dd11..fcb05abced 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -186,6 +186,9 @@ enum mlx5_feature_name {
 #define MLX5_FLOW_ITEM_INNER_FLEX (UINT64_C(1) << 38)
 #define MLX5_FLOW_ITEM_FLEX_TUNNEL (UINT64_C(1) << 39)
 
+/* ESP item */
+#define MLX5_FLOW_ITEM_ESP (UINT64_C(1) << 40)
+
 /* Outer Masks. */
 #define MLX5_FLOW_LAYER_OUTER_L3 \
 	(MLX5_FLOW_LAYER_OUTER_L3_IPV4 | MLX5_FLOW_LAYER_OUTER_L3_IPV6)
@@ -1185,6 +1188,16 @@ struct rte_flow_template_table {
 	(MLX5_RSS_HASH_IPV6 | IBV_RX_HASH_SRC_PORT_TCP)
 #define MLX5_RSS_HASH_IPV6_TCP_DST_ONLY \
 	(MLX5_RSS_HASH_IPV6 | IBV_RX_HASH_DST_PORT_TCP)
+
+#ifndef HAVE_IBV_RX_HASH_IPSEC_SPI
+#define IBV_RX_HASH_IPSEC_SPI (1U << 8)
+#endif
+
+#define MLX5_RSS_HASH_ESP_SPI IBV_RX_HASH_IPSEC_SPI
+#define MLX5_RSS_HASH_IPV4_ESP (MLX5_RSS_HASH_IPV4 | \
+				MLX5_RSS_HASH_ESP_SPI)
+#define MLX5_RSS_HASH_IPV6_ESP (MLX5_RSS_HASH_IPV6 | \
+				MLX5_RSS_HASH_ESP_SPI)
 #define MLX5_RSS_HASH_NONE 0ULL
 
 
@@ -1200,9 +1213,12 @@ static const uint64_t mlx5_rss_hash_fields[] = {
 	MLX5_RSS_HASH_IPV4,
 	MLX5_RSS_HASH_IPV4_TCP,
 	MLX5_RSS_HASH_IPV4_UDP,
+	MLX5_RSS_HASH_IPV4_ESP,
 	MLX5_RSS_HASH_IPV6,
 	MLX5_RSS_HASH_IPV6_TCP,
 	MLX5_RSS_HASH_IPV6_UDP,
+	MLX5_RSS_HASH_IPV6_ESP,
+	MLX5_RSS_HASH_ESP_SPI,
 	MLX5_RSS_HASH_NONE,
 };
 
@@ -1812,6 +1828,10 @@ int mlx5_flow_validate_item_tcp(const struct rte_flow_item *item,
 				uint8_t target_protocol,
 				const struct rte_flow_item_tcp *flow_mask,
 				struct rte_flow_error *error);
+int mlx5_flow_validate_item_esp(const struct rte_flow_item *item,
+				uint64_t item_flags,
+				uint8_t target_protocol,
+				struct rte_flow_error *error);
 int mlx5_flow_validate_item_udp(const struct rte_flow_item *item,
 				uint64_t item_flags,
 				uint8_t target_protocol,
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 1e9bd63635..15097e340a 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -6955,6 +6955,14 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 		switch (type) {
 		case RTE_FLOW_ITEM_TYPE_VOID:
 			break;
+		case RTE_FLOW_ITEM_TYPE_ESP:
+			ret = mlx5_flow_validate_item_esp(items, item_flags,
+							  next_protocol,
+							  error);
+			if (ret < 0)
+				return ret;
+			last_item = MLX5_FLOW_ITEM_ESP;
+			break;
 		case RTE_FLOW_ITEM_TYPE_PORT_ID:
 			ret = flow_dv_validate_item_port_id
 					(dev, items, attr, item_flags, error);
@@ -8729,6 +8737,58 @@ flow_dv_translate_item_tcp(void *matcher, void *key,
 		 (tcp_v->hdr.tcp_flags & tcp_m->hdr.tcp_flags));
 }
 
+/**
+ * Add ESP item to matcher and to the value.
+ *
+ * @param[in, out] matcher
+ *   Flow matcher.
+ * @param[in, out] key
+ *   Flow matcher value.
+ * @param[in] item
+ *   Flow pattern to translate.
+ * @param[in] inner
+ *   Item is inner pattern.
+ */
+static void
+flow_dv_translate_item_esp(void *matcher, void *key,
+			   const struct rte_flow_item *item,
+			   int inner)
+{
+	const struct rte_flow_item_esp *esp_m = item->mask;
+	const struct rte_flow_item_esp *esp_v = item->spec;
+	void *headers_m;
+	void *headers_v;
+	char *spi_m;
+	char *spi_v;
+
+	if (inner) {
+		headers_m = MLX5_ADDR_OF(fte_match_param, matcher,
+					 inner_headers);
+		headers_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers);
+	} else {
+		headers_m = MLX5_ADDR_OF(fte_match_param, matcher,
+					 outer_headers);
+		headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
+	}
+	MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_protocol, 0xff);
+	MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, IPPROTO_ESP);
+	if (!esp_v)
+		return;
+	if (!esp_m)
+		esp_m = &rte_flow_item_esp_mask;
+	headers_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters);
+	headers_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
+	if (inner) {
+		spi_m = MLX5_ADDR_OF(fte_match_set_misc, headers_m, inner_esp_spi);
+		spi_v = MLX5_ADDR_OF(fte_match_set_misc, headers_v, inner_esp_spi);
+	} else {
+		spi_m = MLX5_ADDR_OF(fte_match_set_misc, headers_m, outer_esp_spi);
+		spi_v = MLX5_ADDR_OF(fte_match_set_misc, headers_v, outer_esp_spi);
+	}
+	*(uint32_t *)spi_m = esp_m->hdr.spi;
+	*(uint32_t *)spi_v = esp_m->hdr.spi & esp_v->hdr.spi;
+}
+
 /**
  * Add UDP item to matcher and to the value.
  *
@@ -11188,12 +11248,18 @@ flow_dv_hashfields_set(uint64_t item_flags,
 				fields |= MLX5_IPV6_IBV_RX_HASH;
 		}
 	}
-	if (fields == 0)
+	if (items & MLX5_FLOW_ITEM_ESP) {
+		if (rss_types & RTE_ETH_RSS_ESP)
+			fields |= IBV_RX_HASH_IPSEC_SPI;
+	}
+	if ((fields & ~IBV_RX_HASH_IPSEC_SPI) == 0) {
+		*hash_fields = fields;
 		/*
 		 * There is no match between the RSS types and the
 		 * L3 protocol (IPv4/IPv6) defined in the flow rule.
 		 */
 		return;
+	}
 	if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L4_UDP)) ||
 	    (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L4_UDP)) ||
 	    !items) {
@@ -13538,6 +13604,11 @@ flow_dv_translate(struct rte_eth_dev *dev,
 						  RTE_FLOW_ERROR_TYPE_ITEM,
 						  NULL, "item not supported");
 		switch (item_type) {
+		case RTE_FLOW_ITEM_TYPE_ESP:
+			flow_dv_translate_item_esp(match_mask, match_value,
+						   items, tunnel);
+			last_item = MLX5_FLOW_ITEM_ESP;
+			break;
 		case RTE_FLOW_ITEM_TYPE_PORT_ID:
 			flow_dv_translate_item_port_id
 				(dev, match_mask, match_value, items, attr);
@@ -14007,6 +14078,15 @@ __flow_dv_action_rss_hrxq_set(struct mlx5_shared_action_rss *action,
 	case MLX5_RSS_HASH_NONE:
 		hrxqs[6] = hrxq_idx;
 		return 0;
+	case MLX5_RSS_HASH_IPV4_ESP:
+		hrxqs[7] = hrxq_idx;
+		return 0;
+	case MLX5_RSS_HASH_IPV6_ESP:
+		hrxqs[8] = hrxq_idx;
+		return 0;
+	case MLX5_RSS_HASH_ESP_SPI:
+		hrxqs[9] = hrxq_idx;
+		return 0;
 	default:
 		return -1;
 	}
@@ -14076,6 +14156,12 @@ flow_dv_action_rss_hrxq_lookup(struct rte_eth_dev *dev, uint32_t idx,
 		return hrxqs[5];
 	case MLX5_RSS_HASH_NONE:
 		return hrxqs[6];
+	case MLX5_RSS_HASH_IPV4_ESP:
+		return hrxqs[7];
+	case MLX5_RSS_HASH_IPV6_ESP:
+		return hrxqs[8];
+	case MLX5_RSS_HASH_ESP_SPI:
+		return hrxqs[9];
 	default:
 		return 0;
 	}
-- 
2.21.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH V4] net/mlx5: support ESP SPI match and RSS hash
  2022-04-18 11:01   ` [PATCH V3] " Raja Zidane
@ 2022-04-28 15:43     ` Raja Zidane
  2022-05-11  8:07       ` Matan Azrad
  2022-05-12  9:17       ` [PATCH V5] " Raja Zidane
  0 siblings, 2 replies; 9+ messages in thread
From: Raja Zidane @ 2022-04-28 15:43 UTC (permalink / raw)
  To: dev; +Cc: matan

In packets with ESP header, The Inner IP will be encrypted, and
its fields cannot be used for RSS hashing. So, ESP packets
can be hashed only by the outer IP layer.
So, when using RSS on ESP packets, hashing may not be efficient,
because the fields used by the hash functions are only the Outer IPs,
causing all traffic belonging to all tunnels between a given
pair of GWs to land on one core.
Adding the SPI hash field can extend the spreading of IPSec packets.

support matching on ESP SPI.
Support RSS on ESP header by hashing SPI field.

Signed-off-by: Raja Zidane <rzidane@nvidia.com>
---
V2: added doc.
V3: fixed checkpatch.
V4: rebase
 doc/guides/nics/features/mlx5.ini      |  1 +
 doc/guides/rel_notes/release_22_07.rst |  2 +
 drivers/common/mlx5/linux/meson.build  |  2 +
 drivers/common/mlx5/mlx5_prm.h         |  5 +-
 drivers/net/mlx5/mlx5_defs.h           |  2 +-
 drivers/net/mlx5/mlx5_devx.c           |  4 +-
 drivers/net/mlx5/mlx5_flow.c           | 84 +++++++++++++++++++++++-
 drivers/net/mlx5/mlx5_flow.h           | 20 ++++++
 drivers/net/mlx5/mlx5_flow_dv.c        | 88 +++++++++++++++++++++++++-
 9 files changed, 203 insertions(+), 5 deletions(-)

diff --git a/doc/guides/nics/features/mlx5.ini b/doc/guides/nics/features/mlx5.ini
index fb5993124d..5738f35324 100644
--- a/doc/guides/nics/features/mlx5.ini
+++ b/doc/guides/nics/features/mlx5.ini
@@ -56,6 +56,7 @@ Usage doc            = Y
 [rte_flow items]
 conntrack            = Y
 ecpri                = Y
+esp                  = Y
 eth                  = Y
 flex                 = Y
 geneve               = Y
diff --git a/doc/guides/rel_notes/release_22_07.rst b/doc/guides/rel_notes/release_22_07.rst
index 88d6e96cc1..a4abbf7d02 100644
--- a/doc/guides/rel_notes/release_22_07.rst
+++ b/doc/guides/rel_notes/release_22_07.rst
@@ -64,6 +64,8 @@ New Features
 
   * Added support for promiscuous mode on Windows.
   * Added support for MTU on Windows.
+  * Added new item (ESP).
+  * Added RSS for ESP.
 
 
 Removed Items
diff --git a/drivers/common/mlx5/linux/meson.build b/drivers/common/mlx5/linux/meson.build
index ed48245c67..5335f5b027 100644
--- a/drivers/common/mlx5/linux/meson.build
+++ b/drivers/common/mlx5/linux/meson.build
@@ -72,6 +72,8 @@ has_member_args = [
 # [ "MACRO to define if found", "header for the search",
 #   "symbol to search" ]
 has_sym_args = [
+        [ 'HAVE_IBV_RX_HASH_IPSEC_SPI', 'infiniband/verbs.h',
+            'IBV_RX_HASH_IPSEC_SPI' ],
         [ 'HAVE_IBV_RELAXED_ORDERING', 'infiniband/verbs.h',
             'IBV_ACCESS_RELAXED_ORDERING ' ],
         [ 'HAVE_IBV_DEVICE_STRIDING_RQ_SUPPORT', 'infiniband/mlx5dv.h',
diff --git a/drivers/common/mlx5/mlx5_prm.h b/drivers/common/mlx5/mlx5_prm.h
index 44b18225f6..630b2c5100 100644
--- a/drivers/common/mlx5/mlx5_prm.h
+++ b/drivers/common/mlx5/mlx5_prm.h
@@ -899,7 +899,10 @@ struct mlx5_ifc_fte_match_set_misc_bits {
 	u8 reserved_at_120[0xa];
 	u8 geneve_opt_len[0x6];
 	u8 geneve_protocol_type[0x10];
-	u8 reserved_at_140[0xc0];
+	u8 reserved_at_140[0x20];
+	u8 inner_esp_spi[0x20];
+	u8 outer_esp_spi[0x20];
+	u8 reserved_at_1a0[0x60];
 };
 
 struct mlx5_ifc_ipv4_layout_bits {
diff --git a/drivers/net/mlx5/mlx5_defs.h b/drivers/net/mlx5/mlx5_defs.h
index 15728fb41f..f5c6f23d56 100644
--- a/drivers/net/mlx5/mlx5_defs.h
+++ b/drivers/net/mlx5/mlx5_defs.h
@@ -90,7 +90,7 @@
 
 /* Supported RSS */
 #define MLX5_RSS_HF_MASK (~(RTE_ETH_RSS_IP | RTE_ETH_RSS_UDP | RTE_ETH_RSS_TCP | \
-			    MLX5_RSS_SRC_DST_ONLY))
+			    MLX5_RSS_SRC_DST_ONLY | RTE_ETH_RSS_ESP))
 
 /* Timeout in seconds to get a valid link status. */
 #define MLX5_LINK_STATUS_TIMEOUT 10
diff --git a/drivers/net/mlx5/mlx5_devx.c b/drivers/net/mlx5/mlx5_devx.c
index 03c0fac32f..4b48f9433a 100644
--- a/drivers/net/mlx5/mlx5_devx.c
+++ b/drivers/net/mlx5/mlx5_devx.c
@@ -765,7 +765,9 @@ mlx5_devx_tir_attr_set(struct rte_eth_dev *dev, const uint8_t *rss_key,
 			(!!(hash_fields & MLX5_L4_SRC_IBV_RX_HASH)) <<
 			 MLX5_RX_HASH_FIELD_SELECT_SELECTED_FIELDS_L4_SPORT |
 			(!!(hash_fields & MLX5_L4_DST_IBV_RX_HASH)) <<
-			 MLX5_RX_HASH_FIELD_SELECT_SELECTED_FIELDS_L4_DPORT;
+			 MLX5_RX_HASH_FIELD_SELECT_SELECTED_FIELDS_L4_DPORT |
+			(!!(hash_fields & IBV_RX_HASH_IPSEC_SPI)) <<
+			 MLX5_RX_HASH_FIELD_SELECT_SELECTED_FIELDS_IPSEC_SPI;
 	}
 	if (is_hairpin)
 		tir_attr->transport_domain = priv->sh->td->id;
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index f5bdf661b0..de0c15fef6 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -149,6 +149,7 @@ mlx5_flow_is_rss_expandable_item(const struct rte_flow_item *item)
 	case RTE_FLOW_ITEM_TYPE_IPV6:
 	case RTE_FLOW_ITEM_TYPE_UDP:
 	case RTE_FLOW_ITEM_TYPE_TCP:
+	case RTE_FLOW_ITEM_TYPE_ESP:
 	case RTE_FLOW_ITEM_TYPE_VXLAN:
 	case RTE_FLOW_ITEM_TYPE_NVGRE:
 	case RTE_FLOW_ITEM_TYPE_GRE:
@@ -214,6 +215,9 @@ mlx5_inet_proto_to_item_type(uint8_t proto_spec, uint8_t proto_mask)
 	case IPPROTO_IPV6:
 		type = RTE_FLOW_ITEM_TYPE_IPV6;
 		break;
+	case IPPROTO_ESP:
+		type = RTE_FLOW_ITEM_TYPE_ESP;
+		break;
 	default:
 		type = RTE_FLOW_ITEM_TYPE_END;
 	}
@@ -558,9 +562,11 @@ enum mlx5_expansion {
 	MLX5_EXPANSION_OUTER_IPV4,
 	MLX5_EXPANSION_OUTER_IPV4_UDP,
 	MLX5_EXPANSION_OUTER_IPV4_TCP,
+	MLX5_EXPANSION_OUTER_IPV4_ESP,
 	MLX5_EXPANSION_OUTER_IPV6,
 	MLX5_EXPANSION_OUTER_IPV6_UDP,
 	MLX5_EXPANSION_OUTER_IPV6_TCP,
+	MLX5_EXPANSION_OUTER_IPV6_ESP,
 	MLX5_EXPANSION_VXLAN,
 	MLX5_EXPANSION_STD_VXLAN,
 	MLX5_EXPANSION_L3_VXLAN,
@@ -574,9 +580,11 @@ enum mlx5_expansion {
 	MLX5_EXPANSION_IPV4,
 	MLX5_EXPANSION_IPV4_UDP,
 	MLX5_EXPANSION_IPV4_TCP,
+	MLX5_EXPANSION_IPV4_ESP,
 	MLX5_EXPANSION_IPV6,
 	MLX5_EXPANSION_IPV6_UDP,
 	MLX5_EXPANSION_IPV6_TCP,
+	MLX5_EXPANSION_IPV6_ESP,
 	MLX5_EXPANSION_IPV6_FRAG_EXT,
 	MLX5_EXPANSION_GTP,
 	MLX5_EXPANSION_GENEVE,
@@ -611,6 +619,7 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 		.next = MLX5_FLOW_EXPAND_RSS_NEXT
 			(MLX5_EXPANSION_OUTER_IPV4_UDP,
 			 MLX5_EXPANSION_OUTER_IPV4_TCP,
+			 MLX5_EXPANSION_OUTER_IPV4_ESP,
 			 MLX5_EXPANSION_GRE,
 			 MLX5_EXPANSION_NVGRE,
 			 MLX5_EXPANSION_IPV4,
@@ -632,10 +641,15 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 		.type = RTE_FLOW_ITEM_TYPE_TCP,
 		.rss_types = RTE_ETH_RSS_NONFRAG_IPV4_TCP,
 	},
+	[MLX5_EXPANSION_OUTER_IPV4_ESP] = {
+		.type = RTE_FLOW_ITEM_TYPE_ESP,
+		.rss_types = RTE_ETH_RSS_ESP,
+	},
 	[MLX5_EXPANSION_OUTER_IPV6] = {
 		.next = MLX5_FLOW_EXPAND_RSS_NEXT
 			(MLX5_EXPANSION_OUTER_IPV6_UDP,
 			 MLX5_EXPANSION_OUTER_IPV6_TCP,
+			 MLX5_EXPANSION_OUTER_IPV6_ESP,
 			 MLX5_EXPANSION_IPV4,
 			 MLX5_EXPANSION_IPV6,
 			 MLX5_EXPANSION_GRE,
@@ -657,6 +671,10 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 		.type = RTE_FLOW_ITEM_TYPE_TCP,
 		.rss_types = RTE_ETH_RSS_NONFRAG_IPV6_TCP,
 	},
+	[MLX5_EXPANSION_OUTER_IPV6_ESP] = {
+		.type = RTE_FLOW_ITEM_TYPE_ESP,
+		.rss_types = RTE_ETH_RSS_ESP,
+	},
 	[MLX5_EXPANSION_VXLAN] = {
 		.next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH,
 						  MLX5_EXPANSION_IPV4,
@@ -716,7 +734,8 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 	},
 	[MLX5_EXPANSION_IPV4] = {
 		.next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4_UDP,
-						  MLX5_EXPANSION_IPV4_TCP),
+						  MLX5_EXPANSION_IPV4_TCP,
+						  MLX5_EXPANSION_IPV4_ESP),
 		.type = RTE_FLOW_ITEM_TYPE_IPV4,
 		.rss_types = RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4 |
 			RTE_ETH_RSS_NONFRAG_IPV4_OTHER,
@@ -729,9 +748,14 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 		.type = RTE_FLOW_ITEM_TYPE_TCP,
 		.rss_types = RTE_ETH_RSS_NONFRAG_IPV4_TCP,
 	},
+	[MLX5_EXPANSION_IPV4_ESP] = {
+		.type = RTE_FLOW_ITEM_TYPE_ESP,
+		.rss_types = RTE_ETH_RSS_ESP,
+	},
 	[MLX5_EXPANSION_IPV6] = {
 		.next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV6_UDP,
 						  MLX5_EXPANSION_IPV6_TCP,
+						  MLX5_EXPANSION_IPV6_ESP,
 						  MLX5_EXPANSION_IPV6_FRAG_EXT),
 		.type = RTE_FLOW_ITEM_TYPE_IPV6,
 		.rss_types = RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6 |
@@ -745,6 +769,10 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 		.type = RTE_FLOW_ITEM_TYPE_TCP,
 		.rss_types = RTE_ETH_RSS_NONFRAG_IPV6_TCP,
 	},
+	[MLX5_EXPANSION_IPV6_ESP] = {
+		.type = RTE_FLOW_ITEM_TYPE_ESP,
+		.rss_types = RTE_ETH_RSS_ESP,
+	},
 	[MLX5_EXPANSION_IPV6_FRAG_EXT] = {
 		.type = RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT,
 	},
@@ -2618,6 +2646,60 @@ mlx5_flow_validate_item_ipv6(const struct rte_flow_item *item,
 	return 0;
 }
 
+/**
+ * Validate ESP item.
+ *
+ * @param[in] item
+ *   Item specification.
+ * @param[in] item_flags
+ *   Bit-fields that holds the items detected until now.
+ * @param[in] target_protocol
+ *   The next protocol in the previous item.
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_flow_validate_item_esp(const struct rte_flow_item *item,
+			    uint64_t item_flags,
+			    uint8_t target_protocol,
+			    struct rte_flow_error *error)
+{
+	const struct rte_flow_item_esp *mask = item->mask;
+	const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
+	const uint64_t l3m = tunnel ? MLX5_FLOW_LAYER_INNER_L3 :
+				      MLX5_FLOW_LAYER_OUTER_L3;
+	const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 :
+				      MLX5_FLOW_LAYER_OUTER_L4;
+	int ret;
+
+	if (!(item_flags & l3m))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  "L3 is mandatory to filter on L4");
+	if (item_flags & l4m)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  "multiple L4 layers not supported");
+	if (target_protocol != 0xff && target_protocol != IPPROTO_ESP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  "protocol filtering not compatible"
+					  " with ESP layer");
+	if (!mask)
+		mask = &rte_flow_item_esp_mask;
+	ret = mlx5_flow_item_acceptable
+		(item, (const uint8_t *)mask,
+		 (const uint8_t *)&rte_flow_item_esp_mask,
+		 sizeof(struct rte_flow_item_esp), MLX5_ITEM_RANGE_NOT_ACCEPTED,
+		 error);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
 /**
  * Validate UDP item.
  *
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index f56115dd11..fcb05abced 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -186,6 +186,9 @@ enum mlx5_feature_name {
 #define MLX5_FLOW_ITEM_INNER_FLEX (UINT64_C(1) << 38)
 #define MLX5_FLOW_ITEM_FLEX_TUNNEL (UINT64_C(1) << 39)
 
+/* ESP item */
+#define MLX5_FLOW_ITEM_ESP (UINT64_C(1) << 40)
+
 /* Outer Masks. */
 #define MLX5_FLOW_LAYER_OUTER_L3 \
 	(MLX5_FLOW_LAYER_OUTER_L3_IPV4 | MLX5_FLOW_LAYER_OUTER_L3_IPV6)
@@ -1185,6 +1188,16 @@ struct rte_flow_template_table {
 	(MLX5_RSS_HASH_IPV6 | IBV_RX_HASH_SRC_PORT_TCP)
 #define MLX5_RSS_HASH_IPV6_TCP_DST_ONLY \
 	(MLX5_RSS_HASH_IPV6 | IBV_RX_HASH_DST_PORT_TCP)
+
+#ifndef HAVE_IBV_RX_HASH_IPSEC_SPI
+#define IBV_RX_HASH_IPSEC_SPI (1U << 8)
+#endif
+
+#define MLX5_RSS_HASH_ESP_SPI IBV_RX_HASH_IPSEC_SPI
+#define MLX5_RSS_HASH_IPV4_ESP (MLX5_RSS_HASH_IPV4 | \
+				MLX5_RSS_HASH_ESP_SPI)
+#define MLX5_RSS_HASH_IPV6_ESP (MLX5_RSS_HASH_IPV6 | \
+				MLX5_RSS_HASH_ESP_SPI)
 #define MLX5_RSS_HASH_NONE 0ULL
 
 
@@ -1200,9 +1213,12 @@ static const uint64_t mlx5_rss_hash_fields[] = {
 	MLX5_RSS_HASH_IPV4,
 	MLX5_RSS_HASH_IPV4_TCP,
 	MLX5_RSS_HASH_IPV4_UDP,
+	MLX5_RSS_HASH_IPV4_ESP,
 	MLX5_RSS_HASH_IPV6,
 	MLX5_RSS_HASH_IPV6_TCP,
 	MLX5_RSS_HASH_IPV6_UDP,
+	MLX5_RSS_HASH_IPV6_ESP,
+	MLX5_RSS_HASH_ESP_SPI,
 	MLX5_RSS_HASH_NONE,
 };
 
@@ -1812,6 +1828,10 @@ int mlx5_flow_validate_item_tcp(const struct rte_flow_item *item,
 				uint8_t target_protocol,
 				const struct rte_flow_item_tcp *flow_mask,
 				struct rte_flow_error *error);
+int mlx5_flow_validate_item_esp(const struct rte_flow_item *item,
+				uint64_t item_flags,
+				uint8_t target_protocol,
+				struct rte_flow_error *error);
 int mlx5_flow_validate_item_udp(const struct rte_flow_item *item,
 				uint64_t item_flags,
 				uint8_t target_protocol,
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index cb5006bb11..af7d54ec1f 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -6956,6 +6956,14 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 		switch (type) {
 		case RTE_FLOW_ITEM_TYPE_VOID:
 			break;
+		case RTE_FLOW_ITEM_TYPE_ESP:
+			ret = mlx5_flow_validate_item_esp(items, item_flags,
+							  next_protocol,
+							  error);
+			if (ret < 0)
+				return ret;
+			last_item = MLX5_FLOW_ITEM_ESP;
+			break;
 		case RTE_FLOW_ITEM_TYPE_PORT_ID:
 			ret = flow_dv_validate_item_port_id
 					(dev, items, attr, item_flags, error);
@@ -8730,6 +8738,58 @@ flow_dv_translate_item_tcp(void *matcher, void *key,
 		 (tcp_v->hdr.tcp_flags & tcp_m->hdr.tcp_flags));
 }
 
+/**
+ * Add ESP item to matcher and to the value.
+ *
+ * @param[in, out] matcher
+ *   Flow matcher.
+ * @param[in, out] key
+ *   Flow matcher value.
+ * @param[in] item
+ *   Flow pattern to translate.
+ * @param[in] inner
+ *   Item is inner pattern.
+ */
+static void
+flow_dv_translate_item_esp(void *matcher, void *key,
+			   const struct rte_flow_item *item,
+			   int inner)
+{
+	const struct rte_flow_item_esp *esp_m = item->mask;
+	const struct rte_flow_item_esp *esp_v = item->spec;
+	void *headers_m;
+	void *headers_v;
+	char *spi_m;
+	char *spi_v;
+
+	if (inner) {
+		headers_m = MLX5_ADDR_OF(fte_match_param, matcher,
+					 inner_headers);
+		headers_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers);
+	} else {
+		headers_m = MLX5_ADDR_OF(fte_match_param, matcher,
+					 outer_headers);
+		headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
+	}
+	MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_protocol, 0xff);
+	MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, IPPROTO_ESP);
+	if (!esp_v)
+		return;
+	if (!esp_m)
+		esp_m = &rte_flow_item_esp_mask;
+	headers_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters);
+	headers_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
+	if (inner) {
+		spi_m = MLX5_ADDR_OF(fte_match_set_misc, headers_m, inner_esp_spi);
+		spi_v = MLX5_ADDR_OF(fte_match_set_misc, headers_v, inner_esp_spi);
+	} else {
+		spi_m = MLX5_ADDR_OF(fte_match_set_misc, headers_m, outer_esp_spi);
+		spi_v = MLX5_ADDR_OF(fte_match_set_misc, headers_v, outer_esp_spi);
+	}
+	*(uint32_t *)spi_m = esp_m->hdr.spi;
+	*(uint32_t *)spi_v = esp_m->hdr.spi & esp_v->hdr.spi;
+}
+
 /**
  * Add UDP item to matcher and to the value.
  *
@@ -11189,12 +11249,18 @@ flow_dv_hashfields_set(uint64_t item_flags,
 				fields |= MLX5_IPV6_IBV_RX_HASH;
 		}
 	}
-	if (fields == 0)
+	if (items & MLX5_FLOW_ITEM_ESP) {
+		if (rss_types & RTE_ETH_RSS_ESP)
+			fields |= IBV_RX_HASH_IPSEC_SPI;
+	}
+	if ((fields & ~IBV_RX_HASH_IPSEC_SPI) == 0) {
+		*hash_fields = fields;
 		/*
 		 * There is no match between the RSS types and the
 		 * L3 protocol (IPv4/IPv6) defined in the flow rule.
 		 */
 		return;
+	}
 	if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L4_UDP)) ||
 	    (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L4_UDP)) ||
 	    !items) {
@@ -13539,6 +13605,11 @@ flow_dv_translate(struct rte_eth_dev *dev,
 						  RTE_FLOW_ERROR_TYPE_ITEM,
 						  NULL, "item not supported");
 		switch (item_type) {
+		case RTE_FLOW_ITEM_TYPE_ESP:
+			flow_dv_translate_item_esp(match_mask, match_value,
+						   items, tunnel);
+			last_item = MLX5_FLOW_ITEM_ESP;
+			break;
 		case RTE_FLOW_ITEM_TYPE_PORT_ID:
 			flow_dv_translate_item_port_id
 				(dev, match_mask, match_value, items, attr);
@@ -14008,6 +14079,15 @@ __flow_dv_action_rss_hrxq_set(struct mlx5_shared_action_rss *action,
 	case MLX5_RSS_HASH_NONE:
 		hrxqs[6] = hrxq_idx;
 		return 0;
+	case MLX5_RSS_HASH_IPV4_ESP:
+		hrxqs[7] = hrxq_idx;
+		return 0;
+	case MLX5_RSS_HASH_IPV6_ESP:
+		hrxqs[8] = hrxq_idx;
+		return 0;
+	case MLX5_RSS_HASH_ESP_SPI:
+		hrxqs[9] = hrxq_idx;
+		return 0;
 	default:
 		return -1;
 	}
@@ -14077,6 +14157,12 @@ flow_dv_action_rss_hrxq_lookup(struct rte_eth_dev *dev, uint32_t idx,
 		return hrxqs[5];
 	case MLX5_RSS_HASH_NONE:
 		return hrxqs[6];
+	case MLX5_RSS_HASH_IPV4_ESP:
+		return hrxqs[7];
+	case MLX5_RSS_HASH_IPV6_ESP:
+		return hrxqs[8];
+	case MLX5_RSS_HASH_ESP_SPI:
+		return hrxqs[9];
 	default:
 		return 0;
 	}
-- 
2.21.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [PATCH V4] net/mlx5: support ESP SPI match and RSS hash
  2022-04-28 15:43     ` [PATCH V4] " Raja Zidane
@ 2022-05-11  8:07       ` Matan Azrad
  2022-05-12  9:17       ` [PATCH V5] " Raja Zidane
  1 sibling, 0 replies; 9+ messages in thread
From: Matan Azrad @ 2022-05-11  8:07 UTC (permalink / raw)
  To: Raja Zidane, dev



From: Raja Zidane
> In packets with ESP header, The Inner IP will be encrypted, and its fields cannot
> be used for RSS hashing. So, ESP packets can be hashed only by the outer IP
> layer.
> So, when using RSS on ESP packets, hashing may not be efficient, because the
> fields used by the hash functions are only the Outer IPs, causing all traffic
> belonging to all tunnels between a given pair of GWs to land on one core.
> Adding the SPI hash field can extend the spreading of IPSec packets.
> 
> support matching on ESP SPI.
> Support RSS on ESP header by hashing SPI field.
> 
> Signed-off-by: Raja Zidane <rzidane@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH V5] net/mlx5: support ESP SPI match and RSS hash
  2022-04-28 15:43     ` [PATCH V4] " Raja Zidane
  2022-05-11  8:07       ` Matan Azrad
@ 2022-05-12  9:17       ` Raja Zidane
  2022-05-12 15:05         ` Matan Azrad
  2022-05-15  7:40         ` Raslan Darawsheh
  1 sibling, 2 replies; 9+ messages in thread
From: Raja Zidane @ 2022-05-12  9:17 UTC (permalink / raw)
  To: dev; +Cc: matan

In packets with ESP header, The Inner IP will be encrypted, and
its fields cannot be used for RSS hashing. So, ESP packets
can be hashed only by the outer IP layer.
So, when using RSS on ESP packets, hashing may not be efficient,
because the fields used by the hash functions are only the Outer IPs,
causing all traffic belonging to all tunnels between a given
pair of GWs to land on one core.
Adding the SPI hash field can extend the spreading of IPSec packets.

support matching on ESP SPI.
Support RSS on ESP header by hashing SPI field.

Signed-off-by: Raja Zidane <rzidane@nvidia.com>
---
V2: added doc.
V3: fixed checkpatch.
V4: rebase
V5: rebase and doc.
 doc/guides/nics/features/mlx5.ini      |  1 +
 doc/guides/nics/mlx5.rst               |  1 +
 doc/guides/rel_notes/release_22_07.rst |  2 +
 drivers/common/mlx5/linux/meson.build  |  2 +
 drivers/common/mlx5/mlx5_prm.h         |  5 +-
 drivers/net/mlx5/mlx5_defs.h           |  2 +-
 drivers/net/mlx5/mlx5_devx.c           |  4 +-
 drivers/net/mlx5/mlx5_flow.c           | 84 +++++++++++++++++++++++-
 drivers/net/mlx5/mlx5_flow.h           | 20 ++++++
 drivers/net/mlx5/mlx5_flow_dv.c        | 88 +++++++++++++++++++++++++-
 10 files changed, 204 insertions(+), 5 deletions(-)

diff --git a/doc/guides/nics/features/mlx5.ini b/doc/guides/nics/features/mlx5.ini
index fb5993124d..5738f35324 100644
--- a/doc/guides/nics/features/mlx5.ini
+++ b/doc/guides/nics/features/mlx5.ini
@@ -56,6 +56,7 @@ Usage doc            = Y
 [rte_flow items]
 conntrack            = Y
 ecpri                = Y
+esp                  = Y
 eth                  = Y
 flex                 = Y
 geneve               = Y
diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst
index 4805d08a76..a0b9284c0f 100644
--- a/doc/guides/nics/mlx5.rst
+++ b/doc/guides/nics/mlx5.rst
@@ -81,6 +81,7 @@ Features
 - Matching on IPv4 Internet Header Length (IHL).
 - Matching on GTP extension header with raw encap/decap action.
 - Matching on Geneve TLV option header with raw encap/decap action.
+- Matching on ESP header SPI field.
 - RSS support in sample action.
 - E-Switch mirroring and jump.
 - E-Switch mirroring and modify.
diff --git a/doc/guides/rel_notes/release_22_07.rst b/doc/guides/rel_notes/release_22_07.rst
index 9a8465dc15..bc829062bc 100644
--- a/doc/guides/rel_notes/release_22_07.rst
+++ b/doc/guides/rel_notes/release_22_07.rst
@@ -69,6 +69,8 @@ New Features
 
   * Added support for promiscuous mode on Windows.
   * Added support for MTU on Windows.
+  * Added new item (ESP).
+  * Added RSS for ESP.
 
 
 Removed Items
diff --git a/drivers/common/mlx5/linux/meson.build b/drivers/common/mlx5/linux/meson.build
index ed48245c67..5335f5b027 100644
--- a/drivers/common/mlx5/linux/meson.build
+++ b/drivers/common/mlx5/linux/meson.build
@@ -72,6 +72,8 @@ has_member_args = [
 # [ "MACRO to define if found", "header for the search",
 #   "symbol to search" ]
 has_sym_args = [
+        [ 'HAVE_IBV_RX_HASH_IPSEC_SPI', 'infiniband/verbs.h',
+            'IBV_RX_HASH_IPSEC_SPI' ],
         [ 'HAVE_IBV_RELAXED_ORDERING', 'infiniband/verbs.h',
             'IBV_ACCESS_RELAXED_ORDERING ' ],
         [ 'HAVE_IBV_DEVICE_STRIDING_RQ_SUPPORT', 'infiniband/mlx5dv.h',
diff --git a/drivers/common/mlx5/mlx5_prm.h b/drivers/common/mlx5/mlx5_prm.h
index 44b18225f6..630b2c5100 100644
--- a/drivers/common/mlx5/mlx5_prm.h
+++ b/drivers/common/mlx5/mlx5_prm.h
@@ -899,7 +899,10 @@ struct mlx5_ifc_fte_match_set_misc_bits {
 	u8 reserved_at_120[0xa];
 	u8 geneve_opt_len[0x6];
 	u8 geneve_protocol_type[0x10];
-	u8 reserved_at_140[0xc0];
+	u8 reserved_at_140[0x20];
+	u8 inner_esp_spi[0x20];
+	u8 outer_esp_spi[0x20];
+	u8 reserved_at_1a0[0x60];
 };
 
 struct mlx5_ifc_ipv4_layout_bits {
diff --git a/drivers/net/mlx5/mlx5_defs.h b/drivers/net/mlx5/mlx5_defs.h
index 15728fb41f..f5c6f23d56 100644
--- a/drivers/net/mlx5/mlx5_defs.h
+++ b/drivers/net/mlx5/mlx5_defs.h
@@ -90,7 +90,7 @@
 
 /* Supported RSS */
 #define MLX5_RSS_HF_MASK (~(RTE_ETH_RSS_IP | RTE_ETH_RSS_UDP | RTE_ETH_RSS_TCP | \
-			    MLX5_RSS_SRC_DST_ONLY))
+			    MLX5_RSS_SRC_DST_ONLY | RTE_ETH_RSS_ESP))
 
 /* Timeout in seconds to get a valid link status. */
 #define MLX5_LINK_STATUS_TIMEOUT 10
diff --git a/drivers/net/mlx5/mlx5_devx.c b/drivers/net/mlx5/mlx5_devx.c
index 03c0fac32f..4b48f9433a 100644
--- a/drivers/net/mlx5/mlx5_devx.c
+++ b/drivers/net/mlx5/mlx5_devx.c
@@ -765,7 +765,9 @@ mlx5_devx_tir_attr_set(struct rte_eth_dev *dev, const uint8_t *rss_key,
 			(!!(hash_fields & MLX5_L4_SRC_IBV_RX_HASH)) <<
 			 MLX5_RX_HASH_FIELD_SELECT_SELECTED_FIELDS_L4_SPORT |
 			(!!(hash_fields & MLX5_L4_DST_IBV_RX_HASH)) <<
-			 MLX5_RX_HASH_FIELD_SELECT_SELECTED_FIELDS_L4_DPORT;
+			 MLX5_RX_HASH_FIELD_SELECT_SELECTED_FIELDS_L4_DPORT |
+			(!!(hash_fields & IBV_RX_HASH_IPSEC_SPI)) <<
+			 MLX5_RX_HASH_FIELD_SELECT_SELECTED_FIELDS_IPSEC_SPI;
 	}
 	if (is_hairpin)
 		tir_attr->transport_domain = priv->sh->td->id;
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index f5bdf661b0..de0c15fef6 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -149,6 +149,7 @@ mlx5_flow_is_rss_expandable_item(const struct rte_flow_item *item)
 	case RTE_FLOW_ITEM_TYPE_IPV6:
 	case RTE_FLOW_ITEM_TYPE_UDP:
 	case RTE_FLOW_ITEM_TYPE_TCP:
+	case RTE_FLOW_ITEM_TYPE_ESP:
 	case RTE_FLOW_ITEM_TYPE_VXLAN:
 	case RTE_FLOW_ITEM_TYPE_NVGRE:
 	case RTE_FLOW_ITEM_TYPE_GRE:
@@ -214,6 +215,9 @@ mlx5_inet_proto_to_item_type(uint8_t proto_spec, uint8_t proto_mask)
 	case IPPROTO_IPV6:
 		type = RTE_FLOW_ITEM_TYPE_IPV6;
 		break;
+	case IPPROTO_ESP:
+		type = RTE_FLOW_ITEM_TYPE_ESP;
+		break;
 	default:
 		type = RTE_FLOW_ITEM_TYPE_END;
 	}
@@ -558,9 +562,11 @@ enum mlx5_expansion {
 	MLX5_EXPANSION_OUTER_IPV4,
 	MLX5_EXPANSION_OUTER_IPV4_UDP,
 	MLX5_EXPANSION_OUTER_IPV4_TCP,
+	MLX5_EXPANSION_OUTER_IPV4_ESP,
 	MLX5_EXPANSION_OUTER_IPV6,
 	MLX5_EXPANSION_OUTER_IPV6_UDP,
 	MLX5_EXPANSION_OUTER_IPV6_TCP,
+	MLX5_EXPANSION_OUTER_IPV6_ESP,
 	MLX5_EXPANSION_VXLAN,
 	MLX5_EXPANSION_STD_VXLAN,
 	MLX5_EXPANSION_L3_VXLAN,
@@ -574,9 +580,11 @@ enum mlx5_expansion {
 	MLX5_EXPANSION_IPV4,
 	MLX5_EXPANSION_IPV4_UDP,
 	MLX5_EXPANSION_IPV4_TCP,
+	MLX5_EXPANSION_IPV4_ESP,
 	MLX5_EXPANSION_IPV6,
 	MLX5_EXPANSION_IPV6_UDP,
 	MLX5_EXPANSION_IPV6_TCP,
+	MLX5_EXPANSION_IPV6_ESP,
 	MLX5_EXPANSION_IPV6_FRAG_EXT,
 	MLX5_EXPANSION_GTP,
 	MLX5_EXPANSION_GENEVE,
@@ -611,6 +619,7 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 		.next = MLX5_FLOW_EXPAND_RSS_NEXT
 			(MLX5_EXPANSION_OUTER_IPV4_UDP,
 			 MLX5_EXPANSION_OUTER_IPV4_TCP,
+			 MLX5_EXPANSION_OUTER_IPV4_ESP,
 			 MLX5_EXPANSION_GRE,
 			 MLX5_EXPANSION_NVGRE,
 			 MLX5_EXPANSION_IPV4,
@@ -632,10 +641,15 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 		.type = RTE_FLOW_ITEM_TYPE_TCP,
 		.rss_types = RTE_ETH_RSS_NONFRAG_IPV4_TCP,
 	},
+	[MLX5_EXPANSION_OUTER_IPV4_ESP] = {
+		.type = RTE_FLOW_ITEM_TYPE_ESP,
+		.rss_types = RTE_ETH_RSS_ESP,
+	},
 	[MLX5_EXPANSION_OUTER_IPV6] = {
 		.next = MLX5_FLOW_EXPAND_RSS_NEXT
 			(MLX5_EXPANSION_OUTER_IPV6_UDP,
 			 MLX5_EXPANSION_OUTER_IPV6_TCP,
+			 MLX5_EXPANSION_OUTER_IPV6_ESP,
 			 MLX5_EXPANSION_IPV4,
 			 MLX5_EXPANSION_IPV6,
 			 MLX5_EXPANSION_GRE,
@@ -657,6 +671,10 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 		.type = RTE_FLOW_ITEM_TYPE_TCP,
 		.rss_types = RTE_ETH_RSS_NONFRAG_IPV6_TCP,
 	},
+	[MLX5_EXPANSION_OUTER_IPV6_ESP] = {
+		.type = RTE_FLOW_ITEM_TYPE_ESP,
+		.rss_types = RTE_ETH_RSS_ESP,
+	},
 	[MLX5_EXPANSION_VXLAN] = {
 		.next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH,
 						  MLX5_EXPANSION_IPV4,
@@ -716,7 +734,8 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 	},
 	[MLX5_EXPANSION_IPV4] = {
 		.next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4_UDP,
-						  MLX5_EXPANSION_IPV4_TCP),
+						  MLX5_EXPANSION_IPV4_TCP,
+						  MLX5_EXPANSION_IPV4_ESP),
 		.type = RTE_FLOW_ITEM_TYPE_IPV4,
 		.rss_types = RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4 |
 			RTE_ETH_RSS_NONFRAG_IPV4_OTHER,
@@ -729,9 +748,14 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 		.type = RTE_FLOW_ITEM_TYPE_TCP,
 		.rss_types = RTE_ETH_RSS_NONFRAG_IPV4_TCP,
 	},
+	[MLX5_EXPANSION_IPV4_ESP] = {
+		.type = RTE_FLOW_ITEM_TYPE_ESP,
+		.rss_types = RTE_ETH_RSS_ESP,
+	},
 	[MLX5_EXPANSION_IPV6] = {
 		.next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV6_UDP,
 						  MLX5_EXPANSION_IPV6_TCP,
+						  MLX5_EXPANSION_IPV6_ESP,
 						  MLX5_EXPANSION_IPV6_FRAG_EXT),
 		.type = RTE_FLOW_ITEM_TYPE_IPV6,
 		.rss_types = RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6 |
@@ -745,6 +769,10 @@ static const struct mlx5_flow_expand_node mlx5_support_expansion[] = {
 		.type = RTE_FLOW_ITEM_TYPE_TCP,
 		.rss_types = RTE_ETH_RSS_NONFRAG_IPV6_TCP,
 	},
+	[MLX5_EXPANSION_IPV6_ESP] = {
+		.type = RTE_FLOW_ITEM_TYPE_ESP,
+		.rss_types = RTE_ETH_RSS_ESP,
+	},
 	[MLX5_EXPANSION_IPV6_FRAG_EXT] = {
 		.type = RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT,
 	},
@@ -2618,6 +2646,60 @@ mlx5_flow_validate_item_ipv6(const struct rte_flow_item *item,
 	return 0;
 }
 
+/**
+ * Validate ESP item.
+ *
+ * @param[in] item
+ *   Item specification.
+ * @param[in] item_flags
+ *   Bit-fields that holds the items detected until now.
+ * @param[in] target_protocol
+ *   The next protocol in the previous item.
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_flow_validate_item_esp(const struct rte_flow_item *item,
+			    uint64_t item_flags,
+			    uint8_t target_protocol,
+			    struct rte_flow_error *error)
+{
+	const struct rte_flow_item_esp *mask = item->mask;
+	const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
+	const uint64_t l3m = tunnel ? MLX5_FLOW_LAYER_INNER_L3 :
+				      MLX5_FLOW_LAYER_OUTER_L3;
+	const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 :
+				      MLX5_FLOW_LAYER_OUTER_L4;
+	int ret;
+
+	if (!(item_flags & l3m))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  "L3 is mandatory to filter on L4");
+	if (item_flags & l4m)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  "multiple L4 layers not supported");
+	if (target_protocol != 0xff && target_protocol != IPPROTO_ESP)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  "protocol filtering not compatible"
+					  " with ESP layer");
+	if (!mask)
+		mask = &rte_flow_item_esp_mask;
+	ret = mlx5_flow_item_acceptable
+		(item, (const uint8_t *)mask,
+		 (const uint8_t *)&rte_flow_item_esp_mask,
+		 sizeof(struct rte_flow_item_esp), MLX5_ITEM_RANGE_NOT_ACCEPTED,
+		 error);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
 /**
  * Validate UDP item.
  *
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index f56115dd11..fcb05abced 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -186,6 +186,9 @@ enum mlx5_feature_name {
 #define MLX5_FLOW_ITEM_INNER_FLEX (UINT64_C(1) << 38)
 #define MLX5_FLOW_ITEM_FLEX_TUNNEL (UINT64_C(1) << 39)
 
+/* ESP item */
+#define MLX5_FLOW_ITEM_ESP (UINT64_C(1) << 40)
+
 /* Outer Masks. */
 #define MLX5_FLOW_LAYER_OUTER_L3 \
 	(MLX5_FLOW_LAYER_OUTER_L3_IPV4 | MLX5_FLOW_LAYER_OUTER_L3_IPV6)
@@ -1185,6 +1188,16 @@ struct rte_flow_template_table {
 	(MLX5_RSS_HASH_IPV6 | IBV_RX_HASH_SRC_PORT_TCP)
 #define MLX5_RSS_HASH_IPV6_TCP_DST_ONLY \
 	(MLX5_RSS_HASH_IPV6 | IBV_RX_HASH_DST_PORT_TCP)
+
+#ifndef HAVE_IBV_RX_HASH_IPSEC_SPI
+#define IBV_RX_HASH_IPSEC_SPI (1U << 8)
+#endif
+
+#define MLX5_RSS_HASH_ESP_SPI IBV_RX_HASH_IPSEC_SPI
+#define MLX5_RSS_HASH_IPV4_ESP (MLX5_RSS_HASH_IPV4 | \
+				MLX5_RSS_HASH_ESP_SPI)
+#define MLX5_RSS_HASH_IPV6_ESP (MLX5_RSS_HASH_IPV6 | \
+				MLX5_RSS_HASH_ESP_SPI)
 #define MLX5_RSS_HASH_NONE 0ULL
 
 
@@ -1200,9 +1213,12 @@ static const uint64_t mlx5_rss_hash_fields[] = {
 	MLX5_RSS_HASH_IPV4,
 	MLX5_RSS_HASH_IPV4_TCP,
 	MLX5_RSS_HASH_IPV4_UDP,
+	MLX5_RSS_HASH_IPV4_ESP,
 	MLX5_RSS_HASH_IPV6,
 	MLX5_RSS_HASH_IPV6_TCP,
 	MLX5_RSS_HASH_IPV6_UDP,
+	MLX5_RSS_HASH_IPV6_ESP,
+	MLX5_RSS_HASH_ESP_SPI,
 	MLX5_RSS_HASH_NONE,
 };
 
@@ -1812,6 +1828,10 @@ int mlx5_flow_validate_item_tcp(const struct rte_flow_item *item,
 				uint8_t target_protocol,
 				const struct rte_flow_item_tcp *flow_mask,
 				struct rte_flow_error *error);
+int mlx5_flow_validate_item_esp(const struct rte_flow_item *item,
+				uint64_t item_flags,
+				uint8_t target_protocol,
+				struct rte_flow_error *error);
 int mlx5_flow_validate_item_udp(const struct rte_flow_item *item,
 				uint64_t item_flags,
 				uint8_t target_protocol,
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index f9c56204c4..9a0102abb5 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -6956,6 +6956,14 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 		switch (type) {
 		case RTE_FLOW_ITEM_TYPE_VOID:
 			break;
+		case RTE_FLOW_ITEM_TYPE_ESP:
+			ret = mlx5_flow_validate_item_esp(items, item_flags,
+							  next_protocol,
+							  error);
+			if (ret < 0)
+				return ret;
+			last_item = MLX5_FLOW_ITEM_ESP;
+			break;
 		case RTE_FLOW_ITEM_TYPE_PORT_ID:
 			ret = flow_dv_validate_item_port_id
 					(dev, items, attr, item_flags, error);
@@ -8730,6 +8738,58 @@ flow_dv_translate_item_tcp(void *matcher, void *key,
 		 (tcp_v->hdr.tcp_flags & tcp_m->hdr.tcp_flags));
 }
 
+/**
+ * Add ESP item to matcher and to the value.
+ *
+ * @param[in, out] matcher
+ *   Flow matcher.
+ * @param[in, out] key
+ *   Flow matcher value.
+ * @param[in] item
+ *   Flow pattern to translate.
+ * @param[in] inner
+ *   Item is inner pattern.
+ */
+static void
+flow_dv_translate_item_esp(void *matcher, void *key,
+			   const struct rte_flow_item *item,
+			   int inner)
+{
+	const struct rte_flow_item_esp *esp_m = item->mask;
+	const struct rte_flow_item_esp *esp_v = item->spec;
+	void *headers_m;
+	void *headers_v;
+	char *spi_m;
+	char *spi_v;
+
+	if (inner) {
+		headers_m = MLX5_ADDR_OF(fte_match_param, matcher,
+					 inner_headers);
+		headers_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers);
+	} else {
+		headers_m = MLX5_ADDR_OF(fte_match_param, matcher,
+					 outer_headers);
+		headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
+	}
+	MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_protocol, 0xff);
+	MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, IPPROTO_ESP);
+	if (!esp_v)
+		return;
+	if (!esp_m)
+		esp_m = &rte_flow_item_esp_mask;
+	headers_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters);
+	headers_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
+	if (inner) {
+		spi_m = MLX5_ADDR_OF(fte_match_set_misc, headers_m, inner_esp_spi);
+		spi_v = MLX5_ADDR_OF(fte_match_set_misc, headers_v, inner_esp_spi);
+	} else {
+		spi_m = MLX5_ADDR_OF(fte_match_set_misc, headers_m, outer_esp_spi);
+		spi_v = MLX5_ADDR_OF(fte_match_set_misc, headers_v, outer_esp_spi);
+	}
+	*(uint32_t *)spi_m = esp_m->hdr.spi;
+	*(uint32_t *)spi_v = esp_m->hdr.spi & esp_v->hdr.spi;
+}
+
 /**
  * Add UDP item to matcher and to the value.
  *
@@ -11189,12 +11249,18 @@ flow_dv_hashfields_set(uint64_t item_flags,
 				fields |= MLX5_IPV6_IBV_RX_HASH;
 		}
 	}
-	if (fields == 0)
+	if (items & MLX5_FLOW_ITEM_ESP) {
+		if (rss_types & RTE_ETH_RSS_ESP)
+			fields |= IBV_RX_HASH_IPSEC_SPI;
+	}
+	if ((fields & ~IBV_RX_HASH_IPSEC_SPI) == 0) {
+		*hash_fields = fields;
 		/*
 		 * There is no match between the RSS types and the
 		 * L3 protocol (IPv4/IPv6) defined in the flow rule.
 		 */
 		return;
+	}
 	if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L4_UDP)) ||
 	    (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L4_UDP)) ||
 	    !items) {
@@ -13539,6 +13605,11 @@ flow_dv_translate(struct rte_eth_dev *dev,
 						  RTE_FLOW_ERROR_TYPE_ITEM,
 						  NULL, "item not supported");
 		switch (item_type) {
+		case RTE_FLOW_ITEM_TYPE_ESP:
+			flow_dv_translate_item_esp(match_mask, match_value,
+						   items, tunnel);
+			last_item = MLX5_FLOW_ITEM_ESP;
+			break;
 		case RTE_FLOW_ITEM_TYPE_PORT_ID:
 			flow_dv_translate_item_port_id
 				(dev, match_mask, match_value, items, attr);
@@ -14008,6 +14079,15 @@ __flow_dv_action_rss_hrxq_set(struct mlx5_shared_action_rss *action,
 	case MLX5_RSS_HASH_NONE:
 		hrxqs[6] = hrxq_idx;
 		return 0;
+	case MLX5_RSS_HASH_IPV4_ESP:
+		hrxqs[7] = hrxq_idx;
+		return 0;
+	case MLX5_RSS_HASH_IPV6_ESP:
+		hrxqs[8] = hrxq_idx;
+		return 0;
+	case MLX5_RSS_HASH_ESP_SPI:
+		hrxqs[9] = hrxq_idx;
+		return 0;
 	default:
 		return -1;
 	}
@@ -14077,6 +14157,12 @@ flow_dv_action_rss_hrxq_lookup(struct rte_eth_dev *dev, uint32_t idx,
 		return hrxqs[5];
 	case MLX5_RSS_HASH_NONE:
 		return hrxqs[6];
+	case MLX5_RSS_HASH_IPV4_ESP:
+		return hrxqs[7];
+	case MLX5_RSS_HASH_IPV6_ESP:
+		return hrxqs[8];
+	case MLX5_RSS_HASH_ESP_SPI:
+		return hrxqs[9];
 	default:
 		return 0;
 	}
-- 
2.21.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [PATCH V5] net/mlx5: support ESP SPI match and RSS hash
  2022-05-12  9:17       ` [PATCH V5] " Raja Zidane
@ 2022-05-12 15:05         ` Matan Azrad
  2022-05-15  7:40         ` Raslan Darawsheh
  1 sibling, 0 replies; 9+ messages in thread
From: Matan Azrad @ 2022-05-12 15:05 UTC (permalink / raw)
  To: Raja Zidane, dev



From: Raja Zidane
> In packets with ESP header, The Inner IP will be encrypted, and its fields
> cannot be used for RSS hashing. So, ESP packets can be hashed only by the
> outer IP layer.
> So, when using RSS on ESP packets, hashing may not be efficient, because
> the fields used by the hash functions are only the Outer IPs, causing all traffic
> belonging to all tunnels between a given pair of GWs to land on one core.
> Adding the SPI hash field can extend the spreading of IPSec packets.
> 
> support matching on ESP SPI.
> Support RSS on ESP header by hashing SPI field.
> 
> Signed-off-by: Raja Zidane <rzidane@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [PATCH V5] net/mlx5: support ESP SPI match and RSS hash
  2022-05-12  9:17       ` [PATCH V5] " Raja Zidane
  2022-05-12 15:05         ` Matan Azrad
@ 2022-05-15  7:40         ` Raslan Darawsheh
  1 sibling, 0 replies; 9+ messages in thread
From: Raslan Darawsheh @ 2022-05-15  7:40 UTC (permalink / raw)
  To: Raja Zidane, dev; +Cc: Matan Azrad

Hi,
> -----Original Message-----
> From: Raja Zidane <rzidane@nvidia.com>
> Sent: Thursday, May 12, 2022 12:17 PM
> To: dev@dpdk.org
> Cc: Matan Azrad <matan@nvidia.com>
> Subject: [PATCH V5] net/mlx5: support ESP SPI match and RSS hash
> 
> In packets with ESP header, The Inner IP will be encrypted, and its fields
> cannot be used for RSS hashing. So, ESP packets can be hashed only by the
> outer IP layer.
> So, when using RSS on ESP packets, hashing may not be efficient, because
> the fields used by the hash functions are only the Outer IPs, causing all traffic
> belonging to all tunnels between a given pair of GWs to land on one core.
> Adding the SPI hash field can extend the spreading of IPSec packets.
> 
> support matching on ESP SPI.
> Support RSS on ESP header by hashing SPI field.
> 
> Signed-off-by: Raja Zidane <rzidane@nvidia.com>
> ---
> V2: added doc.
> V3: fixed checkpatch.
> V4: rebase
> V5: rebase and doc.
>  doc/guides/nics/features/mlx5.ini      |  1 +
>  doc/guides/nics/mlx5.rst               |  1 +
>  doc/guides/rel_notes/release_22_07.rst |  2 +
> drivers/common/mlx5/linux/meson.build  |  2 +
>  drivers/common/mlx5/mlx5_prm.h         |  5 +-
>  drivers/net/mlx5/mlx5_defs.h           |  2 +-
>  drivers/net/mlx5/mlx5_devx.c           |  4 +-
>  drivers/net/mlx5/mlx5_flow.c           | 84 +++++++++++++++++++++++-
>  drivers/net/mlx5/mlx5_flow.h           | 20 ++++++
>  drivers/net/mlx5/mlx5_flow_dv.c        | 88 +++++++++++++++++++++++++-
>  10 files changed, 204 insertions(+), 5 deletions(-)
> 

Patch applied to next-net-mlx,

Kindest regards,
Raslan Darawsheh


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2022-05-15  7:40 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-04 13:04 [PATCH] net/mlx5: support ESP SPI match and RSS hash Raja Zidane
2022-04-17  7:12 ` Raslan Darawsheh
2022-04-18 10:57 ` [PATCH V2] " Raja Zidane
2022-04-18 11:01   ` [PATCH V3] " Raja Zidane
2022-04-28 15:43     ` [PATCH V4] " Raja Zidane
2022-05-11  8:07       ` Matan Azrad
2022-05-12  9:17       ` [PATCH V5] " Raja Zidane
2022-05-12 15:05         ` Matan Azrad
2022-05-15  7:40         ` Raslan Darawsheh

DPDK patches and discussions

This inbox may be cloned and mirrored by anyone:

	git clone --mirror http://inbox.dpdk.org/dev/0 dev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 dev dev/ http://inbox.dpdk.org/dev \
		dev@dpdk.org
	public-inbox-index dev

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://inbox.dpdk.org/inbox.dpdk.dev


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git