DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH] net/i40e: enable port filter by switch filter
@ 2020-06-11  5:24 Guinan Sun
  2020-06-15  6:12 ` Zhao1, Wei
                   ` (6 more replies)
  0 siblings, 7 replies; 16+ messages in thread
From: Guinan Sun @ 2020-06-11  5:24 UTC (permalink / raw)
  To: dev; +Cc: Beilei Xing, Jia Guo, Guinan Sun

This patch enables the filter that supports
to create following two rules for the same packet type:
One is to select source port only as input set and the
other is for destination port only.

Signed-off-by: Guinan Sun <guinanx.sun@intel.com>
---
 doc/guides/rel_notes/release_20_08.rst |   7 +
 drivers/net/i40e/i40e_ethdev.c         | 195 ++++++++++++++++++++-
 drivers/net/i40e/i40e_ethdev.h         |  17 ++
 drivers/net/i40e/i40e_flow.c           | 223 +++++++++++++++++++++++++
 4 files changed, 441 insertions(+), 1 deletion(-)

diff --git a/doc/guides/rel_notes/release_20_08.rst b/doc/guides/rel_notes/release_20_08.rst
index 7a67c960c..16870100d 100644
--- a/doc/guides/rel_notes/release_20_08.rst
+++ b/doc/guides/rel_notes/release_20_08.rst
@@ -68,6 +68,13 @@ New Features
 
   * Added new PMD devarg ``reclaim_mem_mode``.
 
+* **Updated Intel i40e driver.**
+
+  Updated i40e PMD with new features and improvements, including:
+
+  * Added a new type of cloud filter to support the coexistence of the
+    following two rules. One selects L4 destination as input set and
+    the other one selects L4 source port.
 
 Removed Items
 -------------
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 970a31cb2..97e6e948a 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -7956,6 +7956,13 @@ i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
 #define I40E_TR_GRE_KEY_MASK			0x400
 #define I40E_TR_GRE_KEY_WITH_XSUM_MASK		0x800
 #define I40E_TR_GRE_NO_KEY_MASK			0x8000
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_PORT_TR_WORD0 0x49
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_DIRECTION_WORD0 0x41
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_INGRESS_WORD0 0x80
+#define I40E_DIRECTION_INGRESS_KEY		0x8000
+#define I40E_TR_L4_TYPE_TCP			0x2
+#define I40E_TR_L4_TYPE_UDP			0x4
+#define I40E_TR_L4_TYPE_SCTP			0x8
 
 static enum
 i40e_status_code i40e_replace_mpls_l1_filter(struct i40e_pf *pf)
@@ -8254,6 +8261,131 @@ i40e_status_code i40e_replace_gtp_cloud_filter(struct i40e_pf *pf)
 	return status;
 }
 
+static enum i40e_status_code
+i40e_replace_port_l1_filter(struct i40e_pf *pf, enum i40e_l4_port_type port_type)
+{
+	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
+	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
+	enum i40e_status_code status = I40E_SUCCESS;
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	struct rte_eth_dev *dev = ((struct i40e_adapter *)hw->back)->eth_dev;
+
+	if (pf->support_multi_driver) {
+		PMD_DRV_LOG(ERR, "Replace l1 filter is not supported.");
+		return I40E_NOT_SUPPORTED;
+	}
+
+	memset(&filter_replace, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+	memset(&filter_replace_buf, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+
+	/* create L1 filter */
+	if (port_type == I40E_L4_PORT_TYPE_SRC) {
+		filter_replace.old_filter_type =
+			I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TUNNLE_KEY;
+		filter_replace.new_filter_type = I40E_AQC_ADD_CLOUD_FILTER_0X11;
+		filter_replace_buf.data[8] =
+			I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_SRC_PORT;
+	} else {
+		filter_replace.old_filter_type =
+			I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG_IVLAN;
+		filter_replace.new_filter_type = I40E_AQC_ADD_CLOUD_FILTER_0X10;
+		filter_replace_buf.data[8] =
+			I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_DST_PORT;
+	}
+
+	filter_replace.tr_bit = 0;
+	/* Prepare the buffer, 3 entries */
+	filter_replace_buf.data[0] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_DIRECTION_WORD0;
+	filter_replace_buf.data[0] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[2] = 0x00;
+	filter_replace_buf.data[3] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_INGRESS_WORD0;
+	filter_replace_buf.data[4] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_PORT_TR_WORD0;
+	filter_replace_buf.data[4] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[5] = 0x00;
+	filter_replace_buf.data[6] = I40E_TR_L4_TYPE_UDP |
+		I40E_TR_L4_TYPE_TCP |
+		I40E_TR_L4_TYPE_SCTP;
+	filter_replace_buf.data[7] = 0x00;
+	filter_replace_buf.data[8] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[9] = 0x00;
+	filter_replace_buf.data[10] = 0xFF;
+	filter_replace_buf.data[11] = 0xFF;
+
+	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+						&filter_replace_buf);
+	if (!status && (filter_replace.old_filter_type !=
+			filter_replace.new_filter_type))
+		PMD_DRV_LOG(WARNING, "i40e device %s changed cloud l1 type."
+			    " original: 0x%x, new: 0x%x",
+			    dev->device->name,
+			    filter_replace.old_filter_type,
+			    filter_replace.new_filter_type);
+
+	return status;
+}
+
+static enum
+i40e_status_code i40e_replace_port_cloud_filter(struct i40e_pf *pf,
+						enum i40e_l4_port_type port_type)
+{
+	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
+	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
+	enum i40e_status_code status = I40E_SUCCESS;
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	struct rte_eth_dev *dev = ((struct i40e_adapter *)hw->back)->eth_dev;
+
+	if (pf->support_multi_driver) {
+		PMD_DRV_LOG(ERR, "Replace cloud filter is not supported.");
+		return I40E_NOT_SUPPORTED;
+	}
+
+	memset(&filter_replace, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+	memset(&filter_replace_buf, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+
+	if (port_type == I40E_L4_PORT_TYPE_SRC) {
+		filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_IIP;
+		filter_replace.new_filter_type =
+			I40E_AQC_ADD_L1_FILTER_0X11;
+		filter_replace_buf.data[4] = I40E_AQC_ADD_CLOUD_FILTER_0X11;
+	} else {
+		filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_OIP;
+		filter_replace.new_filter_type =
+			I40E_AQC_ADD_CLOUD_FILTER_0X10;
+		filter_replace_buf.data[4] = I40E_AQC_ADD_CLOUD_FILTER_0X10;
+	}
+
+	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER;
+	filter_replace.tr_bit = 0;
+	/* Prepare the buffer, 2 entries */
+	filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
+	filter_replace_buf.data[0] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[4] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+						&filter_replace_buf);
+
+	if (!status && (filter_replace.old_filter_type !=
+			filter_replace.new_filter_type))
+		PMD_DRV_LOG(WARNING, "i40e device %s changed cloud filter type."
+			    " original: 0x%x, new: 0x%x",
+			    dev->device->name,
+			    filter_replace.old_filter_type,
+			    filter_replace.new_filter_type);
+
+	return status;
+}
+
 int
 i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		      struct i40e_tunnel_filter_conf *tunnel_filter,
@@ -8401,6 +8533,58 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		pfilter->general_fields[0] = tunnel_filter->inner_vlan;
 		pfilter->general_fields[1] = tunnel_filter->outer_vlan;
 		big_buffer = 1;
+		break;
+	case I40E_TUNNEL_TYPE_UDP:
+	case I40E_TUNNEL_TYPE_TCP:
+	case I40E_TUNNEL_TYPE_SCTP:
+		if (tunnel_filter->port_type == I40E_L4_PORT_TYPE_SRC) {
+			if (!pf->sport_replace_flag) {
+				i40e_replace_port_l1_filter(pf, tunnel_filter->port_type);
+				i40e_replace_port_cloud_filter(pf, tunnel_filter->port_type);
+				pf->sport_replace_flag = 1;
+			}
+			teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
+			pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
+				I40E_DIRECTION_INGRESS_KEY;
+
+			if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_UDP)
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+					I40E_TR_L4_TYPE_UDP;
+			else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_TCP)
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+					I40E_TR_L4_TYPE_TCP;
+			else
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+					I40E_TR_L4_TYPE_SCTP;
+
+			pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
+				(teid_le >> 16) & 0xFFFF;
+			big_buffer = 1;
+		} else {
+			if (!pf->dport_replace_flag) {
+				i40e_replace_port_l1_filter(pf, tunnel_filter->port_type);
+				i40e_replace_port_cloud_filter(pf, tunnel_filter->port_type);
+				pf->dport_replace_flag = 1;
+			}
+			teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
+			pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD0] =
+				I40E_DIRECTION_INGRESS_KEY;
+
+			if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_UDP)
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
+					I40E_TR_L4_TYPE_UDP;
+			else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_TCP)
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
+					I40E_TR_L4_TYPE_TCP;
+			else
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
+					I40E_TR_L4_TYPE_SCTP;
+
+			pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD2] =
+				(teid_le >> 16) & 0xFFFF;
+			big_buffer = 1;
+		}
+
 		break;
 	default:
 		/* Other tunnel types is not supported. */
@@ -8424,7 +8608,16 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_QINQ)
 		pfilter->element.flags |=
 			I40E_AQC_ADD_CLOUD_FILTER_0X10;
