[2/2] net/iavf: support Protocol Agnostic Flow Offloading VF RSS

Message ID 20220523023138.3777313-5-junfeng.guo@intel.com (mailing list archive)
State Rejected, archived
Headers
Series None |

Commit Message

Junfeng Guo May 23, 2022, 2:31 a.m. UTC
  From: Ting Xu <ting.xu@intel.com>

Enable Protocol Agnostic Flow Offloading for RSS hash in VF. It supports
raw pattern flow rule creation in VF based on Parser Library feature. VF
parses the spec and mask input of raw pattern, and passes it to kernel
driver to create the flow rule. Current rte_flow raw API is utilized.

command example:
RSS hash for ipv4-src-dst:
flow create 0 ingress pattern raw pattern spec
00000000000000000000000008004500001400004000401000000000000000000000
pattern mask
0000000000000000000000000000000000000000000000000000ffffffffffffffff /
end actions rss queues end / end

Signed-off-by: Ting Xu <ting.xu@intel.com>
---
 drivers/net/iavf/iavf_hash.c | 96 ++++++++++++++++++++++++++++++++++++
 1 file changed, 96 insertions(+)
  

Comments

Junfeng Guo May 23, 2022, 2:45 a.m. UTC | #1
Sorry to send this commit by mistake. Please drop this one. Thanks!

