[dpdk-dev] [PATCH 51/62] net/sfc: support flow item IPV6 in transfer rules

Andrew Rybchenko arybchenko at solarflare.com
Tue Oct 20 10:48:18 CEST 2020


From: Ivan Malov <ivan.malov at oktetlabs.ru>

Add support for this flow item to MAE-specific RTE flow implementation.

Signed-off-by: Ivan Malov <ivan.malov at oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko at solarflare.com>
Reviewed-by: Andy Moreton <amoreton at xilinx.com>
---
 doc/guides/nics/sfc_efx.rst |   3 +
 drivers/net/sfc/sfc_mae.c   | 106 ++++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_mae.h   |   1 +
 3 files changed, 110 insertions(+)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index e687e1cac3..8209990d23 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -205,6 +205,9 @@ Supported pattern items (***transfer*** rules):
 - IPV4 (source/destination addresses, IP transport protocol,
   type of service, time to live)
 
+- IPV6 (source/destination addresses, IP transport protocol,
+  traffic class, hop limit)
+
 Supported actions (***transfer*** rules):
 
 - OF_POP_VLAN
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index d7c1cd784f..2b0121c0ac 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -946,6 +946,105 @@ sfc_mae_rule_parse_item_ipv4(const struct rte_flow_item *item,
 				  ctx_mae->match_spec_action, error);
 }
 
+static const struct sfc_mae_field_locator flocs_ipv6[] = {
+	{
+		EFX_MAE_FIELD_SRC_IP6_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.src_addr),
+		offsetof(struct rte_flow_item_ipv6, hdr.src_addr),
+	},
+	{
+		EFX_MAE_FIELD_DST_IP6_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.dst_addr),
+		offsetof(struct rte_flow_item_ipv6, hdr.dst_addr),
+	},
+	{
+		/*
+		 * This locator is used only for building supported fields mask.
+		 * The field is handled by sfc_mae_rule_process_pattern_data().
+		 */
+		SFC_MAE_FIELD_HANDLING_DEFERRED,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.proto),
+		offsetof(struct rte_flow_item_ipv6, hdr.proto),
+	},
+	{
+		EFX_MAE_FIELD_IP_TTL,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.hop_limits),
+		offsetof(struct rte_flow_item_ipv6, hdr.hop_limits),
+	},
+};
+
+static int
+sfc_mae_rule_parse_item_ipv6(const struct rte_flow_item *item,
+			     struct sfc_flow_parse_ctx *ctx,
+			     struct rte_flow_error *error)
+{
+	rte_be16_t ethertype_ipv6_be = RTE_BE16(RTE_ETHER_TYPE_IPV6);
+	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
+	struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data;
+	struct rte_flow_item_ipv6 supp_mask;
+	const uint8_t *spec = NULL;
+	const uint8_t *mask = NULL;
+	rte_be32_t vtc_flow_be;
+	uint32_t vtc_flow;
+	uint8_t tc_value;
+	uint8_t tc_mask;
+	int rc;
+
+	sfc_mae_item_build_supp_mask(flocs_ipv6, RTE_DIM(flocs_ipv6),
+				     &supp_mask, sizeof(supp_mask));
+
+	vtc_flow_be = RTE_BE32(RTE_IPV6_HDR_TC_MASK);
+	memcpy(&supp_mask, &vtc_flow_be, sizeof(vtc_flow_be));
+
+	rc = sfc_flow_parse_init(item,
+				 (const void **)&spec, (const void **)&mask,
+				 (const void *)&supp_mask,
+				 &rte_flow_item_ipv6_mask,
+				 sizeof(struct rte_flow_item_ipv6), error);
+	if (rc != 0)
+		return rc;
+
+	pdata->innermost_ethertype_restriction.value = ethertype_ipv6_be;
+	pdata->innermost_ethertype_restriction.mask = RTE_BE16(0xffff);
+
+	if (spec != NULL) {
+		const struct rte_flow_item_ipv6 *item_spec;
+		const struct rte_flow_item_ipv6 *item_mask;
+
+		item_spec = (const struct rte_flow_item_ipv6 *)spec;
+		item_mask = (const struct rte_flow_item_ipv6 *)mask;
+
+		pdata->l3_next_proto_value = item_spec->hdr.proto;
+		pdata->l3_next_proto_mask = item_mask->hdr.proto;
+	} else {
+		return 0;
+	}
+
+	rc = sfc_mae_parse_item(flocs_ipv6, RTE_DIM(flocs_ipv6), spec, mask,
+				ctx_mae->match_spec_action, error);
+	if (rc != 0)
+		return rc;
+
+	memcpy(&vtc_flow_be, spec, sizeof(vtc_flow_be));
+	vtc_flow = rte_be_to_cpu_32(vtc_flow_be);
+	tc_value = (vtc_flow & RTE_IPV6_HDR_TC_MASK) >> RTE_IPV6_HDR_TC_SHIFT;
+
+	memcpy(&vtc_flow_be, mask, sizeof(vtc_flow_be));
+	vtc_flow = rte_be_to_cpu_32(vtc_flow_be);
+	tc_mask = (vtc_flow & RTE_IPV6_HDR_TC_MASK) >> RTE_IPV6_HDR_TC_SHIFT;
+
+	rc = efx_mae_match_spec_field_set(ctx_mae->match_spec_action,
+					  EFX_MAE_FIELD_IP_TOS,
+					  sizeof(tc_value), &tc_value,
+					  sizeof(tc_mask), &tc_mask);
+	if (rc != 0) {
+		return rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ITEM,
+				NULL, "Failed to process item fields");
+	}
+
+	return 0;
+}
+
 static const struct sfc_flow_item sfc_flow_items[] = {
 	{
 		.type = RTE_FLOW_ITEM_TYPE_PORT_ID,
@@ -1012,6 +1111,13 @@ static const struct sfc_flow_item sfc_flow_items[] = {
 		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
 		.parse = sfc_mae_rule_parse_item_ipv4,
 	},
+	{
+		.type = RTE_FLOW_ITEM_TYPE_IPV6,
+		.prev_layer = SFC_FLOW_ITEM_L2,
+		.layer = SFC_FLOW_ITEM_L3,
+		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
+		.parse = sfc_mae_rule_parse_item_ipv6,
+	},
 };
 
 int
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 56be8bf917..993a377861 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -115,6 +115,7 @@ struct sfc_mae_pattern_data {
 	 * L3 requirement for the innermost L2 item's "type" ("inner_type").
 	 * This contains one of:
 	 * - 0x0800/0xffff: IPV4
+	 * - 0x86dd/0xffff: IPV6
 	 * - 0x0000/0x0000: no L3 item
 	 */
 	struct sfc_mae_ethertype	innermost_ethertype_restriction;
-- 
2.17.1



More information about the dev mailing list