-	else {
+	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_UDP ||
+		tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_TCP ||
+		tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_SCTP) {
+		if (tunnel_filter->port_type == I40E_L4_PORT_TYPE_SRC)
+			pfilter->element.flags |=
+				I40E_AQC_ADD_L1_FILTER_0X11;
+		else
+			pfilter->element.flags |=
+				I40E_AQC_ADD_CLOUD_FILTER_0X10;
+	} else {
 		val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
 						&pfilter->element.flags);
 		if (val < 0) {
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index e5d0ce53f..b79ab5880 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -767,6 +767,8 @@ struct i40e_rss_pattern_info {
 
 #define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD0 44
 #define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD1 45
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_SRC_PORT 29
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_DST_PORT 30
 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSOUDP	8
 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSOGRE	9
 #define I40E_AQC_ADD_CLOUD_FILTER_0X10		0x10
@@ -828,9 +830,20 @@ enum i40e_tunnel_type {
 	I40E_TUNNEL_TYPE_GTPU,
 	I40E_TUNNEL_TYPE_ESPoUDP,
 	I40E_TUNNEL_TYPE_ESPoIP,
+	I40E_TUNNEL_TYPE_UDP,
+	I40E_TUNNEL_TYPE_TCP,
+	I40E_TUNNEL_TYPE_SCTP,
 	I40E_TUNNEL_TYPE_MAX,
 };
 
+/**
+ * Port type.
+ */
+enum i40e_l4_port_type {
+	I40E_L4_PORT_TYPE_SRC = 0,
+	I40E_L4_PORT_TYPE_DST,
+};
+
 /**
  * Tunneling Packet filter configuration.
  */
@@ -852,6 +865,7 @@ struct i40e_tunnel_filter_conf {
 	/** Flags from ETH_TUNNEL_FILTER_XX - see above. */
 	uint16_t filter_type;
 	enum i40e_tunnel_type tunnel_type; /**< Tunnel Type. */
+	enum i40e_l4_port_type port_type; /**< L4 Port Type. */
 	uint32_t tenant_id;     /**< Tenant ID to match. VNI, GRE key... */
 	uint16_t queue_id;      /**< Queue assigned to if match. */
 	uint8_t is_to_vf;       /**< 0 - to PF, 1 - to VF */
@@ -1073,6 +1087,9 @@ struct i40e_pf {
 	bool mpls_replace_flag;  /* 1 - MPLS filter replace is done */
 	bool gtp_replace_flag;   /* 1 - GTP-C/U filter replace is done */
 	bool qinq_replace_flag;  /* QINQ filter replace is done */
+	/* l4 port flag */
+	bool sport_replace_flag;   /* source port replace is done */
+	bool dport_replace_flag;   /* dest port replace is done */
 	struct i40e_tm_conf tm_conf;
 	bool support_multi_driver; /* 1 - support multiple driver */
 
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 8f8df6fae..a268ff3d2 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -124,6 +124,12 @@ i40e_flow_parse_qinq_pattern(struct rte_eth_dev *dev,
 			      struct rte_flow_error *error,
 			      struct i40e_tunnel_filter_conf *filter);
 
+static int i40e_flow_parse_l4_proto_filter(struct rte_eth_dev *dev,
+				      const struct rte_flow_attr *attr,
+				      const struct rte_flow_item pattern[],
+				      const struct rte_flow_action actions[],
+				      struct rte_flow_error *error,
+				      union i40e_filter_t *filter);
 const struct rte_flow_ops i40e_flow_ops = {
 	.validate = i40e_flow_validate,
 	.create = i40e_flow_create,
@@ -1845,6 +1851,13 @@ static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	/* L2TPv3 over IP */
 	{ pattern_fdir_ipv4_l2tpv3oip, i40e_flow_parse_fdir_filter },
 	{ pattern_fdir_ipv6_l2tpv3oip, i40e_flow_parse_fdir_filter },
+	/* L4 over port */
+	{ pattern_fdir_ipv4_udp, i40e_flow_parse_l4_proto_filter },
+	{ pattern_fdir_ipv4_tcp, i40e_flow_parse_l4_proto_filter },
+	{ pattern_fdir_ipv4_sctp, i40e_flow_parse_l4_proto_filter },
+	{ pattern_fdir_ipv6_udp, i40e_flow_parse_l4_proto_filter },
+	{ pattern_fdir_ipv6_tcp, i40e_flow_parse_l4_proto_filter },
+	{ pattern_fdir_ipv6_sctp, i40e_flow_parse_l4_proto_filter },
 };
 
 #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
@@ -3541,6 +3554,216 @@ i40e_flow_parse_tunnel_action(struct rte_eth_dev *dev,
 	return 0;
 }
 
+static int
+i40e_flow_parse_l4_proto_pattern(const struct rte_flow_item *pattern,
+				 struct rte_flow_error *error,
+				 struct i40e_tunnel_filter_conf *filter)
+{
+	const struct rte_flow_item_sctp *sctp_spec, *sctp_mask;
+	const struct rte_flow_item_tcp *tcp_spec, *tcp_mask;
+	const struct rte_flow_item_udp *udp_spec, *udp_mask;
+	const struct rte_flow_item *item = pattern;
+	enum rte_flow_item_type item_type;
+
+	for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+		if (item->last) {
+			rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM,
+					   item,
+					   "Not support range");
+			return -rte_errno;
+		}
+		item_type = item->type;
+		switch (item_type) {
+		case RTE_FLOW_ITEM_TYPE_ETH:
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid ETH item");
+				return -rte_errno;
+			}
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV4:
+			filter->ip_type = I40E_TUNNEL_IPTYPE_IPV4;
+			/* IPv4 is used to describe protocol,
+			 * spec and mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid IPv4 item");
+				return -rte_errno;
+			}
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV6:
+			filter->ip_type = I40E_TUNNEL_IPTYPE_IPV6;
+			/* IPv6 is used to describe protocol,
+			 * spec and mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid IPv6 item");
+				return -rte_errno;
+			}
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_UDP:
+			udp_spec = item->spec;
+			udp_mask = item->mask;
+
+			if (!udp_spec || !udp_mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid udp item");
+				return -rte_errno;
+			}
+
+			if (udp_spec->hdr.src_port != 0 &&
+			    udp_spec->hdr.dst_port != 0) {
+				rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_ITEM,
+						item,
+						"Invalid udp spec");
+				return -rte_errno;
+			}
+
+			if (udp_spec->hdr.src_port != 0) {
+				filter->port_type =
+					I40E_L4_PORT_TYPE_SRC;
+				filter->tenant_id =
+				rte_be_to_cpu_32(udp_spec->hdr.src_port);
+			}
+
+			if (udp_spec->hdr.dst_port != 0) {
+				filter->port_type =
+					I40E_L4_PORT_TYPE_DST;
+				filter->tenant_id =
+				rte_be_to_cpu_32(udp_spec->hdr.dst_port);
+			}
+
+			filter->tunnel_type = I40E_TUNNEL_TYPE_UDP;
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_TCP:
+			tcp_spec = item->spec;
+			tcp_mask = item->mask;
+
+			if (!tcp_spec || !tcp_mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid tcp item");
+				return -rte_errno;
+			}
+
+			if (tcp_spec->hdr.src_port != 0 &&
+			    tcp_spec->hdr.dst_port != 0) {
+				rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_ITEM,
+						item,
+						"Invalid tcp spec");
+				return -rte_errno;
+			}
+
+			if (tcp_spec->hdr.src_port != 0) {
+				filter->port_type =
+					I40E_L4_PORT_TYPE_SRC;
+				filter->tenant_id =
+				rte_be_to_cpu_32(tcp_spec->hdr.src_port);
+			}
+
+			if (tcp_spec->hdr.dst_port != 0) {
+				filter->port_type =
+					I40E_L4_PORT_TYPE_DST;
+				filter->tenant_id =
+				rte_be_to_cpu_32(tcp_spec->hdr.dst_port);
+			}
+
+			filter->tunnel_type = I40E_TUNNEL_TYPE_TCP;
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_SCTP:
+			sctp_spec = item->spec;
+			sctp_mask = item->mask;
+
+			if (!sctp_spec || !sctp_mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid sctp item");
+				return -rte_errno;
+			}
+
+			if (sctp_spec->hdr.src_port != 0 &&
+			    sctp_spec->hdr.dst_port != 0) {
+				rte_flow_error_set(error, EINVAL,
+						RTE_FLOW_ERROR_TYPE_ITEM,
+						item,
+						"Invalid sctp spec");
+				return -rte_errno;
+			}
+
+			if (sctp_spec->hdr.src_port != 0) {
+				filter->port_type =
+					I40E_L4_PORT_TYPE_SRC;
+				filter->tenant_id =
+					rte_be_to_cpu_32(sctp_spec->hdr.src_port);
+			}
+
+			if (sctp_spec->hdr.dst_port != 0) {
+				filter->port_type =
+					I40E_L4_PORT_TYPE_DST;
+				filter->tenant_id =
+					rte_be_to_cpu_32(sctp_spec->hdr.dst_port);
+			}
+
+			filter->tunnel_type = I40E_TUNNEL_TYPE_SCTP;
+
+			break;
+		default:
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static int
+i40e_flow_parse_l4_proto_filter(struct rte_eth_dev *dev,
+			   const struct rte_flow_attr *attr,
+			   const struct rte_flow_item pattern[],
+			   const struct rte_flow_action actions[],
+			   struct rte_flow_error *error,
+			   union i40e_filter_t *filter)
+{
+	struct i40e_tunnel_filter_conf *tunnel_filter =
+		&filter->consistent_tunnel_filter;
+	int ret;
+
+	ret = i40e_flow_parse_l4_proto_pattern(pattern, error, tunnel_filter);
+	if (ret)
+		return ret;
+
+	ret = i40e_flow_parse_tunnel_action(dev, actions, error, tunnel_filter);
+	if (ret)
+		return ret;
+
+	ret = i40e_flow_parse_attr(attr, error);
+	if (ret)
+		return ret;
+
+	cons_filter_type = RTE_ETH_FILTER_TUNNEL;
+
+	return ret;
+}
+
 static uint16_t i40e_supported_tunnel_filter_types[] = {
 	ETH_TUNNEL_FILTER_IMAC | ETH_TUNNEL_FILTER_TENID |
 	ETH_TUNNEL_FILTER_IVLAN,
-- 
2.17.1


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

* Re: [dpdk-dev] [PATCH] net/i40e: enable port filter by switch filter
  2020-06-11  5:24 [dpdk-dev] [PATCH] net/i40e: enable port filter by switch filter Guinan Sun
@ 2020-06-15  6:12 ` Zhao1, Wei
  2020-06-15  6:28   ` Sun, GuinanX
  2020-06-21 12:28 ` Jeff Guo
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 16+ messages in thread
From: Zhao1, Wei @ 2020-06-15  6:12 UTC (permalink / raw)
  To: Sun, GuinanX, dev; +Cc: Xing, Beilei, Guo, Jia, Sun, GuinanX

Hi, Guinan

> -----Original Message-----
> From: dev <dev-bounces@dpdk.org> On Behalf Of Guinan Sun
> Sent: Thursday, June 11, 2020 1:24 PM
> To: dev@dpdk.org
> Cc: Xing, Beilei <beilei.xing@intel.com>; Guo, Jia <jia.guo@intel.com>; Sun,
> GuinanX <guinanx.sun@intel.com>
> Subject: [dpdk-dev] [PATCH] net/i40e: enable port filter by switch filter
> 
> This patch enables the filter that supports to create following two rules for the
> same packet type:
> One is to select source port only as input set and the other is for destination
> port only.
> 
> Signed-off-by: Guinan Sun <guinanx.sun@intel.com>
> ---
>  doc/guides/rel_notes/release_20_08.rst |   7 +
>  drivers/net/i40e/i40e_ethdev.c         | 195 ++++++++++++++++++++-
>  drivers/net/i40e/i40e_ethdev.h         |  17 ++
>  drivers/net/i40e/i40e_flow.c           | 223
> +++++++++++++++++++++++++
>  4 files changed, 441 insertions(+), 1 deletion(-)
> 
> diff --git a/doc/guides/rel_notes/release_20_08.rst
> b/doc/guides/rel_notes/release_20_08.rst
> index 7a67c960c..16870100d 100644
> --- a/doc/guides/rel_notes/release_20_08.rst
> +++ b/doc/guides/rel_notes/release_20_08.rst
> @@ -68,6 +68,13 @@ New Features
> 
>    * Added new PMD devarg ``reclaim_mem_mode``.
> 
> +* **Updated Intel i40e driver.**
> +
> +  Updated i40e PMD with new features and improvements, including:
> +
> +  * Added a new type of cloud filter to support the coexistence of the
> +    following two rules. One selects L4 destination as input set and
> +    the other one selects L4 source port.
> 
>  Removed Items
>  -------------
> diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
> index 970a31cb2..97e6e948a 100644
> --- a/drivers/net/i40e/i40e_ethdev.c
> +++ b/drivers/net/i40e/i40e_ethdev.c
> @@ -7956,6 +7956,13 @@ i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
>  #define I40E_TR_GRE_KEY_MASK			0x400
>  #define I40E_TR_GRE_KEY_WITH_XSUM_MASK		0x800
>  #define I40E_TR_GRE_NO_KEY_MASK			0x8000

> +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_PORT_TR_WORD0 0x49

A confused question, this 0x49 seems to be a field vector index? Filed vector table is 128 byte long, why does this can large than 64?


> #define
> +I40E_AQC_REPLACE_CLOUD_CMD_INPUT_DIRECTION_WORD0 0x41 #define
> +I40E_AQC_REPLACE_CLOUD_CMD_INPUT_INGRESS_WORD0 0x80
> +#define I40E_DIRECTION_INGRESS_KEY		0x8000
> +#define I40E_TR_L4_TYPE_TCP			0x2
> +#define I40E_TR_L4_TYPE_UDP			0x4
> +#define I40E_TR_L4_TYPE_SCTP			0x8
> 
>  static enum
>  i40e_status_code i40e_replace_mpls_l1_filter(struct i40e_pf *pf) @@
> -8254,6 +8261,131 @@ i40e_status_code
> i40e_replace_gtp_cloud_filter(struct i40e_pf *pf)
>  	return status;


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

* Re: [dpdk-dev] [PATCH] net/i40e: enable port filter by switch filter
  2020-06-15  6:12 ` Zhao1, Wei
@ 2020-06-15  6:28   ` Sun, GuinanX
  0 siblings, 0 replies; 16+ messages in thread
From: Sun, GuinanX @ 2020-06-15  6:28 UTC (permalink / raw)
  To: Zhao1, Wei, dev; +Cc: Xing, Beilei, Guo, Jia

Hi zhaowei

> -----Original Message-----
> From: Zhao1, Wei
> Sent: Monday, June 15, 2020 2:13 PM
> To: Sun, GuinanX <guinanx.sun@intel.com>; dev@dpdk.org
> Cc: Xing, Beilei <beilei.xing@intel.com>; Guo, Jia <jia.guo@intel.com>; Sun,
> GuinanX <guinanx.sun@intel.com>
> Subject: RE: [dpdk-dev] [PATCH] net/i40e: enable port filter by switch filter
> 
> Hi, Guinan
> 
> > -----Original Message-----
> > From: dev <dev-bounces@dpdk.org> On Behalf Of Guinan Sun
> > Sent: Thursday, June 11, 2020 1:24 PM
> > To: dev@dpdk.org
> > Cc: Xing, Beilei <beilei.xing@intel.com>; Guo, Jia
> > <jia.guo@intel.com>; Sun, GuinanX <guinanx.sun@intel.com>
> > Subject: [dpdk-dev] [PATCH] net/i40e: enable port filter by switch
> > filter
> >
> > This patch enables the filter that supports to create following two
> > rules for the same packet type:
> > One is to select source port only as input set and the other is for
> > destination port only.
> >
> > Signed-off-by: Guinan Sun <guinanx.sun@intel.com>
> > ---
> >  doc/guides/rel_notes/release_20_08.rst |   7 +
> >  drivers/net/i40e/i40e_ethdev.c         | 195 ++++++++++++++++++++-
> >  drivers/net/i40e/i40e_ethdev.h         |  17 ++
> >  drivers/net/i40e/i40e_flow.c           | 223
> > +++++++++++++++++++++++++
> >  4 files changed, 441 insertions(+), 1 deletion(-)
> >
> > diff --git a/doc/guides/rel_notes/release_20_08.rst
> > b/doc/guides/rel_notes/release_20_08.rst
> > index 7a67c960c..16870100d 100644
> > --- a/doc/guides/rel_notes/release_20_08.rst
> > +++ b/doc/guides/rel_notes/release_20_08.rst
> > @@ -68,6 +68,13 @@ New Features
> >
> >    * Added new PMD devarg ``reclaim_mem_mode``.
> >
> > +* **Updated Intel i40e driver.**
> > +
> > +  Updated i40e PMD with new features and improvements, including:
> > +
> > +  * Added a new type of cloud filter to support the coexistence of the
> > +    following two rules. One selects L4 destination as input set and
> > +    the other one selects L4 source port.
> >
> >  Removed Items
> >  -------------
> > diff --git a/drivers/net/i40e/i40e_ethdev.c
> > b/drivers/net/i40e/i40e_ethdev.c index 970a31cb2..97e6e948a 100644
> > --- a/drivers/net/i40e/i40e_ethdev.c
> > +++ b/drivers/net/i40e/i40e_ethdev.c
> > @@ -7956,6 +7956,13 @@ i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
> > #define I40E_TR_GRE_KEY_MASK0x400  #define
> > I40E_TR_GRE_KEY_WITH_XSUM_MASK0x800
> >  #define I40E_TR_GRE_NO_KEY_MASK0x8000
> 
> > +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_PORT_TR_WORD0 0x49
> 
> A confused question, this 0x49 seems to be a field vector index? Filed vector
> table is 128 byte long, why does this can large than 64?
> 

This is not field vector. Examples of filed vector use are as follows
I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1 or 
I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1.

> 
> > #define
> > +I40E_AQC_REPLACE_CLOUD_CMD_INPUT_DIRECTION_WORD0 0x41
> #define
> > +I40E_AQC_REPLACE_CLOUD_CMD_INPUT_INGRESS_WORD0 0x80 #define
> > +I40E_DIRECTION_INGRESS_KEY0x8000 #define I40E_TR_L4_TYPE_TCP0x2
> > +#define I40E_TR_L4_TYPE_UDP0x4 #define I40E_TR_L4_TYPE_SCTP0x8
> >
> >  static enum
> >  i40e_status_code i40e_replace_mpls_l1_filter(struct i40e_pf *pf) @@
> > -8254,6 +8261,131 @@ i40e_status_code
> > i40e_replace_gtp_cloud_filter(struct i40e_pf *pf)  return status;
> 


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

* Re: [dpdk-dev] [PATCH] net/i40e: enable port filter by switch filter
  2020-06-11  5:24 [dpdk-dev] [PATCH] net/i40e: enable port filter by switch filter Guinan Sun
  2020-06-15  6:12 ` Zhao1, Wei
@ 2020-06-21 12:28 ` Jeff Guo
  2020-06-24  3:09   ` Sun, GuinanX
  2020-06-30  4:42 ` [dpdk-dev] [PATCH v2] " Guinan Sun
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 16+ messages in thread
From: Jeff Guo @ 2020-06-21 12:28 UTC (permalink / raw)
  To: Guinan Sun, dev; +Cc: Beilei Xing

hi, guinan

On 6/11/2020 1:24 PM, Guinan Sun wrote:
> This patch enables the filter that supports
> to create following two rules for the same packet type:
> One is to select source port only as input set and the
> other is for destination port only.
>
> Signed-off-by: Guinan Sun <guinanx.sun@intel.com>
> ---
>   doc/guides/rel_notes/release_20_08.rst |   7 +
>   drivers/net/i40e/i40e_ethdev.c         | 195 ++++++++++++++++++++-
>   drivers/net/i40e/i40e_ethdev.h         |  17 ++
>   drivers/net/i40e/i40e_flow.c           | 223 +++++++++++++++++++++++++
>   4 files changed, 441 insertions(+), 1 deletion(-)
>
> diff --git a/doc/guides/rel_notes/release_20_08.rst b/doc/guides/rel_notes/release_20_08.rst
> index 7a67c960c..16870100d 100644
> --- a/doc/guides/rel_notes/release_20_08.rst
> +++ b/doc/guides/rel_notes/release_20_08.rst
> @@ -68,6 +68,13 @@ New Features
>   
>     * Added new PMD devarg ``reclaim_mem_mode``.
>   
> +* **Updated Intel i40e driver.**
> +
> +  Updated i40e PMD with new features and improvements, including:
> +
> +  * Added a new type of cloud filter to support the coexistence of the
> +    following two rules. One selects L4 destination as input set and
> +    the other one selects L4 source port.
>   
>   Removed Items
>   -------------
> diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
> index 970a31cb2..97e6e948a 100644
> --- a/drivers/net/i40e/i40e_ethdev.c
> +++ b/drivers/net/i40e/i40e_ethdev.c
> @@ -7956,6 +7956,13 @@ i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
>   #define I40E_TR_GRE_KEY_MASK			0x400
>   #define I40E_TR_GRE_KEY_WITH_XSUM_MASK		0x800
>   #define I40E_TR_GRE_NO_KEY_MASK			0x8000
> +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_PORT_TR_WORD0 0x49
> +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_DIRECTION_WORD0 0x41
> +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_INGRESS_WORD0 0x80
> +#define I40E_DIRECTION_INGRESS_KEY		0x8000
> +#define I40E_TR_L4_TYPE_TCP			0x2
> +#define I40E_TR_L4_TYPE_UDP			0x4
> +#define I40E_TR_L4_TYPE_SCTP			0x8
>   
>   static enum
>   i40e_status_code i40e_replace_mpls_l1_filter(struct i40e_pf *pf)
> @@ -8254,6 +8261,131 @@ i40e_status_code i40e_replace_gtp_cloud_filter(struct i40e_pf *pf)
>   	return status;
>   }
>   
> +static enum i40e_status_code
> +i40e_replace_port_l1_filter(struct i40e_pf *pf, enum i40e_l4_port_type port_type)
> +{
> +	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
> +	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
> +	enum i40e_status_code status = I40E_SUCCESS;
> +	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
> +	struct rte_eth_dev *dev = ((struct i40e_adapter *)hw->back)->eth_dev;
> +


The Christmas tree would be look good?


> +	if (pf->support_multi_driver) {
> +		PMD_DRV_LOG(ERR, "Replace l1 filter is not supported.");
> +		return I40E_NOT_SUPPORTED;
> +	}
> +
> +	memset(&filter_replace, 0,
> +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
> +	memset(&filter_replace_buf, 0,
> +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
> +
> +	/* create L1 filter */
> +	if (port_type == I40E_L4_PORT_TYPE_SRC) {
> +		filter_replace.old_filter_type =
> +			I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TUNNLE_KEY;
> +		filter_replace.new_filter_type = I40E_AQC_ADD_CLOUD_FILTER_0X11;
> +		filter_replace_buf.data[8] =
> +			I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_SRC_PORT;
> +	} else {
> +		filter_replace.old_filter_type =
> +			I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG_IVLAN;
> +		filter_replace.new_filter_type = I40E_AQC_ADD_CLOUD_FILTER_0X10;
> +		filter_replace_buf.data[8] =
> +			I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_DST_PORT;
> +	}
> +
> +	filter_replace.tr_bit = 0;
> +	/* Prepare the buffer, 3 entries */
> +	filter_replace_buf.data[0] =
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_DIRECTION_WORD0;
> +	filter_replace_buf.data[0] |=
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> +	filter_replace_buf.data[2] = 0x00;
> +	filter_replace_buf.data[3] =
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_INGRESS_WORD0;
> +	filter_replace_buf.data[4] =
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_PORT_TR_WORD0;
> +	filter_replace_buf.data[4] |=
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> +	filter_replace_buf.data[5] = 0x00;
> +	filter_replace_buf.data[6] = I40E_TR_L4_TYPE_UDP |
> +		I40E_TR_L4_TYPE_TCP |
> +		I40E_TR_L4_TYPE_SCTP;
> +	filter_replace_buf.data[7] = 0x00;
> +	filter_replace_buf.data[8] |=
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> +	filter_replace_buf.data[9] = 0x00;
> +	filter_replace_buf.data[10] = 0xFF;
> +	filter_replace_buf.data[11] = 0xFF;
> +
> +	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
> +						&filter_replace_buf);


Please check the alignment here and below.


> +	if (!status && (filter_replace.old_filter_type !=
> +			filter_replace.new_filter_type))
> +		PMD_DRV_LOG(WARNING, "i40e device %s changed cloud l1 type."
> +			    " original: 0x%x, new: 0x%x",
> +			    dev->device->name,
> +			    filter_replace.old_filter_type,
> +			    filter_replace.new_filter_type);
> +
> +	return status;
> +}
> +
> +static enum
> +i40e_status_code i40e_replace_port_cloud_filter(struct i40e_pf *pf,
> +						enum i40e_l4_port_type port_type)


Please check the limit of the line characters and below. I think 
checkpatch could help you for that.


> +{
> +	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
> +	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
> +	enum i40e_status_code status = I40E_SUCCESS;
> +	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
> +	struct rte_eth_dev *dev = ((struct i40e_adapter *)hw->back)->eth_dev;
> +
> +	if (pf->support_multi_driver) {
> +		PMD_DRV_LOG(ERR, "Replace cloud filter is not supported.");
> +		return I40E_NOT_SUPPORTED;
> +	}
> +
> +	memset(&filter_replace, 0,
> +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
> +	memset(&filter_replace_buf, 0,
> +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
> +
> +	if (port_type == I40E_L4_PORT_TYPE_SRC) {
> +		filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_IIP;
> +		filter_replace.new_filter_type =
> +			I40E_AQC_ADD_L1_FILTER_0X11;
> +		filter_replace_buf.data[4] = I40E_AQC_ADD_CLOUD_FILTER_0X11;
> +	} else {
> +		filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_OIP;
> +		filter_replace.new_filter_type =
> +			I40E_AQC_ADD_CLOUD_FILTER_0X10;
> +		filter_replace_buf.data[4] = I40E_AQC_ADD_CLOUD_FILTER_0X10;
> +	}
> +
> +	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER;
> +	filter_replace.tr_bit = 0;
> +	/* Prepare the buffer, 2 entries */
> +	filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
> +	filter_replace_buf.data[0] |=
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> +	filter_replace_buf.data[4] |=
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> +	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
> +						&filter_replace_buf);
> +
> +	if (!status && (filter_replace.old_filter_type !=
> +			filter_replace.new_filter_type))
> +		PMD_DRV_LOG(WARNING, "i40e device %s changed cloud filter type."
> +			    " original: 0x%x, new: 0x%x",
> +			    dev->device->name,
> +			    filter_replace.old_filter_type,
> +			    filter_replace.new_filter_type);
> +
> +	return status;
> +}
> +
>   int
>   i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
>   		      struct i40e_tunnel_filter_conf *tunnel_filter,
> @@ -8401,6 +8533,58 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
>   		pfilter->general_fields[0] = tunnel_filter->inner_vlan;
>   		pfilter->general_fields[1] = tunnel_filter->outer_vlan;
>   		big_buffer = 1;
> +		break;
> +	case I40E_TUNNEL_TYPE_UDP:
> +	case I40E_TUNNEL_TYPE_TCP:
> +	case I40E_TUNNEL_TYPE_SCTP:
> +		if (tunnel_filter->port_type == I40E_L4_PORT_TYPE_SRC) {
> +			if (!pf->sport_replace_flag) {
> +				i40e_replace_port_l1_filter(pf, tunnel_filter->port_type);
> +				i40e_replace_port_cloud_filter(pf, tunnel_filter->port_type);
> +				pf->sport_replace_flag = 1;
> +			}
> +			teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
> +			pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
> +				I40E_DIRECTION_INGRESS_KEY;
> +
> +			if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_UDP)
> +				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
> +					I40E_TR_L4_TYPE_UDP;
> +			else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_TCP)
> +				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
> +					I40E_TR_L4_TYPE_TCP;
> +			else
> +				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
> +					I40E_TR_L4_TYPE_SCTP;
> +
> +			pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
> +				(teid_le >> 16) & 0xFFFF;
> +			big_buffer = 1;
> +		} else {
> +			if (!pf->dport_replace_flag) {
> +				i40e_replace_port_l1_filter(pf, tunnel_filter->port_type);
> +				i40e_replace_port_cloud_filter(pf, tunnel_filter->port_type);
> +				pf->dport_replace_flag = 1;
> +			}
> +			teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
> +			pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD0] =
> +				I40E_DIRECTION_INGRESS_KEY;
> +
> +			if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_UDP)
> +				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
> +					I40E_TR_L4_TYPE_UDP;
> +			else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_TCP)
> +				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
> +					I40E_TR_L4_TYPE_TCP;
> +			else
> +				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
> +					I40E_TR_L4_TYPE_SCTP;
> +
> +			pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD2] =
> +				(teid_le >> 16) & 0xFFFF;
> +			big_buffer = 1;
> +		}
> +
>   		break;
>   	default:
>   		/* Other tunnel types is not supported. */
> @@ -8424,7 +8608,16 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
>   	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_QINQ)
>   		pfilter->element.flags |=
>   			I40E_AQC_ADD_CLOUD_FILTER_0X10;
> -	else {
> +	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_UDP ||
> +		tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_TCP ||
> +		tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_SCTP) {
> +		if (tunnel_filter->port_type == I40E_L4_PORT_TYPE_SRC)
> +			pfilter->element.flags |=
> +				I40E_AQC_ADD_L1_FILTER_0X11;
> +		else
> +			pfilter->element.flags |=
> +				I40E_AQC_ADD_CLOUD_FILTER_0X10;
> +	} else {
>   		val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
>   						&pfilter->element.flags);
>   		if (val < 0) {
> diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
> index e5d0ce53f..b79ab5880 100644
> --- a/drivers/net/i40e/i40e_ethdev.h
> +++ b/drivers/net/i40e/i40e_ethdev.h
> @@ -767,6 +767,8 @@ struct i40e_rss_pattern_info {
>   
>   #define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD0 44
>   #define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD1 45
> +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_SRC_PORT 29
> +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_DST_PORT 30
>   #define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSOUDP	8
>   #define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSOGRE	9
>   #define I40E_AQC_ADD_CLOUD_FILTER_0X10		0x10
> @@ -828,9 +830,20 @@ enum i40e_tunnel_type {
>   	I40E_TUNNEL_TYPE_GTPU,
>   	I40E_TUNNEL_TYPE_ESPoUDP,
>   	I40E_TUNNEL_TYPE_ESPoIP,
> +	I40E_TUNNEL_TYPE_UDP,
> +	I40E_TUNNEL_TYPE_TCP,
> +	I40E_TUNNEL_TYPE_SCTP,
>   	I40E_TUNNEL_TYPE_MAX,
>   };
>   
> +/**
> + * Port type.
> + */
> +enum i40e_l4_port_type {
> +	I40E_L4_PORT_TYPE_SRC = 0,
> +	I40E_L4_PORT_TYPE_DST,
> +};
> +
>   /**
>    * Tunneling Packet filter configuration.
>    */
> @@ -852,6 +865,7 @@ struct i40e_tunnel_filter_conf {
>   	/** Flags from ETH_TUNNEL_FILTER_XX - see above. */
>   	uint16_t filter_type;
>   	enum i40e_tunnel_type tunnel_type; /**< Tunnel Type. */
> +	enum i40e_l4_port_type port_type; /**< L4 Port Type. */


L4_port_type would be better?


>   	uint32_t tenant_id;     /**< Tenant ID to match. VNI, GRE key... */
>   	uint16_t queue_id;      /**< Queue assigned to if match. */
>   	uint8_t is_to_vf;       /**< 0 - to PF, 1 - to VF */
> @@ -1073,6 +1087,9 @@ struct i40e_pf {
>   	bool mpls_replace_flag;  /* 1 - MPLS filter replace is done */
>   	bool gtp_replace_flag;   /* 1 - GTP-C/U filter replace is done */
>   	bool qinq_replace_flag;  /* QINQ filter replace is done */
> +	/* l4 port flag */
> +	bool sport_replace_flag;   /* source port replace is done */
> +	bool dport_replace_flag;   /* dest port replace is done */
>   	struct i40e_tm_conf tm_conf;
>   	bool support_multi_driver; /* 1 - support multiple driver */
>   
> diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
> index 8f8df6fae..a268ff3d2 100644
> --- a/drivers/net/i40e/i40e_flow.c
> +++ b/drivers/net/i40e/i40e_flow.c
> @@ -124,6 +124,12 @@ i40e_flow_parse_qinq_pattern(struct rte_eth_dev *dev,
>   			      struct rte_flow_error *error,
>   			      struct i40e_tunnel_filter_conf *filter);
>   
> +static int i40e_flow_parse_l4_proto_filter(struct rte_eth_dev *dev,
> +				      const struct rte_flow_attr *attr,
> +				      const struct rte_flow_item pattern[],
> +				      const struct rte_flow_action actions[],
> +				      struct rte_flow_error *error,
> +				      union i40e_filter_t *filter);
>   const struct rte_flow_ops i40e_flow_ops = {
>   	.validate = i40e_flow_validate,
>   	.create = i40e_flow_create,
> @@ -1845,6 +1851,13 @@ static struct i40e_valid_pattern i40e_supported_patterns[] = {
>   	/* L2TPv3 over IP */
>   	{ pattern_fdir_ipv4_l2tpv3oip, i40e_flow_parse_fdir_filter },
>   	{ pattern_fdir_ipv6_l2tpv3oip, i40e_flow_parse_fdir_filter },
> +	/* L4 over port */
> +	{ pattern_fdir_ipv4_udp, i40e_flow_parse_l4_proto_filter },
> +	{ pattern_fdir_ipv4_tcp, i40e_flow_parse_l4_proto_filter },
> +	{ pattern_fdir_ipv4_sctp, i40e_flow_parse_l4_proto_filter },
> +	{ pattern_fdir_ipv6_udp, i40e_flow_parse_l4_proto_filter },
> +	{ pattern_fdir_ipv6_tcp, i40e_flow_parse_l4_proto_filter },
> +	{ pattern_fdir_ipv6_sctp, i40e_flow_parse_l4_proto_filter },
>   };
>   
>   #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
> @@ -3541,6 +3554,216 @@ i40e_flow_parse_tunnel_action(struct rte_eth_dev *dev,
>   	return 0;
>   }
>   
> +static int
> +i40e_flow_parse_l4_proto_pattern(const struct rte_flow_item *pattern,
> +				 struct rte_flow_error *error,
> +				 struct i40e_tunnel_filter_conf *filter)
> +{
> +	const struct rte_flow_item_sctp *sctp_spec, *sctp_mask;
> +	const struct rte_flow_item_tcp *tcp_spec, *tcp_mask;
> +	const struct rte_flow_item_udp *udp_spec, *udp_mask;
> +	const struct rte_flow_item *item = pattern;
> +	enum rte_flow_item_type item_type;
> +
> +	for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
> +		if (item->last) {
> +			rte_flow_error_set(error, EINVAL,
> +					   RTE_FLOW_ERROR_TYPE_ITEM,
> +					   item,
> +					   "Not support range");
> +			return -rte_errno;
> +		}


A blank line would help separate the range and type checking.


> +		item_type = item->type;
> +		switch (item_type) {
> +		case RTE_FLOW_ITEM_TYPE_ETH:
> +			if (item->spec || item->mask) {
> +				rte_flow_error_set(error, EINVAL,
> +						   RTE_FLOW_ERROR_TYPE_ITEM,
> +						   item,
> +						   "Invalid ETH item");


This line is no need to be separated from the above line? The same as below.


> +				return -rte_errno;
> +			}
> +
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_IPV4:
> +			filter->ip_type = I40E_TUNNEL_IPTYPE_IPV4;
> +			/* IPv4 is used to describe protocol,
> +			 * spec and mask should be NULL.
> +			 */
> +			if (item->spec || item->mask) {
> +				rte_flow_error_set(error, EINVAL,
> +						   RTE_FLOW_ERROR_TYPE_ITEM,
> +						   item,
> +						   "Invalid IPv4 item");
> +				return -rte_errno;
> +			}
> +
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_IPV6:
> +			filter->ip_type = I40E_TUNNEL_IPTYPE_IPV6;
> +			/* IPv6 is used to describe protocol,
> +			 * spec and mask should be NULL.
> +			 */
> +			if (item->spec || item->mask) {
> +				rte_flow_error_set(error, EINVAL,
> +						   RTE_FLOW_ERROR_TYPE_ITEM,
> +						   item,
> +						   "Invalid IPv6 item");
> +				return -rte_errno;
> +			}
> +
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_UDP:
> +			udp_spec = item->spec;
> +			udp_mask = item->mask;
> +
> +			if (!udp_spec || !udp_mask) {
> +				rte_flow_error_set(error, EINVAL,
> +						   RTE_FLOW_ERROR_TYPE_ITEM,
> +						   item,
> +						   "Invalid udp item");
> +				return -rte_errno;
> +			}
> +
> +			if (udp_spec->hdr.src_port != 0 &&
> +			    udp_spec->hdr.dst_port != 0) {
> +				rte_flow_error_set(error, EINVAL,
> +						RTE_FLOW_ERROR_TYPE_ITEM,
> +						item,
> +						"Invalid udp spec");
> +				return -rte_errno;
> +			}
> +
> +			if (udp_spec->hdr.src_port != 0) {
> +				filter->port_type =
> +					I40E_L4_PORT_TYPE_SRC;
> +				filter->tenant_id =
> +				rte_be_to_cpu_32(udp_spec->hdr.src_port);
> +			}
> +
> +			if (udp_spec->hdr.dst_port != 0) {
> +				filter->port_type =
> +					I40E_L4_PORT_TYPE_DST;
> +				filter->tenant_id =
> +				rte_be_to_cpu_32(udp_spec->hdr.dst_port);
> +			}
> +
> +			filter->tunnel_type = I40E_TUNNEL_TYPE_UDP;
> +
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_TCP:
> +			tcp_spec = item->spec;
> +			tcp_mask = item->mask;
> +
> +			if (!tcp_spec || !tcp_mask) {
> +				rte_flow_error_set(error, EINVAL,
> +						   RTE_FLOW_ERROR_TYPE_ITEM,
> +						   item,
> +						   "Invalid tcp item");
> +				return -rte_errno;
> +			}
> +
> +			if (tcp_spec->hdr.src_port != 0 &&
> +			    tcp_spec->hdr.dst_port != 0) {
> +				rte_flow_error_set(error, EINVAL,
> +						RTE_FLOW_ERROR_TYPE_ITEM,
> +						item,
> +						"Invalid tcp spec");
> +				return -rte_errno;
> +			}
> +
> +			if (tcp_spec->hdr.src_port != 0) {
> +				filter->port_type =
> +					I40E_L4_PORT_TYPE_SRC;
> +				filter->tenant_id =
> +				rte_be_to_cpu_32(tcp_spec->hdr.src_port);
> +			}
> +
> +			if (tcp_spec->hdr.dst_port != 0) {
> +				filter->port_type =
> +					I40E_L4_PORT_TYPE_DST;
> +				filter->tenant_id =
> +				rte_be_to_cpu_32(tcp_spec->hdr.dst_port);
> +			}
> +
> +			filter->tunnel_type = I40E_TUNNEL_TYPE_TCP;
> +
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_SCTP:
> +			sctp_spec = item->spec;
> +			sctp_mask = item->mask;
> +
> +			if (!sctp_spec || !sctp_mask) {
> +				rte_flow_error_set(error, EINVAL,
> +						   RTE_FLOW_ERROR_TYPE_ITEM,
> +						   item,
> +						   "Invalid sctp item");
> +				return -rte_errno;
> +			}
> +
> +			if (sctp_spec->hdr.src_port != 0 &&
> +			    sctp_spec->hdr.dst_port != 0) {
> +				rte_flow_error_set(error, EINVAL,
> +						RTE_FLOW_ERROR_TYPE_ITEM,
> +						item,
> +						"Invalid sctp spec");
> +				return -rte_errno;
> +			}
> +
> +			if (sctp_spec->hdr.src_port != 0) {
> +				filter->port_type =
> +					I40E_L4_PORT_TYPE_SRC;
> +				filter->tenant_id =
> +					rte_be_to_cpu_32(sctp_spec->hdr.src_port);
> +			}
> +
> +			if (sctp_spec->hdr.dst_port != 0) {
> +				filter->port_type =
> +					I40E_L4_PORT_TYPE_DST;
> +				filter->tenant_id =
> +					rte_be_to_cpu_32(sctp_spec->hdr.dst_port);
> +			}
> +
> +			filter->tunnel_type = I40E_TUNNEL_TYPE_SCTP;
> +
> +			break;
> +		default:
> +			break;
> +		}
> +	}
> +


I saw a duplicate process for UDP/TCP/SCTP in switch, do you think it 
need to fine a better way to combine them?


> +	return 0;
> +}
> +
> +static int
> +i40e_flow_parse_l4_proto_filter(struct rte_eth_dev *dev,
> +			   const struct rte_flow_attr *attr,
> +			   const struct rte_flow_item pattern[],
> +			   const struct rte_flow_action actions[],
> +			   struct rte_flow_error *error,
> +			   union i40e_filter_t *filter)
> +{
> +	struct i40e_tunnel_filter_conf *tunnel_filter =
> +		&filter->consistent_tunnel_filter;
> +	int ret;
> +
> +	ret = i40e_flow_parse_l4_proto_pattern(pattern, error, tunnel_filter);
> +	if (ret)
> +		return ret;
> +
> +	ret = i40e_flow_parse_tunnel_action(dev, actions, error, tunnel_filter);
> +	if (ret)
> +		return ret;
> +
> +	ret = i40e_flow_parse_attr(attr, error);
> +	if (ret)
> +		return ret;
> +
> +	cons_filter_type = RTE_ETH_FILTER_TUNNEL;
> +
> +	return ret;
> +}
> +
>   static uint16_t i40e_supported_tunnel_filter_types[] = {
>   	ETH_TUNNEL_FILTER_IMAC | ETH_TUNNEL_FILTER_TENID |
>   	ETH_TUNNEL_FILTER_IVLAN,

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

* Re: [dpdk-dev] [PATCH] net/i40e: enable port filter by switch filter
  2020-06-21 12:28 ` Jeff Guo
@ 2020-06-24  3:09   ` Sun, GuinanX
  0 siblings, 0 replies; 16+ messages in thread
From: Sun, GuinanX @ 2020-06-24  3:09 UTC (permalink / raw)
  To: Guo, Jia, dev; +Cc: Xing, Beilei

Hi Guojia

> -----Original Message-----
> From: Guo, Jia
> Sent: Sunday, June 21, 2020 8:29 PM
> To: Sun, GuinanX <guinanx.sun@intel.com>; dev@dpdk.org
> Cc: Xing, Beilei <beilei.xing@intel.com>
> Subject: Re: [PATCH] net/i40e: enable port filter by switch filter
> 
> hi, guinan
> 
> On 6/11/2020 1:24 PM, Guinan Sun wrote:
> > This patch enables the filter that supports to create following two
> > rules for the same packet type:
> > One is to select source port only as input set and the other is for
> > destination port only.
> >
> > Signed-off-by: Guinan Sun <guinanx.sun@intel.com>
> > ---
> >   doc/guides/rel_notes/release_20_08.rst |   7 +
> >   drivers/net/i40e/i40e_ethdev.c         | 195 ++++++++++++++++++++-
> >   drivers/net/i40e/i40e_ethdev.h         |  17 ++
> >   drivers/net/i40e/i40e_flow.c           | 223 +++++++++++++++++++++++++
> >   4 files changed, 441 insertions(+), 1 deletion(-)
> >
> > diff --git a/doc/guides/rel_notes/release_20_08.rst
> > b/doc/guides/rel_notes/release_20_08.rst
> > index 7a67c960c..16870100d 100644
> > --- a/doc/guides/rel_notes/release_20_08.rst
> > +++ b/doc/guides/rel_notes/release_20_08.rst
> > @@ -68,6 +68,13 @@ New Features
> >
> >     * Added new PMD devarg ``reclaim_mem_mode``.
> >
> > +* **Updated Intel i40e driver.**
> > +
> > +  Updated i40e PMD with new features and improvements, including:
> > +
> > +  * Added a new type of cloud filter to support the coexistence of the
> > +    following two rules. One selects L4 destination as input set and
> > +    the other one selects L4 source port.
> >
> >   Removed Items
> >   -------------
> > diff --git a/drivers/net/i40e/i40e_ethdev.c
> > b/drivers/net/i40e/i40e_ethdev.c index 970a31cb2..97e6e948a 100644
> > --- a/drivers/net/i40e/i40e_ethdev.c
> > +++ b/drivers/net/i40e/i40e_ethdev.c
> > @@ -7956,6 +7956,13 @@ i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
> >   #define I40E_TR_GRE_KEY_MASK			0x400
> >   #define I40E_TR_GRE_KEY_WITH_XSUM_MASK		0x800
> >   #define I40E_TR_GRE_NO_KEY_MASK			0x8000
> > +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_PORT_TR_WORD0 0x49
> #define
> > +I40E_AQC_REPLACE_CLOUD_CMD_INPUT_DIRECTION_WORD0 0x41
> #define
> > +I40E_AQC_REPLACE_CLOUD_CMD_INPUT_INGRESS_WORD0 0x80
> > +#define I40E_DIRECTION_INGRESS_KEY		0x8000
> > +#define I40E_TR_L4_TYPE_TCP			0x2
> > +#define I40E_TR_L4_TYPE_UDP			0x4
> > +#define I40E_TR_L4_TYPE_SCTP			0x8
> >
> >   static enum
> >   i40e_status_code i40e_replace_mpls_l1_filter(struct i40e_pf *pf) @@
> > -8254,6 +8261,131 @@ i40e_status_code
> i40e_replace_gtp_cloud_filter(struct i40e_pf *pf)
> >   	return status;
> >   }
> >
> > +static enum i40e_status_code
> > +i40e_replace_port_l1_filter(struct i40e_pf *pf, enum
> > +i40e_l4_port_type port_type) {
> > +	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
> > +	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
> > +	enum i40e_status_code status = I40E_SUCCESS;
> > +	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
> > +	struct rte_eth_dev *dev = ((struct i40e_adapter
> > +*)hw->back)->eth_dev;
> > +
> 
> 
> The Christmas tree would be look good?
> 
The definition of dev has no way to follow the chrismas tree principle.
> 
> > +	if (pf->support_multi_driver) {
> > +		PMD_DRV_LOG(ERR, "Replace l1 filter is not supported.");
> > +		return I40E_NOT_SUPPORTED;
> > +	}
> > +
> > +	memset(&filter_replace, 0,
> > +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
> > +	memset(&filter_replace_buf, 0,
> > +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
> > +
> > +	/* create L1 filter */
> > +	if (port_type == I40E_L4_PORT_TYPE_SRC) {
> > +		filter_replace.old_filter_type =
> > +
> 	I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TUNNLE_KEY;
> > +		filter_replace.new_filter_type =
> I40E_AQC_ADD_CLOUD_FILTER_0X11;
> > +		filter_replace_buf.data[8] =
> > +
> 	I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_SRC_PORT;
> > +	} else {
> > +		filter_replace.old_filter_type =
> > +
> 	I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG_IVLAN;
> > +		filter_replace.new_filter_type =
> I40E_AQC_ADD_CLOUD_FILTER_0X10;
> > +		filter_replace_buf.data[8] =
> > +
> 	I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_DST_PORT;
> > +	}
> > +
> > +	filter_replace.tr_bit = 0;
> > +	/* Prepare the buffer, 3 entries */
> > +	filter_replace_buf.data[0] =
> > +
> 	I40E_AQC_REPLACE_CLOUD_CMD_INPUT_DIRECTION_WORD0;
> > +	filter_replace_buf.data[0] |=
> > +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> > +	filter_replace_buf.data[2] = 0x00;
> > +	filter_replace_buf.data[3] =
> > +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_INGRESS_WORD0;
> > +	filter_replace_buf.data[4] =
> > +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_PORT_TR_WORD0;
> > +	filter_replace_buf.data[4] |=
> > +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> > +	filter_replace_buf.data[5] = 0x00;
> > +	filter_replace_buf.data[6] = I40E_TR_L4_TYPE_UDP |
> > +		I40E_TR_L4_TYPE_TCP |
> > +		I40E_TR_L4_TYPE_SCTP;
> > +	filter_replace_buf.data[7] = 0x00;
> > +	filter_replace_buf.data[8] |=
> > +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> > +	filter_replace_buf.data[9] = 0x00;
> > +	filter_replace_buf.data[10] = 0xFF;
> > +	filter_replace_buf.data[11] = 0xFF;
> > +
> > +	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
> > +						&filter_replace_buf);
> 
> 
> Please check the alignment here and below.
Patch V2 will fix this problem.
> 
> 
> > +	if (!status && (filter_replace.old_filter_type !=
> > +			filter_replace.new_filter_type))
> > +		PMD_DRV_LOG(WARNING, "i40e device %s changed cloud l1
> type."
> > +			    " original: 0x%x, new: 0x%x",
> > +			    dev->device->name,
> > +			    filter_replace.old_filter_type,
> > +			    filter_replace.new_filter_type);
> > +
> > +	return status;
> > +}
> > +
> > +static enum
> > +i40e_status_code i40e_replace_port_cloud_filter(struct i40e_pf *pf,
> > +						enum i40e_l4_port_type
> port_type)
> 
> 
> Please check the limit of the line characters and below. I think checkpatch could
> help you for that.

Patch V2 will fix this problem.
> 
> 
> > +{
> > +	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
> > +	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
> > +	enum i40e_status_code status = I40E_SUCCESS;
> > +	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
> > +	struct rte_eth_dev *dev = ((struct i40e_adapter *)hw->back)->eth_dev;
> > +
> > +	if (pf->support_multi_driver) {
> > +		PMD_DRV_LOG(ERR, "Replace cloud filter is not supported.");
> > +		return I40E_NOT_SUPPORTED;
> > +	}
> > +
> > +	memset(&filter_replace, 0,
> > +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
> > +	memset(&filter_replace_buf, 0,
> > +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
> > +
> > +	if (port_type == I40E_L4_PORT_TYPE_SRC) {
> > +		filter_replace.old_filter_type =
> I40E_AQC_ADD_CLOUD_FILTER_IIP;
> > +		filter_replace.new_filter_type =
> > +			I40E_AQC_ADD_L1_FILTER_0X11;
> > +		filter_replace_buf.data[4] =
> I40E_AQC_ADD_CLOUD_FILTER_0X11;
> > +	} else {
> > +		filter_replace.old_filter_type =
> I40E_AQC_ADD_CLOUD_FILTER_OIP;
> > +		filter_replace.new_filter_type =
> > +			I40E_AQC_ADD_CLOUD_FILTER_0X10;
> > +		filter_replace_buf.data[4] =
> I40E_AQC_ADD_CLOUD_FILTER_0X10;
> > +	}
> > +
> > +	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER;
> > +	filter_replace.tr_bit = 0;
> > +	/* Prepare the buffer, 2 entries */
> > +	filter_replace_buf.data[0] =
> I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
> > +	filter_replace_buf.data[0] |=
> > +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> > +	filter_replace_buf.data[4] |=
> > +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> > +	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
> > +						&filter_replace_buf);
> > +
> > +	if (!status && (filter_replace.old_filter_type !=
> > +			filter_replace.new_filter_type))
> > +		PMD_DRV_LOG(WARNING, "i40e device %s changed cloud filter
> type."
> > +			    " original: 0x%x, new: 0x%x",
> > +			    dev->device->name,
> > +			    filter_replace.old_filter_type,
> > +			    filter_replace.new_filter_type);
> > +
> > +	return status;
> > +}
> > +
> >   int
> >   i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
> >   		      struct i40e_tunnel_filter_conf *tunnel_filter,
> > @@ -8401,6 +8533,58 @@ i40e_dev_consistent_tunnel_filter_set(struct
> i40e_pf *pf,
> >   		pfilter->general_fields[0] = tunnel_filter->inner_vlan;
> >   		pfilter->general_fields[1] = tunnel_filter->outer_vlan;
> >   		big_buffer = 1;
> > +		break;
> > +	case I40E_TUNNEL_TYPE_UDP:
> > +	case I40E_TUNNEL_TYPE_TCP:
> > +	case I40E_TUNNEL_TYPE_SCTP:
> > +		if (tunnel_filter->port_type == I40E_L4_PORT_TYPE_SRC) {
> > +			if (!pf->sport_replace_flag) {
> > +				i40e_replace_port_l1_filter(pf, tunnel_filter-
> >port_type);
> > +				i40e_replace_port_cloud_filter(pf,
> tunnel_filter->port_type);
> > +				pf->sport_replace_flag = 1;
> > +			}
> > +			teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
> > +			pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
> > +				I40E_DIRECTION_INGRESS_KEY;
> > +
> > +			if (tunnel_filter->tunnel_type ==
> I40E_TUNNEL_TYPE_UDP)
> > +				pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
> > +					I40E_TR_L4_TYPE_UDP;
> > +			else if (tunnel_filter->tunnel_type ==
> I40E_TUNNEL_TYPE_TCP)
> > +				pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
> > +					I40E_TR_L4_TYPE_TCP;
> > +			else
> > +				pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
> > +					I40E_TR_L4_TYPE_SCTP;
> > +
> > +			pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
> > +				(teid_le >> 16) & 0xFFFF;
> > +			big_buffer = 1;
> > +		} else {
> > +			if (!pf->dport_replace_flag) {
> > +				i40e_replace_port_l1_filter(pf, tunnel_filter-
> >port_type);
> > +				i40e_replace_port_cloud_filter(pf,
> tunnel_filter->port_type);
> > +				pf->dport_replace_flag = 1;
> > +			}
> > +			teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
> > +			pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD0] =
> > +				I40E_DIRECTION_INGRESS_KEY;
> > +
> > +			if (tunnel_filter->tunnel_type ==
> I40E_TUNNEL_TYPE_UDP)
> > +				pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
> > +					I40E_TR_L4_TYPE_UDP;
> > +			else if (tunnel_filter->tunnel_type ==
> I40E_TUNNEL_TYPE_TCP)
> > +				pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
> > +					I40E_TR_L4_TYPE_TCP;
> > +			else
> > +				pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
> > +					I40E_TR_L4_TYPE_SCTP;
> > +
> > +			pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD2] =
> > +				(teid_le >> 16) & 0xFFFF;
> > +			big_buffer = 1;
> > +		}
> > +
> >   		break;
> >   	default:
> >   		/* Other tunnel types is not supported. */
> > @@ -8424,7 +8608,16 @@ i40e_dev_consistent_tunnel_filter_set(struct
> i40e_pf *pf,
> >   	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_QINQ)
> >   		pfilter->element.flags |=
> >   			I40E_AQC_ADD_CLOUD_FILTER_0X10;
> > -	else {
> > +	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_UDP ||
> > +		tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_TCP ||
> > +		tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_SCTP) {
> > +		if (tunnel_filter->port_type == I40E_L4_PORT_TYPE_SRC)
> > +			pfilter->element.flags |=
> > +				I40E_AQC_ADD_L1_FILTER_0X11;
> > +		else
> > +			pfilter->element.flags |=
> > +				I40E_AQC_ADD_CLOUD_FILTER_0X10;
> > +	} else {
> >   		val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
> >   						&pfilter->element.flags);
> >   		if (val < 0) {
> > diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
> > index e5d0ce53f..b79ab5880 100644
> > --- a/drivers/net/i40e/i40e_ethdev.h
> > +++ b/drivers/net/i40e/i40e_ethdev.h
> > @@ -767,6 +767,8 @@ struct i40e_rss_pattern_info {
> >
> >   #define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD0 44
> >   #define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD1 45
> > +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_SRC_PORT 29
> > +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_DST_PORT 30
> >   #define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSOUDP	8
> >   #define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSOGRE	9
> >   #define I40E_AQC_ADD_CLOUD_FILTER_0X10		0x10
> > @@ -828,9 +830,20 @@ enum i40e_tunnel_type {
> >   	I40E_TUNNEL_TYPE_GTPU,
> >   	I40E_TUNNEL_TYPE_ESPoUDP,
> >   	I40E_TUNNEL_TYPE_ESPoIP,
> > +	I40E_TUNNEL_TYPE_UDP,
> > +	I40E_TUNNEL_TYPE_TCP,
> > +	I40E_TUNNEL_TYPE_SCTP,
> >   	I40E_TUNNEL_TYPE_MAX,
> >   };
> >
> > +/**
> > + * Port type.
> > + */
> > +enum i40e_l4_port_type {
> > +	I40E_L4_PORT_TYPE_SRC = 0,
> > +	I40E_L4_PORT_TYPE_DST,
> > +};
> > +
> >   /**
> >    * Tunneling Packet filter configuration.
> >    */
> > @@ -852,6 +865,7 @@ struct i40e_tunnel_filter_conf {
> >   	/** Flags from ETH_TUNNEL_FILTER_XX - see above. */
> >   	uint16_t filter_type;
> >   	enum i40e_tunnel_type tunnel_type; /**< Tunnel Type. */
> > +	enum i40e_l4_port_type port_type; /**< L4 Port Type. */
> 
> 
> L4_port_type would be better?

Patch V2 will fix this problem.
> 
> 
> >   	uint32_t tenant_id;     /**< Tenant ID to match. VNI, GRE key... */
> >   	uint16_t queue_id;      /**< Queue assigned to if match. */
> >   	uint8_t is_to_vf;       /**< 0 - to PF, 1 - to VF */
> > @@ -1073,6 +1087,9 @@ struct i40e_pf {
> >   	bool mpls_replace_flag;  /* 1 - MPLS filter replace is done */
> >   	bool gtp_replace_flag;   /* 1 - GTP-C/U filter replace is done */
> >   	bool qinq_replace_flag;  /* QINQ filter replace is done */
> > +	/* l4 port flag */
> > +	bool sport_replace_flag;   /* source port replace is done */
> > +	bool dport_replace_flag;   /* dest port replace is done */
> >   	struct i40e_tm_conf tm_conf;
> >   	bool support_multi_driver; /* 1 - support multiple driver */
> >
> > diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
> > index 8f8df6fae..a268ff3d2 100644
> > --- a/drivers/net/i40e/i40e_flow.c
> > +++ b/drivers/net/i40e/i40e_flow.c
> > @@ -124,6 +124,12 @@ i40e_flow_parse_qinq_pattern(struct rte_eth_dev
> *dev,
> >   			      struct rte_flow_error *error,
> >   			      struct i40e_tunnel_filter_conf *filter);
> >
> > +static int i40e_flow_parse_l4_proto_filter(struct rte_eth_dev *dev,
> > +				      const struct rte_flow_attr *attr,
> > +				      const struct rte_flow_item pattern[],
> > +				      const struct rte_flow_action actions[],
> > +				      struct rte_flow_error *error,
> > +				      union i40e_filter_t *filter);
> >   const struct rte_flow_ops i40e_flow_ops = {
> >   	.validate = i40e_flow_validate,
> >   	.create = i40e_flow_create,
> > @@ -1845,6 +1851,13 @@ static struct i40e_valid_pattern
> i40e_supported_patterns[] = {
> >   	/* L2TPv3 over IP */
> >   	{ pattern_fdir_ipv4_l2tpv3oip, i40e_flow_parse_fdir_filter },
> >   	{ pattern_fdir_ipv6_l2tpv3oip, i40e_flow_parse_fdir_filter },
> > +	/* L4 over port */
> > +	{ pattern_fdir_ipv4_udp, i40e_flow_parse_l4_proto_filter },
> > +	{ pattern_fdir_ipv4_tcp, i40e_flow_parse_l4_proto_filter },
> > +	{ pattern_fdir_ipv4_sctp, i40e_flow_parse_l4_proto_filter },
> > +	{ pattern_fdir_ipv6_udp, i40e_flow_parse_l4_proto_filter },
> > +	{ pattern_fdir_ipv6_tcp, i40e_flow_parse_l4_proto_filter },
> > +	{ pattern_fdir_ipv6_sctp, i40e_flow_parse_l4_proto_filter },
> >   };
> >
> >   #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
> > @@ -3541,6 +3554,216 @@ i40e_flow_parse_tunnel_action(struct
> rte_eth_dev *dev,
> >   	return 0;
> >   }
> >
> > +static int
> > +i40e_flow_parse_l4_proto_pattern(const struct rte_flow_item *pattern,
> > +				 struct rte_flow_error *error,
> > +				 struct i40e_tunnel_filter_conf *filter)
> > +{
> > +	const struct rte_flow_item_sctp *sctp_spec, *sctp_mask;
> > +	const struct rte_flow_item_tcp *tcp_spec, *tcp_mask;
> > +	const struct rte_flow_item_udp *udp_spec, *udp_mask;
> > +	const struct rte_flow_item *item = pattern;
> > +	enum rte_flow_item_type item_type;
> > +
> > +	for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
> > +		if (item->last) {
> > +			rte_flow_error_set(error, EINVAL,
> > +					   RTE_FLOW_ERROR_TYPE_ITEM,
> > +					   item,
> > +					   "Not support range");
> > +			return -rte_errno;
> > +		}
> 
> 
> A blank line would help separate the range and type checking.

Patch V2 will fix this problem.
> 
> 
> > +		item_type = item->type;
> > +		switch (item_type) {
> > +		case RTE_FLOW_ITEM_TYPE_ETH:
> > +			if (item->spec || item->mask) {
> > +				rte_flow_error_set(error, EINVAL,
> > +
> RTE_FLOW_ERROR_TYPE_ITEM,
> > +						   item,
> > +						   "Invalid ETH item");
> 
> 
> This line is no need to be separated from the above line? The same as below.

Patch V2 will fix this problem.
> 
> 
> > +				return -rte_errno;
> > +			}
> > +
> > +			break;
> > +		case RTE_FLOW_ITEM_TYPE_IPV4:
> > +			filter->ip_type = I40E_TUNNEL_IPTYPE_IPV4;
> > +			/* IPv4 is used to describe protocol,
> > +			 * spec and mask should be NULL.
> > +			 */
> > +			if (item->spec || item->mask) {
> > +				rte_flow_error_set(error, EINVAL,
> > +
> RTE_FLOW_ERROR_TYPE_ITEM,
> > +						   item,
> > +						   "Invalid IPv4 item");
> > +				return -rte_errno;
> > +			}
> > +
> > +			break;
> > +		case RTE_FLOW_ITEM_TYPE_IPV6:
> > +			filter->ip_type = I40E_TUNNEL_IPTYPE_IPV6;
> > +			/* IPv6 is used to describe protocol,
> > +			 * spec and mask should be NULL.
> > +			 */
> > +			if (item->spec || item->mask) {
> > +				rte_flow_error_set(error, EINVAL,
> > +
> RTE_FLOW_ERROR_TYPE_ITEM,
> > +						   item,
> > +						   "Invalid IPv6 item");
> > +				return -rte_errno;
> > +			}
> > +
> > +			break;
> > +		case RTE_FLOW_ITEM_TYPE_UDP:
> > +			udp_spec = item->spec;
> > +			udp_mask = item->mask;
> > +
> > +			if (!udp_spec || !udp_mask) {
> > +				rte_flow_error_set(error, EINVAL,
> > +
> RTE_FLOW_ERROR_TYPE_ITEM,
> > +						   item,
> > +						   "Invalid udp item");
> > +				return -rte_errno;
> > +			}
> > +
> > +			if (udp_spec->hdr.src_port != 0 &&
> > +			    udp_spec->hdr.dst_port != 0) {
> > +				rte_flow_error_set(error, EINVAL,
> > +
> 	RTE_FLOW_ERROR_TYPE_ITEM,
> > +						item,
> > +						"Invalid udp spec");
> > +				return -rte_errno;
> > +			}
> > +
> > +			if (udp_spec->hdr.src_port != 0) {
> > +				filter->port_type =
> > +					I40E_L4_PORT_TYPE_SRC;
> > +				filter->tenant_id =
> > +				rte_be_to_cpu_32(udp_spec->hdr.src_port);
> > +			}
> > +
> > +			if (udp_spec->hdr.dst_port != 0) {
> > +				filter->port_type =
> > +					I40E_L4_PORT_TYPE_DST;
> > +				filter->tenant_id =
> > +				rte_be_to_cpu_32(udp_spec->hdr.dst_port);
> > +			}
> > +
> > +			filter->tunnel_type = I40E_TUNNEL_TYPE_UDP;
> > +
> > +			break;
> > +		case RTE_FLOW_ITEM_TYPE_TCP:
> > +			tcp_spec = item->spec;
> > +			tcp_mask = item->mask;
> > +
> > +			if (!tcp_spec || !tcp_mask) {
> > +				rte_flow_error_set(error, EINVAL,
> > +
> RTE_FLOW_ERROR_TYPE_ITEM,
> > +						   item,
> > +						   "Invalid tcp item");
> > +				return -rte_errno;
> > +			}
> > +
> > +			if (tcp_spec->hdr.src_port != 0 &&
> > +			    tcp_spec->hdr.dst_port != 0) {
> > +				rte_flow_error_set(error, EINVAL,
> > +
> 	RTE_FLOW_ERROR_TYPE_ITEM,
> > +						item,
> > +						"Invalid tcp spec");
> > +				return -rte_errno;
> > +			}
> > +
> > +			if (tcp_spec->hdr.src_port != 0) {
> > +				filter->port_type =
> > +					I40E_L4_PORT_TYPE_SRC;
> > +				filter->tenant_id =
> > +				rte_be_to_cpu_32(tcp_spec->hdr.src_port);
> > +			}
> > +
> > +			if (tcp_spec->hdr.dst_port != 0) {
> > +				filter->port_type =
> > +					I40E_L4_PORT_TYPE_DST;
> > +				filter->tenant_id =
> > +				rte_be_to_cpu_32(tcp_spec->hdr.dst_port);
> > +			}
> > +
> > +			filter->tunnel_type = I40E_TUNNEL_TYPE_TCP;
> > +
> > +			break;
> > +		case RTE_FLOW_ITEM_TYPE_SCTP:
> > +			sctp_spec = item->spec;
> > +			sctp_mask = item->mask;
> > +
> > +			if (!sctp_spec || !sctp_mask) {
> > +				rte_flow_error_set(error, EINVAL,
> > +
> RTE_FLOW_ERROR_TYPE_ITEM,
> > +						   item,
> > +						   "Invalid sctp item");
> > +				return -rte_errno;
> > +			}
> > +
> > +			if (sctp_spec->hdr.src_port != 0 &&
> > +			    sctp_spec->hdr.dst_port != 0) {
> > +				rte_flow_error_set(error, EINVAL,
> > +
> 	RTE_FLOW_ERROR_TYPE_ITEM,
> > +						item,
> > +						"Invalid sctp spec");
> > +				return -rte_errno;
> > +			}
> > +
> > +			if (sctp_spec->hdr.src_port != 0) {
> > +				filter->port_type =
> > +					I40E_L4_PORT_TYPE_SRC;
> > +				filter->tenant_id =
> > +					rte_be_to_cpu_32(sctp_spec-
> >hdr.src_port);
> > +			}
> > +
> > +			if (sctp_spec->hdr.dst_port != 0) {
> > +				filter->port_type =
> > +					I40E_L4_PORT_TYPE_DST;
> > +				filter->tenant_id =
> > +					rte_be_to_cpu_32(sctp_spec-
> >hdr.dst_port);
> > +			}
> > +
> > +			filter->tunnel_type = I40E_TUNNEL_TYPE_SCTP;
> > +
> > +			break;
> > +		default:
> > +			break;
> > +		}
> > +	}
> > +
> 
> 
> I saw a duplicate process for UDP/TCP/SCTP in switch, do you think it
> need to fine a better way to combine them?

The assignment of item is different, so there is no way to combine them.
> 
> 
> > +	return 0;
> > +}
> > +
> > +static int
> > +i40e_flow_parse_l4_proto_filter(struct rte_eth_dev *dev,
> > +			   const struct rte_flow_attr *attr,
> > +			   const struct rte_flow_item pattern[],
> > +			   const struct rte_flow_action actions[],
> > +			   struct rte_flow_error *error,
> > +			   union i40e_filter_t *filter)
> > +{
> > +	struct i40e_tunnel_filter_conf *tunnel_filter =
> > +		&filter->consistent_tunnel_filter;
> > +	int ret;
> > +
> > +	ret = i40e_flow_parse_l4_proto_pattern(pattern, error, tunnel_filter);
> > +	if (ret)
> > +		return ret;
> > +
> > +	ret = i40e_flow_parse_tunnel_action(dev, actions, error, tunnel_filter);
> > +	if (ret)
> > +		return ret;
> > +
> > +	ret = i40e_flow_parse_attr(attr, error);
> > +	if (ret)
> > +		return ret;
> > +
> > +	cons_filter_type = RTE_ETH_FILTER_TUNNEL;
> > +
> > +	return ret;
> > +}
> > +
> >   static uint16_t i40e_supported_tunnel_filter_types[] = {
> >   	ETH_TUNNEL_FILTER_IMAC | ETH_TUNNEL_FILTER_TENID |
> >   	ETH_TUNNEL_FILTER_IVLAN,

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

* [dpdk-dev] [PATCH v2] net/i40e: enable port filter by switch filter
  2020-06-11  5:24 [dpdk-dev] [PATCH] net/i40e: enable port filter by switch filter Guinan Sun
  2020-06-15  6:12 ` Zhao1, Wei
  2020-06-21 12:28 ` Jeff Guo
@ 2020-06-30  4:42 ` Guinan Sun
  2020-06-30  6:15   ` Xing, Beilei
  2020-07-07  6:33 ` [dpdk-dev] [PATCH v3] net/i40e: support cloud filter with L4 port Guinan Sun
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 16+ messages in thread
From: Guinan Sun @ 2020-06-30  4:42 UTC (permalink / raw)
  To: dev; +Cc: Beilei Xing, Jia Guo, Guinan Sun

This patch enables the filter that supports
to create following two rules for the same packet type:
One is to select source port only as input set and the
other is for destination port only.

Signed-off-by: Guinan Sun <guinanx.sun@intel.com>
---
v2:
* Fixed code style and variable naming
---
 doc/guides/rel_notes/release_20_08.rst |   8 +
 drivers/net/i40e/i40e_ethdev.c         | 195 ++++++++++++++++++++-
 drivers/net/i40e/i40e_ethdev.h         |  17 ++
 drivers/net/i40e/i40e_flow.c           | 223 +++++++++++++++++++++++++
 4 files changed, 442 insertions(+), 1 deletion(-)

diff --git a/doc/guides/rel_notes/release_20_08.rst b/doc/guides/rel_notes/release_20_08.rst
index 3c40424cc..c4d094eac 100644
--- a/doc/guides/rel_notes/release_20_08.rst
+++ b/doc/guides/rel_notes/release_20_08.rst
@@ -87,6 +87,14 @@ New Features
 
   * Added support for DCF datapath configuration.
 
+* **Updated Intel i40e driver.**
+
+  Updated i40e PMD with new features and improvements, including:
+
+  * Added a new type of cloud filter to support the coexistence of the
+    following two rules. One selects L4 destination as input set and
+    the other one selects L4 source port.
+
 Removed Items
 -------------
 
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 970a31cb2..cea7f6b59 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -7956,6 +7956,13 @@ i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
 #define I40E_TR_GRE_KEY_MASK			0x400
 #define I40E_TR_GRE_KEY_WITH_XSUM_MASK		0x800
 #define I40E_TR_GRE_NO_KEY_MASK			0x8000
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_PORT_TR_WORD0 0x49
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_DIRECTION_WORD0 0x41
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_INGRESS_WORD0 0x80
+#define I40E_DIRECTION_INGRESS_KEY		0x8000
+#define I40E_TR_L4_TYPE_TCP			0x2
+#define I40E_TR_L4_TYPE_UDP			0x4
+#define I40E_TR_L4_TYPE_SCTP			0x8
 
 static enum
 i40e_status_code i40e_replace_mpls_l1_filter(struct i40e_pf *pf)
@@ -8254,6 +8261,131 @@ i40e_status_code i40e_replace_gtp_cloud_filter(struct i40e_pf *pf)
 	return status;
 }
 
+static enum i40e_status_code
+i40e_replace_port_l1_filter(struct i40e_pf *pf, enum i40e_l4_port_type l4_port_type)
+{
+	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
+	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
+	enum i40e_status_code status = I40E_SUCCESS;
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	struct rte_eth_dev *dev = ((struct i40e_adapter *)hw->back)->eth_dev;
+
+	if (pf->support_multi_driver) {
+		PMD_DRV_LOG(ERR, "Replace l1 filter is not supported.");
+		return I40E_NOT_SUPPORTED;
+	}
+
+	memset(&filter_replace, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+	memset(&filter_replace_buf, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+
+	/* create L1 filter */
+	if (l4_port_type == I40E_L4_PORT_TYPE_SRC) {
+		filter_replace.old_filter_type =
+			I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TUNNLE_KEY;
+		filter_replace.new_filter_type = I40E_AQC_ADD_CLOUD_FILTER_0X11;
+		filter_replace_buf.data[8] =
+			I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_SRC_PORT;
+	} else {
+		filter_replace.old_filter_type =
+			I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG_IVLAN;
+		filter_replace.new_filter_type = I40E_AQC_ADD_CLOUD_FILTER_0X10;
+		filter_replace_buf.data[8] =
+			I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_DST_PORT;
+	}
+
+	filter_replace.tr_bit = 0;
+	/* Prepare the buffer, 3 entries */
+	filter_replace_buf.data[0] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_DIRECTION_WORD0;
+	filter_replace_buf.data[0] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[2] = 0x00;
+	filter_replace_buf.data[3] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_INGRESS_WORD0;
+	filter_replace_buf.data[4] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_PORT_TR_WORD0;
+	filter_replace_buf.data[4] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[5] = 0x00;
+	filter_replace_buf.data[6] = I40E_TR_L4_TYPE_UDP |
+		I40E_TR_L4_TYPE_TCP |
+		I40E_TR_L4_TYPE_SCTP;
+	filter_replace_buf.data[7] = 0x00;
+	filter_replace_buf.data[8] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[9] = 0x00;
+	filter_replace_buf.data[10] = 0xFF;
+	filter_replace_buf.data[11] = 0xFF;
+
+	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+					       &filter_replace_buf);
+	if (!status && (filter_replace.old_filter_type !=
+		filter_replace.new_filter_type))
+		PMD_DRV_LOG(WARNING, "i40e device %s changed cloud l1 type."
+			    " original: 0x%x, new: 0x%x",
+			    dev->device->name,
+			    filter_replace.old_filter_type,
+			    filter_replace.new_filter_type);
+
+	return status;
+}
+
+static enum
+i40e_status_code i40e_replace_port_cloud_filter(struct i40e_pf *pf,
+					enum i40e_l4_port_type l4_port_type)
+{
+	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
+	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
+	enum i40e_status_code status = I40E_SUCCESS;
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	struct rte_eth_dev *dev = ((struct i40e_adapter *)hw->back)->eth_dev;
+
+	if (pf->support_multi_driver) {
+		PMD_DRV_LOG(ERR, "Replace cloud filter is not supported.");
+		return I40E_NOT_SUPPORTED;
+	}
+
+	memset(&filter_replace, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+	memset(&filter_replace_buf, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+
+	if (l4_port_type == I40E_L4_PORT_TYPE_SRC) {
+		filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_IIP;
+		filter_replace.new_filter_type =
+			I40E_AQC_ADD_L1_FILTER_0X11;
+		filter_replace_buf.data[4] = I40E_AQC_ADD_CLOUD_FILTER_0X11;
+	} else {
+		filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_OIP;
+		filter_replace.new_filter_type =
+			I40E_AQC_ADD_CLOUD_FILTER_0X10;
+		filter_replace_buf.data[4] = I40E_AQC_ADD_CLOUD_FILTER_0X10;
+	}
+
+	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER;
+	filter_replace.tr_bit = 0;
+	/* Prepare the buffer, 2 entries */
+	filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
+	filter_replace_buf.data[0] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[4] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+					       &filter_replace_buf);
+
+	if (!status && (filter_replace.old_filter_type !=
+			filter_replace.new_filter_type))
+		PMD_DRV_LOG(WARNING, "i40e device %s changed cloud filter type."
+			    " original: 0x%x, new: 0x%x",
+			    dev->device->name,
+			    filter_replace.old_filter_type,
+			    filter_replace.new_filter_type);
+
+	return status;
+}
+
 int
 i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		      struct i40e_tunnel_filter_conf *tunnel_filter,
@@ -8401,6 +8533,58 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		pfilter->general_fields[0] = tunnel_filter->inner_vlan;
 		pfilter->general_fields[1] = tunnel_filter->outer_vlan;
 		big_buffer = 1;
+		break;
+	case I40E_TUNNEL_TYPE_UDP:
+	case I40E_TUNNEL_TYPE_TCP:
+	case I40E_TUNNEL_TYPE_SCTP:
+		if (tunnel_filter->l4_port_type == I40E_L4_PORT_TYPE_SRC) {
+			if (!pf->sport_replace_flag) {
+				i40e_replace_port_l1_filter(pf, tunnel_filter->l4_port_type);
+				i40e_replace_port_cloud_filter(pf, tunnel_filter->l4_port_type);
+				pf->sport_replace_flag = 1;
+			}
+			teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
+			pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
+				I40E_DIRECTION_INGRESS_KEY;
+
+			if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_UDP)
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+					I40E_TR_L4_TYPE_UDP;
+			else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_TCP)
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+					I40E_TR_L4_TYPE_TCP;
+			else
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+					I40E_TR_L4_TYPE_SCTP;
+
+			pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
+				(teid_le >> 16) & 0xFFFF;
+			big_buffer = 1;
+		} else {
+			if (!pf->dport_replace_flag) {
+				i40e_replace_port_l1_filter(pf, tunnel_filter->l4_port_type);
+				i40e_replace_port_cloud_filter(pf, tunnel_filter->l4_port_type);
+				pf->dport_replace_flag = 1;
+			}
+			teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
+			pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD0] =
+				I40E_DIRECTION_INGRESS_KEY;
+
+			if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_UDP)
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
+					I40E_TR_L4_TYPE_UDP;
+			else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_TCP)
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
+					I40E_TR_L4_TYPE_TCP;
+			else
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
+					I40E_TR_L4_TYPE_SCTP;
+
+			pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD2] =
+				(teid_le >> 16) & 0xFFFF;
+			big_buffer = 1;
+		}
+
 		break;
 	default:
 		/* Other tunnel types is not supported. */
@@ -8424,7 +8608,16 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_QINQ)
 		pfilter->element.flags |=
 			I40E_AQC_ADD_CLOUD_FILTER_0X10;
-	else {
+	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_UDP ||
+		 tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_TCP ||
+		 tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_SCTP) {
+		if (tunnel_filter->l4_port_type == I40E_L4_PORT_TYPE_SRC)
+			pfilter->element.flags |=
+				I40E_AQC_ADD_L1_FILTER_0X11;
+		else
+			pfilter->element.flags |=
+				I40E_AQC_ADD_CLOUD_FILTER_0X10;
+	} else {
 		val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
 						&pfilter->element.flags);
 		if (val < 0) {
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index e5d0ce53f..56955068b 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -767,6 +767,8 @@ struct i40e_rss_pattern_info {
 
 #define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD0 44
 #define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD1 45
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_SRC_PORT 29
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_DST_PORT 30
 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSOUDP	8
 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSOGRE	9
 #define I40E_AQC_ADD_CLOUD_FILTER_0X10		0x10
@@ -828,9 +830,20 @@ enum i40e_tunnel_type {
 	I40E_TUNNEL_TYPE_GTPU,
 	I40E_TUNNEL_TYPE_ESPoUDP,
 	I40E_TUNNEL_TYPE_ESPoIP,
+	I40E_TUNNEL_TYPE_UDP,
+	I40E_TUNNEL_TYPE_TCP,
+	I40E_TUNNEL_TYPE_SCTP,
 	I40E_TUNNEL_TYPE_MAX,
 };
 
+/**
+ * L4 port type.
+ */
+enum i40e_l4_port_type {
+	I40E_L4_PORT_TYPE_SRC = 0,
+	I40E_L4_PORT_TYPE_DST,
+};
+
 /**
  * Tunneling Packet filter configuration.
  */
@@ -852,6 +865,7 @@ struct i40e_tunnel_filter_conf {
 	/** Flags from ETH_TUNNEL_FILTER_XX - see above. */
 	uint16_t filter_type;
 	enum i40e_tunnel_type tunnel_type; /**< Tunnel Type. */
+	enum i40e_l4_port_type l4_port_type; /**< L4 Port Type. */
 	uint32_t tenant_id;     /**< Tenant ID to match. VNI, GRE key... */
 	uint16_t queue_id;      /**< Queue assigned to if match. */
 	uint8_t is_to_vf;       /**< 0 - to PF, 1 - to VF */
@@ -1073,6 +1087,9 @@ struct i40e_pf {
 	bool mpls_replace_flag;  /* 1 - MPLS filter replace is done */
 	bool gtp_replace_flag;   /* 1 - GTP-C/U filter replace is done */
 	bool qinq_replace_flag;  /* QINQ filter replace is done */
+	/* l4 port flag */
+	bool sport_replace_flag;   /* source port replace is done */
+	bool dport_replace_flag;   /* dest port replace is done */
 	struct i40e_tm_conf tm_conf;
 	bool support_multi_driver; /* 1 - support multiple driver */
 
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 8f8df6fae..ba42b30db 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -124,6 +124,12 @@ i40e_flow_parse_qinq_pattern(struct rte_eth_dev *dev,
 			      struct rte_flow_error *error,
 			      struct i40e_tunnel_filter_conf *filter);
 
+static int i40e_flow_parse_l4_proto_filter(struct rte_eth_dev *dev,
+					   const struct rte_flow_attr *attr,
+					   const struct rte_flow_item pattern[],
+					   const struct rte_flow_action actions[],
+					   struct rte_flow_error *error,
+					   union i40e_filter_t *filter);
 const struct rte_flow_ops i40e_flow_ops = {
 	.validate = i40e_flow_validate,
 	.create = i40e_flow_create,
@@ -1845,6 +1851,13 @@ static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	/* L2TPv3 over IP */
 	{ pattern_fdir_ipv4_l2tpv3oip, i40e_flow_parse_fdir_filter },
 	{ pattern_fdir_ipv6_l2tpv3oip, i40e_flow_parse_fdir_filter },
+	/* L4 over port */
+	{ pattern_fdir_ipv4_udp, i40e_flow_parse_l4_proto_filter },
+	{ pattern_fdir_ipv4_tcp, i40e_flow_parse_l4_proto_filter },
+	{ pattern_fdir_ipv4_sctp, i40e_flow_parse_l4_proto_filter },
+	{ pattern_fdir_ipv6_udp, i40e_flow_parse_l4_proto_filter },
+	{ pattern_fdir_ipv6_tcp, i40e_flow_parse_l4_proto_filter },
+	{ pattern_fdir_ipv6_sctp, i40e_flow_parse_l4_proto_filter },
 };
 
 #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
@@ -3541,6 +3554,216 @@ i40e_flow_parse_tunnel_action(struct rte_eth_dev *dev,
 	return 0;
 }
 
+static int
+i40e_flow_parse_l4_proto_pattern(const struct rte_flow_item *pattern,
+				 struct rte_flow_error *error,
+				 struct i40e_tunnel_filter_conf *filter)
+{
+	const struct rte_flow_item_sctp *sctp_spec, *sctp_mask;
+	const struct rte_flow_item_tcp *tcp_spec, *tcp_mask;
+	const struct rte_flow_item_udp *udp_spec, *udp_mask;
+	const struct rte_flow_item *item = pattern;
+	enum rte_flow_item_type item_type;
+
+	for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+		if (item->last) {
+			rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM,
+					   item,
+					   "Not support range");
+			return -rte_errno;
+		}
+		item_type = item->type;
+		switch (item_type) {
+		case RTE_FLOW_ITEM_TYPE_ETH:
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid ETH item");
+				return -rte_errno;
+			}
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV4:
+			filter->ip_type = I40E_TUNNEL_IPTYPE_IPV4;
+			/* IPv4 is used to describe protocol,
+			 * spec and mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid IPv4 item");
+				return -rte_errno;
+			}
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV6:
+			filter->ip_type = I40E_TUNNEL_IPTYPE_IPV6;
+			/* IPv6 is used to describe protocol,
+			 * spec and mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid IPv6 item");
+				return -rte_errno;
+			}
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_UDP:
+			udp_spec = item->spec;
+			udp_mask = item->mask;
+
+			if (!udp_spec || !udp_mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid udp item");
+				return -rte_errno;
+			}
+
+			if (udp_spec->hdr.src_port != 0 &&
+			    udp_spec->hdr.dst_port != 0) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid udp spec");
+				return -rte_errno;
+			}
+
+			if (udp_spec->hdr.src_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_SRC;
+				filter->tenant_id =
+				rte_be_to_cpu_32(udp_spec->hdr.src_port);
+			}
+
+			if (udp_spec->hdr.dst_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_DST;
+				filter->tenant_id =
+				rte_be_to_cpu_32(udp_spec->hdr.dst_port);
+			}
+
+			filter->tunnel_type = I40E_TUNNEL_TYPE_UDP;
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_TCP:
+			tcp_spec = item->spec;
+			tcp_mask = item->mask;
+
+			if (!tcp_spec || !tcp_mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid tcp item");
+				return -rte_errno;
+			}
+
+			if (tcp_spec->hdr.src_port != 0 &&
+			    tcp_spec->hdr.dst_port != 0) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid tcp spec");
+				return -rte_errno;
+			}
+
+			if (tcp_spec->hdr.src_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_SRC;
+				filter->tenant_id =
+				rte_be_to_cpu_32(tcp_spec->hdr.src_port);
+			}
+
+			if (tcp_spec->hdr.dst_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_DST;
+				filter->tenant_id =
+				rte_be_to_cpu_32(tcp_spec->hdr.dst_port);
+			}
+
+			filter->tunnel_type = I40E_TUNNEL_TYPE_TCP;
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_SCTP:
+			sctp_spec = item->spec;
+			sctp_mask = item->mask;
+
+			if (!sctp_spec || !sctp_mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid sctp item");
+				return -rte_errno;
+			}
+
+			if (sctp_spec->hdr.src_port != 0 &&
+			    sctp_spec->hdr.dst_port != 0) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid sctp spec");
+				return -rte_errno;
+			}
+
+			if (sctp_spec->hdr.src_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_SRC;
+				filter->tenant_id =
+					rte_be_to_cpu_32(sctp_spec->hdr.src_port);
+			}
+
+			if (sctp_spec->hdr.dst_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_DST;
+				filter->tenant_id =
+					rte_be_to_cpu_32(sctp_spec->hdr.dst_port);
+			}
+
+			filter->tunnel_type = I40E_TUNNEL_TYPE_SCTP;
+
+			break;
+		default:
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static int
+i40e_flow_parse_l4_proto_filter(struct rte_eth_dev *dev,
+				const struct rte_flow_attr *attr,
+				const struct rte_flow_item pattern[],
+				const struct rte_flow_action actions[],
+				struct rte_flow_error *error,
+				union i40e_filter_t *filter)
+{
+	struct i40e_tunnel_filter_conf *tunnel_filter =
+		&filter->consistent_tunnel_filter;
+	int ret;
+
+	ret = i40e_flow_parse_l4_proto_pattern(pattern, error, tunnel_filter);
+	if (ret)
+		return ret;
+
+	ret = i40e_flow_parse_tunnel_action(dev, actions, error, tunnel_filter);
+	if (ret)
+		return ret;
+
+	ret = i40e_flow_parse_attr(attr, error);
+	if (ret)
+		return ret;
+
+	cons_filter_type = RTE_ETH_FILTER_TUNNEL;
+
+	return ret;
+}
+
 static uint16_t i40e_supported_tunnel_filter_types[] = {
 	ETH_TUNNEL_FILTER_IMAC | ETH_TUNNEL_FILTER_TENID |
 	ETH_TUNNEL_FILTER_IVLAN,
-- 
2.17.1


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

* Re: [dpdk-dev] [PATCH v2] net/i40e: enable port filter by switch filter
  2020-06-30  4:42 ` [dpdk-dev] [PATCH v2] " Guinan Sun
@ 2020-06-30  6:15   ` Xing, Beilei
  2020-07-07  6:11     ` Sun, GuinanX
  0 siblings, 1 reply; 16+ messages in thread
From: Xing, Beilei @ 2020-06-30  6:15 UTC (permalink / raw)
  To: Sun, GuinanX, dev; +Cc: Guo, Jia



> -----Original Message-----
> From: Sun, GuinanX <guinanx.sun@intel.com>
> Sent: Tuesday, June 30, 2020 12:42 PM
> To: dev@dpdk.org
> Cc: Xing, Beilei <beilei.xing@intel.com>; Guo, Jia <jia.guo@intel.com>; Sun,
> GuinanX <guinanx.sun@intel.com>
> Subject: [PATCH v2] net/i40e: enable port filter by switch filter

How about 'support cloud filter with l4 port'?

Please also fix all the warnings in patchwork: http://mails.dpdk.org/archives/test-report/2020-June/139555.html.

> 
> This patch enables the filter that supports to create following two rules for
> the same packet type:

Better to clarify which packet types will be supported.

> One is to select source port only as input set and the other is for destination
> port only.
> 
> Signed-off-by: Guinan Sun <guinanx.sun@intel.com>
> ---
> v2:
> * Fixed code style and variable naming
> ---
>  doc/guides/rel_notes/release_20_08.rst |   8 +
>  drivers/net/i40e/i40e_ethdev.c         | 195 ++++++++++++++++++++-
>  drivers/net/i40e/i40e_ethdev.h         |  17 ++
>  drivers/net/i40e/i40e_flow.c           | 223 +++++++++++++++++++++++++
>  4 files changed, 442 insertions(+), 1 deletion(-)
> 
> diff --git a/doc/guides/rel_notes/release_20_08.rst
> b/doc/guides/rel_notes/release_20_08.rst
> index 3c40424cc..c4d094eac 100644
> --- a/doc/guides/rel_notes/release_20_08.rst
> +++ b/doc/guides/rel_notes/release_20_08.rst
> @@ -87,6 +87,14 @@ New Features
> 
>    * Added support for DCF datapath configuration.
> 
> +* **Updated Intel i40e driver.**
> +
> +  Updated i40e PMD with new features and improvements, including:
> +
> +  * Added a new type of cloud filter to support the coexistence of the
> +    following two rules. One selects L4 destination as input set and

L4 destination port

> +    the other one selects L4 source port.
> +

BTW, replace filter is used for the patch, so which protocol is impacted with this change?
e.g. If using this feature, can cloud filter for vxlan work well?
If there's any impact, please add the limitation in the doc.

>  Removed Items
>  -------------
> 
> diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
> index 970a31cb2..cea7f6b59 100644
> --- a/drivers/net/i40e/i40e_ethdev.c
> +++ b/drivers/net/i40e/i40e_ethdev.c
> @@ -7956,6 +7956,13 @@ i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
>  #define I40E_TR_GRE_KEY_MASK			0x400
>  #define I40E_TR_GRE_KEY_WITH_XSUM_MASK		0x800
>  #define I40E_TR_GRE_NO_KEY_MASK			0x8000
> +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_PORT_TR_WORD0 0x49
> #define
> +I40E_AQC_REPLACE_CLOUD_CMD_INPUT_DIRECTION_WORD0 0x41
> #define
> +I40E_AQC_REPLACE_CLOUD_CMD_INPUT_INGRESS_WORD0 0x80
> +#define I40E_DIRECTION_INGRESS_KEY		0x8000
> +#define I40E_TR_L4_TYPE_TCP			0x2
> +#define I40E_TR_L4_TYPE_UDP			0x4
> +#define I40E_TR_L4_TYPE_SCTP			0x8
> 
>  static enum
>  i40e_status_code i40e_replace_mpls_l1_filter(struct i40e_pf *pf) @@ -
> 8254,6 +8261,131 @@ i40e_status_code i40e_replace_gtp_cloud_filter(struct
> i40e_pf *pf)
>  	return status;
>  }
> 
> +static enum i40e_status_code
> +i40e_replace_port_l1_filter(struct i40e_pf *pf, enum i40e_l4_port_type
> +l4_port_type) {
> +	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
> +	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
> +	enum i40e_status_code status = I40E_SUCCESS;
> +	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
> +	struct rte_eth_dev *dev = ((struct i40e_adapter *)hw->back)-
> >eth_dev;
> +
> +	if (pf->support_multi_driver) {
> +		PMD_DRV_LOG(ERR, "Replace l1 filter is not supported.");
> +		return I40E_NOT_SUPPORTED;
> +	}
> +
> +	memset(&filter_replace, 0,
> +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
> +	memset(&filter_replace_buf, 0,
> +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
> +
> +	/* create L1 filter */
> +	if (l4_port_type == I40E_L4_PORT_TYPE_SRC) {
> +		filter_replace.old_filter_type =
> +
> 	I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TUNNLE_KEY;
> +		filter_replace.new_filter_type =
> I40E_AQC_ADD_CLOUD_FILTER_0X11;

To create L1 filter, so should be I40E_AQC_ADD_L1_FILTER_0X11 here?

> +		filter_replace_buf.data[8] =
> +
> 	I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_SRC_PORT;
> +	} else {
> +		filter_replace.old_filter_type =
> +
> 	I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG_IVLAN;
> +		filter_replace.new_filter_type =
> I40E_AQC_ADD_CLOUD_FILTER_0X10;

Same as above.

> +		filter_replace_buf.data[8] =
> +
> 	I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_DST_PORT;
> +	}
> +
> +	filter_replace.tr_bit = 0;
> +	/* Prepare the buffer, 3 entries */
> +	filter_replace_buf.data[0] =
> +
> 	I40E_AQC_REPLACE_CLOUD_CMD_INPUT_DIRECTION_WORD0;
> +	filter_replace_buf.data[0] |=
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> +	filter_replace_buf.data[2] = 0x00;
> +	filter_replace_buf.data[3] =
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_INGRESS_WORD0;
> +	filter_replace_buf.data[4] =
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_PORT_TR_WORD0;
> +	filter_replace_buf.data[4] |=
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> +	filter_replace_buf.data[5] = 0x00;
> +	filter_replace_buf.data[6] = I40E_TR_L4_TYPE_UDP |
> +		I40E_TR_L4_TYPE_TCP |
> +		I40E_TR_L4_TYPE_SCTP;
> +	filter_replace_buf.data[7] = 0x00;
> +	filter_replace_buf.data[8] |=
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> +	filter_replace_buf.data[9] = 0x00;
> +	filter_replace_buf.data[10] = 0xFF;
> +	filter_replace_buf.data[11] = 0xFF;
> +
> +	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
> +					       &filter_replace_buf);
> +	if (!status && (filter_replace.old_filter_type !=
> +		filter_replace.new_filter_type))
> +		PMD_DRV_LOG(WARNING, "i40e device %s changed cloud l1
> type."
> +			    " original: 0x%x, new: 0x%x",
> +			    dev->device->name,
> +			    filter_replace.old_filter_type,
> +			    filter_replace.new_filter_type);
> +
> +	return status;
> +}
> +
> +static enum
> +i40e_status_code i40e_replace_port_cloud_filter(struct i40e_pf *pf,
> +					enum i40e_l4_port_type
> l4_port_type) {
> +	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
> +	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
> +	enum i40e_status_code status = I40E_SUCCESS;
> +	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
> +	struct rte_eth_dev *dev = ((struct i40e_adapter *)hw->back)-
> >eth_dev;
> +
> +	if (pf->support_multi_driver) {
> +		PMD_DRV_LOG(ERR, "Replace cloud filter is not supported.");
> +		return I40E_NOT_SUPPORTED;
> +	}
> +
> +	memset(&filter_replace, 0,
> +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
> +	memset(&filter_replace_buf, 0,
> +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
> +
> +	if (l4_port_type == I40E_L4_PORT_TYPE_SRC) {
> +		filter_replace.old_filter_type =
> I40E_AQC_ADD_CLOUD_FILTER_IIP;
> +		filter_replace.new_filter_type =
> +			I40E_AQC_ADD_L1_FILTER_0X11;
> +		filter_replace_buf.data[4] =
> I40E_AQC_ADD_CLOUD_FILTER_0X11;
> +	} else {
> +		filter_replace.old_filter_type =
> I40E_AQC_ADD_CLOUD_FILTER_OIP;
> +		filter_replace.new_filter_type =
> +			I40E_AQC_ADD_CLOUD_FILTER_0X10;
> +		filter_replace_buf.data[4] =
> I40E_AQC_ADD_CLOUD_FILTER_0X10;
> +	}
> +
> +	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER;
> +	filter_replace.tr_bit = 0;
> +	/* Prepare the buffer, 2 entries */
> +	filter_replace_buf.data[0] =
> I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
> +	filter_replace_buf.data[0] |=
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> +	filter_replace_buf.data[4] |=
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> +	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
> +					       &filter_replace_buf);
> +
> +	if (!status && (filter_replace.old_filter_type !=
> +			filter_replace.new_filter_type))
> +		PMD_DRV_LOG(WARNING, "i40e device %s changed cloud
> filter type."
> +			    " original: 0x%x, new: 0x%x",
> +			    dev->device->name,
> +			    filter_replace.old_filter_type,
> +			    filter_replace.new_filter_type);
> +
> +	return status;
> +}
> +
>  int
>  i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
>  		      struct i40e_tunnel_filter_conf *tunnel_filter, @@ -8401,6
> +8533,58 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
>  		pfilter->general_fields[0] = tunnel_filter->inner_vlan;
>  		pfilter->general_fields[1] = tunnel_filter->outer_vlan;
>  		big_buffer = 1;
> +		break;
> +	case I40E_TUNNEL_TYPE_UDP:
> +	case I40E_TUNNEL_TYPE_TCP:
> +	case I40E_TUNNEL_TYPE_SCTP:

What's the tunnel_type_udp/tcp/sctp? It's not for tunnel, just normal UDP/TCP/SCTP. 

> +		if (tunnel_filter->l4_port_type == I40E_L4_PORT_TYPE_SRC) {
> +			if (!pf->sport_replace_flag) {
> +				i40e_replace_port_l1_filter(pf, tunnel_filter-
> >l4_port_type);
> +				i40e_replace_port_cloud_filter(pf,
> tunnel_filter->l4_port_type);
> +				pf->sport_replace_flag = 1;
> +			}
> +			teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
> +			pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
> +				I40E_DIRECTION_INGRESS_KEY;
> +
> +			if (tunnel_filter->tunnel_type ==
> I40E_TUNNEL_TYPE_UDP)
> +				pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
> +					I40E_TR_L4_TYPE_UDP;
> +			else if (tunnel_filter->tunnel_type ==
> I40E_TUNNEL_TYPE_TCP)
> +				pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
> +					I40E_TR_L4_TYPE_TCP;
> +			else
> +				pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
> +					I40E_TR_L4_TYPE_SCTP;
> +
> +			pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
> +				(teid_le >> 16) & 0xFFFF;
> +			big_buffer = 1;
> +		} else {
> +			if (!pf->dport_replace_flag) {
> +				i40e_replace_port_l1_filter(pf, tunnel_filter-
> >l4_port_type);
> +				i40e_replace_port_cloud_filter(pf,
> tunnel_filter->l4_port_type);
> +				pf->dport_replace_flag = 1;
> +			}
> +			teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
> +			pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD0] =
> +				I40E_DIRECTION_INGRESS_KEY;
> +
> +			if (tunnel_filter->tunnel_type ==
> I40E_TUNNEL_TYPE_UDP)
> +				pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
> +					I40E_TR_L4_TYPE_UDP;
> +			else if (tunnel_filter->tunnel_type ==
> I40E_TUNNEL_TYPE_TCP)
> +				pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
> +					I40E_TR_L4_TYPE_TCP;
> +			else
> +				pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
> +					I40E_TR_L4_TYPE_SCTP;
> +
> +			pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD2] =
> +				(teid_le >> 16) & 0xFFFF;
> +			big_buffer = 1;
> +		}
> +
>  		break;
>  	default:
>  		/* Other tunnel types is not supported. */ @@ -8424,7
> +8608,16 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
>  	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_QINQ)
>  		pfilter->element.flags |=
>  			I40E_AQC_ADD_CLOUD_FILTER_0X10;
> -	else {
> +	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_UDP ||
> +		 tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_TCP ||
> +		 tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_SCTP) {
> +		if (tunnel_filter->l4_port_type == I40E_L4_PORT_TYPE_SRC)
> +			pfilter->element.flags |=
> +				I40E_AQC_ADD_L1_FILTER_0X11;
> +		else
> +			pfilter->element.flags |=
> +				I40E_AQC_ADD_CLOUD_FILTER_0X10;
> +	} else {
>  		val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
>  						&pfilter->element.flags);
>  		if (val < 0) {
> diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
> index e5d0ce53f..56955068b 100644
> --- a/drivers/net/i40e/i40e_ethdev.h
> +++ b/drivers/net/i40e/i40e_ethdev.h
> @@ -767,6 +767,8 @@ struct i40e_rss_pattern_info {
> 
>  #define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD0 44
> #define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD1 45
> +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_SRC_PORT 29 #define
> +I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_DST_PORT 30
>  #define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSOUDP	8
>  #define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSOGRE	9
>  #define I40E_AQC_ADD_CLOUD_FILTER_0X10		0x10
> @@ -828,9 +830,20 @@ enum i40e_tunnel_type {
>  	I40E_TUNNEL_TYPE_GTPU,
>  	I40E_TUNNEL_TYPE_ESPoUDP,
>  	I40E_TUNNEL_TYPE_ESPoIP,
> +	I40E_TUNNEL_TYPE_UDP,
> +	I40E_TUNNEL_TYPE_TCP,
> +	I40E_TUNNEL_TYPE_SCTP,

the macro name should be changed.

>  	I40E_TUNNEL_TYPE_MAX,
>  };
> 
> +/**
> + * L4 port type.
> + */
> +enum i40e_l4_port_type {
> +	I40E_L4_PORT_TYPE_SRC = 0,
> +	I40E_L4_PORT_TYPE_DST,
> +};
> +
...


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

* Re: [dpdk-dev] [PATCH v2] net/i40e: enable port filter by switch filter
  2020-06-30  6:15   ` Xing, Beilei
@ 2020-07-07  6:11     ` Sun, GuinanX
  0 siblings, 0 replies; 16+ messages in thread
From: Sun, GuinanX @ 2020-07-07  6:11 UTC (permalink / raw)
  To: Xing, Beilei, dev; +Cc: Guo, Jia

Hi beilei

> -----Original Message-----
> From: Xing, Beilei
> Sent: Tuesday, June 30, 2020 2:16 PM
> To: Sun, GuinanX <guinanx.sun@intel.com>; dev@dpdk.org
> Cc: Guo, Jia <jia.guo@intel.com>
> Subject: RE: [PATCH v2] net/i40e: enable port filter by switch filter
> 
> 
> 
> > -----Original Message-----
> > From: Sun, GuinanX <guinanx.sun@intel.com>
> > Sent: Tuesday, June 30, 2020 12:42 PM
> > To: dev@dpdk.org
> > Cc: Xing, Beilei <beilei.xing@intel.com>; Guo, Jia
> > <jia.guo@intel.com>; Sun, GuinanX <guinanx.sun@intel.com>
> > Subject: [PATCH v2] net/i40e: enable port filter by switch filter
> 
> How about 'support cloud filter with l4 port'?

I agree with you , patch v3 will fix it.

> 
> Please also fix all the warnings in patchwork:
> http://mails.dpdk.org/archives/test-report/2020-June/139555.html.

Issues that affect readability have not been modified, others have been modified.

> 
> >
> > This patch enables the filter that supports to create following two
> > rules for the same packet type:
> 
> Better to clarify which packet types will be supported.

Patch V3 will fix it.

> 
> > One is to select source port only as input set and the other is for
> > destination port only.
> >
> > Signed-off-by: Guinan Sun <guinanx.sun@intel.com>
> > ---
> > v2:
> > * Fixed code style and variable naming
> > ---
> >  doc/guides/rel_notes/release_20_08.rst |   8 +
> >  drivers/net/i40e/i40e_ethdev.c         | 195 ++++++++++++++++++++-
> >  drivers/net/i40e/i40e_ethdev.h         |  17 ++
> >  drivers/net/i40e/i40e_flow.c           | 223 +++++++++++++++++++++++++
> >  4 files changed, 442 insertions(+), 1 deletion(-)
> >
> > diff --git a/doc/guides/rel_notes/release_20_08.rst
> > b/doc/guides/rel_notes/release_20_08.rst
> > index 3c40424cc..c4d094eac 100644
> > --- a/doc/guides/rel_notes/release_20_08.rst
> > +++ b/doc/guides/rel_notes/release_20_08.rst
> > @@ -87,6 +87,14 @@ New Features
> >
> >    * Added support for DCF datapath configuration.
> >
> > +* **Updated Intel i40e driver.**
> > +
> > +  Updated i40e PMD with new features and improvements, including:
> > +
> > +  * Added a new type of cloud filter to support the coexistence of the
> > +    following two rules. One selects L4 destination as input set and
> 
> L4 destination port

Patch V3 will fix it.

> 
> > +    the other one selects L4 source port.
> > +
> 
> BTW, replace filter is used for the patch, so which protocol is impacted with
> this change?
> e.g. If using this feature, can cloud filter for vxlan work well?
> If there's any impact, please add the limitation in the doc.

Limitation has been added in the doc.

> 
> >  Removed Items
> >  -------------
> >
> > diff --git a/drivers/net/i40e/i40e_ethdev.c
> > b/drivers/net/i40e/i40e_ethdev.c index 970a31cb2..cea7f6b59 100644
> > --- a/drivers/net/i40e/i40e_ethdev.c
> > +++ b/drivers/net/i40e/i40e_ethdev.c
> > @@ -7956,6 +7956,13 @@ i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
> > #define I40E_TR_GRE_KEY_MASK0x400  #define
> > I40E_TR_GRE_KEY_WITH_XSUM_MASK0x800
> >  #define I40E_TR_GRE_NO_KEY_MASK0x8000
> > +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_PORT_TR_WORD0 0x49
> > #define
> > +I40E_AQC_REPLACE_CLOUD_CMD_INPUT_DIRECTION_WORD0 0x41
> > #define
> > +I40E_AQC_REPLACE_CLOUD_CMD_INPUT_INGRESS_WORD0 0x80 #define
> > +I40E_DIRECTION_INGRESS_KEY0x8000 #define I40E_TR_L4_TYPE_TCP0x2
> > +#define I40E_TR_L4_TYPE_UDP0x4 #define I40E_TR_L4_TYPE_SCTP0x8
> >
> >  static enum
> >  i40e_status_code i40e_replace_mpls_l1_filter(struct i40e_pf *pf) @@ -
> > 8254,6 +8261,131 @@ i40e_status_code
> > i40e_replace_gtp_cloud_filter(struct
> > i40e_pf *pf)
> >  return status;
> >  }
> >
> > +static enum i40e_status_code
> > +i40e_replace_port_l1_filter(struct i40e_pf *pf, enum
> > +i40e_l4_port_type
> > +l4_port_type) {
> > +struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
> > +struct i40e_aqc_replace_cloud_filters_cmd  filter_replace; enum
> > +i40e_status_code status = I40E_SUCCESS; struct i40e_hw *hw =
> > +I40E_PF_TO_HW(pf); struct rte_eth_dev *dev = ((struct i40e_adapter
> > +*)hw->back)-
> > >eth_dev;
> > +
> > +if (pf->support_multi_driver) {
> > +PMD_DRV_LOG(ERR, "Replace l1 filter is not supported."); return
> > +I40E_NOT_SUPPORTED; }
> > +
> > +memset(&filter_replace, 0,
> > +       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
> > +memset(&filter_replace_buf, 0,
> > +       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
> > +
> > +/* create L1 filter */
> > +if (l4_port_type == I40E_L4_PORT_TYPE_SRC) {
> > +filter_replace.old_filter_type =
> > +
> > I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TUNNLE_KEY;
> > +filter_replace.new_filter_type =
> > I40E_AQC_ADD_CLOUD_FILTER_0X11;
> 
> To create L1 filter, so should be I40E_AQC_ADD_L1_FILTER_0X11 here?

Patch V3 will fix it.

> 
> > +filter_replace_buf.data[8] =
> > +
> > I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_SRC_PORT;
> > +} else {
> > +filter_replace.old_filter_type =
> > +
> > I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG_IVLAN;
> > +filter_replace.new_filter_type =
> > I40E_AQC_ADD_CLOUD_FILTER_0X10;
> 
> Same as above.

Patch V3 will fix it.

> 
> > +filter_replace_buf.data[8] =
> > +
> > I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_DST_PORT;
> > +}
> > +
> > +filter_replace.tr_bit = 0;
> > +/* Prepare the buffer, 3 entries */
> > +filter_replace_buf.data[0] =
> > +
> > I40E_AQC_REPLACE_CLOUD_CMD_INPUT_DIRECTION_WORD0;
> > +filter_replace_buf.data[0] |=
> > +I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> > +filter_replace_buf.data[2] = 0x00;
> > +filter_replace_buf.data[3] =
> > +I40E_AQC_REPLACE_CLOUD_CMD_INPUT_INGRESS_WORD0;
> > +filter_replace_buf.data[4] =
> > +I40E_AQC_REPLACE_CLOUD_CMD_INPUT_PORT_TR_WORD0;
> > +filter_replace_buf.data[4] |=
> > +I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> > +filter_replace_buf.data[5] = 0x00;
> > +filter_replace_buf.data[6] = I40E_TR_L4_TYPE_UDP |
> > +I40E_TR_L4_TYPE_TCP | I40E_TR_L4_TYPE_SCTP;
> > +filter_replace_buf.data[7] = 0x00; filter_replace_buf.data[8] |=
> > +I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> > +filter_replace_buf.data[9] = 0x00;
> > +filter_replace_buf.data[10] = 0xFF;
> > +filter_replace_buf.data[11] = 0xFF;
> > +
> > +status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
> > +       &filter_replace_buf);
> > +if (!status && (filter_replace.old_filter_type !=
> > +filter_replace.new_filter_type))
> > +PMD_DRV_LOG(WARNING, "i40e device %s changed cloud l1
> > type."
> > +    " original: 0x%x, new: 0x%x",
> > +    dev->device->name,
> > +    filter_replace.old_filter_type,
> > +    filter_replace.new_filter_type);
> > +
> > +return status;
> > +}
> > +
> > +static enum
> > +i40e_status_code i40e_replace_port_cloud_filter(struct i40e_pf *pf,
> > +enum i40e_l4_port_type
> > l4_port_type) {
> > +struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
> > +struct i40e_aqc_replace_cloud_filters_cmd  filter_replace; enum
> > +i40e_status_code status = I40E_SUCCESS; struct i40e_hw *hw =
> > +I40E_PF_TO_HW(pf); struct rte_eth_dev *dev = ((struct i40e_adapter
> > +*)hw->back)-
> > >eth_dev;
> > +
> > +if (pf->support_multi_driver) {
> > +PMD_DRV_LOG(ERR, "Replace cloud filter is not supported."); return
> > +I40E_NOT_SUPPORTED; }
> > +
> > +memset(&filter_replace, 0,
> > +       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
> > +memset(&filter_replace_buf, 0,
> > +       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
> > +
> > +if (l4_port_type == I40E_L4_PORT_TYPE_SRC) {
> > +filter_replace.old_filter_type =
> > I40E_AQC_ADD_CLOUD_FILTER_IIP;
> > +filter_replace.new_filter_type =
> > +I40E_AQC_ADD_L1_FILTER_0X11;
> > +filter_replace_buf.data[4] =
> > I40E_AQC_ADD_CLOUD_FILTER_0X11;
> > +} else {
> > +filter_replace.old_filter_type =
> > I40E_AQC_ADD_CLOUD_FILTER_OIP;
> > +filter_replace.new_filter_type =
> > +I40E_AQC_ADD_CLOUD_FILTER_0X10;
> > +filter_replace_buf.data[4] =
> > I40E_AQC_ADD_CLOUD_FILTER_0X10;
> > +}
> > +
> > +filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER;
> > +filter_replace.tr_bit = 0;
> > +/* Prepare the buffer, 2 entries */
> > +filter_replace_buf.data[0] =
> > I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
> > +filter_replace_buf.data[0] |=
> > +I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> > +filter_replace_buf.data[4] |=
> > +I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> > +status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
> > +       &filter_replace_buf);
> > +
> > +if (!status && (filter_replace.old_filter_type !=
> > +filter_replace.new_filter_type))
> > +PMD_DRV_LOG(WARNING, "i40e device %s changed cloud
> > filter type."
> > +    " original: 0x%x, new: 0x%x",
> > +    dev->device->name,
> > +    filter_replace.old_filter_type,
> > +    filter_replace.new_filter_type);
> > +
> > +return status;
> > +}
> > +
> >  int
> >  i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
> >        struct i40e_tunnel_filter_conf *tunnel_filter, @@ -8401,6
> > +8533,58 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
> >  pfilter->general_fields[0] = tunnel_filter->inner_vlan;
> > pfilter->general_fields[1] = tunnel_filter->outer_vlan;  big_buffer =
> > 1;
> > +break;
> > +case I40E_TUNNEL_TYPE_UDP:
> > +case I40E_TUNNEL_TYPE_TCP:
> > +case I40E_TUNNEL_TYPE_SCTP:
> 
> What's the tunnel_type_udp/tcp/sctp? It's not for tunnel, just normal
> UDP/TCP/SCTP.

Patch V3 will fix it.

> 
> > +if (tunnel_filter->l4_port_type == I40E_L4_PORT_TYPE_SRC) { if
> > +(!pf->sport_replace_flag) { i40e_replace_port_l1_filter(pf,
> > +tunnel_filter-
> > >l4_port_type);
> > +i40e_replace_port_cloud_filter(pf,
> > tunnel_filter->l4_port_type);
> > +pf->sport_replace_flag = 1;
> > +}
> > +teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
> > +pfilter-
> > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
> > +I40E_DIRECTION_INGRESS_KEY;
> > +
> > +if (tunnel_filter->tunnel_type ==
> > I40E_TUNNEL_TYPE_UDP)
> > +pfilter-
> > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
> > +I40E_TR_L4_TYPE_UDP;
> > +else if (tunnel_filter->tunnel_type ==
> > I40E_TUNNEL_TYPE_TCP)
> > +pfilter-
> > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
> > +I40E_TR_L4_TYPE_TCP;
> > +else
> > +pfilter-
> > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
> > +I40E_TR_L4_TYPE_SCTP;
> > +
> > +pfilter-
> > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
> > +(teid_le >> 16) & 0xFFFF;
> > +big_buffer = 1;
> > +} else {
> > +if (!pf->dport_replace_flag) {
> > +i40e_replace_port_l1_filter(pf, tunnel_filter-
> > >l4_port_type);
> > +i40e_replace_port_cloud_filter(pf,
> > tunnel_filter->l4_port_type);
> > +pf->dport_replace_flag = 1;
> > +}
> > +teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
> > +pfilter-
> > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD0] =
> > +I40E_DIRECTION_INGRESS_KEY;
> > +
> > +if (tunnel_filter->tunnel_type ==
> > I40E_TUNNEL_TYPE_UDP)
> > +pfilter-
> > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
> > +I40E_TR_L4_TYPE_UDP;
> > +else if (tunnel_filter->tunnel_type ==
> > I40E_TUNNEL_TYPE_TCP)
> > +pfilter-
> > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
> > +I40E_TR_L4_TYPE_TCP;
> > +else
> > +pfilter-
> > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
> > +I40E_TR_L4_TYPE_SCTP;
> > +
> > +pfilter-
> > >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD2] =
> > +(teid_le >> 16) & 0xFFFF;
> > +big_buffer = 1;
> > +}
> > +
> >  break;
> >  default:
> >  /* Other tunnel types is not supported. */ @@ -8424,7
> > +8608,16 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
> >  else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_QINQ)
> > pfilter->element.flags |=  I40E_AQC_ADD_CLOUD_FILTER_0X10; -else {
> > +else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_UDP ||
> > +tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_TCP ||
> > +tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_SCTP) { if
> > +(tunnel_filter->l4_port_type == I40E_L4_PORT_TYPE_SRC)
> > +pfilter->element.flags |=
> > +I40E_AQC_ADD_L1_FILTER_0X11;
> > +else
> > +pfilter->element.flags |=
> > +I40E_AQC_ADD_CLOUD_FILTER_0X10;
> > +} else {
> >  val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
> >  &pfilter->element.flags);
> >  if (val < 0) {
> > diff --git a/drivers/net/i40e/i40e_ethdev.h
> > b/drivers/net/i40e/i40e_ethdev.h index e5d0ce53f..56955068b 100644
> > --- a/drivers/net/i40e/i40e_ethdev.h
> > +++ b/drivers/net/i40e/i40e_ethdev.h
> > @@ -767,6 +767,8 @@ struct i40e_rss_pattern_info {
> >
> >  #define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD0 44
> #define
> > I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD1 45
> > +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_SRC_PORT 29
> #define
> > +I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_DST_PORT 30
> >  #define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSOUDP8
> >  #define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSOGRE9
> >  #define I40E_AQC_ADD_CLOUD_FILTER_0X100x10
> > @@ -828,9 +830,20 @@ enum i40e_tunnel_type
> {  I40E_TUNNEL_TYPE_GTPU,
> > I40E_TUNNEL_TYPE_ESPoUDP,  I40E_TUNNEL_TYPE_ESPoIP,
> > +I40E_TUNNEL_TYPE_UDP,
> > +I40E_TUNNEL_TYPE_TCP,
> > +I40E_TUNNEL_TYPE_SCTP,
> 
> the macro name should be changed.

Patch V3 will fix it.

> 
> >  I40E_TUNNEL_TYPE_MAX,
> >  };
> >
> > +/**
> > + * L4 port type.
> > + */
> > +enum i40e_l4_port_type {
> > +I40E_L4_PORT_TYPE_SRC = 0,
> > +I40E_L4_PORT_TYPE_DST,
> > +};
> > +
> ...
> 


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

* [dpdk-dev] [PATCH v3] net/i40e: support cloud filter with L4 port
  2020-06-11  5:24 [dpdk-dev] [PATCH] net/i40e: enable port filter by switch filter Guinan Sun
                   ` (2 preceding siblings ...)
  2020-06-30  4:42 ` [dpdk-dev] [PATCH v2] " Guinan Sun
@ 2020-07-07  6:33 ` Guinan Sun
  2020-07-07  8:15   ` Xing, Beilei
  2020-07-08  3:11 ` [dpdk-dev] [PATCH v4] " Guinan Sun
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 16+ messages in thread
From: Guinan Sun @ 2020-07-07  6:33 UTC (permalink / raw)
  To: dev; +Cc: Beilei Xing, Jeff Guo, Guinan Sun

This patch enables the filter that supports
to create following two rules for the same packet type:
One is to select source port only as input set and the
other is for destination port only.
And the supported packet types are UDP/TCP/SCTP.

Signed-off-by: Guinan Sun <guinanx.sun@intel.com>
---
v3:
* Add limitation to i40e.rst
* Rename variables.
* Fixed the variable assignment.
v2:
* Fixed code style and variable naming
---
 doc/guides/nics/i40e.rst               |   9 +
 doc/guides/rel_notes/release_20_08.rst |   8 +
 drivers/net/i40e/i40e_ethdev.c         | 200 +++++++++++++++++++++-
 drivers/net/i40e/i40e_ethdev.h         |  18 ++
 drivers/net/i40e/i40e_flow.c           | 223 +++++++++++++++++++++++++
 5 files changed, 457 insertions(+), 1 deletion(-)

diff --git a/doc/guides/nics/i40e.rst b/doc/guides/nics/i40e.rst
index 00c3042d5..98a5537d7 100644
--- a/doc/guides/nics/i40e.rst
+++ b/doc/guides/nics/i40e.rst
@@ -736,6 +736,15 @@ with DPDK, then the configuration will also impact port B in the NIC with
 kernel driver, which don't want to use the TPID.
 So PMD reports warning to clarify what is changed by writing global register.
 
+L4 port filter
+~~~~~~~~~~~~~~
+
+L4 port filter is a new type of cloud filter.
+It is possible to generate two filters - one to select L4 DST port
+and second to select L4 SRC port.
+If the L4 port filter is used, the cloud filter using inner Vlan and
+Tunnel Key will be invalid.
+
 High Performance of Small Packets on 40GbE NIC
 ----------------------------------------------
 
diff --git a/doc/guides/rel_notes/release_20_08.rst b/doc/guides/rel_notes/release_20_08.rst
index f4b858727..d7d4c4e3b 100644
--- a/doc/guides/rel_notes/release_20_08.rst
+++ b/doc/guides/rel_notes/release_20_08.rst
@@ -108,6 +108,14 @@ New Features
   * Dump ``rte_flow`` memory consumption.
   * Measure packet per second forwarding.
 
+* **Updated Intel i40e driver.**
+
+  Updated i40e PMD with new features and improvements, including:
+
+  * Added a new type of cloud filter to support the coexistence of the
+    following two rules. One selects L4 destination port as input set and
+    the other one selects L4 source port. We call it L4 port filter.
+    But there are limitations on using the L4 port filter.
 
 Removed Items
 -------------
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 777e14926..06f5e77e1 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -7944,6 +7944,13 @@ i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
 #define I40E_TR_GRE_KEY_MASK			0x400
 #define I40E_TR_GRE_KEY_WITH_XSUM_MASK		0x800
 #define I40E_TR_GRE_NO_KEY_MASK			0x8000
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_PORT_TR_WORD0 0x49
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_DIRECTION_WORD0 0x41
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_INGRESS_WORD0 0x80
+#define I40E_DIRECTION_INGRESS_KEY		0x8000
+#define I40E_TR_L4_TYPE_TCP			0x2
+#define I40E_TR_L4_TYPE_UDP			0x4
+#define I40E_TR_L4_TYPE_SCTP			0x8
 
 static enum
 i40e_status_code i40e_replace_mpls_l1_filter(struct i40e_pf *pf)
@@ -8242,6 +8249,132 @@ i40e_status_code i40e_replace_gtp_cloud_filter(struct i40e_pf *pf)
 	return status;
 }
 
+static enum i40e_status_code
+i40e_replace_port_l1_filter(struct i40e_pf *pf,
+			    enum i40e_l4_port_type l4_port_type)
+{
+	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
+	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
+	enum i40e_status_code status = I40E_SUCCESS;
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	struct rte_eth_dev *dev = ((struct i40e_adapter *)hw->back)->eth_dev;
+
+	if (pf->support_multi_driver) {
+		PMD_DRV_LOG(ERR, "Replace l1 filter is not supported.");
+		return I40E_NOT_SUPPORTED;
+	}
+
+	memset(&filter_replace, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+	memset(&filter_replace_buf, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+
+	/* create L1 filter */
+	if (l4_port_type == I40E_L4_PORT_TYPE_SRC) {
+		filter_replace.old_filter_type =
+			I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TUNNLE_KEY;
+		filter_replace.new_filter_type = I40E_AQC_ADD_L1_FILTER_0X11;
+		filter_replace_buf.data[8] =
+			I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_SRC_PORT;
+	} else {
+		filter_replace.old_filter_type =
+			I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG_IVLAN;
+		filter_replace.new_filter_type = I40E_AQC_ADD_L1_FILTER_0X10;
+		filter_replace_buf.data[8] =
+			I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_DST_PORT;
+	}
+
+	filter_replace.tr_bit = 0;
+	/* Prepare the buffer, 3 entries */
+	filter_replace_buf.data[0] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_DIRECTION_WORD0;
+	filter_replace_buf.data[0] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[2] = 0x00;
+	filter_replace_buf.data[3] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_INGRESS_WORD0;
+	filter_replace_buf.data[4] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_PORT_TR_WORD0;
+	filter_replace_buf.data[4] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[5] = 0x00;
+	filter_replace_buf.data[6] = I40E_TR_L4_TYPE_UDP |
+		I40E_TR_L4_TYPE_TCP |
+		I40E_TR_L4_TYPE_SCTP;
+	filter_replace_buf.data[7] = 0x00;
+	filter_replace_buf.data[8] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[9] = 0x00;
+	filter_replace_buf.data[10] = 0xFF;
+	filter_replace_buf.data[11] = 0xFF;
+
+	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+					       &filter_replace_buf);
+	if (!status && filter_replace.old_filter_type !=
+	    filter_replace.new_filter_type)
+		PMD_DRV_LOG(WARNING, "i40e device %s changed cloud l1 type."
+			    " original: 0x%x, new: 0x%x",
+			    dev->device->name,
+			    filter_replace.old_filter_type,
+			    filter_replace.new_filter_type);
+
+	return status;
+}
+
+static enum i40e_status_code
+i40e_replace_port_cloud_filter(struct i40e_pf *pf,
+			       enum i40e_l4_port_type l4_port_type)
+{
+	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
+	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
+	enum i40e_status_code status = I40E_SUCCESS;
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	struct rte_eth_dev *dev = ((struct i40e_adapter *)hw->back)->eth_dev;
+
+	if (pf->support_multi_driver) {
+		PMD_DRV_LOG(ERR, "Replace cloud filter is not supported.");
+		return I40E_NOT_SUPPORTED;
+	}
+
+	memset(&filter_replace, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+	memset(&filter_replace_buf, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+
+	if (l4_port_type == I40E_L4_PORT_TYPE_SRC) {
+		filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_IIP;
+		filter_replace.new_filter_type =
+			I40E_AQC_ADD_L1_FILTER_0X11;
+		filter_replace_buf.data[4] = I40E_AQC_ADD_CLOUD_FILTER_0X11;
+	} else {
+		filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_OIP;
+		filter_replace.new_filter_type =
+			I40E_AQC_ADD_CLOUD_FILTER_0X10;
+		filter_replace_buf.data[4] = I40E_AQC_ADD_CLOUD_FILTER_0X10;
+	}
+
+	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER;
+	filter_replace.tr_bit = 0;
+	/* Prepare the buffer, 2 entries */
+	filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
+	filter_replace_buf.data[0] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[4] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+					       &filter_replace_buf);
+
+	if (!status && filter_replace.old_filter_type !=
+	    filter_replace.new_filter_type)
+		PMD_DRV_LOG(WARNING, "i40e device %s changed cloud filter type."
+			    " original: 0x%x, new: 0x%x",
+			    dev->device->name,
+			    filter_replace.old_filter_type,
+			    filter_replace.new_filter_type);
+
+	return status;
+}
+
 int
 i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		      struct i40e_tunnel_filter_conf *tunnel_filter,
@@ -8389,6 +8522,62 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		pfilter->general_fields[0] = tunnel_filter->inner_vlan;
 		pfilter->general_fields[1] = tunnel_filter->outer_vlan;
 		big_buffer = 1;
+		break;
+	case I40E_CLOUD_TYPE_UDP:
+	case I40E_CLOUD_TYPE_TCP:
+	case I40E_CLOUD_TYPE_SCTP:
+		if (tunnel_filter->l4_port_type == I40E_L4_PORT_TYPE_SRC) {
+			if (!pf->sport_replace_flag) {
+				i40e_replace_port_l1_filter(pf,
+						tunnel_filter->l4_port_type);
+				i40e_replace_port_cloud_filter(pf,
+						tunnel_filter->l4_port_type);
+				pf->sport_replace_flag = 1;
+			}
+			teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
+			pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
+				I40E_DIRECTION_INGRESS_KEY;
+
+			if (tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_UDP)
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+					I40E_TR_L4_TYPE_UDP;
+			else if (tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_TCP)
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+					I40E_TR_L4_TYPE_TCP;
+			else
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+					I40E_TR_L4_TYPE_SCTP;
+
+			pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
+				(teid_le >> 16) & 0xFFFF;
+			big_buffer = 1;
+		} else {
+			if (!pf->dport_replace_flag) {
+				i40e_replace_port_l1_filter(pf,
+						tunnel_filter->l4_port_type);
+				i40e_replace_port_cloud_filter(pf,
+						tunnel_filter->l4_port_type);
+				pf->dport_replace_flag = 1;
+			}
+			teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
+			pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD0] =
+				I40E_DIRECTION_INGRESS_KEY;
+
+			if (tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_UDP)
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
+					I40E_TR_L4_TYPE_UDP;
+			else if (tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_TCP)
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
+					I40E_TR_L4_TYPE_TCP;
+			else
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
+					I40E_TR_L4_TYPE_SCTP;
+
+			pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD2] =
+				(teid_le >> 16) & 0xFFFF;
+			big_buffer = 1;
+		}
+
 		break;
 	default:
 		/* Other tunnel types is not supported. */
@@ -8412,7 +8601,16 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_QINQ)
 		pfilter->element.flags |=
 			I40E_AQC_ADD_CLOUD_FILTER_0X10;
-	else {
+	else if (tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_UDP ||
+		 tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_TCP ||
+		 tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_SCTP) {
+		if (tunnel_filter->l4_port_type == I40E_L4_PORT_TYPE_SRC)
+			pfilter->element.flags |=
+				I40E_AQC_ADD_L1_FILTER_0X11;
+		else
+			pfilter->element.flags |=
+				I40E_AQC_ADD_CLOUD_FILTER_0X10;
+	} else {
 		val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
 						&pfilter->element.flags);
 		if (val < 0) {
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index e5d0ce53f..53e737b39 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -767,11 +767,14 @@ struct i40e_rss_pattern_info {
 
 #define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD0 44
 #define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD1 45
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_SRC_PORT 29
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_DST_PORT 30
 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSOUDP	8
 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSOGRE	9
 #define I40E_AQC_ADD_CLOUD_FILTER_0X10		0x10
 #define I40E_AQC_ADD_CLOUD_FILTER_0X11		0x11
 #define I40E_AQC_ADD_CLOUD_FILTER_0X12		0x12
+#define I40E_AQC_ADD_L1_FILTER_0X10		0x10
 #define I40E_AQC_ADD_L1_FILTER_0X11		0x11
 #define I40E_AQC_ADD_L1_FILTER_0X12		0x12
 #define I40E_AQC_ADD_L1_FILTER_0X13		0x13
@@ -828,9 +831,20 @@ enum i40e_tunnel_type {
 	I40E_TUNNEL_TYPE_GTPU,
 	I40E_TUNNEL_TYPE_ESPoUDP,
 	I40E_TUNNEL_TYPE_ESPoIP,
+	I40E_CLOUD_TYPE_UDP,
+	I40E_CLOUD_TYPE_TCP,
+	I40E_CLOUD_TYPE_SCTP,
 	I40E_TUNNEL_TYPE_MAX,
 };
 
+/**
+ * L4 port type.
+ */
+enum i40e_l4_port_type {
+	I40E_L4_PORT_TYPE_SRC = 0,
+	I40E_L4_PORT_TYPE_DST,
+};
+
 /**
  * Tunneling Packet filter configuration.
  */
@@ -852,6 +866,7 @@ struct i40e_tunnel_filter_conf {
 	/** Flags from ETH_TUNNEL_FILTER_XX - see above. */
 	uint16_t filter_type;
 	enum i40e_tunnel_type tunnel_type; /**< Tunnel Type. */
+	enum i40e_l4_port_type l4_port_type; /**< L4 Port Type. */
 	uint32_t tenant_id;     /**< Tenant ID to match. VNI, GRE key... */
 	uint16_t queue_id;      /**< Queue assigned to if match. */
 	uint8_t is_to_vf;       /**< 0 - to PF, 1 - to VF */
@@ -1073,6 +1088,9 @@ struct i40e_pf {
 	bool mpls_replace_flag;  /* 1 - MPLS filter replace is done */
 	bool gtp_replace_flag;   /* 1 - GTP-C/U filter replace is done */
 	bool qinq_replace_flag;  /* QINQ filter replace is done */
+	/* l4 port flag */
+	bool sport_replace_flag;   /* source port replace is done */
+	bool dport_replace_flag;   /* dest port replace is done */
 	struct i40e_tm_conf tm_conf;
 	bool support_multi_driver; /* 1 - support multiple driver */
 
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 8f8df6fae..0904c063c 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -124,6 +124,12 @@ i40e_flow_parse_qinq_pattern(struct rte_eth_dev *dev,
 			      struct rte_flow_error *error,
 			      struct i40e_tunnel_filter_conf *filter);
 
+static int i40e_flow_parse_l4_proto_filter(struct rte_eth_dev *dev,
+					   const struct rte_flow_attr *attr,
+					   const struct rte_flow_item pattern[],
+					   const struct rte_flow_action actions[],
+					   struct rte_flow_error *error,
+					   union i40e_filter_t *filter);
 const struct rte_flow_ops i40e_flow_ops = {
 	.validate = i40e_flow_validate,
 	.create = i40e_flow_create,
@@ -1845,6 +1851,13 @@ static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	/* L2TPv3 over IP */
 	{ pattern_fdir_ipv4_l2tpv3oip, i40e_flow_parse_fdir_filter },
 	{ pattern_fdir_ipv6_l2tpv3oip, i40e_flow_parse_fdir_filter },
+	/* L4 over port */
+	{ pattern_fdir_ipv4_udp, i40e_flow_parse_l4_proto_filter },
+	{ pattern_fdir_ipv4_tcp, i40e_flow_parse_l4_proto_filter },
+	{ pattern_fdir_ipv4_sctp, i40e_flow_parse_l4_proto_filter },
+	{ pattern_fdir_ipv6_udp, i40e_flow_parse_l4_proto_filter },
+	{ pattern_fdir_ipv6_tcp, i40e_flow_parse_l4_proto_filter },
+	{ pattern_fdir_ipv6_sctp, i40e_flow_parse_l4_proto_filter },
 };
 
 #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
@@ -3541,6 +3554,216 @@ i40e_flow_parse_tunnel_action(struct rte_eth_dev *dev,
 	return 0;
 }
 
+static int
+i40e_flow_parse_l4_proto_pattern(const struct rte_flow_item *pattern,
+				 struct rte_flow_error *error,
+				 struct i40e_tunnel_filter_conf *filter)
+{
+	const struct rte_flow_item_sctp *sctp_spec, *sctp_mask;
+	const struct rte_flow_item_tcp *tcp_spec, *tcp_mask;
+	const struct rte_flow_item_udp *udp_spec, *udp_mask;
+	const struct rte_flow_item *item = pattern;
+	enum rte_flow_item_type item_type;
+
+	for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+		if (item->last) {
+			rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM,
+					   item,
+					   "Not support range");
+			return -rte_errno;
+		}
+		item_type = item->type;
+		switch (item_type) {
+		case RTE_FLOW_ITEM_TYPE_ETH:
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid ETH item");
+				return -rte_errno;
+			}
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV4:
+			filter->ip_type = I40E_TUNNEL_IPTYPE_IPV4;
+			/* IPv4 is used to describe protocol,
+			 * spec and mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid IPv4 item");
+				return -rte_errno;
+			}
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV6:
+			filter->ip_type = I40E_TUNNEL_IPTYPE_IPV6;
+			/* IPv6 is used to describe protocol,
+			 * spec and mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid IPv6 item");
+				return -rte_errno;
+			}
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_UDP:
+			udp_spec = item->spec;
+			udp_mask = item->mask;
+
+			if (!udp_spec || !udp_mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid udp item");
+				return -rte_errno;
+			}
+
+			if (udp_spec->hdr.src_port != 0 &&
+			    udp_spec->hdr.dst_port != 0) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid udp spec");
+				return -rte_errno;
+			}
+
+			if (udp_spec->hdr.src_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_SRC;
+				filter->tenant_id =
+				rte_be_to_cpu_32(udp_spec->hdr.src_port);
+			}
+
+			if (udp_spec->hdr.dst_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_DST;
+				filter->tenant_id =
+				rte_be_to_cpu_32(udp_spec->hdr.dst_port);
+			}
+
+			filter->tunnel_type = I40E_CLOUD_TYPE_UDP;
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_TCP:
+			tcp_spec = item->spec;
+			tcp_mask = item->mask;
+
+			if (!tcp_spec || !tcp_mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid tcp item");
+				return -rte_errno;
+			}
+
+			if (tcp_spec->hdr.src_port != 0 &&
+			    tcp_spec->hdr.dst_port != 0) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid tcp spec");
+				return -rte_errno;
+			}
+
+			if (tcp_spec->hdr.src_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_SRC;
+				filter->tenant_id =
+				rte_be_to_cpu_32(tcp_spec->hdr.src_port);
+			}
+
+			if (tcp_spec->hdr.dst_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_DST;
+				filter->tenant_id =
+				rte_be_to_cpu_32(tcp_spec->hdr.dst_port);
+			}
+
+			filter->tunnel_type = I40E_CLOUD_TYPE_TCP;
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_SCTP:
+			sctp_spec = item->spec;
+			sctp_mask = item->mask;
+
+			if (!sctp_spec || !sctp_mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid sctp item");
+				return -rte_errno;
+			}
+
+			if (sctp_spec->hdr.src_port != 0 &&
+			    sctp_spec->hdr.dst_port != 0) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid sctp spec");
+				return -rte_errno;
+			}
+
+			if (sctp_spec->hdr.src_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_SRC;
+				filter->tenant_id =
+					rte_be_to_cpu_32(sctp_spec->hdr.src_port);
+			}
+
+			if (sctp_spec->hdr.dst_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_DST;
+				filter->tenant_id =
+					rte_be_to_cpu_32(sctp_spec->hdr.dst_port);
+			}
+
+			filter->tunnel_type = I40E_CLOUD_TYPE_SCTP;
+
+			break;
+		default:
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static int
+i40e_flow_parse_l4_proto_filter(struct rte_eth_dev *dev,
+				const struct rte_flow_attr *attr,
+				const struct rte_flow_item pattern[],
+				const struct rte_flow_action actions[],
+				struct rte_flow_error *error,
+				union i40e_filter_t *filter)
+{
+	struct i40e_tunnel_filter_conf *tunnel_filter =
+		&filter->consistent_tunnel_filter;
+	int ret;
+
+	ret = i40e_flow_parse_l4_proto_pattern(pattern, error, tunnel_filter);
+	if (ret)
+		return ret;
+
+	ret = i40e_flow_parse_tunnel_action(dev, actions, error, tunnel_filter);
+	if (ret)
+		return ret;
+
+	ret = i40e_flow_parse_attr(attr, error);
+	if (ret)
+		return ret;
+
+	cons_filter_type = RTE_ETH_FILTER_TUNNEL;
+
+	return ret;
+}
+
 static uint16_t i40e_supported_tunnel_filter_types[] = {
 	ETH_TUNNEL_FILTER_IMAC | ETH_TUNNEL_FILTER_TENID |
 	ETH_TUNNEL_FILTER_IVLAN,
-- 
2.17.1


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

* Re: [dpdk-dev] [PATCH v3] net/i40e: support cloud filter with L4 port
  2020-07-07  6:33 ` [dpdk-dev] [PATCH v3] net/i40e: support cloud filter with L4 port Guinan Sun
@ 2020-07-07  8:15   ` Xing, Beilei
  0 siblings, 0 replies; 16+ messages in thread
From: Xing, Beilei @ 2020-07-07  8:15 UTC (permalink / raw)
  To: Sun, GuinanX, dev; +Cc: Guo, Jia



> -----Original Message-----
> From: Sun, GuinanX <guinanx.sun@intel.com>
> Sent: Tuesday, July 7, 2020 2:34 PM
> To: dev@dpdk.org
> Cc: Xing, Beilei <beilei.xing@intel.com>; Guo, Jia <jia.guo@intel.com>; Sun,
> GuinanX <guinanx.sun@intel.com>
> Subject: [PATCH v3] net/i40e: support cloud filter with L4 port
> 
> This patch enables the filter that supports to create following two rules for
> the same packet type:
> One is to select source port only as input set and the other is for destination
> port only.
> And the supported packet types are UDP/TCP/SCTP.
> 
> Signed-off-by: Guinan Sun <guinanx.sun@intel.com>
> ---
> v3:
> * Add limitation to i40e.rst
> * Rename variables.
> * Fixed the variable assignment.
> v2:
> * Fixed code style and variable naming
> ---
>  doc/guides/nics/i40e.rst               |   9 +
>  doc/guides/rel_notes/release_20_08.rst |   8 +
>  drivers/net/i40e/i40e_ethdev.c         | 200 +++++++++++++++++++++-
>  drivers/net/i40e/i40e_ethdev.h         |  18 ++
>  drivers/net/i40e/i40e_flow.c           | 223 +++++++++++++++++++++++++
>  5 files changed, 457 insertions(+), 1 deletion(-)
> 
> diff --git a/doc/guides/nics/i40e.rst b/doc/guides/nics/i40e.rst index
> 00c3042d5..98a5537d7 100644
> --- a/doc/guides/nics/i40e.rst
> +++ b/doc/guides/nics/i40e.rst
> @@ -736,6 +736,15 @@ with DPDK, then the configuration will also impact
> port B in the NIC with  kernel driver, which don't want to use the TPID.
>  So PMD reports warning to clarify what is changed by writing global register.
> 
> +L4 port filter

Please don't use 'L4 port filter', there's no such filter type in i40e pipeline.

> +~~~~~~~~~~~~~~
> +
> +L4 port filter is a new type of cloud filter.
> +It is possible to generate two filters - one to select L4 DST port and
> +second to select L4 SRC port.
> +If the L4 port filter is used, the cloud filter using inner Vlan and
> +Tunnel Key will be invalid.
> +
>  High Performance of Small Packets on 40GbE NIC
>  ----------------------------------------------
> 
> diff --git a/doc/guides/rel_notes/release_20_08.rst
> b/doc/guides/rel_notes/release_20_08.rst
> index f4b858727..d7d4c4e3b 100644
> --- a/doc/guides/rel_notes/release_20_08.rst
> +++ b/doc/guides/rel_notes/release_20_08.rst
> @@ -108,6 +108,14 @@ New Features
>    * Dump ``rte_flow`` memory consumption.
>    * Measure packet per second forwarding.
> 
> +* **Updated Intel i40e driver.**
> +
> +  Updated i40e PMD with new features and improvements, including:
> +
> +  * Added a new type of cloud filter to support the coexistence of the
> +    following two rules. One selects L4 destination port as input set and
> +    the other one selects L4 source port. We call it L4 port filter.
We didn't call it L4 port filter.

> +    But there are limitations on using the L4 port filter.
I think no need to mention the limitation here, since you have added in i40e.rst

<snip>


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

* [dpdk-dev] [PATCH v4] net/i40e: support cloud filter with L4 port
  2020-06-11  5:24 [dpdk-dev] [PATCH] net/i40e: enable port filter by switch filter Guinan Sun
                   ` (3 preceding siblings ...)
  2020-07-07  6:33 ` [dpdk-dev] [PATCH v3] net/i40e: support cloud filter with L4 port Guinan Sun
@ 2020-07-08  3:11 ` Guinan Sun
  2020-07-08  6:01   ` Xing, Beilei
  2020-07-08  6:27 ` [dpdk-dev] [PATCH v5] " Guinan Sun
  2020-07-08  7:40 ` [dpdk-dev] [PATCH v6] " Guinan Sun
  6 siblings, 1 reply; 16+ messages in thread
From: Guinan Sun @ 2020-07-08  3:11 UTC (permalink / raw)
  To: dev; +Cc: Beilei Xing, Jeff Guo, Guinan Sun

This patch enables cloud filter for IPv4_UDP/IPv4_TCP/IPv4_SCTP
with SRC port only or DST port only.
This supports different filter types for the same packet type.
E.g. one IPv4_UDP rules with SRC port only and another IPv4_UDP rule
with DST port only.

Signed-off-by: Guinan Sun <guinanx.sun@intel.com>
---
v4:
* Modify release_20_08.rst and i40e.rst.
* Rename L4 port filter.
* Modify commit log.
* Fixed the variable assignment.
v3:
* Add limitation to i40e.rst.
* Rename variables.
* Fixed the variable assignment.
v2:
* Fixed code style and variable naming.
---
 doc/guides/nics/i40e.rst               |   7 +
 doc/guides/rel_notes/release_20_08.rst |  11 ++
 drivers/net/i40e/i40e_ethdev.c         | 200 ++++++++++++++++++++-
 drivers/net/i40e/i40e_ethdev.h         |  18 ++
 drivers/net/i40e/i40e_flow.c           | 230 +++++++++++++++++++++++++
 5 files changed, 465 insertions(+), 1 deletion(-)

diff --git a/doc/guides/nics/i40e.rst b/doc/guides/nics/i40e.rst
index 00c3042d5..cf35d51b3 100644
--- a/doc/guides/nics/i40e.rst
+++ b/doc/guides/nics/i40e.rst
@@ -736,6 +736,13 @@ with DPDK, then the configuration will also impact port B in the NIC with
 kernel driver, which don't want to use the TPID.
 So PMD reports warning to clarify what is changed by writing global register.
 
+Cloud Filter
+~~~~~~~~~~~~
+
+When programming cloud filters for IPv4_UDP/IPv4_TCP/IPv4_SCTP with SRC port only or DST port only,
+it will make any cloud filter using inner_vlan or tunnel key invalid. Default configuration will be
+recovered only by NIC core reset.
+
 High Performance of Small Packets on 40GbE NIC
 ----------------------------------------------
 
diff --git a/doc/guides/rel_notes/release_20_08.rst b/doc/guides/rel_notes/release_20_08.rst
index eaa9d13b5..c64083cf0 100644
--- a/doc/guides/rel_notes/release_20_08.rst
+++ b/doc/guides/rel_notes/release_20_08.rst
@@ -137,6 +137,17 @@ New Features
   See the :doc:`../sample_app_ug/l2_forward_real_virtual` for more
   details of this parameter usage.
 
+* **Updated Intel i40e driver.**
+
+  Updated i40e PMD with new features and improvements, including:
+
+  * Added a new type of cloud filte.
+    This new feature enables cloud filter for IPv4_UDP/IPv4_TCP/IPv4_SCTP
+    with SRC port only or DST port only.
+    This supports different filter types for the same packet type.
+    E.g. one IPv4_UDP rules with SRC port only and another IPv4_UDP rule
+    with DST port only.
+
 
 Removed Items
 -------------
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 777e14926..fd4582c84 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -7944,6 +7944,13 @@ i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
 #define I40E_TR_GRE_KEY_MASK			0x400
 #define I40E_TR_GRE_KEY_WITH_XSUM_MASK		0x800
 #define I40E_TR_GRE_NO_KEY_MASK			0x8000
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_PORT_TR_WORD0 0x49
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_DIRECTION_WORD0 0x41
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_INGRESS_WORD0 0x80
+#define I40E_DIRECTION_INGRESS_KEY		0x8000
+#define I40E_TR_L4_TYPE_TCP			0x2
+#define I40E_TR_L4_TYPE_UDP			0x4
+#define I40E_TR_L4_TYPE_SCTP			0x8
 
 static enum
 i40e_status_code i40e_replace_mpls_l1_filter(struct i40e_pf *pf)
@@ -8242,6 +8249,132 @@ i40e_status_code i40e_replace_gtp_cloud_filter(struct i40e_pf *pf)
 	return status;
 }
 
+static enum i40e_status_code
+i40e_replace_port_l1_filter(struct i40e_pf *pf,
+			    enum i40e_l4_port_type l4_port_type)
+{
+	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
+	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
+	enum i40e_status_code status = I40E_SUCCESS;
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	struct rte_eth_dev *dev = ((struct i40e_adapter *)hw->back)->eth_dev;
+
+	if (pf->support_multi_driver) {
+		PMD_DRV_LOG(ERR, "Replace l1 filter is not supported.");
+		return I40E_NOT_SUPPORTED;
+	}
+
+	memset(&filter_replace, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+	memset(&filter_replace_buf, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+
+	/* create L1 filter */
+	if (l4_port_type == I40E_L4_PORT_TYPE_SRC) {
+		filter_replace.old_filter_type =
+			I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TUNNLE_KEY;
+		filter_replace.new_filter_type = I40E_AQC_ADD_L1_FILTER_0X11;
+		filter_replace_buf.data[8] =
+			I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_SRC_PORT;
+	} else {
+		filter_replace.old_filter_type =
+			I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG_IVLAN;
+		filter_replace.new_filter_type = I40E_AQC_ADD_L1_FILTER_0X10;
+		filter_replace_buf.data[8] =
+			I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_DST_PORT;
+	}
+
+	filter_replace.tr_bit = 0;
+	/* Prepare the buffer, 3 entries */
+	filter_replace_buf.data[0] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_DIRECTION_WORD0;
+	filter_replace_buf.data[0] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[2] = 0x00;
+	filter_replace_buf.data[3] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_INGRESS_WORD0;
+	filter_replace_buf.data[4] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_PORT_TR_WORD0;
+	filter_replace_buf.data[4] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[5] = 0x00;
+	filter_replace_buf.data[6] = I40E_TR_L4_TYPE_UDP |
+		I40E_TR_L4_TYPE_TCP |
+		I40E_TR_L4_TYPE_SCTP;
+	filter_replace_buf.data[7] = 0x00;
+	filter_replace_buf.data[8] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[9] = 0x00;
+	filter_replace_buf.data[10] = 0xFF;
+	filter_replace_buf.data[11] = 0xFF;
+
+	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+					       &filter_replace_buf);
+	if (!status && filter_replace.old_filter_type !=
+	    filter_replace.new_filter_type)
+		PMD_DRV_LOG(WARNING, "i40e device %s changed cloud l1 type."
+			    " original: 0x%x, new: 0x%x",
+			    dev->device->name,
+			    filter_replace.old_filter_type,
+			    filter_replace.new_filter_type);
+
+	return status;
+}
+
+static enum i40e_status_code
+i40e_replace_port_cloud_filter(struct i40e_pf *pf,
+			       enum i40e_l4_port_type l4_port_type)
+{
+	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
+	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
+	enum i40e_status_code status = I40E_SUCCESS;
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	struct rte_eth_dev *dev = ((struct i40e_adapter *)hw->back)->eth_dev;
+
+	if (pf->support_multi_driver) {
+		PMD_DRV_LOG(ERR, "Replace cloud filter is not supported.");
+		return I40E_NOT_SUPPORTED;
+	}
+
+	memset(&filter_replace, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+	memset(&filter_replace_buf, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+
+	if (l4_port_type == I40E_L4_PORT_TYPE_SRC) {
+		filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_IIP;
+		filter_replace.new_filter_type =
+			I40E_AQC_ADD_CLOUD_FILTER_0X11;
+		filter_replace_buf.data[4] = I40E_AQC_ADD_CLOUD_FILTER_0X11;
+	} else {
+		filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_OIP;
+		filter_replace.new_filter_type =
+			I40E_AQC_ADD_CLOUD_FILTER_0X10;
+		filter_replace_buf.data[4] = I40E_AQC_ADD_CLOUD_FILTER_0X10;
+	}
+
+	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER;
+	filter_replace.tr_bit = 0;
+	/* Prepare the buffer, 2 entries */
+	filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
+	filter_replace_buf.data[0] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[4] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+					       &filter_replace_buf);
+
+	if (!status && filter_replace.old_filter_type !=
+	    filter_replace.new_filter_type)
+		PMD_DRV_LOG(WARNING, "i40e device %s changed cloud filter type."
+			    " original: 0x%x, new: 0x%x",
+			    dev->device->name,
+			    filter_replace.old_filter_type,
+			    filter_replace.new_filter_type);
+
+	return status;
+}
+
 int
 i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		      struct i40e_tunnel_filter_conf *tunnel_filter,
@@ -8389,6 +8522,62 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		pfilter->general_fields[0] = tunnel_filter->inner_vlan;
 		pfilter->general_fields[1] = tunnel_filter->outer_vlan;
 		big_buffer = 1;
+		break;
+	case I40E_CLOUD_TYPE_UDP:
+	case I40E_CLOUD_TYPE_TCP:
+	case I40E_CLOUD_TYPE_SCTP:
+		if (tunnel_filter->l4_port_type == I40E_L4_PORT_TYPE_SRC) {
+			if (!pf->sport_replace_flag) {
+				i40e_replace_port_l1_filter(pf,
+						tunnel_filter->l4_port_type);
+				i40e_replace_port_cloud_filter(pf,
+						tunnel_filter->l4_port_type);
+				pf->sport_replace_flag = 1;
+			}
+			teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
+			pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
+				I40E_DIRECTION_INGRESS_KEY;
+
+			if (tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_UDP)
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+					I40E_TR_L4_TYPE_UDP;
+			else if (tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_TCP)
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+					I40E_TR_L4_TYPE_TCP;
+			else
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+					I40E_TR_L4_TYPE_SCTP;
+
+			pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
+				(teid_le >> 16) & 0xFFFF;
+			big_buffer = 1;
+		} else {
+			if (!pf->dport_replace_flag) {
+				i40e_replace_port_l1_filter(pf,
+						tunnel_filter->l4_port_type);
+				i40e_replace_port_cloud_filter(pf,
+						tunnel_filter->l4_port_type);
+				pf->dport_replace_flag = 1;
+			}
+			teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
+			pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD0] =
+				I40E_DIRECTION_INGRESS_KEY;
+
+			if (tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_UDP)
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
+					I40E_TR_L4_TYPE_UDP;
+			else if (tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_TCP)
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
+					I40E_TR_L4_TYPE_TCP;
+			else
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
+					I40E_TR_L4_TYPE_SCTP;
+
+			pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD2] =
+				(teid_le >> 16) & 0xFFFF;
+			big_buffer = 1;
+		}
+
 		break;
 	default:
 		/* Other tunnel types is not supported. */
@@ -8412,7 +8601,16 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_QINQ)
 		pfilter->element.flags |=
 			I40E_AQC_ADD_CLOUD_FILTER_0X10;
-	else {
+	else if (tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_UDP ||
+		 tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_TCP ||
+		 tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_SCTP) {
+		if (tunnel_filter->l4_port_type == I40E_L4_PORT_TYPE_SRC)
+			pfilter->element.flags |=
+				I40E_AQC_ADD_L1_FILTER_0X11;
+		else
+			pfilter->element.flags |=
+				I40E_AQC_ADD_CLOUD_FILTER_0X10;
+	} else {
 		val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
 						&pfilter->element.flags);
 		if (val < 0) {
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index e5d0ce53f..8442eb256 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -767,11 +767,14 @@ struct i40e_rss_pattern_info {
 
 #define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD0 44
 #define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD1 45
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_SRC_PORT 29
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_DST_PORT 30
 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSOUDP	8
 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSOGRE	9
 #define I40E_AQC_ADD_CLOUD_FILTER_0X10		0x10
 #define I40E_AQC_ADD_CLOUD_FILTER_0X11		0x11
 #define I40E_AQC_ADD_CLOUD_FILTER_0X12		0x12
+#define I40E_AQC_ADD_L1_FILTER_0X10		0x10
 #define I40E_AQC_ADD_L1_FILTER_0X11		0x11
 #define I40E_AQC_ADD_L1_FILTER_0X12		0x12
 #define I40E_AQC_ADD_L1_FILTER_0X13		0x13
@@ -828,9 +831,20 @@ enum i40e_tunnel_type {
 	I40E_TUNNEL_TYPE_GTPU,
 	I40E_TUNNEL_TYPE_ESPoUDP,
 	I40E_TUNNEL_TYPE_ESPoIP,
+	I40E_CLOUD_TYPE_UDP,
+	I40E_CLOUD_TYPE_TCP,
+	I40E_CLOUD_TYPE_SCTP,
 	I40E_TUNNEL_TYPE_MAX,
 };
 
+/**
+ * L4 port type.
+ */
+enum i40e_l4_port_type {
+	I40E_L4_PORT_TYPE_SRC = 0,
+	I40E_L4_PORT_TYPE_DST,
+};
+
 /**
  * Tunneling Packet filter configuration.
  */
@@ -852,6 +866,7 @@ struct i40e_tunnel_filter_conf {
 	/** Flags from ETH_TUNNEL_FILTER_XX - see above. */
 	uint16_t filter_type;
 	enum i40e_tunnel_type tunnel_type; /**< Tunnel Type. */
+	enum i40e_l4_port_type l4_port_type; /**< L4 Port Type. */
 	uint32_t tenant_id;     /**< Tenant ID to match. VNI, GRE key... */
 	uint16_t queue_id;      /**< Queue assigned to if match. */
 	uint8_t is_to_vf;       /**< 0 - to PF, 1 - to VF */
@@ -1073,6 +1088,9 @@ struct i40e_pf {
 	bool mpls_replace_flag;  /* 1 - MPLS filter replace is done */
 	bool gtp_replace_flag;   /* 1 - GTP-C/U filter replace is done */
 	bool qinq_replace_flag;  /* QINQ filter replace is done */
+	/* l4 port flag */
+	bool sport_replace_flag;   /* Source port replace is done */
+	bool dport_replace_flag;   /* Destination port replace is done */
 	struct i40e_tm_conf tm_conf;
 	bool support_multi_driver; /* 1 - support multiple driver */
 
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 8f8df6fae..955aead58 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -124,6 +124,12 @@ i40e_flow_parse_qinq_pattern(struct rte_eth_dev *dev,
 			      struct rte_flow_error *error,
 			      struct i40e_tunnel_filter_conf *filter);
 
+static int i40e_flow_parse_l4_cloud_filter(struct rte_eth_dev *dev,
+					   const struct rte_flow_attr *attr,
+					   const struct rte_flow_item pattern[],
+					   const struct rte_flow_action actions[],
+					   struct rte_flow_error *error,
+					   union i40e_filter_t *filter);
 const struct rte_flow_ops i40e_flow_ops = {
 	.validate = i40e_flow_validate,
 	.create = i40e_flow_create,
@@ -1845,6 +1851,13 @@ static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	/* L2TPv3 over IP */
 	{ pattern_fdir_ipv4_l2tpv3oip, i40e_flow_parse_fdir_filter },
 	{ pattern_fdir_ipv6_l2tpv3oip, i40e_flow_parse_fdir_filter },
+	/* L4 over port */
+	{ pattern_fdir_ipv4_udp, i40e_flow_parse_l4_cloud_filter },
+	{ pattern_fdir_ipv4_tcp, i40e_flow_parse_l4_cloud_filter },
+	{ pattern_fdir_ipv4_sctp, i40e_flow_parse_l4_cloud_filter },
+	{ pattern_fdir_ipv6_udp, i40e_flow_parse_l4_cloud_filter },
+	{ pattern_fdir_ipv6_tcp, i40e_flow_parse_l4_cloud_filter },
+	{ pattern_fdir_ipv6_sctp, i40e_flow_parse_l4_cloud_filter },
 };
 
 #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
@@ -3541,6 +3554,223 @@ i40e_flow_parse_tunnel_action(struct rte_eth_dev *dev,
 	return 0;
 }
 
+/* 1. Last in item should be NULL as range is not supported.
+ * 2. Supported filter types: Source port only and Destination port only.
+ * 3. Mask of fields which need to be matched should be
+ *    filled with 1.
+ * 4. Mask of fields which needn't to be matched should be
+ *    filled with 0.
+ */
+static int
+i40e_flow_parse_l4_pattern(const struct rte_flow_item *pattern,
+			   struct rte_flow_error *error,
+			   struct i40e_tunnel_filter_conf *filter)
+{
+	const struct rte_flow_item_sctp *sctp_spec, *sctp_mask;
+	const struct rte_flow_item_tcp *tcp_spec, *tcp_mask;
+	const struct rte_flow_item_udp *udp_spec, *udp_mask;
+	const struct rte_flow_item *item = pattern;
+	enum rte_flow_item_type item_type;
+
+	for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+		if (item->last) {
+			rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM,
+					   item,
+					   "Not support range");
+			return -rte_errno;
+		}
+		item_type = item->type;
+		switch (item_type) {
+		case RTE_FLOW_ITEM_TYPE_ETH:
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid ETH item");
+				return -rte_errno;
+			}
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV4:
+			filter->ip_type = I40E_TUNNEL_IPTYPE_IPV4;
+			/* IPv4 is used to describe protocol,
+			 * spec and mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid IPv4 item");
+				return -rte_errno;
+			}
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV6:
+			filter->ip_type = I40E_TUNNEL_IPTYPE_IPV6;
+			/* IPv6 is used to describe protocol,
+			 * spec and mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid IPv6 item");
+				return -rte_errno;
+			}
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_UDP:
+			udp_spec = item->spec;
+			udp_mask = item->mask;
+
+			if (!udp_spec || !udp_mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid udp item");
+				return -rte_errno;
+			}
+
+			if (udp_spec->hdr.src_port != 0 &&
+			    udp_spec->hdr.dst_port != 0) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid udp spec");
+				return -rte_errno;
+			}
+
+			if (udp_spec->hdr.src_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_SRC;
+				filter->tenant_id =
+				rte_be_to_cpu_32(udp_spec->hdr.src_port);
+			}
+
+			if (udp_spec->hdr.dst_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_DST;
+				filter->tenant_id =
+				rte_be_to_cpu_32(udp_spec->hdr.dst_port);
+			}
+
+			filter->tunnel_type = I40E_CLOUD_TYPE_UDP;
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_TCP:
+			tcp_spec = item->spec;
+			tcp_mask = item->mask;
+
+			if (!tcp_spec || !tcp_mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid tcp item");
+				return -rte_errno;
+			}
+
+			if (tcp_spec->hdr.src_port != 0 &&
+			    tcp_spec->hdr.dst_port != 0) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid tcp spec");
+				return -rte_errno;
+			}
+
+			if (tcp_spec->hdr.src_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_SRC;
+				filter->tenant_id =
+				rte_be_to_cpu_32(tcp_spec->hdr.src_port);
+			}
+
+			if (tcp_spec->hdr.dst_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_DST;
+				filter->tenant_id =
+				rte_be_to_cpu_32(tcp_spec->hdr.dst_port);
+			}
+
+			filter->tunnel_type = I40E_CLOUD_TYPE_TCP;
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_SCTP:
+			sctp_spec = item->spec;
+			sctp_mask = item->mask;
+
+			if (!sctp_spec || !sctp_mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid sctp item");
+				return -rte_errno;
+			}
+
+			if (sctp_spec->hdr.src_port != 0 &&
+			    sctp_spec->hdr.dst_port != 0) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid sctp spec");
+				return -rte_errno;
+			}
+
+			if (sctp_spec->hdr.src_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_SRC;
+				filter->tenant_id =
+					rte_be_to_cpu_32(sctp_spec->hdr.src_port);
+			}
+
+			if (sctp_spec->hdr.dst_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_DST;
+				filter->tenant_id =
+					rte_be_to_cpu_32(sctp_spec->hdr.dst_port);
+			}
+
+			filter->tunnel_type = I40E_CLOUD_TYPE_SCTP;
+
+			break;
+		default:
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static int
+i40e_flow_parse_l4_cloud_filter(struct rte_eth_dev *dev,
+				const struct rte_flow_attr *attr,
+				const struct rte_flow_item pattern[],
+				const struct rte_flow_action actions[],
+				struct rte_flow_error *error,
+				union i40e_filter_t *filter)
+{
+	struct i40e_tunnel_filter_conf *tunnel_filter =
+		&filter->consistent_tunnel_filter;
+	int ret;
+
+	ret = i40e_flow_parse_l4_pattern(pattern, error, tunnel_filter);
+	if (ret)
+		return ret;
+
+	ret = i40e_flow_parse_tunnel_action(dev, actions, error, tunnel_filter);
+	if (ret)
+		return ret;
+
+	ret = i40e_flow_parse_attr(attr, error);
+	if (ret)
+		return ret;
+
+	cons_filter_type = RTE_ETH_FILTER_TUNNEL;
+
+	return ret;
+}
+
 static uint16_t i40e_supported_tunnel_filter_types[] = {
 	ETH_TUNNEL_FILTER_IMAC | ETH_TUNNEL_FILTER_TENID |
 	ETH_TUNNEL_FILTER_IVLAN,
-- 
2.17.1


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

* Re: [dpdk-dev] [PATCH v4] net/i40e: support cloud filter with L4 port
  2020-07-08  3:11 ` [dpdk-dev] [PATCH v4] " Guinan Sun
@ 2020-07-08  6:01   ` Xing, Beilei
  0 siblings, 0 replies; 16+ messages in thread
From: Xing, Beilei @ 2020-07-08  6:01 UTC (permalink / raw)
  To: Sun, GuinanX, dev; +Cc: Guo, Jia



> -----Original Message-----
> From: Sun, GuinanX <guinanx.sun@intel.com>
> Sent: Wednesday, July 8, 2020 11:12 AM
> To: dev@dpdk.org
> Cc: Xing, Beilei <beilei.xing@intel.com>; Guo, Jia <jia.guo@intel.com>; Sun,
> GuinanX <guinanx.sun@intel.com>
> Subject: [PATCH v4] net/i40e: support cloud filter with L4 port
> 
> This patch enables cloud filter for IPv4_UDP/IPv4_TCP/IPv4_SCTP with SRC
> port only or DST port only.

Does it support IPv6_XXX?

> This supports different filter types for the same packet type.
> E.g. one IPv4_UDP rules with SRC port only and another IPv4_UDP rule with
> DST port only.
> 
> Signed-off-by: Guinan Sun <guinanx.sun@intel.com>
> ---
> v4:
> * Modify release_20_08.rst and i40e.rst.
> * Rename L4 port filter.
> * Modify commit log.
> * Fixed the variable assignment.
> v3:
> * Add limitation to i40e.rst.
> * Rename variables.
> * Fixed the variable assignment.
> v2:
> * Fixed code style and variable naming.
> ---
>  doc/guides/nics/i40e.rst               |   7 +
>  doc/guides/rel_notes/release_20_08.rst |  11 ++
>  drivers/net/i40e/i40e_ethdev.c         | 200 ++++++++++++++++++++-
>  drivers/net/i40e/i40e_ethdev.h         |  18 ++
>  drivers/net/i40e/i40e_flow.c           | 230 +++++++++++++++++++++++++
>  5 files changed, 465 insertions(+), 1 deletion(-)
> 
> diff --git a/doc/guides/nics/i40e.rst b/doc/guides/nics/i40e.rst index
> 00c3042d5..cf35d51b3 100644
> --- a/doc/guides/nics/i40e.rst
> +++ b/doc/guides/nics/i40e.rst
> @@ -736,6 +736,13 @@ with DPDK, then the configuration will also impact
> port B in the NIC with  kernel driver, which don't want to use the TPID.
>  So PMD reports warning to clarify what is changed by writing global register.
> 
> +Cloud Filter
> +~~~~~~~~~~~~
> +
> +When programming cloud filters for IPv4_UDP/IPv4_TCP/IPv4_SCTP with SRC

Same as above.

> +port only or DST port only, it will make any cloud filter using
> +inner_vlan or tunnel key invalid. Default configuration will be recovered only
> by NIC core reset.
> +
>  High Performance of Small Packets on 40GbE NIC
>  ----------------------------------------------
> 
> diff --git a/doc/guides/rel_notes/release_20_08.rst
> b/doc/guides/rel_notes/release_20_08.rst
> index eaa9d13b5..c64083cf0 100644
> --- a/doc/guides/rel_notes/release_20_08.rst
> +++ b/doc/guides/rel_notes/release_20_08.rst
> @@ -137,6 +137,17 @@ New Features
>    See the :doc:`../sample_app_ug/l2_forward_real_virtual` for more
>    details of this parameter usage.
> 
> +* **Updated Intel i40e driver.**
> +
> +  Updated i40e PMD with new features and improvements, including:
> +
> +  * Added a new type of cloud filte.

* Improved cloud filter

> +    This new feature enables cloud filter for IPv4_UDP/IPv4_TCP/IPv4_SCTP
> +    with SRC port only or DST port only.
> +    This supports different filter types for the same packet type.
> +    E.g. one IPv4_UDP rules with SRC port only and another IPv4_UDP rule
> +    with DST port only.
> +
> 
>  Removed Items
>  -------------
> diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
> index 777e14926..fd4582c84 100644
> --- a/drivers/net/i40e/i40e_ethdev.c
> +++ b/drivers/net/i40e/i40e_ethdev.c
> @@ -7944,6 +7944,13 @@ i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
>  #define I40E_TR_GRE_KEY_MASK			0x400
>  #define I40E_TR_GRE_KEY_WITH_XSUM_MASK		0x800
>  #define I40E_TR_GRE_NO_KEY_MASK			0x8000
> +#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_PORT_TR_WORD0 0x49
> #define
> +I40E_AQC_REPLACE_CLOUD_CMD_INPUT_DIRECTION_WORD0 0x41 #define
> +I40E_AQC_REPLACE_CLOUD_CMD_INPUT_INGRESS_WORD0 0x80
> +#define I40E_DIRECTION_INGRESS_KEY		0x8000
> +#define I40E_TR_L4_TYPE_TCP			0x2
> +#define I40E_TR_L4_TYPE_UDP			0x4
> +#define I40E_TR_L4_TYPE_SCTP			0x8
> 
>  static enum
>  i40e_status_code i40e_replace_mpls_l1_filter(struct i40e_pf *pf) @@ -8242,6
> +8249,132 @@ i40e_status_code i40e_replace_gtp_cloud_filter(struct i40e_pf
> *pf)
>  	return status;
>  }
> 
> +static enum i40e_status_code
> +i40e_replace_port_l1_filter(struct i40e_pf *pf,
> +			    enum i40e_l4_port_type l4_port_type) {
> +	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
> +	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
> +	enum i40e_status_code status = I40E_SUCCESS;
> +	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
> +	struct rte_eth_dev *dev = ((struct i40e_adapter *)hw->back)->eth_dev;
> +
> +	if (pf->support_multi_driver) {
> +		PMD_DRV_LOG(ERR, "Replace l1 filter is not supported.");
> +		return I40E_NOT_SUPPORTED;
> +	}
> +
> +	memset(&filter_replace, 0,
> +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
> +	memset(&filter_replace_buf, 0,
> +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
> +
> +	/* create L1 filter */
> +	if (l4_port_type == I40E_L4_PORT_TYPE_SRC) {
> +		filter_replace.old_filter_type =
> +
> 	I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TUNNLE_KEY;
> +		filter_replace.new_filter_type =
> I40E_AQC_ADD_L1_FILTER_0X11;
> +		filter_replace_buf.data[8] =
> +
> 	I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_SRC_PORT;
> +	} else {
> +		filter_replace.old_filter_type =
> +
> 	I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG_IVLAN;
> +		filter_replace.new_filter_type =
> I40E_AQC_ADD_L1_FILTER_0X10;
> +		filter_replace_buf.data[8] =
> +
> 	I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_DST_PORT;
> +	}
> +
> +	filter_replace.tr_bit = 0;
> +	/* Prepare the buffer, 3 entries */
> +	filter_replace_buf.data[0] =
> +
> 	I40E_AQC_REPLACE_CLOUD_CMD_INPUT_DIRECTION_WORD0;
> +	filter_replace_buf.data[0] |=
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> +	filter_replace_buf.data[2] = 0x00;
> +	filter_replace_buf.data[3] =
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_INGRESS_WORD0;
> +	filter_replace_buf.data[4] =
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_PORT_TR_WORD0;
> +	filter_replace_buf.data[4] |=
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> +	filter_replace_buf.data[5] = 0x00;
> +	filter_replace_buf.data[6] = I40E_TR_L4_TYPE_UDP |
> +		I40E_TR_L4_TYPE_TCP |
> +		I40E_TR_L4_TYPE_SCTP;
> +	filter_replace_buf.data[7] = 0x00;
> +	filter_replace_buf.data[8] |=
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> +	filter_replace_buf.data[9] = 0x00;
> +	filter_replace_buf.data[10] = 0xFF;
> +	filter_replace_buf.data[11] = 0xFF;
> +
> +	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
> +					       &filter_replace_buf);
> +	if (!status && filter_replace.old_filter_type !=
> +	    filter_replace.new_filter_type)
> +		PMD_DRV_LOG(WARNING, "i40e device %s changed cloud l1
> type."
> +			    " original: 0x%x, new: 0x%x",
> +			    dev->device->name,
> +			    filter_replace.old_filter_type,
> +			    filter_replace.new_filter_type);
> +
> +	return status;
> +}
> +
> +static enum i40e_status_code
> +i40e_replace_port_cloud_filter(struct i40e_pf *pf,
> +			       enum i40e_l4_port_type l4_port_type) {
> +	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
> +	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
> +	enum i40e_status_code status = I40E_SUCCESS;
> +	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
> +	struct rte_eth_dev *dev = ((struct i40e_adapter *)hw->back)->eth_dev;
> +
> +	if (pf->support_multi_driver) {
> +		PMD_DRV_LOG(ERR, "Replace cloud filter is not supported.");
> +		return I40E_NOT_SUPPORTED;
> +	}
> +
> +	memset(&filter_replace, 0,
> +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
> +	memset(&filter_replace_buf, 0,
> +	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
> +
> +	if (l4_port_type == I40E_L4_PORT_TYPE_SRC) {
> +		filter_replace.old_filter_type =
> I40E_AQC_ADD_CLOUD_FILTER_IIP;
> +		filter_replace.new_filter_type =
> +			I40E_AQC_ADD_CLOUD_FILTER_0X11;
> +		filter_replace_buf.data[4] =
> I40E_AQC_ADD_CLOUD_FILTER_0X11;
> +	} else {
> +		filter_replace.old_filter_type =
> I40E_AQC_ADD_CLOUD_FILTER_OIP;
> +		filter_replace.new_filter_type =
> +			I40E_AQC_ADD_CLOUD_FILTER_0X10;
> +		filter_replace_buf.data[4] =
> I40E_AQC_ADD_CLOUD_FILTER_0X10;
> +	}
> +
> +	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER;
> +	filter_replace.tr_bit = 0;
> +	/* Prepare the buffer, 2 entries */
> +	filter_replace_buf.data[0] =
> I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
> +	filter_replace_buf.data[0] |=
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> +	filter_replace_buf.data[4] |=
> +		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
> +	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
> +					       &filter_replace_buf);
> +
> +	if (!status && filter_replace.old_filter_type !=
> +	    filter_replace.new_filter_type)
> +		PMD_DRV_LOG(WARNING, "i40e device %s changed cloud
> filter type."
> +			    " original: 0x%x, new: 0x%x",
> +			    dev->device->name,
> +			    filter_replace.old_filter_type,
> +			    filter_replace.new_filter_type);
> +
> +	return status;
> +}
> +
>  int
>  i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
>  		      struct i40e_tunnel_filter_conf *tunnel_filter, @@ -8389,6
> +8522,62 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
>  		pfilter->general_fields[0] = tunnel_filter->inner_vlan;
>  		pfilter->general_fields[1] = tunnel_filter->outer_vlan;
>  		big_buffer = 1;
> +		break;
> +	case I40E_CLOUD_TYPE_UDP:
> +	case I40E_CLOUD_TYPE_TCP:
> +	case I40E_CLOUD_TYPE_SCTP:
> +		if (tunnel_filter->l4_port_type == I40E_L4_PORT_TYPE_SRC) {
> +			if (!pf->sport_replace_flag) {
> +				i40e_replace_port_l1_filter(pf,
> +						tunnel_filter->l4_port_type);
> +				i40e_replace_port_cloud_filter(pf,
> +						tunnel_filter->l4_port_type);
> +				pf->sport_replace_flag = 1;
> +			}
> +			teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
> +			pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
> +				I40E_DIRECTION_INGRESS_KEY;
> +
> +			if (tunnel_filter->tunnel_type ==
> I40E_CLOUD_TYPE_UDP)
> +				pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
> +					I40E_TR_L4_TYPE_UDP;
> +			else if (tunnel_filter->tunnel_type ==
> I40E_CLOUD_TYPE_TCP)
> +				pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
> +					I40E_TR_L4_TYPE_TCP;
> +			else
> +				pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
> +					I40E_TR_L4_TYPE_SCTP;
> +
> +			pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
> +				(teid_le >> 16) & 0xFFFF;
> +			big_buffer = 1;
> +		} else {
> +			if (!pf->dport_replace_flag) {
> +				i40e_replace_port_l1_filter(pf,
> +						tunnel_filter->l4_port_type);
> +				i40e_replace_port_cloud_filter(pf,
> +						tunnel_filter->l4_port_type);
> +				pf->dport_replace_flag = 1;
> +			}
> +			teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
> +			pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD0] =
> +				I40E_DIRECTION_INGRESS_KEY;
> +
> +			if (tunnel_filter->tunnel_type ==
> I40E_CLOUD_TYPE_UDP)
> +				pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
> +					I40E_TR_L4_TYPE_UDP;
> +			else if (tunnel_filter->tunnel_type ==
> I40E_CLOUD_TYPE_TCP)
> +				pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
> +					I40E_TR_L4_TYPE_TCP;
> +			else
> +				pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
> +					I40E_TR_L4_TYPE_SCTP;
> +
> +			pfilter-
> >general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD2] =
> +				(teid_le >> 16) & 0xFFFF;
> +			big_buffer = 1;
> +		}

Can we merge the duplicate code?

> +
>  		break;
>  	default:
>  		/* Other tunnel types is not supported. */ @@ -8412,7
> +8601,16 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
>  	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_QINQ)
>  		pfilter->element.flags |=
>  			I40E_AQC_ADD_CLOUD_FILTER_0X10;
> -	else {
> +	else if (tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_UDP ||
> +		 tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_TCP ||
> +		 tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_SCTP) {
> +		if (tunnel_filter->l4_port_type == I40E_L4_PORT_TYPE_SRC)
> +			pfilter->element.flags |=
> +				I40E_AQC_ADD_L1_FILTER_0X11;

Please check  I40E_AQC_ADD_L1_FILTER_0X11 or I40E_AQC_ADD_CLOUD_FILTER_0X11 here.

> +		else
> +			pfilter->element.flags |=
> +				I40E_AQC_ADD_CLOUD_FILTER_0X10;
> +	} else {
>  		val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
>  						&pfilter->element.flags);
>  		if (val < 0) {
<snip>


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

* [dpdk-dev] [PATCH v5] net/i40e: support cloud filter with L4 port
  2020-06-11  5:24 [dpdk-dev] [PATCH] net/i40e: enable port filter by switch filter Guinan Sun
                   ` (4 preceding siblings ...)
  2020-07-08  3:11 ` [dpdk-dev] [PATCH v4] " Guinan Sun
@ 2020-07-08  6:27 ` Guinan Sun
  2020-07-08  7:40 ` [dpdk-dev] [PATCH v6] " Guinan Sun
  6 siblings, 0 replies; 16+ messages in thread
From: Guinan Sun @ 2020-07-08  6:27 UTC (permalink / raw)
  To: dev; +Cc: Beilei Xing, Jeff Guo, Guinan Sun

This patch enables cloud filter for IPv4_UDP/IPv4_TCP/IPv4_SCTP
and IPv6_UDP/IPv6_TCP/IPv6_SCTP with SRC port only or DST port only.
This supports different filter types for the same packet type.
E.g. one IPv4_UDP rules with SRC port only and another IPv4_UDP rule
with DST port only.

Signed-off-by: Guinan Sun <guinanx.sun@intel.com>
---
v5:
* Add IPv6 to release_20_08.rst and i40e.rst.
* Fixed the variable assignment.
v4:
* Modify release_20_08.rst and i40e.rst.
* Rename L4 port filter.
* Modify commit log.
* Fixed the variable assignment.
v3:
* Add limitation to i40e.rst.
* Rename variables.
* Fixed the variable assignment.
v2:
* Fixed code style and variable naming.
---
 doc/guides/nics/i40e.rst               |   7 +
 doc/guides/rel_notes/release_20_08.rst |  11 ++
 drivers/net/i40e/i40e_ethdev.c         | 200 ++++++++++++++++++++-
 drivers/net/i40e/i40e_ethdev.h         |  18 ++
 drivers/net/i40e/i40e_flow.c           | 230 +++++++++++++++++++++++++
 5 files changed, 465 insertions(+), 1 deletion(-)

diff --git a/doc/guides/nics/i40e.rst b/doc/guides/nics/i40e.rst
index 00c3042d5..c0b45c637 100644
--- a/doc/guides/nics/i40e.rst
+++ b/doc/guides/nics/i40e.rst
@@ -736,6 +736,13 @@ with DPDK, then the configuration will also impact port B in the NIC with
 kernel driver, which don't want to use the TPID.
 So PMD reports warning to clarify what is changed by writing global register.
 
+Cloud Filter
+~~~~~~~~~~~~
+
+When programming cloud filters for IPv4_UDP/IPv4_TCP/IPv4_SCTP and IPv6_UDP/IPv6_TCP/IPv6_SCTP
+with SRC port only or DST port only, it will make any cloud filter using inner_vlan or tunnel key
+invalid. Default configuration will be recovered only by NIC core reset.
+
 High Performance of Small Packets on 40GbE NIC
 ----------------------------------------------
 
diff --git a/doc/guides/rel_notes/release_20_08.rst b/doc/guides/rel_notes/release_20_08.rst
index eaa9d13b5..3458bec02 100644
--- a/doc/guides/rel_notes/release_20_08.rst
+++ b/doc/guides/rel_notes/release_20_08.rst
@@ -137,6 +137,17 @@ New Features
   See the :doc:`../sample_app_ug/l2_forward_real_virtual` for more
   details of this parameter usage.
 
+* **Updated Intel i40e driver.**
+
+  Updated i40e PMD with new features and improvements, including:
+
+  * Improved cloud filter.
+    This new feature enables cloud filter for IPv4_UDP/IPv4_TCP/IPv4_SCTP
+    and IPv6_UDP/IPv6_TCP/IPv6_SCTP with SRC port only or DST port only.
+    This supports different filter types for the same packet type.
+    E.g. one IPv4_UDP rules with SRC port only and another IPv4_UDP rule
+    with DST port only.
+
 
 Removed Items
 -------------
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 777e14926..503097cb5 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -7944,6 +7944,13 @@ i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
 #define I40E_TR_GRE_KEY_MASK			0x400
 #define I40E_TR_GRE_KEY_WITH_XSUM_MASK		0x800
 #define I40E_TR_GRE_NO_KEY_MASK			0x8000
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_PORT_TR_WORD0 0x49
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_DIRECTION_WORD0 0x41
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_INGRESS_WORD0 0x80
+#define I40E_DIRECTION_INGRESS_KEY		0x8000
+#define I40E_TR_L4_TYPE_TCP			0x2
+#define I40E_TR_L4_TYPE_UDP			0x4
+#define I40E_TR_L4_TYPE_SCTP			0x8
 
 static enum
 i40e_status_code i40e_replace_mpls_l1_filter(struct i40e_pf *pf)
@@ -8242,6 +8249,132 @@ i40e_status_code i40e_replace_gtp_cloud_filter(struct i40e_pf *pf)
 	return status;
 }
 
+static enum i40e_status_code
+i40e_replace_port_l1_filter(struct i40e_pf *pf,
+			    enum i40e_l4_port_type l4_port_type)
+{
+	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
+	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
+	enum i40e_status_code status = I40E_SUCCESS;
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	struct rte_eth_dev *dev = ((struct i40e_adapter *)hw->back)->eth_dev;
+
+	if (pf->support_multi_driver) {
+		PMD_DRV_LOG(ERR, "Replace l1 filter is not supported.");
+		return I40E_NOT_SUPPORTED;
+	}
+
+	memset(&filter_replace, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+	memset(&filter_replace_buf, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+
+	/* create L1 filter */
+	if (l4_port_type == I40E_L4_PORT_TYPE_SRC) {
+		filter_replace.old_filter_type =
+			I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TUNNLE_KEY;
+		filter_replace.new_filter_type = I40E_AQC_ADD_L1_FILTER_0X11;
+		filter_replace_buf.data[8] =
+			I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_SRC_PORT;
+	} else {
+		filter_replace.old_filter_type =
+			I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG_IVLAN;
+		filter_replace.new_filter_type = I40E_AQC_ADD_L1_FILTER_0X10;
+		filter_replace_buf.data[8] =
+			I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_DST_PORT;
+	}
+
+	filter_replace.tr_bit = 0;
+	/* Prepare the buffer, 3 entries */
+	filter_replace_buf.data[0] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_DIRECTION_WORD0;
+	filter_replace_buf.data[0] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[2] = 0x00;
+	filter_replace_buf.data[3] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_INGRESS_WORD0;
+	filter_replace_buf.data[4] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_PORT_TR_WORD0;
+	filter_replace_buf.data[4] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[5] = 0x00;
+	filter_replace_buf.data[6] = I40E_TR_L4_TYPE_UDP |
+		I40E_TR_L4_TYPE_TCP |
+		I40E_TR_L4_TYPE_SCTP;
+	filter_replace_buf.data[7] = 0x00;
+	filter_replace_buf.data[8] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[9] = 0x00;
+	filter_replace_buf.data[10] = 0xFF;
+	filter_replace_buf.data[11] = 0xFF;
+
+	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+					       &filter_replace_buf);
+	if (!status && filter_replace.old_filter_type !=
+	    filter_replace.new_filter_type)
+		PMD_DRV_LOG(WARNING, "i40e device %s changed cloud l1 type."
+			    " original: 0x%x, new: 0x%x",
+			    dev->device->name,
+			    filter_replace.old_filter_type,
+			    filter_replace.new_filter_type);
+
+	return status;
+}
+
+static enum i40e_status_code
+i40e_replace_port_cloud_filter(struct i40e_pf *pf,
+			       enum i40e_l4_port_type l4_port_type)
+{
+	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
+	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
+	enum i40e_status_code status = I40E_SUCCESS;
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	struct rte_eth_dev *dev = ((struct i40e_adapter *)hw->back)->eth_dev;
+
+	if (pf->support_multi_driver) {
+		PMD_DRV_LOG(ERR, "Replace cloud filter is not supported.");
+		return I40E_NOT_SUPPORTED;
+	}
+
+	memset(&filter_replace, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+	memset(&filter_replace_buf, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+
+	if (l4_port_type == I40E_L4_PORT_TYPE_SRC) {
+		filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_IIP;
+		filter_replace.new_filter_type =
+			I40E_AQC_ADD_CLOUD_FILTER_0X11;
+		filter_replace_buf.data[4] = I40E_AQC_ADD_CLOUD_FILTER_0X11;
+	} else {
+		filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_OIP;
+		filter_replace.new_filter_type =
+			I40E_AQC_ADD_CLOUD_FILTER_0X10;
+		filter_replace_buf.data[4] = I40E_AQC_ADD_CLOUD_FILTER_0X10;
+	}
+
+	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER;
+	filter_replace.tr_bit = 0;
+	/* Prepare the buffer, 2 entries */
+	filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
+	filter_replace_buf.data[0] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[4] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+					       &filter_replace_buf);
+
+	if (!status && filter_replace.old_filter_type !=
+	    filter_replace.new_filter_type)
+		PMD_DRV_LOG(WARNING, "i40e device %s changed cloud filter type."
+			    " original: 0x%x, new: 0x%x",
+			    dev->device->name,
+			    filter_replace.old_filter_type,
+			    filter_replace.new_filter_type);
+
+	return status;
+}
+
 int
 i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		      struct i40e_tunnel_filter_conf *tunnel_filter,
@@ -8389,6 +8522,62 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		pfilter->general_fields[0] = tunnel_filter->inner_vlan;
 		pfilter->general_fields[1] = tunnel_filter->outer_vlan;
 		big_buffer = 1;
+		break;
+	case I40E_CLOUD_TYPE_UDP:
+	case I40E_CLOUD_TYPE_TCP:
+	case I40E_CLOUD_TYPE_SCTP:
+		if (tunnel_filter->l4_port_type == I40E_L4_PORT_TYPE_SRC) {
+			if (!pf->sport_replace_flag) {
+				i40e_replace_port_l1_filter(pf,
+						tunnel_filter->l4_port_type);
+				i40e_replace_port_cloud_filter(pf,
+						tunnel_filter->l4_port_type);
+				pf->sport_replace_flag = 1;
+			}
+			teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
+			pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
+				I40E_DIRECTION_INGRESS_KEY;
+
+			if (tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_UDP)
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+					I40E_TR_L4_TYPE_UDP;
+			else if (tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_TCP)
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+					I40E_TR_L4_TYPE_TCP;
+			else
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+					I40E_TR_L4_TYPE_SCTP;
+
+			pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
+				(teid_le >> 16) & 0xFFFF;
+			big_buffer = 1;
+		} else {
+			if (!pf->dport_replace_flag) {
+				i40e_replace_port_l1_filter(pf,
+						tunnel_filter->l4_port_type);
+				i40e_replace_port_cloud_filter(pf,
+						tunnel_filter->l4_port_type);
+				pf->dport_replace_flag = 1;
+			}
+			teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
+			pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD0] =
+				I40E_DIRECTION_INGRESS_KEY;
+
+			if (tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_UDP)
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
+					I40E_TR_L4_TYPE_UDP;
+			else if (tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_TCP)
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
+					I40E_TR_L4_TYPE_TCP;
+			else
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
+					I40E_TR_L4_TYPE_SCTP;
+
+			pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD2] =
+				(teid_le >> 16) & 0xFFFF;
+			big_buffer = 1;
+		}
+
 		break;
 	default:
 		/* Other tunnel types is not supported. */
@@ -8412,7 +8601,16 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_QINQ)
 		pfilter->element.flags |=
 			I40E_AQC_ADD_CLOUD_FILTER_0X10;
-	else {
+	else if (tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_UDP ||
+		 tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_TCP ||
+		 tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_SCTP) {
+		if (tunnel_filter->l4_port_type == I40E_L4_PORT_TYPE_SRC)
+			pfilter->element.flags |=
+				I40E_AQC_ADD_CLOUD_FILTER_0X11;
+		else
+			pfilter->element.flags |=
+				I40E_AQC_ADD_CLOUD_FILTER_0X10;
+	} else {
 		val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
 						&pfilter->element.flags);
 		if (val < 0) {
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index e5d0ce53f..8442eb256 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -767,11 +767,14 @@ struct i40e_rss_pattern_info {
 
 #define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD0 44
 #define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD1 45
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_SRC_PORT 29
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_DST_PORT 30
 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSOUDP	8
 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSOGRE	9
 #define I40E_AQC_ADD_CLOUD_FILTER_0X10		0x10
 #define I40E_AQC_ADD_CLOUD_FILTER_0X11		0x11
 #define I40E_AQC_ADD_CLOUD_FILTER_0X12		0x12
+#define I40E_AQC_ADD_L1_FILTER_0X10		0x10
 #define I40E_AQC_ADD_L1_FILTER_0X11		0x11
 #define I40E_AQC_ADD_L1_FILTER_0X12		0x12
 #define I40E_AQC_ADD_L1_FILTER_0X13		0x13
@@ -828,9 +831,20 @@ enum i40e_tunnel_type {
 	I40E_TUNNEL_TYPE_GTPU,
 	I40E_TUNNEL_TYPE_ESPoUDP,
 	I40E_TUNNEL_TYPE_ESPoIP,
+	I40E_CLOUD_TYPE_UDP,
+	I40E_CLOUD_TYPE_TCP,
+	I40E_CLOUD_TYPE_SCTP,
 	I40E_TUNNEL_TYPE_MAX,
 };
 
+/**
+ * L4 port type.
+ */
+enum i40e_l4_port_type {
+	I40E_L4_PORT_TYPE_SRC = 0,
+	I40E_L4_PORT_TYPE_DST,
+};
+
 /**
  * Tunneling Packet filter configuration.
  */
@@ -852,6 +866,7 @@ struct i40e_tunnel_filter_conf {
 	/** Flags from ETH_TUNNEL_FILTER_XX - see above. */
 	uint16_t filter_type;
 	enum i40e_tunnel_type tunnel_type; /**< Tunnel Type. */
+	enum i40e_l4_port_type l4_port_type; /**< L4 Port Type. */
 	uint32_t tenant_id;     /**< Tenant ID to match. VNI, GRE key... */
 	uint16_t queue_id;      /**< Queue assigned to if match. */
 	uint8_t is_to_vf;       /**< 0 - to PF, 1 - to VF */
@@ -1073,6 +1088,9 @@ struct i40e_pf {
 	bool mpls_replace_flag;  /* 1 - MPLS filter replace is done */
 	bool gtp_replace_flag;   /* 1 - GTP-C/U filter replace is done */
 	bool qinq_replace_flag;  /* QINQ filter replace is done */
+	/* l4 port flag */
+	bool sport_replace_flag;   /* Source port replace is done */
+	bool dport_replace_flag;   /* Destination port replace is done */
 	struct i40e_tm_conf tm_conf;
 	bool support_multi_driver; /* 1 - support multiple driver */
 
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 8f8df6fae..955aead58 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -124,6 +124,12 @@ i40e_flow_parse_qinq_pattern(struct rte_eth_dev *dev,
 			      struct rte_flow_error *error,
 			      struct i40e_tunnel_filter_conf *filter);
 
+static int i40e_flow_parse_l4_cloud_filter(struct rte_eth_dev *dev,
+					   const struct rte_flow_attr *attr,
+					   const struct rte_flow_item pattern[],
+					   const struct rte_flow_action actions[],
+					   struct rte_flow_error *error,
+					   union i40e_filter_t *filter);
 const struct rte_flow_ops i40e_flow_ops = {
 	.validate = i40e_flow_validate,
 	.create = i40e_flow_create,
@@ -1845,6 +1851,13 @@ static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	/* L2TPv3 over IP */
 	{ pattern_fdir_ipv4_l2tpv3oip, i40e_flow_parse_fdir_filter },
 	{ pattern_fdir_ipv6_l2tpv3oip, i40e_flow_parse_fdir_filter },
+	/* L4 over port */
+	{ pattern_fdir_ipv4_udp, i40e_flow_parse_l4_cloud_filter },
+	{ pattern_fdir_ipv4_tcp, i40e_flow_parse_l4_cloud_filter },
+	{ pattern_fdir_ipv4_sctp, i40e_flow_parse_l4_cloud_filter },
+	{ pattern_fdir_ipv6_udp, i40e_flow_parse_l4_cloud_filter },
+	{ pattern_fdir_ipv6_tcp, i40e_flow_parse_l4_cloud_filter },
+	{ pattern_fdir_ipv6_sctp, i40e_flow_parse_l4_cloud_filter },
 };
 
 #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
@@ -3541,6 +3554,223 @@ i40e_flow_parse_tunnel_action(struct rte_eth_dev *dev,
 	return 0;
 }
 
+/* 1. Last in item should be NULL as range is not supported.
+ * 2. Supported filter types: Source port only and Destination port only.
+ * 3. Mask of fields which need to be matched should be
+ *    filled with 1.
+ * 4. Mask of fields which needn't to be matched should be
+ *    filled with 0.
+ */
+static int
+i40e_flow_parse_l4_pattern(const struct rte_flow_item *pattern,
+			   struct rte_flow_error *error,
+			   struct i40e_tunnel_filter_conf *filter)
+{
+	const struct rte_flow_item_sctp *sctp_spec, *sctp_mask;
+	const struct rte_flow_item_tcp *tcp_spec, *tcp_mask;
+	const struct rte_flow_item_udp *udp_spec, *udp_mask;
+	const struct rte_flow_item *item = pattern;
+	enum rte_flow_item_type item_type;
+
+	for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+		if (item->last) {
+			rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM,
+					   item,
+					   "Not support range");
+			return -rte_errno;
+		}
+		item_type = item->type;
+		switch (item_type) {
+		case RTE_FLOW_ITEM_TYPE_ETH:
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid ETH item");
+				return -rte_errno;
+			}
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV4:
+			filter->ip_type = I40E_TUNNEL_IPTYPE_IPV4;
+			/* IPv4 is used to describe protocol,
+			 * spec and mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid IPv4 item");
+				return -rte_errno;
+			}
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV6:
+			filter->ip_type = I40E_TUNNEL_IPTYPE_IPV6;
+			/* IPv6 is used to describe protocol,
+			 * spec and mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid IPv6 item");
+				return -rte_errno;
+			}
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_UDP:
+			udp_spec = item->spec;
+			udp_mask = item->mask;
+
+			if (!udp_spec || !udp_mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid udp item");
+				return -rte_errno;
+			}
+
+			if (udp_spec->hdr.src_port != 0 &&
+			    udp_spec->hdr.dst_port != 0) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid udp spec");
+				return -rte_errno;
+			}
+
+			if (udp_spec->hdr.src_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_SRC;
+				filter->tenant_id =
+				rte_be_to_cpu_32(udp_spec->hdr.src_port);
+			}
+
+			if (udp_spec->hdr.dst_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_DST;
+				filter->tenant_id =
+				rte_be_to_cpu_32(udp_spec->hdr.dst_port);
+			}
+
+			filter->tunnel_type = I40E_CLOUD_TYPE_UDP;
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_TCP:
+			tcp_spec = item->spec;
+			tcp_mask = item->mask;
+
+			if (!tcp_spec || !tcp_mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid tcp item");
+				return -rte_errno;
+			}
+
+			if (tcp_spec->hdr.src_port != 0 &&
+			    tcp_spec->hdr.dst_port != 0) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid tcp spec");
+				return -rte_errno;
+			}
+
+			if (tcp_spec->hdr.src_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_SRC;
+				filter->tenant_id =
+				rte_be_to_cpu_32(tcp_spec->hdr.src_port);
+			}
+
+			if (tcp_spec->hdr.dst_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_DST;
+				filter->tenant_id =
+				rte_be_to_cpu_32(tcp_spec->hdr.dst_port);
+			}
+
+			filter->tunnel_type = I40E_CLOUD_TYPE_TCP;
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_SCTP:
+			sctp_spec = item->spec;
+			sctp_mask = item->mask;
+
+			if (!sctp_spec || !sctp_mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid sctp item");
+				return -rte_errno;
+			}
+
+			if (sctp_spec->hdr.src_port != 0 &&
+			    sctp_spec->hdr.dst_port != 0) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid sctp spec");
+				return -rte_errno;
+			}
+
+			if (sctp_spec->hdr.src_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_SRC;
+				filter->tenant_id =
+					rte_be_to_cpu_32(sctp_spec->hdr.src_port);
+			}
+
+			if (sctp_spec->hdr.dst_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_DST;
+				filter->tenant_id =
+					rte_be_to_cpu_32(sctp_spec->hdr.dst_port);
+			}
+
+			filter->tunnel_type = I40E_CLOUD_TYPE_SCTP;
+
+			break;
+		default:
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static int
+i40e_flow_parse_l4_cloud_filter(struct rte_eth_dev *dev,
+				const struct rte_flow_attr *attr,
+				const struct rte_flow_item pattern[],
+				const struct rte_flow_action actions[],
+				struct rte_flow_error *error,
+				union i40e_filter_t *filter)
+{
+	struct i40e_tunnel_filter_conf *tunnel_filter =
+		&filter->consistent_tunnel_filter;
+	int ret;
+
+	ret = i40e_flow_parse_l4_pattern(pattern, error, tunnel_filter);
+	if (ret)
+		return ret;
+
+	ret = i40e_flow_parse_tunnel_action(dev, actions, error, tunnel_filter);
+	if (ret)
+		return ret;
+
+	ret = i40e_flow_parse_attr(attr, error);
+	if (ret)
+		return ret;
+
+	cons_filter_type = RTE_ETH_FILTER_TUNNEL;
+
+	return ret;
+}
+
 static uint16_t i40e_supported_tunnel_filter_types[] = {
 	ETH_TUNNEL_FILTER_IMAC | ETH_TUNNEL_FILTER_TENID |
 	ETH_TUNNEL_FILTER_IVLAN,
-- 
2.17.1


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

* [dpdk-dev] [PATCH v6] net/i40e: support cloud filter with L4 port
  2020-06-11  5:24 [dpdk-dev] [PATCH] net/i40e: enable port filter by switch filter Guinan Sun
                   ` (5 preceding siblings ...)
  2020-07-08  6:27 ` [dpdk-dev] [PATCH v5] " Guinan Sun
@ 2020-07-08  7:40 ` Guinan Sun
  2020-07-08  8:20   ` Xing, Beilei
  6 siblings, 1 reply; 16+ messages in thread
From: Guinan Sun @ 2020-07-08  7:40 UTC (permalink / raw)
  To: dev; +Cc: Beilei Xing, Jeff Guo, Guinan Sun

This patch enables cloud filter for IPv4/6_UDP/TCP/SCTP with
SRC port only or DST port only.
This supports different filter types for the same packet type.
E.g. one IPv4_UDP rules with SRC port only and another IPv4_UDP rule
with DST port only.

Signed-off-by: Guinan Sun <guinanx.sun@intel.com>
---
v6:
* Modify commit log.
* Modify release_20_08.rst and i40e.rst.
v5:
* Add IPv6 to release_20_08.rst and i40e.rst.
* Fixed the variable assignment.
v4:
* Modify release_20_08.rst and i40e.rst.
* Rename L4 port filter.
* Modify commit log.
* Fixed the variable assignment.
v3:
* Add limitation to i40e.rst.
* Rename variables.
* Fixed the variable assignment.
v2:
* Fixed code style and variable naming.
---
 doc/guides/nics/i40e.rst               |   7 +
 doc/guides/rel_notes/release_20_08.rst |   6 +
 drivers/net/i40e/i40e_ethdev.c         | 200 ++++++++++++++++++++-
 drivers/net/i40e/i40e_ethdev.h         |  18 ++
 drivers/net/i40e/i40e_flow.c           | 230 +++++++++++++++++++++++++
 5 files changed, 460 insertions(+), 1 deletion(-)

diff --git a/doc/guides/nics/i40e.rst b/doc/guides/nics/i40e.rst
index 00c3042d5..cf1ae2d0b 100644
--- a/doc/guides/nics/i40e.rst
+++ b/doc/guides/nics/i40e.rst
@@ -736,6 +736,13 @@ with DPDK, then the configuration will also impact port B in the NIC with
 kernel driver, which don't want to use the TPID.
 So PMD reports warning to clarify what is changed by writing global register.
 
+Cloud Filter
+~~~~~~~~~~~~
+
+When programming cloud filters for IPv4/6_UDP/TCP/SCTP with SRC port only or DST port only,
+it will make any cloud filter using inner_vlan or tunnel key invalid. Default configuration will be
+recovered only by NIC core reset.
+
 High Performance of Small Packets on 40GbE NIC
 ----------------------------------------------
 
diff --git a/doc/guides/rel_notes/release_20_08.rst b/doc/guides/rel_notes/release_20_08.rst
index eaa9d13b5..89920a1a1 100644
--- a/doc/guides/rel_notes/release_20_08.rst
+++ b/doc/guides/rel_notes/release_20_08.rst
@@ -137,6 +137,12 @@ New Features
   See the :doc:`../sample_app_ug/l2_forward_real_virtual` for more
   details of this parameter usage.
 
+* **Updated Intel i40e driver.**
+
+  Updated i40e PMD with new features and improvements, including:
+
+  * Supported cloud filter for IPv4/6_TCP/UDP/SCTP with SRC port only or DST port only.
+
 
 Removed Items
 -------------
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 777e14926..503097cb5 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -7944,6 +7944,13 @@ i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
 #define I40E_TR_GRE_KEY_MASK			0x400
 #define I40E_TR_GRE_KEY_WITH_XSUM_MASK		0x800
 #define I40E_TR_GRE_NO_KEY_MASK			0x8000
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_PORT_TR_WORD0 0x49
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_DIRECTION_WORD0 0x41
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_INGRESS_WORD0 0x80
+#define I40E_DIRECTION_INGRESS_KEY		0x8000
+#define I40E_TR_L4_TYPE_TCP			0x2
+#define I40E_TR_L4_TYPE_UDP			0x4
+#define I40E_TR_L4_TYPE_SCTP			0x8
 
 static enum
 i40e_status_code i40e_replace_mpls_l1_filter(struct i40e_pf *pf)
@@ -8242,6 +8249,132 @@ i40e_status_code i40e_replace_gtp_cloud_filter(struct i40e_pf *pf)
 	return status;
 }
 
+static enum i40e_status_code
+i40e_replace_port_l1_filter(struct i40e_pf *pf,
+			    enum i40e_l4_port_type l4_port_type)
+{
+	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
+	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
+	enum i40e_status_code status = I40E_SUCCESS;
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	struct rte_eth_dev *dev = ((struct i40e_adapter *)hw->back)->eth_dev;
+
+	if (pf->support_multi_driver) {
+		PMD_DRV_LOG(ERR, "Replace l1 filter is not supported.");
+		return I40E_NOT_SUPPORTED;
+	}
+
+	memset(&filter_replace, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+	memset(&filter_replace_buf, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+
+	/* create L1 filter */
+	if (l4_port_type == I40E_L4_PORT_TYPE_SRC) {
+		filter_replace.old_filter_type =
+			I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TUNNLE_KEY;
+		filter_replace.new_filter_type = I40E_AQC_ADD_L1_FILTER_0X11;
+		filter_replace_buf.data[8] =
+			I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_SRC_PORT;
+	} else {
+		filter_replace.old_filter_type =
+			I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG_IVLAN;
+		filter_replace.new_filter_type = I40E_AQC_ADD_L1_FILTER_0X10;
+		filter_replace_buf.data[8] =
+			I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_DST_PORT;
+	}
+
+	filter_replace.tr_bit = 0;
+	/* Prepare the buffer, 3 entries */
+	filter_replace_buf.data[0] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_DIRECTION_WORD0;
+	filter_replace_buf.data[0] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[2] = 0x00;
+	filter_replace_buf.data[3] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_INGRESS_WORD0;
+	filter_replace_buf.data[4] =
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_PORT_TR_WORD0;
+	filter_replace_buf.data[4] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[5] = 0x00;
+	filter_replace_buf.data[6] = I40E_TR_L4_TYPE_UDP |
+		I40E_TR_L4_TYPE_TCP |
+		I40E_TR_L4_TYPE_SCTP;
+	filter_replace_buf.data[7] = 0x00;
+	filter_replace_buf.data[8] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[9] = 0x00;
+	filter_replace_buf.data[10] = 0xFF;
+	filter_replace_buf.data[11] = 0xFF;
+
+	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+					       &filter_replace_buf);
+	if (!status && filter_replace.old_filter_type !=
+	    filter_replace.new_filter_type)
+		PMD_DRV_LOG(WARNING, "i40e device %s changed cloud l1 type."
+			    " original: 0x%x, new: 0x%x",
+			    dev->device->name,
+			    filter_replace.old_filter_type,
+			    filter_replace.new_filter_type);
+
+	return status;
+}
+
+static enum i40e_status_code
+i40e_replace_port_cloud_filter(struct i40e_pf *pf,
+			       enum i40e_l4_port_type l4_port_type)
+{
+	struct i40e_aqc_replace_cloud_filters_cmd_buf  filter_replace_buf;
+	struct i40e_aqc_replace_cloud_filters_cmd  filter_replace;
+	enum i40e_status_code status = I40E_SUCCESS;
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	struct rte_eth_dev *dev = ((struct i40e_adapter *)hw->back)->eth_dev;
+
+	if (pf->support_multi_driver) {
+		PMD_DRV_LOG(ERR, "Replace cloud filter is not supported.");
+		return I40E_NOT_SUPPORTED;
+	}
+
+	memset(&filter_replace, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd));
+	memset(&filter_replace_buf, 0,
+	       sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf));
+
+	if (l4_port_type == I40E_L4_PORT_TYPE_SRC) {
+		filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_IIP;
+		filter_replace.new_filter_type =
+			I40E_AQC_ADD_CLOUD_FILTER_0X11;
+		filter_replace_buf.data[4] = I40E_AQC_ADD_CLOUD_FILTER_0X11;
+	} else {
+		filter_replace.old_filter_type = I40E_AQC_ADD_CLOUD_FILTER_OIP;
+		filter_replace.new_filter_type =
+			I40E_AQC_ADD_CLOUD_FILTER_0X10;
+		filter_replace_buf.data[4] = I40E_AQC_ADD_CLOUD_FILTER_0X10;
+	}
+
+	filter_replace.valid_flags = I40E_AQC_REPLACE_CLOUD_FILTER;
+	filter_replace.tr_bit = 0;
+	/* Prepare the buffer, 2 entries */
+	filter_replace_buf.data[0] = I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_STAG;
+	filter_replace_buf.data[0] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	filter_replace_buf.data[4] |=
+		I40E_AQC_REPLACE_CLOUD_CMD_INPUT_VALIDATED;
+	status = i40e_aq_replace_cloud_filters(hw, &filter_replace,
+					       &filter_replace_buf);
+
+	if (!status && filter_replace.old_filter_type !=
+	    filter_replace.new_filter_type)
+		PMD_DRV_LOG(WARNING, "i40e device %s changed cloud filter type."
+			    " original: 0x%x, new: 0x%x",
+			    dev->device->name,
+			    filter_replace.old_filter_type,
+			    filter_replace.new_filter_type);
+
+	return status;
+}
+
 int
 i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		      struct i40e_tunnel_filter_conf *tunnel_filter,
@@ -8389,6 +8522,62 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 		pfilter->general_fields[0] = tunnel_filter->inner_vlan;
 		pfilter->general_fields[1] = tunnel_filter->outer_vlan;
 		big_buffer = 1;
+		break;
+	case I40E_CLOUD_TYPE_UDP:
+	case I40E_CLOUD_TYPE_TCP:
+	case I40E_CLOUD_TYPE_SCTP:
+		if (tunnel_filter->l4_port_type == I40E_L4_PORT_TYPE_SRC) {
+			if (!pf->sport_replace_flag) {
+				i40e_replace_port_l1_filter(pf,
+						tunnel_filter->l4_port_type);
+				i40e_replace_port_cloud_filter(pf,
+						tunnel_filter->l4_port_type);
+				pf->sport_replace_flag = 1;
+			}
+			teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
+			pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD0] =
+				I40E_DIRECTION_INGRESS_KEY;
+
+			if (tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_UDP)
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+					I40E_TR_L4_TYPE_UDP;
+			else if (tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_TCP)
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+					I40E_TR_L4_TYPE_TCP;
+			else
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD1] =
+					I40E_TR_L4_TYPE_SCTP;
+
+			pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X11_WORD2] =
+				(teid_le >> 16) & 0xFFFF;
+			big_buffer = 1;
+		} else {
+			if (!pf->dport_replace_flag) {
+				i40e_replace_port_l1_filter(pf,
+						tunnel_filter->l4_port_type);
+				i40e_replace_port_cloud_filter(pf,
+						tunnel_filter->l4_port_type);
+				pf->dport_replace_flag = 1;
+			}
+			teid_le = rte_cpu_to_le_32(tunnel_filter->tenant_id);
+			pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD0] =
+				I40E_DIRECTION_INGRESS_KEY;
+
+			if (tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_UDP)
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
+					I40E_TR_L4_TYPE_UDP;
+			else if (tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_TCP)
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
+					I40E_TR_L4_TYPE_TCP;
+			else
+				pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD1] =
+					I40E_TR_L4_TYPE_SCTP;
+
+			pfilter->general_fields[I40E_AQC_ADD_CLOUD_FV_FLU_0X10_WORD2] =
+				(teid_le >> 16) & 0xFFFF;
+			big_buffer = 1;
+		}
+
 		break;
 	default:
 		/* Other tunnel types is not supported. */
@@ -8412,7 +8601,16 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
 	else if (tunnel_filter->tunnel_type == I40E_TUNNEL_TYPE_QINQ)
 		pfilter->element.flags |=
 			I40E_AQC_ADD_CLOUD_FILTER_0X10;
-	else {
+	else if (tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_UDP ||
+		 tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_TCP ||
+		 tunnel_filter->tunnel_type == I40E_CLOUD_TYPE_SCTP) {
+		if (tunnel_filter->l4_port_type == I40E_L4_PORT_TYPE_SRC)
+			pfilter->element.flags |=
+				I40E_AQC_ADD_CLOUD_FILTER_0X11;
+		else
+			pfilter->element.flags |=
+				I40E_AQC_ADD_CLOUD_FILTER_0X10;
+	} else {
 		val = i40e_dev_get_filter_type(tunnel_filter->filter_type,
 						&pfilter->element.flags);
 		if (val < 0) {
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index e5d0ce53f..8442eb256 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -767,11 +767,14 @@ struct i40e_rss_pattern_info {
 
 #define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD0 44
 #define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_TEID_WORD1 45
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_SRC_PORT 29
+#define I40E_AQC_REPLACE_CLOUD_CMD_INPUT_FV_DST_PORT 30
 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSOUDP	8
 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_MPLSOGRE	9
 #define I40E_AQC_ADD_CLOUD_FILTER_0X10		0x10
 #define I40E_AQC_ADD_CLOUD_FILTER_0X11		0x11
 #define I40E_AQC_ADD_CLOUD_FILTER_0X12		0x12
+#define I40E_AQC_ADD_L1_FILTER_0X10		0x10
 #define I40E_AQC_ADD_L1_FILTER_0X11		0x11
 #define I40E_AQC_ADD_L1_FILTER_0X12		0x12
 #define I40E_AQC_ADD_L1_FILTER_0X13		0x13
@@ -828,9 +831,20 @@ enum i40e_tunnel_type {
 	I40E_TUNNEL_TYPE_GTPU,
 	I40E_TUNNEL_TYPE_ESPoUDP,
 	I40E_TUNNEL_TYPE_ESPoIP,
+	I40E_CLOUD_TYPE_UDP,
+	I40E_CLOUD_TYPE_TCP,
+	I40E_CLOUD_TYPE_SCTP,
 	I40E_TUNNEL_TYPE_MAX,
 };
 
+/**
+ * L4 port type.
+ */
+enum i40e_l4_port_type {
+	I40E_L4_PORT_TYPE_SRC = 0,
+	I40E_L4_PORT_TYPE_DST,
+};
+
 /**
  * Tunneling Packet filter configuration.
  */
@@ -852,6 +866,7 @@ struct i40e_tunnel_filter_conf {
 	/** Flags from ETH_TUNNEL_FILTER_XX - see above. */
 	uint16_t filter_type;
 	enum i40e_tunnel_type tunnel_type; /**< Tunnel Type. */
+	enum i40e_l4_port_type l4_port_type; /**< L4 Port Type. */
 	uint32_t tenant_id;     /**< Tenant ID to match. VNI, GRE key... */
 	uint16_t queue_id;      /**< Queue assigned to if match. */
 	uint8_t is_to_vf;       /**< 0 - to PF, 1 - to VF */
@@ -1073,6 +1088,9 @@ struct i40e_pf {
 	bool mpls_replace_flag;  /* 1 - MPLS filter replace is done */
 	bool gtp_replace_flag;   /* 1 - GTP-C/U filter replace is done */
 	bool qinq_replace_flag;  /* QINQ filter replace is done */
+	/* l4 port flag */
+	bool sport_replace_flag;   /* Source port replace is done */
+	bool dport_replace_flag;   /* Destination port replace is done */
 	struct i40e_tm_conf tm_conf;
 	bool support_multi_driver; /* 1 - support multiple driver */
 
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 8f8df6fae..955aead58 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -124,6 +124,12 @@ i40e_flow_parse_qinq_pattern(struct rte_eth_dev *dev,
 			      struct rte_flow_error *error,
 			      struct i40e_tunnel_filter_conf *filter);
 
+static int i40e_flow_parse_l4_cloud_filter(struct rte_eth_dev *dev,
+					   const struct rte_flow_attr *attr,
+					   const struct rte_flow_item pattern[],
+					   const struct rte_flow_action actions[],
+					   struct rte_flow_error *error,
+					   union i40e_filter_t *filter);
 const struct rte_flow_ops i40e_flow_ops = {
 	.validate = i40e_flow_validate,
 	.create = i40e_flow_create,
@@ -1845,6 +1851,13 @@ static struct i40e_valid_pattern i40e_supported_patterns[] = {
 	/* L2TPv3 over IP */
 	{ pattern_fdir_ipv4_l2tpv3oip, i40e_flow_parse_fdir_filter },
 	{ pattern_fdir_ipv6_l2tpv3oip, i40e_flow_parse_fdir_filter },
+	/* L4 over port */
+	{ pattern_fdir_ipv4_udp, i40e_flow_parse_l4_cloud_filter },
+	{ pattern_fdir_ipv4_tcp, i40e_flow_parse_l4_cloud_filter },
+	{ pattern_fdir_ipv4_sctp, i40e_flow_parse_l4_cloud_filter },
+	{ pattern_fdir_ipv6_udp, i40e_flow_parse_l4_cloud_filter },
+	{ pattern_fdir_ipv6_tcp, i40e_flow_parse_l4_cloud_filter },
+	{ pattern_fdir_ipv6_sctp, i40e_flow_parse_l4_cloud_filter },
 };
 
 #define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
@@ -3541,6 +3554,223 @@ i40e_flow_parse_tunnel_action(struct rte_eth_dev *dev,
 	return 0;
 }
 
+/* 1. Last in item should be NULL as range is not supported.
+ * 2. Supported filter types: Source port only and Destination port only.
+ * 3. Mask of fields which need to be matched should be
+ *    filled with 1.
+ * 4. Mask of fields which needn't to be matched should be
+ *    filled with 0.
+ */
+static int
+i40e_flow_parse_l4_pattern(const struct rte_flow_item *pattern,
+			   struct rte_flow_error *error,
+			   struct i40e_tunnel_filter_conf *filter)
+{
+	const struct rte_flow_item_sctp *sctp_spec, *sctp_mask;
+	const struct rte_flow_item_tcp *tcp_spec, *tcp_mask;
+	const struct rte_flow_item_udp *udp_spec, *udp_mask;
+	const struct rte_flow_item *item = pattern;
+	enum rte_flow_item_type item_type;
+
+	for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+		if (item->last) {
+			rte_flow_error_set(error, EINVAL,
+					   RTE_FLOW_ERROR_TYPE_ITEM,
+					   item,
+					   "Not support range");
+			return -rte_errno;
+		}
+		item_type = item->type;
+		switch (item_type) {
+		case RTE_FLOW_ITEM_TYPE_ETH:
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid ETH item");
+				return -rte_errno;
+			}
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV4:
+			filter->ip_type = I40E_TUNNEL_IPTYPE_IPV4;
+			/* IPv4 is used to describe protocol,
+			 * spec and mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid IPv4 item");
+				return -rte_errno;
+			}
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_IPV6:
+			filter->ip_type = I40E_TUNNEL_IPTYPE_IPV6;
+			/* IPv6 is used to describe protocol,
+			 * spec and mask should be NULL.
+			 */
+			if (item->spec || item->mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid IPv6 item");
+				return -rte_errno;
+			}
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_UDP:
+			udp_spec = item->spec;
+			udp_mask = item->mask;
+
+			if (!udp_spec || !udp_mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid udp item");
+				return -rte_errno;
+			}
+
+			if (udp_spec->hdr.src_port != 0 &&
+			    udp_spec->hdr.dst_port != 0) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid udp spec");
+				return -rte_errno;
+			}
+
+			if (udp_spec->hdr.src_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_SRC;
+				filter->tenant_id =
+				rte_be_to_cpu_32(udp_spec->hdr.src_port);
+			}
+
+			if (udp_spec->hdr.dst_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_DST;
+				filter->tenant_id =
+				rte_be_to_cpu_32(udp_spec->hdr.dst_port);
+			}
+
+			filter->tunnel_type = I40E_CLOUD_TYPE_UDP;
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_TCP:
+			tcp_spec = item->spec;
+			tcp_mask = item->mask;
+
+			if (!tcp_spec || !tcp_mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid tcp item");
+				return -rte_errno;
+			}
+
+			if (tcp_spec->hdr.src_port != 0 &&
+			    tcp_spec->hdr.dst_port != 0) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid tcp spec");
+				return -rte_errno;
+			}
+
+			if (tcp_spec->hdr.src_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_SRC;
+				filter->tenant_id =
+				rte_be_to_cpu_32(tcp_spec->hdr.src_port);
+			}
+
+			if (tcp_spec->hdr.dst_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_DST;
+				filter->tenant_id =
+				rte_be_to_cpu_32(tcp_spec->hdr.dst_port);
+			}
+
+			filter->tunnel_type = I40E_CLOUD_TYPE_TCP;
+
+			break;
+		case RTE_FLOW_ITEM_TYPE_SCTP:
+			sctp_spec = item->spec;
+			sctp_mask = item->mask;
+
+			if (!sctp_spec || !sctp_mask) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid sctp item");
+				return -rte_errno;
+			}
+
+			if (sctp_spec->hdr.src_port != 0 &&
+			    sctp_spec->hdr.dst_port != 0) {
+				rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Invalid sctp spec");
+				return -rte_errno;
+			}
+
+			if (sctp_spec->hdr.src_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_SRC;
+				filter->tenant_id =
+					rte_be_to_cpu_32(sctp_spec->hdr.src_port);
+			}
+
+			if (sctp_spec->hdr.dst_port != 0) {
+				filter->l4_port_type =
+					I40E_L4_PORT_TYPE_DST;
+				filter->tenant_id =
+					rte_be_to_cpu_32(sctp_spec->hdr.dst_port);
+			}
+
+			filter->tunnel_type = I40E_CLOUD_TYPE_SCTP;
+
+			break;
+		default:
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static int
+i40e_flow_parse_l4_cloud_filter(struct rte_eth_dev *dev,
+				const struct rte_flow_attr *attr,
+				const struct rte_flow_item pattern[],
+				const struct rte_flow_action actions[],
+				struct rte_flow_error *error,
+				union i40e_filter_t *filter)
+{
+	struct i40e_tunnel_filter_conf *tunnel_filter =
+		&filter->consistent_tunnel_filter;
+	int ret;
+
+	ret = i40e_flow_parse_l4_pattern(pattern, error, tunnel_filter);
+	if (ret)
+		return ret;
+
+	ret = i40e_flow_parse_tunnel_action(dev, actions, error, tunnel_filter);
+	if (ret)
+		return ret;
+
+	ret = i40e_flow_parse_attr(attr, error);
+	if (ret)
+		return ret;
+
+	cons_filter_type = RTE_ETH_FILTER_TUNNEL;
+
+	return ret;
+}
+
 static uint16_t i40e_supported_tunnel_filter_types[] = {
 	ETH_TUNNEL_FILTER_IMAC | ETH_TUNNEL_FILTER_TENID |
 	ETH_TUNNEL_FILTER_IVLAN,
-- 
2.17.1


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

* Re: [dpdk-dev] [PATCH v6] net/i40e: support cloud filter with L4 port
  2020-07-08  7:40 ` [dpdk-dev] [PATCH v6] " Guinan Sun
@ 2020-07-08  8:20   ` Xing, Beilei
  2020-07-08  8:52     ` Zhang, Qi Z
  0 siblings, 1 reply; 16+ messages in thread
From: Xing, Beilei @ 2020-07-08  8:20 UTC (permalink / raw)
  To: Sun, GuinanX, dev; +Cc: Guo, Jia



> -----Original Message-----
> From: Sun, GuinanX <guinanx.sun@intel.com>
> Sent: Wednesday, July 8, 2020 3:41 PM
> To: dev@dpdk.org
> Cc: Xing, Beilei <beilei.xing@intel.com>; Guo, Jia <jia.guo@intel.com>; Sun,
> GuinanX <guinanx.sun@intel.com>
> Subject: [PATCH v6] net/i40e: support cloud filter with L4 port
> 
> This patch enables cloud filter for IPv4/6_UDP/TCP/SCTP with SRC port only or
> DST port only.
> This supports different filter types for the same packet type.
> E.g. one IPv4_UDP rules with SRC port only and another IPv4_UDP rule with
> DST port only.
> 
> Signed-off-by: Guinan Sun <guinanx.sun@intel.com>
Acked-by: Beilei Xing <beilei.xing@intel.com>

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

* Re: [dpdk-dev] [PATCH v6] net/i40e: support cloud filter with L4 port
  2020-07-08  8:20   ` Xing, Beilei
@ 2020-07-08  8:52     ` Zhang, Qi Z
  0 siblings, 0 replies; 16+ messages in thread
From: Zhang, Qi Z @ 2020-07-08  8:52 UTC (permalink / raw)
  To: Xing, Beilei, Sun, GuinanX, dev; +Cc: Guo, Jia



> -----Original Message-----
> From: dev <dev-bounces@dpdk.org> On Behalf Of Xing, Beilei
> Sent: Wednesday, July 8, 2020 4:20 PM
> To: Sun, GuinanX <guinanx.sun@intel.com>; dev@dpdk.org
> Cc: Guo, Jia <jia.guo@intel.com>
> Subject: Re: [dpdk-dev] [PATCH v6] net/i40e: support cloud filter with L4
> port
> 
> 
> 
> > -----Original Message-----
> > From: Sun, GuinanX <guinanx.sun@intel.com>
> > Sent: Wednesday, July 8, 2020 3:41 PM
> > To: dev@dpdk.org
> > Cc: Xing, Beilei <beilei.xing@intel.com>; Guo, Jia
> > <jia.guo@intel.com>; Sun, GuinanX <guinanx.sun@intel.com>
> > Subject: [PATCH v6] net/i40e: support cloud filter with L4 port
> >
> > This patch enables cloud filter for IPv4/6_UDP/TCP/SCTP with SRC port
> > only or DST port only.
> > This supports different filter types for the same packet type.
> > E.g. one IPv4_UDP rules with SRC port only and another IPv4_UDP rule
> > with DST port only.
> >
> > Signed-off-by: Guinan Sun <guinanx.sun@intel.com>
> Acked-by: Beilei Xing <beilei.xing@intel.com>

Applied to dpdk-next-net-intel.

Thanks
Qi

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

end of thread, other threads:[~2020-07-08  8:52 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-11  5:24 [dpdk-dev] [PATCH] net/i40e: enable port filter by switch filter Guinan Sun
2020-06-15  6:12 ` Zhao1, Wei
2020-06-15  6:28   ` Sun, GuinanX
2020-06-21 12:28 ` Jeff Guo
2020-06-24  3:09   ` Sun, GuinanX
2020-06-30  4:42 ` [dpdk-dev] [PATCH v2] " Guinan Sun
2020-06-30  6:15   ` Xing, Beilei
2020-07-07  6:11     ` Sun, GuinanX
2020-07-07  6:33 ` [dpdk-dev] [PATCH v3] net/i40e: support cloud filter with L4 port Guinan Sun
2020-07-07  8:15   ` Xing, Beilei
2020-07-08  3:11 ` [dpdk-dev] [PATCH v4] " Guinan Sun
2020-07-08  6:01   ` Xing, Beilei
2020-07-08  6:27 ` [dpdk-dev] [PATCH v5] " Guinan Sun
2020-07-08  7:40 ` [dpdk-dev] [PATCH v6] " Guinan Sun
2020-07-08  8:20   ` Xing, Beilei
2020-07-08  8:52     ` Zhang, Qi Z

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).