> -----Original Message-----
> From: Guo, Junfeng <junfeng.guo@intel.com>
> Sent: Monday, May 23, 2022 10:32
> To: Zhang, Qi Z <qi.z.zhang@intel.com>; Wu, Jingjing
> <jingjing.wu@intel.com>; Xing, Beilei <beilei.xing@intel.com>
> Cc: dev@dpdk.org; Xu, Ting <ting.xu@intel.com>; Guo, Junfeng
> <junfeng.guo@intel.com>
> Subject: [PATCH 2/2] net/iavf: support Protocol Agnostic Flow Offloading
> VF RSS
> 
> From: Ting Xu <ting.xu@intel.com>
> 
> Enable Protocol Agnostic Flow Offloading for RSS hash in VF. It supports
> raw pattern flow rule creation in VF based on Parser Library feature. VF
> parses the spec and mask input of raw pattern, and passes it to kernel
> driver to create the flow rule. Current rte_flow raw API is utilized.
> 
> command example:
> RSS hash for ipv4-src-dst:
> flow create 0 ingress pattern raw pattern spec
> 000000000000000000000000080045000014000040004010000000000000
> 00000000
> pattern mask
> 0000000000000000000000000000000000000000000000000000ffffffffffff
> ffff /
> end actions rss queues end / end
> 
> Signed-off-by: Ting Xu <ting.xu@intel.com>
> ---
>  drivers/net/iavf/iavf_hash.c | 96
> ++++++++++++++++++++++++++++++++++++
>  1 file changed, 96 insertions(+)
> 
> diff --git a/drivers/net/iavf/iavf_hash.c b/drivers/net/iavf/iavf_hash.c
> index 278e75117d..42df7c4e48 100644
> --- a/drivers/net/iavf/iavf_hash.c
> +++ b/drivers/net/iavf/iavf_hash.c
> @@ -37,6 +37,8 @@
>  /* L2TPv2 */
>  #define IAVF_PHINT_L2TPV2			BIT_ULL(9)
>  #define IAVF_PHINT_L2TPV2_LEN			BIT_ULL(10)
> +/* Raw */
> +#define IAVF_PHINT_RAW				BIT_ULL(11)
> 
>  #define IAVF_PHINT_GTPU_MSK	(IAVF_PHINT_GTPU	| \
>  				 IAVF_PHINT_GTPU_EH	| \
> @@ -58,6 +60,7 @@ struct iavf_hash_match_type {
>  struct iavf_rss_meta {
>  	struct virtchnl_proto_hdrs proto_hdrs;
>  	enum virtchnl_rss_algorithm rss_algorithm;
> +	bool raw_ena;
>  };
> 
>  struct iavf_hash_flow_cfg {
> @@ -532,6 +535,7 @@ struct virtchnl_proto_hdrs ipv6_l2tpv2_ppp_tmplt
> = {
>   */
>  static struct iavf_pattern_match_item iavf_hash_pattern_list[] = {
>  	/* IPv4 */
> +	{iavf_pattern_raw,
> 	IAVF_INSET_NONE,		NULL},
>  	{iavf_pattern_eth_ipv4,
> 	IAVF_RSS_TYPE_OUTER_IPV4,	&outer_ipv4_tmplt},
>  	{iavf_pattern_eth_ipv4_udp,
> 	IAVF_RSS_TYPE_OUTER_IPV4_UDP,
> 	&outer_ipv4_udp_tmplt},
>  	{iavf_pattern_eth_ipv4_tcp,
> 	IAVF_RSS_TYPE_OUTER_IPV4_TCP,	&outer_ipv4_tcp_tmplt},
> @@ -804,6 +808,9 @@ iavf_hash_parse_pattern(const struct
> rte_flow_item pattern[], uint64_t *phint,
>  		}
> 
>  		switch (item->type) {
> +		case RTE_FLOW_ITEM_TYPE_RAW:
> +			*phint |= IAVF_PHINT_RAW;
> +			break;
>  		case RTE_FLOW_ITEM_TYPE_IPV4:
>  			if (!(*phint & IAVF_PHINT_GTPU_MSK) &&
>  			    !(*phint & IAVF_PHINT_GRE) &&
> @@ -873,6 +880,80 @@ iavf_hash_parse_pattern(const struct
> rte_flow_item pattern[], uint64_t *phint,
>  	return 0;
>  }
> 
> +static int
> +iavf_hash_parse_raw_pattern(const struct rte_flow_item *item,
> +			struct iavf_rss_meta *meta)
> +{
> +	const struct rte_flow_item_raw *raw_spec, *raw_mask;
> +	uint8_t *pkt_buf, *msk_buf;
> +	uint8_t spec_len, pkt_len;
> +	uint8_t tmp_val = 0;
> +	uint8_t tmp_c = 0;
> +	int i, j;
> +
> +	raw_spec = item->spec;
> +	raw_mask = item->mask;
> +
> +	spec_len = strlen((char *)(uintptr_t)raw_spec->pattern);
> +	if (strlen((char *)(uintptr_t)raw_mask->pattern) !=
> +		spec_len)
> +		return -rte_errno;
> +
> +	pkt_len = spec_len / 2;
> +
> +	pkt_buf = rte_zmalloc(NULL, pkt_len, 0);
> +	if (!pkt_buf)
> +		return -ENOMEM;
> +
> +	msk_buf = rte_zmalloc(NULL, pkt_len, 0);
> +	if (!msk_buf)
> +		return -ENOMEM;
> +
> +	/* convert string to int array */
> +	for (i = 0, j = 0; i < spec_len; i += 2, j++) {
> +		tmp_c = raw_spec->pattern[i];
> +		if (tmp_c >= 'a' && tmp_c <= 'f')
> +			tmp_val = tmp_c - 'a' + 10;
> +		if (tmp_c >= 'A' && tmp_c <= 'F')
> +			tmp_val = tmp_c - 'A' + 10;
> +		if (tmp_c >= '0' && tmp_c <= '9')
> +			tmp_val = tmp_c - '0';
> +
> +		tmp_c = raw_spec->pattern[i + 1];
> +		if (tmp_c >= 'a' && tmp_c <= 'f')
> +			pkt_buf[j] = tmp_val * 16 + tmp_c - 'a' + 10;
> +		if (tmp_c >= 'A' && tmp_c <= 'F')
> +			pkt_buf[j] = tmp_val * 16 + tmp_c - 'A' + 10;
> +		if (tmp_c >= '0' && tmp_c <= '9')
> +			pkt_buf[j] = tmp_val * 16 + tmp_c - '0';
> +
> +		tmp_c = raw_mask->pattern[i];
> +		if (tmp_c >= 'a' && tmp_c <= 'f')
> +			tmp_val = tmp_c - 0x57;
> +		if (tmp_c >= 'A' && tmp_c <= 'F')
> +			tmp_val = tmp_c - 0x37;
> +		if (tmp_c >= '0' && tmp_c <= '9')
> +			tmp_val = tmp_c - '0';
> +
> +		tmp_c = raw_mask->pattern[i + 1];
> +		if (tmp_c >= 'a' && tmp_c <= 'f')
> +			msk_buf[j] = tmp_val * 16 + tmp_c - 'a' + 10;
> +		if (tmp_c >= 'A' && tmp_c <= 'F')
> +			msk_buf[j] = tmp_val * 16 + tmp_c - 'A' + 10;
> +		if (tmp_c >= '0' && tmp_c <= '9')
> +			msk_buf[j] = tmp_val * 16 + tmp_c - '0';
> +	}
> +
> +	rte_memcpy(meta->proto_hdrs.raw.spec, pkt_buf, pkt_len);
> +	rte_memcpy(meta->proto_hdrs.raw.mask, msk_buf, pkt_len);
> +	meta->proto_hdrs.raw.pkt_len = pkt_len;
> +
> +	rte_free(pkt_buf);
> +	rte_free(msk_buf);
> +
> +	return 0;
> +}
> +
>  #define REFINE_PROTO_FLD(op, fld) \
>  	VIRTCHNL_##op##_PROTO_HDR_FIELD(hdr,
> VIRTCHNL_PROTO_HDR_##fld)
>  #define REPALCE_PROTO_FLD(fld_1, fld_2) \
> @@ -1387,6 +1468,10 @@ iavf_hash_parse_action(struct
> iavf_pattern_match_item *match_item,
> 
> 	RTE_FLOW_ERROR_TYPE_ACTION, action,
>  					"a non-NULL RSS queue is not
> supported");
> 
> +			/* If pattern type is raw, no need to refine rss
> type */
> +			if (pattern_hint == IAVF_PHINT_RAW)
> +				break;
> +
>  			/**
>  			 * Check simultaneous use of SRC_ONLY and
> DST_ONLY
>  			 * of the same level.
> @@ -1453,6 +1538,17 @@
> iavf_hash_parse_pattern_action(__rte_unused struct iavf_adapter *ad,
>  	if (ret)
>  		goto error;
> 
> +	if (phint == IAVF_PHINT_RAW) {
> +		rss_meta_ptr->raw_ena = true;
> +		ret = iavf_hash_parse_raw_pattern(pattern,
> rss_meta_ptr);
> +		if (ret) {
> +			rte_flow_error_set(error, EINVAL,
> +
> RTE_FLOW_ERROR_TYPE_ITEM, NULL,
> +					   "Parse raw pattern failed");
> +			goto error;
> +		}
> +	}
> +
>  	ret = iavf_hash_parse_action(pattern_match_item, actions, phint,
>  				     rss_meta_ptr, error);
> 
> --
> 2.25.1
  

Patch

diff --git a/drivers/net/iavf/iavf_hash.c b/drivers/net/iavf/iavf_hash.c
index 278e75117d..42df7c4e48 100644
--- a/drivers/net/iavf/iavf_hash.c
+++ b/drivers/net/iavf/iavf_hash.c
@@ -37,6 +37,8 @@ 
 /* L2TPv2 */
 #define IAVF_PHINT_L2TPV2			BIT_ULL(9)
 #define IAVF_PHINT_L2TPV2_LEN			BIT_ULL(10)
+/* Raw */
+#define IAVF_PHINT_RAW				BIT_ULL(11)
 
 #define IAVF_PHINT_GTPU_MSK	(IAVF_PHINT_GTPU	| \
 				 IAVF_PHINT_GTPU_EH	| \
@@ -58,6 +60,7 @@  struct iavf_hash_match_type {
 struct iavf_rss_meta {
 	struct virtchnl_proto_hdrs proto_hdrs;
 	enum virtchnl_rss_algorithm rss_algorithm;
+	bool raw_ena;
 };
 
 struct iavf_hash_flow_cfg {
@@ -532,6 +535,7 @@  struct virtchnl_proto_hdrs ipv6_l2tpv2_ppp_tmplt = {
  */
 static struct iavf_pattern_match_item iavf_hash_pattern_list[] = {
 	/* IPv4 */
+	{iavf_pattern_raw,				IAVF_INSET_NONE,		NULL},
 	{iavf_pattern_eth_ipv4,				IAVF_RSS_TYPE_OUTER_IPV4,	&outer_ipv4_tmplt},
 	{iavf_pattern_eth_ipv4_udp,			IAVF_RSS_TYPE_OUTER_IPV4_UDP,	&outer_ipv4_udp_tmplt},
 	{iavf_pattern_eth_ipv4_tcp,			IAVF_RSS_TYPE_OUTER_IPV4_TCP,	&outer_ipv4_tcp_tmplt},
@@ -804,6 +808,9 @@  iavf_hash_parse_pattern(const struct rte_flow_item pattern[], uint64_t *phint,
 		}
 
 		switch (item->type) {
+		case RTE_FLOW_ITEM_TYPE_RAW:
+			*phint |= IAVF_PHINT_RAW;
+			break;
 		case RTE_FLOW_ITEM_TYPE_IPV4:
 			if (!(*phint & IAVF_PHINT_GTPU_MSK) &&
 			    !(*phint & IAVF_PHINT_GRE) &&
@@ -873,6 +880,80 @@  iavf_hash_parse_pattern(const struct rte_flow_item pattern[], uint64_t *phint,
 	return 0;
 }
 
+static int
+iavf_hash_parse_raw_pattern(const struct rte_flow_item *item,
+			struct iavf_rss_meta *meta)
+{
+	const struct rte_flow_item_raw *raw_spec, *raw_mask;
+	uint8_t *pkt_buf, *msk_buf;
+	uint8_t spec_len, pkt_len;
+	uint8_t tmp_val = 0;
+	uint8_t tmp_c = 0;
+	int i, j;
+
+	raw_spec = item->spec;
+	raw_mask = item->mask;
+
+	spec_len = strlen((char *)(uintptr_t)raw_spec->pattern);
+	if (strlen((char *)(uintptr_t)raw_mask->pattern) !=
+		spec_len)
+		return -rte_errno;
+
+	pkt_len = spec_len / 2;
+
+	pkt_buf = rte_zmalloc(NULL, pkt_len, 0);
+	if (!pkt_buf)
+		return -ENOMEM;
+
+	msk_buf = rte_zmalloc(NULL, pkt_len, 0);
+	if (!msk_buf)
+		return -ENOMEM;
+
+	/* convert string to int array */
+	for (i = 0, j = 0; i < spec_len; i += 2, j++) {
+		tmp_c = raw_spec->pattern[i];
+		if (tmp_c >= 'a' && tmp_c <= 'f')
+			tmp_val = tmp_c - 'a' + 10;
+		if (tmp_c >= 'A' && tmp_c <= 'F')
+			tmp_val = tmp_c - 'A' + 10;
+		if (tmp_c >= '0' && tmp_c <= '9')
+			tmp_val = tmp_c - '0';
+
+		tmp_c = raw_spec->pattern[i + 1];
+		if (tmp_c >= 'a' && tmp_c <= 'f')
+			pkt_buf[j] = tmp_val * 16 + tmp_c - 'a' + 10;
+		if (tmp_c >= 'A' && tmp_c <= 'F')
+			pkt_buf[j] = tmp_val * 16 + tmp_c - 'A' + 10;
+		if (tmp_c >= '0' && tmp_c <= '9')
+			pkt_buf[j] = tmp_val * 16 + tmp_c - '0';
+
+		tmp_c = raw_mask->pattern[i];
+		if (tmp_c >= 'a' && tmp_c <= 'f')
+			tmp_val = tmp_c - 0x57;
+		if (tmp_c >= 'A' && tmp_c <= 'F')
+			tmp_val = tmp_c - 0x37;
+		if (tmp_c >= '0' && tmp_c <= '9')
+			tmp_val = tmp_c - '0';
+
+		tmp_c = raw_mask->pattern[i + 1];
+		if (tmp_c >= 'a' && tmp_c <= 'f')
+			msk_buf[j] = tmp_val * 16 + tmp_c - 'a' + 10;
+		if (tmp_c >= 'A' && tmp_c <= 'F')
+			msk_buf[j] = tmp_val * 16 + tmp_c - 'A' + 10;
+		if (tmp_c >= '0' && tmp_c <= '9')
+			msk_buf[j] = tmp_val * 16 + tmp_c - '0';
+	}
+
+	rte_memcpy(meta->proto_hdrs.raw.spec, pkt_buf, pkt_len);
+	rte_memcpy(meta->proto_hdrs.raw.mask, msk_buf, pkt_len);
+	meta->proto_hdrs.raw.pkt_len = pkt_len;
+
+	rte_free(pkt_buf);
+	rte_free(msk_buf);
+
+	return 0;
+}
+
 #define REFINE_PROTO_FLD(op, fld) \
 	VIRTCHNL_##op##_PROTO_HDR_FIELD(hdr, VIRTCHNL_PROTO_HDR_##fld)
 #define REPALCE_PROTO_FLD(fld_1, fld_2) \
@@ -1387,6 +1468,10 @@  iavf_hash_parse_action(struct iavf_pattern_match_item *match_item,
 					RTE_FLOW_ERROR_TYPE_ACTION, action,
 					"a non-NULL RSS queue is not supported");
 
+			/* If pattern type is raw, no need to refine rss type */
+			if (pattern_hint == IAVF_PHINT_RAW)
+				break;
+
 			/**
 			 * Check simultaneous use of SRC_ONLY and DST_ONLY
 			 * of the same level.
@@ -1453,6 +1538,17 @@  iavf_hash_parse_pattern_action(__rte_unused struct iavf_adapter *ad,
 	if (ret)
 		goto error;
 
+	if (phint == IAVF_PHINT_RAW) {
+		rss_meta_ptr->raw_ena = true;
+		ret = iavf_hash_parse_raw_pattern(pattern, rss_meta_ptr);
+		if (ret) {
+			rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+					   "Parse raw pattern failed");
+			goto error;
+		}
+	}
+
 	ret = iavf_hash_parse_action(pattern_match_item, actions, phint,
 				     rss_meta_ptr, error);