DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 0/2] add generic filter support for iavf
@ 2020-03-17  8:17 Qiming Yang
  2020-03-17  8:17 ` [dpdk-dev] [PATCH 1/2] net/iavf: support generic flow Qiming Yang
                   ` (3 more replies)
  0 siblings, 4 replies; 14+ messages in thread
From: Qiming Yang @ 2020-03-17  8:17 UTC (permalink / raw)
  To: dev; +Cc: Qiming Yang

This patch set added generic flow APIs and supported patterns includes:
/* L2 */
/* ARP */
/* IPv4 */
/* IPv6  */
/* GTPU */
/* ESP */
/* AH */
/* L2TPV3 */
/* PFCP */


Qiming Yang (2):
  net/iavf: support generic flow
  net/iavf: support more patterns

 doc/guides/rel_notes/release_20_05.rst |    5 +
 drivers/net/iavf/Makefile              |    1 +
 drivers/net/iavf/iavf.h                |    9 +
 drivers/net/iavf/iavf_ethdev.c         |   46 ++
 drivers/net/iavf/iavf_generic_flow.c   | 1023 ++++++++++++++++++++++++++++++++
 drivers/net/iavf/iavf_generic_flow.h   |  318 ++++++++++
 drivers/net/iavf/meson.build           |    1 +
 7 files changed, 1403 insertions(+)
 create mode 100644 drivers/net/iavf/iavf_generic_flow.c
 create mode 100644 drivers/net/iavf/iavf_generic_flow.h

-- 
2.9.5


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

* [dpdk-dev] [PATCH 1/2] net/iavf: support generic flow
  2020-03-17  8:17 [dpdk-dev] [PATCH 0/2] add generic filter support for iavf Qiming Yang
@ 2020-03-17  8:17 ` Qiming Yang
  2020-03-19  2:01   ` Zhang, Qi Z
  2020-03-17  8:17 ` [dpdk-dev] [PATCH 2/2] net/iavf: support more patterns Qiming Yang
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 14+ messages in thread
From: Qiming Yang @ 2020-03-17  8:17 UTC (permalink / raw)
  To: dev; +Cc: Qiming Yang

This patch added iavf_flow_create, iavf_flow_destroy,
iavf_flow_flush and iavf_flow_validate support,
these are used to handle all the generic filters.

This patch supported basic L2, L3, L4 and GTPU patterns.

Signed-off-by: Qiming Yang <qiming.yang@intel.com>
---
 doc/guides/rel_notes/release_20_05.rst |   5 +
 drivers/net/iavf/Makefile              |   1 +
 drivers/net/iavf/iavf.h                |   9 +
 drivers/net/iavf/iavf_ethdev.c         |  46 ++
 drivers/net/iavf/iavf_generic_flow.c   | 928 +++++++++++++++++++++++++++++++++
 drivers/net/iavf/iavf_generic_flow.h   | 279 ++++++++++
 drivers/net/iavf/meson.build           |   1 +
 7 files changed, 1269 insertions(+)
 create mode 100644 drivers/net/iavf/iavf_generic_flow.c
 create mode 100644 drivers/net/iavf/iavf_generic_flow.h

diff --git a/doc/guides/rel_notes/release_20_05.rst b/doc/guides/rel_notes/release_20_05.rst
index 2190eaf..44d375a 100644
--- a/doc/guides/rel_notes/release_20_05.rst
+++ b/doc/guides/rel_notes/release_20_05.rst
@@ -56,6 +56,11 @@ New Features
      Also, make sure to start the actual text at the margin.
      =========================================================
 
+* **Updated the Intel ice driver.**
+
+  Updated the Intel ice driver with new features and improvements, including:
+
+  * Added support for DCF (Device Config Function) feature.
 
 Removed Items
 -------------
diff --git a/drivers/net/iavf/Makefile b/drivers/net/iavf/Makefile
index 514073d..1bf0f26 100644
--- a/drivers/net/iavf/Makefile
+++ b/drivers/net/iavf/Makefile
@@ -23,6 +23,7 @@ EXPORT_MAP := rte_pmd_iavf_version.map
 SRCS-$(CONFIG_RTE_LIBRTE_IAVF_PMD) += iavf_ethdev.c
 SRCS-$(CONFIG_RTE_LIBRTE_IAVF_PMD) += iavf_vchnl.c
 SRCS-$(CONFIG_RTE_LIBRTE_IAVF_PMD) += iavf_rxtx.c
+SRCS-$(CONFIG_RTE_LIBRTE_IAVF_PMD) += iavf_generic_flow.c
 ifeq ($(CONFIG_RTE_ARCH_X86), y)
 SRCS-$(CONFIG_RTE_LIBRTE_IAVF_PMD) += iavf_rxtx_vec_sse.c
 endif
diff --git a/drivers/net/iavf/iavf.h b/drivers/net/iavf/iavf.h
index fe25d80..b10d5ab 100644
--- a/drivers/net/iavf/iavf.h
+++ b/drivers/net/iavf/iavf.h
@@ -83,6 +83,12 @@ struct iavf_vsi {
 	struct virtchnl_eth_stats eth_stats_offset;
 };
 
+struct rte_flow;
+TAILQ_HEAD(iavf_flow_list, rte_flow);
+
+struct iavf_flow_parser_node;
+TAILQ_HEAD(iavf_parser_list, iavf_flow_parser_node);
+
 /* TODO: is that correct to assume the max number to be 16 ?*/
 #define IAVF_MAX_MSIX_VECTORS   16
 
@@ -117,6 +123,9 @@ struct iavf_info {
 	uint16_t msix_base; /* msix vector base from */
 	/* queue bitmask for each vector */
 	uint16_t rxq_map[IAVF_MAX_MSIX_VECTORS];
+	struct iavf_flow_list flow_list;
+	struct iavf_parser_list rss_parser_list;
+	struct iavf_parser_list dist_parser_list;
 };
 
 #define IAVF_MAX_PKT_TYPE 256
diff --git a/drivers/net/iavf/iavf_ethdev.c b/drivers/net/iavf/iavf_ethdev.c
index 34913f9..639b7eb 100644
--- a/drivers/net/iavf/iavf_ethdev.c
+++ b/drivers/net/iavf/iavf_ethdev.c
@@ -27,6 +27,7 @@
 
 #include "iavf.h"
 #include "iavf_rxtx.h"
+#include "iavf_generic_flow.h"
 
 static int iavf_dev_configure(struct rte_eth_dev *dev);
 static int iavf_dev_start(struct rte_eth_dev *dev);
@@ -67,6 +68,11 @@ static int iavf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev,
 					uint16_t queue_id);
 static int iavf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev,
 					 uint16_t queue_id);
+static int iavf_dev_filter_ctrl(struct rte_eth_dev *dev,
+		     enum rte_filter_type filter_type,
+		     enum rte_filter_op filter_op,
+		     void *arg);
+
 
 int iavf_logtype_init;
 int iavf_logtype_driver;
@@ -125,6 +131,7 @@ static const struct eth_dev_ops iavf_eth_dev_ops = {
 	.mtu_set                    = iavf_dev_mtu_set,
 	.rx_queue_intr_enable       = iavf_dev_rx_queue_intr_enable,
 	.rx_queue_intr_disable      = iavf_dev_rx_queue_intr_disable,
+	.filter_ctrl                = iavf_dev_filter_ctrl,
 };
 
 static int
@@ -1291,12 +1298,41 @@ iavf_dev_interrupt_handler(void *param)
 }
 
 static int
+iavf_dev_filter_ctrl(struct rte_eth_dev *dev,
+		     enum rte_filter_type filter_type,
+		     enum rte_filter_op filter_op,
+		     void *arg)
+{
+	int ret = 0;
+
+	if (!dev)
+		return -EINVAL;
+
+	switch (filter_type) {
+	case RTE_ETH_FILTER_GENERIC:
+		if (filter_op != RTE_ETH_FILTER_GET)
+			return -EINVAL;
+		*(const void **)arg = &iavf_flow_ops;
+		break;
+	default:
+		PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
+			    filter_type);
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+
+static int
 iavf_dev_init(struct rte_eth_dev *eth_dev)
 {
 	struct iavf_adapter *adapter =
 		IAVF_DEV_PRIVATE_TO_ADAPTER(eth_dev->data->dev_private);
 	struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(adapter);
 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
+	int ret = 0;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -1363,6 +1399,12 @@ iavf_dev_init(struct rte_eth_dev *eth_dev)
 	/* configure and enable device interrupt */
 	iavf_enable_irq0(hw);
 
+	ret = iavf_flow_init(adapter);
+	if (ret) {
+		PMD_INIT_LOG(ERR, "Failed to initialize flow");
+		return ret;
+	}
+
 	return 0;
 }
 
@@ -1372,6 +1414,8 @@ iavf_dev_close(struct rte_eth_dev *dev)
 	struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
 	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
+	struct iavf_adapter *adapter =
+		IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
 
 	iavf_dev_stop(dev);
 	iavf_shutdown_adminq(hw);
@@ -1382,6 +1426,8 @@ iavf_dev_close(struct rte_eth_dev *dev)
 	rte_intr_callback_unregister(intr_handle,
 				     iavf_dev_interrupt_handler, dev);
 	iavf_disable_irq0(hw);
+
+	iavf_flow_uninit(adapter);
 }
 
 static int
diff --git a/drivers/net/iavf/iavf_generic_flow.c b/drivers/net/iavf/iavf_generic_flow.c
new file mode 100644
index 0000000..65767aa
--- /dev/null
+++ b/drivers/net/iavf/iavf_generic_flow.c
@@ -0,0 +1,928 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#include <sys/queue.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+#include <rte_ether.h>
+#include <rte_ethdev_driver.h>
+#include <rte_malloc.h>
+#include <rte_tailq.h>
+
+#include "iavf.h"
+#include "iavf_generic_flow.h"
+
+static struct iavf_engine_list engine_list =
+		TAILQ_HEAD_INITIALIZER(engine_list);
+
+static int iavf_flow_validate(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);
+static struct rte_flow *iavf_flow_create(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);
+static int iavf_flow_destroy(struct rte_eth_dev *dev,
+		struct rte_flow *flow,
+		struct rte_flow_error *error);
+static int iavf_flow_flush(struct rte_eth_dev *dev,
+		struct rte_flow_error *error);
+static int iavf_flow_query(struct rte_eth_dev *dev,
+		struct rte_flow *flow,
+		const struct rte_flow_action *actions,
+		void *data,
+		struct rte_flow_error *error);
+
+const struct rte_flow_ops iavf_flow_ops = {
+	.validate = iavf_flow_validate,
+	.create = iavf_flow_create,
+	.destroy = iavf_flow_destroy,
+	.flush = iavf_flow_flush,
+	.query = iavf_flow_query,
+};
+
+/* empty */
+enum rte_flow_item_type iavf_pattern_empty[] = {
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+/* L2 */
+enum rte_flow_item_type iavf_pattern_ethertype[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_ethertype_vlan[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_ethertype_qinq[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+/* ARP */
+enum rte_flow_item_type iavf_pattern_eth_arp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_ARP_ETH_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+/* non-tunnel IPv4 */
+enum rte_flow_item_type iavf_pattern_eth_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_sctp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_SCTP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_sctp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_SCTP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_sctp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_SCTP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_icmp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_ICMP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_icmp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_ICMP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_icmp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_ICMP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+/* non-tunnel IPv6 */
+enum rte_flow_item_type iavf_pattern_eth_ipv6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv6_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv6_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv6_sctp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_SCTP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_sctp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_SCTP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_sctp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_SCTP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv6_icmp6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_ICMP6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_icmp6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_ICMP6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_icmp6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_ICMP6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+/* GTPU */
+enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_GTPU,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_GTPU,
+	RTE_FLOW_ITEM_TYPE_GTP_PSC,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_GTPU,
+	RTE_FLOW_ITEM_TYPE_GTP_PSC,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_GTPU,
+	RTE_FLOW_ITEM_TYPE_GTP_PSC,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_icmp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_GTPU,
+	RTE_FLOW_ITEM_TYPE_GTP_PSC,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_ICMP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+typedef struct iavf_flow_engine * (*parse_engine_t)(struct iavf_adapter *ad,
+		struct rte_flow *flow,
+		struct iavf_parser_list *parser_list,
+		const struct rte_flow_item pattern[],
+		const struct rte_flow_action actions[],
+		struct rte_flow_error *error);
+
+void
+iavf_register_flow_engine(struct iavf_flow_engine *engine)
+{
+	TAILQ_INSERT_TAIL(&engine_list, engine, node);
+}
+
+int
+iavf_flow_init(struct iavf_adapter *ad)
+{
+	int ret;
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
+	void *temp;
+	struct iavf_flow_engine *engine;
+
+	TAILQ_INIT(&vf->flow_list);
+	TAILQ_INIT(&vf->rss_parser_list);
+	TAILQ_INIT(&vf->dist_parser_list);
+
+	TAILQ_FOREACH_SAFE(engine, &engine_list, node, temp) {
+		if (engine->init == NULL) {
+			PMD_INIT_LOG(ERR, "Invalid engine type (%d)",
+				     engine->type);
+			return -ENOTSUP;
+		}
+
+		ret = engine->init(ad);
+		if (ret && ret != -ENOTSUP) {
+			PMD_INIT_LOG(ERR, "Failed to initialize engine %d",
+				     engine->type);
+			return ret;
+		}
+	}
+	return 0;
+}
+
+void
+iavf_flow_uninit(struct iavf_adapter *ad)
+{
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
+	struct iavf_flow_engine *engine;
+	struct rte_flow *p_flow;
+	struct iavf_flow_parser_node *p_parser;
+	void *temp;
+
+	TAILQ_FOREACH_SAFE(engine, &engine_list, node, temp) {
+		if (engine->uninit)
+			engine->uninit(ad);
+	}
+
+	/* Remove all flows */
+	while ((p_flow = TAILQ_FIRST(&vf->flow_list))) {
+		TAILQ_REMOVE(&vf->flow_list, p_flow, node);
+		if (p_flow->engine->free)
+			p_flow->engine->free(p_flow);
+		rte_free(p_flow);
+	}
+
+	/* Cleanup parser list */
+	while ((p_parser = TAILQ_FIRST(&vf->rss_parser_list))) {
+		TAILQ_REMOVE(&vf->rss_parser_list, p_parser, node);
+		rte_free(p_parser);
+	}
+
+	while ((p_parser = TAILQ_FIRST(&vf->dist_parser_list))) {
+		TAILQ_REMOVE(&vf->dist_parser_list, p_parser, node);
+		rte_free(p_parser);
+	}
+}
+
+int
+iavf_register_parser(struct iavf_flow_parser *parser,
+		     struct iavf_adapter *ad)
+{
+	struct iavf_parser_list *list = NULL;
+	struct iavf_flow_parser_node *parser_node;
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
+
+	parser_node = rte_zmalloc("iavf_parser", sizeof(*parser_node), 0);
+	if (parser_node == NULL) {
+		PMD_DRV_LOG(ERR, "Failed to allocate memory.");
+		return -ENOMEM;
+	}
+	parser_node->parser = parser;
+
+	if (parser->engine->type == IAVF_FLOW_ENGINE_HASH) {
+		list = &vf->rss_parser_list;
+		TAILQ_INSERT_TAIL(list, parser_node, node);
+	} else if (parser->engine->type == IAVF_FLOW_ENGINE_FDIR) {
+		list = &vf->dist_parser_list;
+		TAILQ_INSERT_HEAD(list, parser_node, node);
+	} else
+		return -EINVAL;
+
+	return 0;
+}
+
+void
+iavf_unregister_parser(struct iavf_flow_parser *parser,
+		       struct iavf_adapter *ad)
+{
+	struct iavf_parser_list *list = NULL;
+	struct iavf_flow_parser_node *p_parser;
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
+	void *temp;
+
+	if (parser->engine->type == IAVF_FLOW_ENGINE_HASH)
+		list = &vf->rss_parser_list;
+	else if (parser->engine->type == IAVF_FLOW_ENGINE_FDIR)
+		list = &vf->dist_parser_list;
+
+	if (list == NULL)
+		return;
+
+	TAILQ_FOREACH_SAFE(p_parser, list, node, temp) {
+		if (p_parser->parser->engine->type == parser->engine->type) {
+			TAILQ_REMOVE(list, p_parser, node);
+			rte_free(p_parser);
+		}
+	}
+}
+
+static int
+iavf_flow_valid_attr(const struct rte_flow_attr *attr,
+		     struct rte_flow_error *error)
+{
+	/* Must be input direction */
+	if (!attr->ingress) {
+		rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
+				attr, "Only support ingress.");
+		return -rte_errno;
+	}
+
+	/* Not supported */
+	if (attr->egress) {
+		rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
+				attr, "Not support egress.");
+		return -rte_errno;
+	}
+
+	/* Not supported */
+	if (attr->priority) {
+		rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
+				attr, "Not support priority.");
+		return -rte_errno;
+	}
+
+	/* Not supported */
+	if (attr->group) {
+		rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
+				attr, "Not support group.");
+		return -rte_errno;
+	}
+
+	return 0;
+}
+
+/* Find the first VOID or non-VOID item pointer */
+static const struct rte_flow_item *
+iavf_find_first_item(const struct rte_flow_item *item, bool is_void)
+{
+	bool is_find;
+
+	while (item->type != RTE_FLOW_ITEM_TYPE_END) {
+		if (is_void)
+			is_find = item->type == RTE_FLOW_ITEM_TYPE_VOID;
+		else
+			is_find = item->type != RTE_FLOW_ITEM_TYPE_VOID;
+		if (is_find)
+			break;
+		item++;
+	}
+	return item;
+}
+
+/* Skip all VOID items of the pattern */
+static void
+iavf_pattern_skip_void_item(struct rte_flow_item *items,
+			const struct rte_flow_item *pattern)
+{
+	uint32_t cpy_count = 0;
+	const struct rte_flow_item *pb = pattern, *pe = pattern;
+
+	for (;;) {
+		/* Find a non-void item first */
+		pb = iavf_find_first_item(pb, false);
+		if (pb->type == RTE_FLOW_ITEM_TYPE_END) {
+			pe = pb;
+			break;
+		}
+
+		/* Find a void item */
+		pe = iavf_find_first_item(pb + 1, true);
+
+		cpy_count = pe - pb;
+		rte_memcpy(items, pb, sizeof(struct rte_flow_item) * cpy_count);
+
+		items += cpy_count;
+
+		if (pe->type == RTE_FLOW_ITEM_TYPE_END)
+			break;
+
+		pb = pe + 1;
+	}
+	/* Copy the END item. */
+	rte_memcpy(items, pe, sizeof(struct rte_flow_item));
+}
+
+/* Check if the pattern matches a supported item type array */
+static bool
+iavf_match_pattern(enum rte_flow_item_type *item_array,
+		   const struct rte_flow_item *pattern)
+{
+	const struct rte_flow_item *item = pattern;
+
+	while ((*item_array == item->type) &&
+	       (*item_array != RTE_FLOW_ITEM_TYPE_END)) {
+		item_array++;
+		item++;
+	}
+
+	return (*item_array == RTE_FLOW_ITEM_TYPE_END &&
+		item->type == RTE_FLOW_ITEM_TYPE_END);
+}
+
+struct iavf_pattern_match_item *
+iavf_search_pattern_match_item(const struct rte_flow_item pattern[],
+		struct iavf_pattern_match_item *array,
+		uint32_t array_len,
+		struct rte_flow_error *error)
+{
+	uint16_t i = 0;
+	struct iavf_pattern_match_item *pattern_match_item;
+	/* need free by each filter */
+	struct rte_flow_item *items; /* used for pattern without VOID items */
+	uint32_t item_num = 0; /* non-void item number */
+
+	/* Get the non-void item number of pattern */
+	while ((pattern + i)->type != RTE_FLOW_ITEM_TYPE_END) {
+		if ((pattern + i)->type != RTE_FLOW_ITEM_TYPE_VOID)
+			item_num++;
+		i++;
+	}
+	item_num++;
+
+	items = rte_zmalloc("iavf_pattern",
+			    item_num * sizeof(struct rte_flow_item), 0);
+	if (!items) {
+		rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_ITEM_NUM,
+				   NULL, "No memory for PMD internal items.");
+		return NULL;
+	}
+	pattern_match_item = rte_zmalloc("iavf_pattern_match_item",
+				sizeof(struct iavf_pattern_match_item), 0);
+	if (!pattern_match_item) {
+		rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
+				   NULL, "Failed to allocate memory.");
+		return NULL;
+	}
+
+	iavf_pattern_skip_void_item(items, pattern);
+
+	for (i = 0; i < array_len; i++)
+		if (iavf_match_pattern(array[i].pattern_list,
+				       items)) {
+			pattern_match_item->input_set_mask =
+				array[i].input_set_mask;
+			pattern_match_item->pattern_list =
+				array[i].pattern_list;
+			pattern_match_item->meta = array[i].meta;
+			rte_free(items);
+			return pattern_match_item;
+		}
+	rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
+			   pattern, "Unsupported pattern");
+
+	rte_free(items);
+	rte_free(pattern_match_item);
+	return NULL;
+}
+
+static struct iavf_flow_engine *
+iavf_parse_engine_create(struct iavf_adapter *ad,
+		struct rte_flow *flow,
+		struct iavf_parser_list *parser_list,
+		const struct rte_flow_item pattern[],
+		const struct rte_flow_action actions[],
+		struct rte_flow_error *error)
+{
+	struct iavf_flow_engine *engine = NULL;
+	struct iavf_flow_parser_node *parser_node;
+	void *temp;
+	void *meta = NULL;
+
+	TAILQ_FOREACH_SAFE(parser_node, parser_list, node, temp) {
+		if (parser_node->parser->parse_pattern_action(ad,
+				parser_node->parser->array,
+				parser_node->parser->array_len,
+				pattern, actions, &meta, error) < 0)
+			continue;
+
+		engine = parser_node->parser->engine;
+		if (engine->create == NULL) {
+			rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_HANDLE,
+				NULL, "Invalid engine");
+			continue;
+		}
+
+		if (!(engine->create(ad, flow, meta, error)))
+			return engine;
+	}
+	return NULL;
+}
+
+static struct iavf_flow_engine *
+iavf_parse_engine_validate(struct iavf_adapter *ad,
+		struct rte_flow *flow,
+		struct iavf_parser_list *parser_list,
+		const struct rte_flow_item pattern[],
+		const struct rte_flow_action actions[],
+		struct rte_flow_error *error)
+{
+	struct iavf_flow_engine *engine = NULL;
+	struct iavf_flow_parser_node *parser_node;
+	void *temp;
+	void *meta = NULL;
+
+	TAILQ_FOREACH_SAFE(parser_node, parser_list, node, temp) {
+		if (parser_node->parser->parse_pattern_action(ad,
+				parser_node->parser->array,
+				parser_node->parser->array_len,
+				pattern, actions, &meta,  error) < 0)
+			continue;
+
+		engine = parser_node->parser->engine;
+		if (engine->validation == NULL) {
+			rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_HANDLE,
+				NULL, "Validation not support");
+			continue;
+		}
+
+		if (engine->validation(ad, flow, meta, error)) {
+			rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_HANDLE,
+				NULL, "Validation failed");
+			break;
+		}
+	}
+	return engine;
+}
+
+
+static int
+iavf_flow_process_filter(struct rte_eth_dev *dev,
+		struct rte_flow *flow,
+		const struct rte_flow_attr *attr,
+		const struct rte_flow_item pattern[],
+		const struct rte_flow_action actions[],
+		struct iavf_flow_engine **engine,
+		parse_engine_t iavf_parse_engine,
+		struct rte_flow_error *error)
+{
+	int ret = IAVF_ERR_CONFIG;
+	struct iavf_adapter *ad =
+		IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
+
+	if (!pattern) {
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_NUM,
+				   NULL, "NULL pattern.");
+		return -rte_errno;
+	}
+
+	if (!actions) {
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_ACTION_NUM,
+				   NULL, "NULL action.");
+		return -rte_errno;
+	}
+
+	if (!attr) {
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_ATTR,
+				   NULL, "NULL attribute.");
+		return -rte_errno;
+	}
+
+	ret = iavf_flow_valid_attr(attr, error);
+	if (ret)
+		return ret;
+
+	*engine = iavf_parse_engine(ad, flow, &vf->rss_parser_list, pattern,
+				    actions, error);
+	if (*engine != NULL)
+		return 0;
+
+	*engine = iavf_parse_engine(ad, flow, &vf->dist_parser_list, pattern,
+				    actions, error);
+
+	if (*engine == NULL)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int
+iavf_flow_validate(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)
+{
+	struct iavf_flow_engine *engine;
+
+	return iavf_flow_process_filter(dev, NULL, attr, pattern, actions,
+			&engine, iavf_parse_engine_validate, error);
+}
+
+static struct rte_flow *
+iavf_flow_create(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)
+{
+	struct iavf_adapter *ad =
+		IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
+	struct iavf_flow_engine *engine = NULL;
+	struct rte_flow *flow = NULL;
+	int ret;
+
+	flow = rte_zmalloc("iavf_flow", sizeof(struct rte_flow), 0);
+	if (!flow) {
+		rte_flow_error_set(error, ENOMEM,
+				   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+				   "Failed to allocate memory");
+		return flow;
+	}
+
+	ret = iavf_flow_process_filter(dev, flow, attr, pattern, actions,
+			&engine, iavf_parse_engine_create, error);
+	if (ret < 0)
+		goto free_flow;
+
+	flow->engine = engine;
+	TAILQ_INSERT_TAIL(&vf->flow_list, flow, node);
+	PMD_DRV_LOG(INFO, "Succeeded to create (%d) flow", engine->type);
+	return flow;
+
+free_flow:
+	PMD_DRV_LOG(ERR, "Failed to create flow");
+	rte_free(flow);
+	return NULL;
+}
+
+static int
+iavf_flow_destroy(struct rte_eth_dev *dev,
+		  struct rte_flow *flow,
+		  struct rte_flow_error *error)
+{
+	struct iavf_adapter *ad =
+		IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
+	int ret = 0;
+
+	if (!flow || !flow->engine || !flow->engine->destroy) {
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_HANDLE,
+				   NULL, "Invalid flow");
+		return -rte_errno;
+	}
+
+	ret = flow->engine->destroy(ad, flow, error);
+
+	if (!ret) {
+		TAILQ_REMOVE(&vf->flow_list, flow, node);
+		rte_free(flow);
+	} else {
+		PMD_DRV_LOG(ERR, "Failed to destroy flow");
+	}
+
+	return ret;
+}
+
+static int
+iavf_flow_flush(struct rte_eth_dev *dev,
+		struct rte_flow_error *error)
+{
+	struct iavf_adapter *ad =
+		IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
+	struct rte_flow *p_flow;
+	void *temp;
+	int ret = 0;
+
+	TAILQ_FOREACH_SAFE(p_flow, &vf->flow_list, node, temp) {
+		ret = iavf_flow_destroy(dev, p_flow, error);
+		if (ret) {
+			PMD_DRV_LOG(ERR, "Failed to flush flows");
+			return -EINVAL;
+		}
+	}
+
+	return ret;
+}
+
+static int
+iavf_flow_query(struct rte_eth_dev *dev,
+		struct rte_flow *flow,
+		const struct rte_flow_action *actions,
+		void *data,
+		struct rte_flow_error *error)
+{
+	int ret = -EINVAL;
+	struct iavf_adapter *ad =
+		IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+	struct rte_flow_query_count *count = data;
+
+	if (!flow || !flow->engine || !flow->engine->query_count) {
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_HANDLE,
+				   NULL, "Invalid flow");
+		return -rte_errno;
+	}
+
+	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
+		switch (actions->type) {
+		case RTE_FLOW_ACTION_TYPE_VOID:
+			break;
+		case RTE_FLOW_ACTION_TYPE_COUNT:
+			ret = flow->engine->query_count(ad, flow, count, error);
+			break;
+		default:
+			return rte_flow_error_set(error, ENOTSUP,
+					RTE_FLOW_ERROR_TYPE_ACTION,
+					actions,
+					"action not supported");
+		}
+	}
+	return ret;
+}
+
diff --git a/drivers/net/iavf/iavf_generic_flow.h b/drivers/net/iavf/iavf_generic_flow.h
new file mode 100644
index 0000000..1e69863
--- /dev/null
+++ b/drivers/net/iavf/iavf_generic_flow.h
@@ -0,0 +1,279 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#ifndef _IAVF_GENERIC_FLOW_H_
+#define _IAVF_GENERIC_FLOW_H_
+
+#include <rte_flow_driver.h>
+
+/* protocol */
+
+#define IAVF_PROT_MAC_INNER         (1ULL << 1)
+#define IAVF_PROT_MAC_OUTER         (1ULL << 2)
+#define IAVF_PROT_VLAN_INNER        (1ULL << 3)
+#define IAVF_PROT_VLAN_OUTER        (1ULL << 4)
+#define IAVF_PROT_IPV4_INNER        (1ULL << 5)
+#define IAVF_PROT_IPV4_OUTER        (1ULL << 6)
+#define IAVF_PROT_IPV6_INNER        (1ULL << 7)
+#define IAVF_PROT_IPV6_OUTER        (1ULL << 8)
+#define IAVF_PROT_TCP_INNER         (1ULL << 9)
+#define IAVF_PROT_TCP_OUTER         (1ULL << 10)
+#define IAVF_PROT_UDP_INNER         (1ULL << 11)
+#define IAVF_PROT_UDP_OUTER         (1ULL << 12)
+#define IAVF_PROT_SCTP_INNER        (1ULL << 13)
+#define IAVF_PROT_SCTP_OUTER        (1ULL << 14)
+#define IAVF_PROT_ICMP4_INNER       (1ULL << 15)
+#define IAVF_PROT_ICMP4_OUTER       (1ULL << 16)
+#define IAVF_PROT_ICMP6_INNER       (1ULL << 17)
+#define IAVF_PROT_ICMP6_OUTER       (1ULL << 18)
+#define IAVF_PROT_VXLAN             (1ULL << 19)
+#define IAVF_PROT_NVGRE             (1ULL << 20)
+#define IAVF_PROT_GTPU              (1ULL << 21)
+
+
+/* field */
+
+#define IAVF_SMAC                   (1ULL << 63)
+#define IAVF_DMAC                   (1ULL << 62)
+#define IAVF_ETHERTYPE              (1ULL << 61)
+#define IAVF_IP_SRC                 (1ULL << 60)
+#define IAVF_IP_DST                 (1ULL << 59)
+#define IAVF_IP_PROTO               (1ULL << 58)
+#define IAVF_IP_TTL                 (1ULL << 57)
+#define IAVF_IP_TOS                 (1ULL << 56)
+#define IAVF_SPORT                  (1ULL << 55)
+#define IAVF_DPORT                  (1ULL << 54)
+#define IAVF_ICMP_TYPE              (1ULL << 53)
+#define IAVF_ICMP_CODE              (1ULL << 52)
+#define IAVF_VXLAN_VNI              (1ULL << 51)
+#define IAVF_NVGRE_TNI              (1ULL << 50)
+#define IAVF_GTPU_TEID              (1ULL << 49)
+#define IAVF_GTPU_QFI               (1ULL << 48)
+
+/* input set */
+
+#define IAVF_INSET_NONE             0ULL
+
+/* non-tunnel */
+
+#define IAVF_INSET_SMAC         (IAVF_PROT_MAC_OUTER | IAVF_SMAC)
+#define IAVF_INSET_DMAC         (IAVF_PROT_MAC_OUTER | IAVF_DMAC)
+#define IAVF_INSET_VLAN_INNER   (IAVF_PROT_VLAN_INNER)
+#define IAVF_INSET_VLAN_OUTER   (IAVF_PROT_VLAN_OUTER)
+#define IAVF_INSET_ETHERTYPE    (IAVF_ETHERTYPE)
+
+#define IAVF_INSET_IPV4_SRC \
+	(IAVF_PROT_IPV4_OUTER | IAVF_IP_SRC)
+#define IAVF_INSET_IPV4_DST \
+	(IAVF_PROT_IPV4_OUTER | IAVF_IP_DST)
+#define IAVF_INSET_IPV4_TOS \
+	(IAVF_PROT_IPV4_OUTER | IAVF_IP_TOS)
+#define IAVF_INSET_IPV4_PROTO \
+	(IAVF_PROT_IPV4_OUTER | IAVF_IP_PROTO)
+#define IAVF_INSET_IPV4_TTL \
+	(IAVF_PROT_IPV4_OUTER | IAVF_IP_TTL)
+#define IAVF_INSET_IPV6_SRC \
+	(IAVF_PROT_IPV6_OUTER | IAVF_IP_SRC)
+#define IAVF_INSET_IPV6_DST \
+	(IAVF_PROT_IPV6_OUTER | IAVF_IP_DST)
+#define IAVF_INSET_IPV6_NEXT_HDR \
+	(IAVF_PROT_IPV6_OUTER | IAVF_IP_PROTO)
+#define IAVF_INSET_IPV6_HOP_LIMIT \
+	(IAVF_PROT_IPV6_OUTER | IAVF_IP_TTL)
+#define IAVF_INSET_IPV6_TC \
+	(IAVF_PROT_IPV6_OUTER | IAVF_IP_TOS)
+
+#define IAVF_INSET_TCP_SRC_PORT \
+	(IAVF_PROT_TCP_OUTER | IAVF_SPORT)
+#define IAVF_INSET_TCP_DST_PORT \
+	(IAVF_PROT_TCP_OUTER | IAVF_DPORT)
+#define IAVF_INSET_UDP_SRC_PORT \
+	(IAVF_PROT_UDP_OUTER | IAVF_SPORT)
+#define IAVF_INSET_UDP_DST_PORT \
+	(IAVF_PROT_UDP_OUTER | IAVF_DPORT)
+#define IAVF_INSET_SCTP_SRC_PORT \
+	(IAVF_PROT_SCTP_OUTER | IAVF_SPORT)
+#define IAVF_INSET_SCTP_DST_PORT \
+	(IAVF_PROT_SCTP_OUTER | IAVF_DPORT)
+#define IAVF_INSET_ICMP4_SRC_PORT \
+	(IAVF_PROT_ICMP4_OUTER | IAVF_SPORT)
+#define IAVF_INSET_ICMP4_DST_PORT \
+	(IAVF_PROT_ICMP4_OUTER | IAVF_DPORT)
+#define IAVF_INSET_ICMP6_SRC_PORT \
+	(IAVF_PROT_ICMP6_OUTER | IAVF_SPORT)
+#define IAVF_INSET_ICMP6_DST_PORT \
+	(IAVF_PROT_ICMP6_OUTER | IAVF_DPORT)
+#define IAVF_INSET_ICMP4_TYPE \
+	(IAVF_PROT_ICMP4_OUTER | IAVF_ICMP_TYPE)
+#define IAVF_INSET_ICMP4_CODE \
+	(IAVF_PROT_ICMP4_OUTER | IAVF_ICMP_CODE)
+#define IAVF_INSET_ICMP6_TYPE \
+	(IAVF_PROT_ICMP6_OUTER | IAVF_ICMP_TYPE)
+#define IAVF_INSET_ICMP6_CODE \
+	(IAVF_PROT_ICMP6_OUTER | IAVF_ICMP_CODE)
+#define IAVF_INSET_GTPU_TEID \
+	(IAVF_PROT_GTPU | IAVF_GTPU_TEID)
+#define IAVF_INSET_GTPU_QFI \
+	(IAVF_PROT_GTPU | IAVF_GTPU_QFI)
+
+
+/* empty pattern */
+extern enum rte_flow_item_type iavf_pattern_empty[];
+
+/* L2 */
+extern enum rte_flow_item_type iavf_pattern_ethertype[];
+extern enum rte_flow_item_type iavf_pattern_ethertype_vlan[];
+extern enum rte_flow_item_type iavf_pattern_ethertype_qinq[];
+
+/* ARP */
+extern enum rte_flow_item_type iavf_pattern_eth_arp[];
+
+/* non-tunnel IPv4 */
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_udp[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_udp[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_udp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_tcp[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_tcp[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_tcp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_sctp[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_sctp[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_sctp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_icmp[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_icmp[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_icmp[];
+
+/* non-tunnel IPv6 */
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6_udp[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_udp[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_udp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6_tcp[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_tcp[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_tcp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6_sctp[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_sctp[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_sctp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6_icmp6[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_icmp6[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_icmp6[];
+
+/* GTPU */
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_ipv4[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_udp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_tcp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_icmp[];
+
+
+extern const struct rte_flow_ops iavf_flow_ops;
+
+/* pattern structure */
+struct iavf_pattern_match_item {
+	enum rte_flow_item_type *pattern_list;
+	/* pattern_list must end with RTE_FLOW_ITEM_TYPE_END */
+	uint64_t input_set_mask;
+	void *meta;
+};
+
+typedef int (*engine_init_t)(struct iavf_adapter *ad);
+typedef void (*engine_uninit_t)(struct iavf_adapter *ad);
+typedef int (*engine_validation_t)(struct iavf_adapter *ad,
+		struct rte_flow *flow,
+		void *meta,
+		struct rte_flow_error *error);
+typedef int (*engine_create_t)(struct iavf_adapter *ad,
+		struct rte_flow *flow,
+		void *meta,
+		struct rte_flow_error *error);
+typedef int (*engine_destroy_t)(struct iavf_adapter *ad,
+		struct rte_flow *flow,
+		struct rte_flow_error *error);
+typedef int (*engine_query_t)(struct iavf_adapter *ad,
+		struct rte_flow *flow,
+		struct rte_flow_query_count *count,
+		struct rte_flow_error *error);
+typedef void (*engine_free_t) (struct rte_flow *flow);
+typedef int (*parse_pattern_action_t)(struct iavf_adapter *ad,
+		struct iavf_pattern_match_item *array,
+		uint32_t array_len,
+		const struct rte_flow_item pattern[],
+		const struct rte_flow_action actions[],
+		void **meta,
+		struct rte_flow_error *error);
+
+/* engine types. */
+enum iavf_flow_engine_type {
+	IAVF_FLOW_ENGINE_NONE = 0,
+	IAVF_FLOW_ENGINE_FDIR,
+	IAVF_FLOW_ENGINE_HASH,
+	IAVF_FLOW_ENGINE_MAX,
+};
+
+/**
+ * classification stages.
+ * for non-pipeline mode, we have two classification stages: Distributor/RSS
+ * for pipeline-mode we have three classification stages:
+ * Permission/Distributor/RSS
+ */
+enum iavf_flow_classification_stage {
+	IAVF_FLOW_STAGE_NONE = 0,
+	IAVF_FLOW_STAGE_RSS,
+	IAVF_FLOW_STAGE_DISTRIBUTOR,
+	IAVF_FLOW_STAGE_MAX,
+};
+
+/* Struct to store engine created. */
+struct iavf_flow_engine {
+	TAILQ_ENTRY(iavf_flow_engine) node;
+	engine_init_t init;
+	engine_uninit_t uninit;
+	engine_validation_t validation;
+	engine_create_t create;
+	engine_destroy_t destroy;
+	engine_query_t query_count;
+	engine_free_t free;
+	enum iavf_flow_engine_type type;
+};
+
+TAILQ_HEAD(iavf_engine_list, iavf_flow_engine);
+
+/* Struct to store flow created. */
+struct rte_flow {
+	TAILQ_ENTRY(rte_flow) node;
+	struct iavf_flow_engine *engine;
+	void *rule;
+};
+
+struct iavf_flow_parser {
+	struct iavf_flow_engine *engine;
+	struct iavf_pattern_match_item *array;
+	uint32_t array_len;
+	parse_pattern_action_t parse_pattern_action;
+	enum iavf_flow_classification_stage stage;
+};
+
+/* Struct to store parser created. */
+struct iavf_flow_parser_node {
+	TAILQ_ENTRY(iavf_flow_parser_node) node;
+	struct iavf_flow_parser *parser;
+};
+
+void iavf_register_flow_engine(struct iavf_flow_engine *engine);
+int iavf_flow_init(struct iavf_adapter *ad);
+void iavf_flow_uninit(struct iavf_adapter *ad);
+int iavf_register_parser(struct iavf_flow_parser *parser,
+			 struct iavf_adapter *ad);
+void iavf_unregister_parser(struct iavf_flow_parser *parser,
+			    struct iavf_adapter *ad);
+struct iavf_pattern_match_item *
+iavf_search_pattern_match_item(const struct rte_flow_item pattern[],
+		struct iavf_pattern_match_item *array,
+		uint32_t array_len,
+		struct rte_flow_error *error);
+#endif
diff --git a/drivers/net/iavf/meson.build b/drivers/net/iavf/meson.build
index dbd0b01..32eabca 100644
--- a/drivers/net/iavf/meson.build
+++ b/drivers/net/iavf/meson.build
@@ -12,6 +12,7 @@ sources = files(
 	'iavf_ethdev.c',
 	'iavf_rxtx.c',
 	'iavf_vchnl.c',
+	'iavf_generic_flow.c',
 )
 
 if arch_subdir == 'x86'
-- 
2.9.5


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

* [dpdk-dev] [PATCH 2/2] net/iavf: support more patterns
  2020-03-17  8:17 [dpdk-dev] [PATCH 0/2] add generic filter support for iavf Qiming Yang
  2020-03-17  8:17 ` [dpdk-dev] [PATCH 1/2] net/iavf: support generic flow Qiming Yang
@ 2020-03-17  8:17 ` Qiming Yang
  2020-03-30  8:30 ` [dpdk-dev] [PATCH v2 0/2] add generic filter support for iavf Qiming Yang
  2020-04-03  5:42 ` [dpdk-dev] [PATCH v3 0/2] add generic filter support for iavf Qiming Yang
  3 siblings, 0 replies; 14+ messages in thread
From: Qiming Yang @ 2020-03-17  8:17 UTC (permalink / raw)
  To: dev; +Cc: Qiming Yang, Zhang Xiao

Add patterns support for AH/ESP/L2TPV3OIP/PFCP.
Added patterns are as follows:
/* GTPU */
    eth/ipv4/udp/gtpu
    eth/ipv4/udp/gtpu/gtp_psc
/* ESP */
    eth/ipv4/esp  eth/ipv4/udp/esp
    eth/ipv6/esp  eth/ipv6/udp/esp
/* AH */
    eth/ipv4/ah  eth/ipv6/ah
/* L2TPV3 */
    eth/ipv4/l2tpv3oip  eth/ipv6/l2tpv3oip
/* PFCP */
    eth/ipv4/udp/pfcp  eth/ipv6/udp/pfcp

Depends on patch: ethdev: add PFCP header to flow API

Signed-off-by: Zhang Xiao <xiao.zhang@intel.com>
---
 drivers/net/iavf/iavf_generic_flow.c | 95 ++++++++++++++++++++++++++++++++++++
 drivers/net/iavf/iavf_generic_flow.h | 39 +++++++++++++++
 2 files changed, 134 insertions(+)

diff --git a/drivers/net/iavf/iavf_generic_flow.c b/drivers/net/iavf/iavf_generic_flow.c
index 65767aa..c187265 100644
--- a/drivers/net/iavf/iavf_generic_flow.c
+++ b/drivers/net/iavf/iavf_generic_flow.c
@@ -318,6 +318,23 @@ enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_icmp6[] = {
 };
 
 /* GTPU */
+enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_GTPU,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_GTPU,
+	RTE_FLOW_ITEM_TYPE_GTP_PSC,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
 enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_ipv4[] = {
 	RTE_FLOW_ITEM_TYPE_ETH,
 	RTE_FLOW_ITEM_TYPE_IPV4,
@@ -371,6 +388,84 @@ enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_icmp[] = {
 	RTE_FLOW_ITEM_TYPE_END,
 };
 
+/* ESP */
+enum rte_flow_item_type iavf_pattern_eth_ipv4_esp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_ESP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_udp_esp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_ESP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv6_esp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_ESP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv6_udp_esp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_ESP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+/* AH */
+enum rte_flow_item_type iavf_pattern_eth_ipv4_ah[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_AH,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv6_ah[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_AH,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+/* L2TPV3 */
+enum rte_flow_item_type iavf_pattern_eth_ipv4_l2tpv3[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_L2TPV3OIP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv6_l2tpv3[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_L2TPV3OIP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+/* PFCP */
+enum rte_flow_item_type iavf_pattern_eth_ipv4_pfcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_PFCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv6_pfcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_PFCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
 typedef struct iavf_flow_engine * (*parse_engine_t)(struct iavf_adapter *ad,
 		struct rte_flow *flow,
 		struct iavf_parser_list *parser_list,
diff --git a/drivers/net/iavf/iavf_generic_flow.h b/drivers/net/iavf/iavf_generic_flow.h
index 1e69863..c41ca1b 100644
--- a/drivers/net/iavf/iavf_generic_flow.h
+++ b/drivers/net/iavf/iavf_generic_flow.h
@@ -30,6 +30,10 @@
 #define IAVF_PROT_VXLAN             (1ULL << 19)
 #define IAVF_PROT_NVGRE             (1ULL << 20)
 #define IAVF_PROT_GTPU              (1ULL << 21)
+#define IAVF_PROT_ESP		    (1ULL << 22)
+#define IAVF_PROT_AH		    (1ULL << 23)
+#define IAVF_PROT_L2TPV3OIP	    (1ULL << 24)
+#define IAVF_PROT_PFCP		    (1ULL << 25)
 
 
 /* field */
@@ -50,6 +54,11 @@
 #define IAVF_NVGRE_TNI              (1ULL << 50)
 #define IAVF_GTPU_TEID              (1ULL << 49)
 #define IAVF_GTPU_QFI               (1ULL << 48)
+#define IAVF_ESP_SPI		    (1ULL << 47)
+#define IAVF_AH_SPI		    (1ULL << 46)
+#define IAVF_L2TPV3OIP_SESSION_ID   (1ULL << 45)
+#define IAVF_PFCP_S_FIELD	    (1ULL << 44)
+#define IAVF_PFCP_SEID		    (1ULL << 43)
 
 /* input set */
 
@@ -116,6 +125,16 @@
 	(IAVF_PROT_GTPU | IAVF_GTPU_TEID)
 #define IAVF_INSET_GTPU_QFI \
 	(IAVF_PROT_GTPU | IAVF_GTPU_QFI)
+#define IAVF_INSET_ESP_SPI \
+	(IAVF_PROT_ESP | IAVF_ESP_SPI)
+#define IAVF_INSET_AH_SPI \
+	(IAVF_PROT_AH | IAVF_AH_SPI)
+#define IAVF_INSET_L2TPV3OIP_SESSION_ID \
+	(IAVF_PROT_L2TPV3OIP | IAVF_L2TPV3OIP_SESSION_ID)
+#define IAVF_INSET_PFCP_S_FIELD \
+	(IAVF_PROT_PFCP | IAVF_PFCP_S_FIELD)
+#define IAVF_INSET_PFCP_SEID \
+	(IAVF_PROT_PFCP | IAVF_PFCP_S_FIELD | IAVF_PFCP_SEID)
 
 
 /* empty pattern */
@@ -164,12 +183,32 @@ extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_icmp6[];
 extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_icmp6[];
 
 /* GTPU */
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu[];
 extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_ipv4[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh[];
 extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4[];
 extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_udp[];
 extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_tcp[];
 extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_icmp[];
 
+/* ESP */
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_esp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_udp_esp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6_esp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6_udp_esp[];
+
+/* AH */
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_ah[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6_ah[];
+
+/* L2TPV3 */
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_l2tpv3[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6_l2tpv3[];
+
+/* PFCP */
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_pfcp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6_pfcp[];
+
 
 extern const struct rte_flow_ops iavf_flow_ops;
 
-- 
2.9.5


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

* Re: [dpdk-dev] [PATCH 1/2] net/iavf: support generic flow
  2020-03-17  8:17 ` [dpdk-dev] [PATCH 1/2] net/iavf: support generic flow Qiming Yang
@ 2020-03-19  2:01   ` Zhang, Qi Z
  2020-03-20  1:20     ` Yang, Qiming
  0 siblings, 1 reply; 14+ messages in thread
From: Zhang, Qi Z @ 2020-03-19  2:01 UTC (permalink / raw)
  To: Yang, Qiming, dev; +Cc: Yang, Qiming



> -----Original Message-----
> From: dev <dev-bounces@dpdk.org> On Behalf Of Qiming Yang
> Sent: Tuesday, March 17, 2020 4:18 PM
> To: dev@dpdk.org
> Cc: Yang, Qiming <qiming.yang@intel.com>
> Subject: [dpdk-dev] [PATCH 1/2] net/iavf: support generic flow
> 
> This patch added iavf_flow_create, iavf_flow_destroy, iavf_flow_flush and
> iavf_flow_validate support, these are used to handle all the generic filters.
> 
> This patch supported basic L2, L3, L4 and GTPU patterns.
> 
> Signed-off-by: Qiming Yang <qiming.yang@intel.com>
> ---
>  doc/guides/rel_notes/release_20_05.rst |   5 +
>  drivers/net/iavf/Makefile              |   1 +
>  drivers/net/iavf/iavf.h                |   9 +
>  drivers/net/iavf/iavf_ethdev.c         |  46 ++
>  drivers/net/iavf/iavf_generic_flow.c   | 928
> +++++++++++++++++++++++++++++++++
>  drivers/net/iavf/iavf_generic_flow.h   | 279 ++++++++++
>  drivers/net/iavf/meson.build           |   1 +
>  7 files changed, 1269 insertions(+)
>  create mode 100644 drivers/net/iavf/iavf_generic_flow.c
>  create mode 100644 drivers/net/iavf/iavf_generic_flow.h
> 
> diff --git a/doc/guides/rel_notes/release_20_05.rst
> b/doc/guides/rel_notes/release_20_05.rst
> index 2190eaf..44d375a 100644
> --- a/doc/guides/rel_notes/release_20_05.rst
> +++ b/doc/guides/rel_notes/release_20_05.rst
> @@ -56,6 +56,11 @@ New Features
>       Also, make sure to start the actual text at the margin.
> 
> =========================================================
> 
> +* **Updated the Intel ice driver.**
> +
> +  Updated the Intel ice driver with new features and improvements,
> including:
> +
> +  * Added support for DCF (Device Config Function) feature.

Above comment is not related with this patch, right?

> 
>  Removed Items
>  -------------
....


> +
> +static struct iavf_flow_engine *
> +iavf_parse_engine_create(struct iavf_adapter *ad,
> +		struct rte_flow *flow,
> +		struct iavf_parser_list *parser_list,
> +		const struct rte_flow_item pattern[],
> +		const struct rte_flow_action actions[],
> +		struct rte_flow_error *error)
> +{
> +	struct iavf_flow_engine *engine = NULL;
> +	struct iavf_flow_parser_node *parser_node;
> +	void *temp;
> +	void *meta = NULL;
> +
> +	TAILQ_FOREACH_SAFE(parser_node, parser_list, node, temp) {
> +		if (parser_node->parser->parse_pattern_action(ad,
> +				parser_node->parser->array,
> +				parser_node->parser->array_len,
> +				pattern, actions, &meta, error) < 0)
> +			continue;
> +
> +		engine = parser_node->parser->engine;
> +		if (engine->create == NULL) {
> +			rte_flow_error_set(error, EINVAL,
> +				RTE_FLOW_ERROR_TYPE_HANDLE,
> +				NULL, "Invalid engine");
> +			continue;
> +		}

Please sync with below fix for ice
https://patchwork.dpdk.org/patch/66232/

> +
> +		if (!(engine->create(ad, flow, meta, error)))
> +			return engine;
> +	}
> +	return NULL;
> +}
> +
> +static struct iavf_flow_engine *
> +iavf_parse_engine_validate(struct iavf_adapter *ad,
> +		struct rte_flow *flow,
> +		struct iavf_parser_list *parser_list,
> +		const struct rte_flow_item pattern[],
> +		const struct rte_flow_action actions[],
> +		struct rte_flow_error *error)
> +{
> +	struct iavf_flow_engine *engine = NULL;
> +	struct iavf_flow_parser_node *parser_node;
> +	void *temp;
> +	void *meta = NULL;
> +
> +	TAILQ_FOREACH_SAFE(parser_node, parser_list, node, temp) {
> +		if (parser_node->parser->parse_pattern_action(ad,
> +				parser_node->parser->array,
> +				parser_node->parser->array_len,
> +				pattern, actions, &meta,  error) < 0)
> +			continue;
> +
Please sync with below fix for ice
https://patchwork.dpdk.org/patch/66232/


> +		engine = parser_node->parser->engine;
> +		if (engine->validation == NULL) {
> +			rte_flow_error_set(error, EINVAL,
> +				RTE_FLOW_ERROR_TYPE_HANDLE,
> +				NULL, "Validation not support");
> +			continue;
> +		}

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

* Re: [dpdk-dev] [PATCH 1/2] net/iavf: support generic flow
  2020-03-19  2:01   ` Zhang, Qi Z
@ 2020-03-20  1:20     ` Yang, Qiming
  0 siblings, 0 replies; 14+ messages in thread
From: Yang, Qiming @ 2020-03-20  1:20 UTC (permalink / raw)
  To: Zhang, Qi Z, dev

Thanks, I'll fix them in v2

> -----Original Message-----
> From: Zhang, Qi Z <qi.z.zhang@intel.com>
> Sent: 2020年3月19日 10:01
> To: Yang, Qiming <qiming.yang@intel.com>; dev@dpdk.org
> Cc: Yang, Qiming <qiming.yang@intel.com>
> Subject: RE: [dpdk-dev] [PATCH 1/2] net/iavf: support generic flow
> 
> 
> 
> > -----Original Message-----
> > From: dev <dev-bounces@dpdk.org> On Behalf Of Qiming Yang
> > Sent: Tuesday, March 17, 2020 4:18 PM
> > To: dev@dpdk.org
> > Cc: Yang, Qiming <qiming.yang@intel.com>
> > Subject: [dpdk-dev] [PATCH 1/2] net/iavf: support generic flow
> >
> > This patch added iavf_flow_create, iavf_flow_destroy, iavf_flow_flush
> > and iavf_flow_validate support, these are used to handle all the generic
> filters.
> >
> > This patch supported basic L2, L3, L4 and GTPU patterns.
> >
> > Signed-off-by: Qiming Yang <qiming.yang@intel.com>
> > ---
> >  doc/guides/rel_notes/release_20_05.rst |   5 +
> >  drivers/net/iavf/Makefile              |   1 +
> >  drivers/net/iavf/iavf.h                |   9 +
> >  drivers/net/iavf/iavf_ethdev.c         |  46 ++
> >  drivers/net/iavf/iavf_generic_flow.c   | 928
> > +++++++++++++++++++++++++++++++++
> >  drivers/net/iavf/iavf_generic_flow.h   | 279 ++++++++++
> >  drivers/net/iavf/meson.build           |   1 +
> >  7 files changed, 1269 insertions(+)
> >  create mode 100644 drivers/net/iavf/iavf_generic_flow.c
> >  create mode 100644 drivers/net/iavf/iavf_generic_flow.h
> >
> > diff --git a/doc/guides/rel_notes/release_20_05.rst
> > b/doc/guides/rel_notes/release_20_05.rst
> > index 2190eaf..44d375a 100644
> > --- a/doc/guides/rel_notes/release_20_05.rst
> > +++ b/doc/guides/rel_notes/release_20_05.rst
> > @@ -56,6 +56,11 @@ New Features
> >       Also, make sure to start the actual text at the margin.
> >
> > =========================================================
> >
> > +* **Updated the Intel ice driver.**
> > +
> > +  Updated the Intel ice driver with new features and improvements,
> > including:
> > +
> > +  * Added support for DCF (Device Config Function) feature.
> 
> Above comment is not related with this patch, right?
> 
> >
> >  Removed Items
> >  -------------
> ....
> 
> 
> > +
> > +static struct iavf_flow_engine *
> > +iavf_parse_engine_create(struct iavf_adapter *ad,
> > +		struct rte_flow *flow,
> > +		struct iavf_parser_list *parser_list,
> > +		const struct rte_flow_item pattern[],
> > +		const struct rte_flow_action actions[],
> > +		struct rte_flow_error *error)
> > +{
> > +	struct iavf_flow_engine *engine = NULL;
> > +	struct iavf_flow_parser_node *parser_node;
> > +	void *temp;
> > +	void *meta = NULL;
> > +
> > +	TAILQ_FOREACH_SAFE(parser_node, parser_list, node, temp) {
> > +		if (parser_node->parser->parse_pattern_action(ad,
> > +				parser_node->parser->array,
> > +				parser_node->parser->array_len,
> > +				pattern, actions, &meta, error) < 0)
> > +			continue;
> > +
> > +		engine = parser_node->parser->engine;
> > +		if (engine->create == NULL) {
> > +			rte_flow_error_set(error, EINVAL,
> > +				RTE_FLOW_ERROR_TYPE_HANDLE,
> > +				NULL, "Invalid engine");
> > +			continue;
> > +		}
> 
> Please sync with below fix for ice
> https://patchwork.dpdk.org/patch/66232/
> 
> > +
> > +		if (!(engine->create(ad, flow, meta, error)))
> > +			return engine;
> > +	}
> > +	return NULL;
> > +}
> > +
> > +static struct iavf_flow_engine *
> > +iavf_parse_engine_validate(struct iavf_adapter *ad,
> > +		struct rte_flow *flow,
> > +		struct iavf_parser_list *parser_list,
> > +		const struct rte_flow_item pattern[],
> > +		const struct rte_flow_action actions[],
> > +		struct rte_flow_error *error)
> > +{
> > +	struct iavf_flow_engine *engine = NULL;
> > +	struct iavf_flow_parser_node *parser_node;
> > +	void *temp;
> > +	void *meta = NULL;
> > +
> > +	TAILQ_FOREACH_SAFE(parser_node, parser_list, node, temp) {
> > +		if (parser_node->parser->parse_pattern_action(ad,
> > +				parser_node->parser->array,
> > +				parser_node->parser->array_len,
> > +				pattern, actions, &meta,  error) < 0)
> > +			continue;
> > +
> Please sync with below fix for ice
> https://patchwork.dpdk.org/patch/66232/
> 
> 
> > +		engine = parser_node->parser->engine;
> > +		if (engine->validation == NULL) {
> > +			rte_flow_error_set(error, EINVAL,
> > +				RTE_FLOW_ERROR_TYPE_HANDLE,
> > +				NULL, "Validation not support");
> > +			continue;
> > +		}


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

* [dpdk-dev] [PATCH v2 0/2] add generic filter support for iavf
  2020-03-17  8:17 [dpdk-dev] [PATCH 0/2] add generic filter support for iavf Qiming Yang
  2020-03-17  8:17 ` [dpdk-dev] [PATCH 1/2] net/iavf: support generic flow Qiming Yang
  2020-03-17  8:17 ` [dpdk-dev] [PATCH 2/2] net/iavf: support more patterns Qiming Yang
@ 2020-03-30  8:30 ` Qiming Yang
  2020-03-30  8:30   ` [dpdk-dev] [PATCH v2 1/2] net/iavf: support generic flow Qiming Yang
  2020-03-30  8:30   ` [dpdk-dev] [PATCH v2 2/2] net/iavf: support more patterns Qiming Yang
  2020-04-03  5:42 ` [dpdk-dev] [PATCH v3 0/2] add generic filter support for iavf Qiming Yang
  3 siblings, 2 replies; 14+ messages in thread
From: Qiming Yang @ 2020-03-30  8:30 UTC (permalink / raw)
  To: dev; +Cc: qi.z.zhang, Qiming Yang

This patch set added generic flow APIs and supported patterns includes:
/* L2 */
/* ARP */
/* IPv4 */
/* IPv6  */
/* GTPU */
/* ESP */
/* AH */
/* L2TPV3 */
/* PFCP */

---
v2 changes:
 - fixed document error.
 - fixed multiple thread not safe issue.
 - use RTE_ASSERT to replace runtime check for engine->create == NULL.

Qiming Yang (2):
  net/iavf: support generic flow
  net/iavf: support more patterns

 doc/guides/rel_notes/release_20_05.rst |    6 +
 drivers/net/iavf/Makefile              |    1 +
 drivers/net/iavf/iavf.h                |   10 +
 drivers/net/iavf/iavf_ethdev.c         |   46 ++
 drivers/net/iavf/iavf_generic_flow.c   | 1025 ++++++++++++++++++++++++++++++++
 drivers/net/iavf/iavf_generic_flow.h   |  318 ++++++++++
 drivers/net/iavf/meson.build           |    1 +
 7 files changed, 1407 insertions(+)
 create mode 100644 drivers/net/iavf/iavf_generic_flow.c
 create mode 100644 drivers/net/iavf/iavf_generic_flow.h

-- 
2.9.5


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

* [dpdk-dev] [PATCH v2 1/2] net/iavf: support generic flow
  2020-03-30  8:30 ` [dpdk-dev] [PATCH v2 0/2] add generic filter support for iavf Qiming Yang
@ 2020-03-30  8:30   ` Qiming Yang
  2020-04-01  2:48     ` Zhang, Qi Z
  2020-03-30  8:30   ` [dpdk-dev] [PATCH v2 2/2] net/iavf: support more patterns Qiming Yang
  1 sibling, 1 reply; 14+ messages in thread
From: Qiming Yang @ 2020-03-30  8:30 UTC (permalink / raw)
  To: dev; +Cc: qi.z.zhang, Qiming Yang

This patch added iavf_flow_create, iavf_flow_destroy,
iavf_flow_flush and iavf_flow_validate support,
these are used to handle all the generic filters.

This patch supported basic L2, L3, L4 and GTPU patterns.

Signed-off-by: Qiming Yang <qiming.yang@intel.com>
---
 doc/guides/rel_notes/release_20_05.rst |   6 +
 drivers/net/iavf/Makefile              |   1 +
 drivers/net/iavf/iavf.h                |  10 +
 drivers/net/iavf/iavf_ethdev.c         |  46 ++
 drivers/net/iavf/iavf_generic_flow.c   | 930 +++++++++++++++++++++++++++++++++
 drivers/net/iavf/iavf_generic_flow.h   | 279 ++++++++++
 drivers/net/iavf/meson.build           |   1 +
 7 files changed, 1273 insertions(+)
 create mode 100644 drivers/net/iavf/iavf_generic_flow.c
 create mode 100644 drivers/net/iavf/iavf_generic_flow.h

diff --git a/doc/guides/rel_notes/release_20_05.rst b/doc/guides/rel_notes/release_20_05.rst
index f404ee7..0cfd720 100644
--- a/doc/guides/rel_notes/release_20_05.rst
+++ b/doc/guides/rel_notes/release_20_05.rst
@@ -68,6 +68,12 @@ New Features
 
   * Added support for DCF (Device Config Function) feature.
 
+* **Updated the Intel iavf driver.**
+
+  Update the Intel iavf driver with new features and improvements, including:
+
+  * Added generic filter support.
+
 Removed Items
 -------------
 
diff --git a/drivers/net/iavf/Makefile b/drivers/net/iavf/Makefile
index 514073d..1bf0f26 100644
--- a/drivers/net/iavf/Makefile
+++ b/drivers/net/iavf/Makefile
@@ -23,6 +23,7 @@ EXPORT_MAP := rte_pmd_iavf_version.map
 SRCS-$(CONFIG_RTE_LIBRTE_IAVF_PMD) += iavf_ethdev.c
 SRCS-$(CONFIG_RTE_LIBRTE_IAVF_PMD) += iavf_vchnl.c
 SRCS-$(CONFIG_RTE_LIBRTE_IAVF_PMD) += iavf_rxtx.c
+SRCS-$(CONFIG_RTE_LIBRTE_IAVF_PMD) += iavf_generic_flow.c
 ifeq ($(CONFIG_RTE_ARCH_X86), y)
 SRCS-$(CONFIG_RTE_LIBRTE_IAVF_PMD) += iavf_rxtx_vec_sse.c
 endif
diff --git a/drivers/net/iavf/iavf.h b/drivers/net/iavf/iavf.h
index 526040c..368ddf6 100644
--- a/drivers/net/iavf/iavf.h
+++ b/drivers/net/iavf/iavf.h
@@ -83,6 +83,12 @@ struct iavf_vsi {
 	struct virtchnl_eth_stats eth_stats_offset;
 };
 
+struct rte_flow;
+TAILQ_HEAD(iavf_flow_list, rte_flow);
+
+struct iavf_flow_parser_node;
+TAILQ_HEAD(iavf_parser_list, iavf_flow_parser_node);
+
 /* TODO: is that correct to assume the max number to be 16 ?*/
 #define IAVF_MAX_MSIX_VECTORS   16
 
@@ -117,6 +123,10 @@ struct iavf_info {
 	uint16_t msix_base; /* msix vector base from */
 	/* queue bitmask for each vector */
 	uint16_t rxq_map[IAVF_MAX_MSIX_VECTORS];
+	struct iavf_flow_list flow_list;
+	rte_spinlock_t flow_ops_lock;
+	struct iavf_parser_list rss_parser_list;
+	struct iavf_parser_list dist_parser_list;
 };
 
 #define IAVF_MAX_PKT_TYPE 1024
diff --git a/drivers/net/iavf/iavf_ethdev.c b/drivers/net/iavf/iavf_ethdev.c
index 7a8bec9..a5f492d 100644
--- a/drivers/net/iavf/iavf_ethdev.c
+++ b/drivers/net/iavf/iavf_ethdev.c
@@ -27,6 +27,7 @@
 
 #include "iavf.h"
 #include "iavf_rxtx.h"
+#include "iavf_generic_flow.h"
 
 static int iavf_dev_configure(struct rte_eth_dev *dev);
 static int iavf_dev_start(struct rte_eth_dev *dev);
@@ -67,6 +68,11 @@ static int iavf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev,
 					uint16_t queue_id);
 static int iavf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev,
 					 uint16_t queue_id);
+static int iavf_dev_filter_ctrl(struct rte_eth_dev *dev,
+		     enum rte_filter_type filter_type,
+		     enum rte_filter_op filter_op,
+		     void *arg);
+
 
 int iavf_logtype_init;
 int iavf_logtype_driver;
@@ -125,6 +131,7 @@ static const struct eth_dev_ops iavf_eth_dev_ops = {
 	.mtu_set                    = iavf_dev_mtu_set,
 	.rx_queue_intr_enable       = iavf_dev_rx_queue_intr_enable,
 	.rx_queue_intr_disable      = iavf_dev_rx_queue_intr_disable,
+	.filter_ctrl                = iavf_dev_filter_ctrl,
 };
 
 static int
@@ -1291,12 +1298,41 @@ iavf_dev_interrupt_handler(void *param)
 }
 
 static int
+iavf_dev_filter_ctrl(struct rte_eth_dev *dev,
+		     enum rte_filter_type filter_type,
+		     enum rte_filter_op filter_op,
+		     void *arg)
+{
+	int ret = 0;
+
+	if (!dev)
+		return -EINVAL;
+
+	switch (filter_type) {
+	case RTE_ETH_FILTER_GENERIC:
+		if (filter_op != RTE_ETH_FILTER_GET)
+			return -EINVAL;
+		*(const void **)arg = &iavf_flow_ops;
+		break;
+	default:
+		PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
+			    filter_type);
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+
+static int
 iavf_dev_init(struct rte_eth_dev *eth_dev)
 {
 	struct iavf_adapter *adapter =
 		IAVF_DEV_PRIVATE_TO_ADAPTER(eth_dev->data->dev_private);
 	struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(adapter);
 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
+	int ret = 0;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -1366,6 +1402,12 @@ iavf_dev_init(struct rte_eth_dev *eth_dev)
 	/* configure and enable device interrupt */
 	iavf_enable_irq0(hw);
 
+	ret = iavf_flow_init(adapter);
+	if (ret) {
+		PMD_INIT_LOG(ERR, "Failed to initialize flow");
+		return ret;
+	}
+
 	return 0;
 }
 
@@ -1375,6 +1417,8 @@ iavf_dev_close(struct rte_eth_dev *dev)
 	struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
 	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
+	struct iavf_adapter *adapter =
+		IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
 
 	iavf_dev_stop(dev);
 	iavf_shutdown_adminq(hw);
@@ -1385,6 +1429,8 @@ iavf_dev_close(struct rte_eth_dev *dev)
 	rte_intr_callback_unregister(intr_handle,
 				     iavf_dev_interrupt_handler, dev);
 	iavf_disable_irq0(hw);
+
+	iavf_flow_uninit(adapter);
 }
 
 static int
diff --git a/drivers/net/iavf/iavf_generic_flow.c b/drivers/net/iavf/iavf_generic_flow.c
new file mode 100644
index 0000000..1e2231d
--- /dev/null
+++ b/drivers/net/iavf/iavf_generic_flow.c
@@ -0,0 +1,930 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#include <sys/queue.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+#include <rte_ether.h>
+#include <rte_ethdev_driver.h>
+#include <rte_malloc.h>
+#include <rte_tailq.h>
+
+#include "iavf.h"
+#include "iavf_generic_flow.h"
+
+static struct iavf_engine_list engine_list =
+		TAILQ_HEAD_INITIALIZER(engine_list);
+
+static int iavf_flow_validate(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);
+static struct rte_flow *iavf_flow_create(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);
+static int iavf_flow_destroy(struct rte_eth_dev *dev,
+		struct rte_flow *flow,
+		struct rte_flow_error *error);
+static int iavf_flow_flush(struct rte_eth_dev *dev,
+		struct rte_flow_error *error);
+static int iavf_flow_query(struct rte_eth_dev *dev,
+		struct rte_flow *flow,
+		const struct rte_flow_action *actions,
+		void *data,
+		struct rte_flow_error *error);
+
+const struct rte_flow_ops iavf_flow_ops = {
+	.validate = iavf_flow_validate,
+	.create = iavf_flow_create,
+	.destroy = iavf_flow_destroy,
+	.flush = iavf_flow_flush,
+	.query = iavf_flow_query,
+};
+
+/* empty */
+enum rte_flow_item_type iavf_pattern_empty[] = {
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+/* L2 */
+enum rte_flow_item_type iavf_pattern_ethertype[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_ethertype_vlan[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_ethertype_qinq[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+/* ARP */
+enum rte_flow_item_type iavf_pattern_eth_arp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_ARP_ETH_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+/* non-tunnel IPv4 */
+enum rte_flow_item_type iavf_pattern_eth_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_sctp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_SCTP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_sctp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_SCTP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_sctp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_SCTP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_icmp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_ICMP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_icmp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_ICMP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_icmp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_ICMP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+/* non-tunnel IPv6 */
+enum rte_flow_item_type iavf_pattern_eth_ipv6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv6_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv6_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv6_sctp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_SCTP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_sctp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_SCTP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_sctp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_SCTP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv6_icmp6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_ICMP6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_icmp6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_ICMP6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_icmp6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_ICMP6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+/* GTPU */
+enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_GTPU,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_GTPU,
+	RTE_FLOW_ITEM_TYPE_GTP_PSC,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_GTPU,
+	RTE_FLOW_ITEM_TYPE_GTP_PSC,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_GTPU,
+	RTE_FLOW_ITEM_TYPE_GTP_PSC,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_icmp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_GTPU,
+	RTE_FLOW_ITEM_TYPE_GTP_PSC,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_ICMP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+typedef struct iavf_flow_engine * (*parse_engine_t)(struct iavf_adapter *ad,
+		struct rte_flow *flow,
+		struct iavf_parser_list *parser_list,
+		const struct rte_flow_item pattern[],
+		const struct rte_flow_action actions[],
+		struct rte_flow_error *error);
+
+void
+iavf_register_flow_engine(struct iavf_flow_engine *engine)
+{
+	TAILQ_INSERT_TAIL(&engine_list, engine, node);
+}
+
+int
+iavf_flow_init(struct iavf_adapter *ad)
+{
+	int ret;
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
+	void *temp;
+	struct iavf_flow_engine *engine;
+
+	TAILQ_INIT(&vf->flow_list);
+	TAILQ_INIT(&vf->rss_parser_list);
+	TAILQ_INIT(&vf->dist_parser_list);
+	rte_spinlock_init(&vf->flow_ops_lock);
+
+	TAILQ_FOREACH_SAFE(engine, &engine_list, node, temp) {
+		if (engine->init == NULL) {
+			PMD_INIT_LOG(ERR, "Invalid engine type (%d)",
+				     engine->type);
+			return -ENOTSUP;
+		}
+
+		ret = engine->init(ad);
+		if (ret && ret != -ENOTSUP) {
+			PMD_INIT_LOG(ERR, "Failed to initialize engine %d",
+				     engine->type);
+			return ret;
+		}
+	}
+	return 0;
+}
+
+void
+iavf_flow_uninit(struct iavf_adapter *ad)
+{
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
+	struct iavf_flow_engine *engine;
+	struct rte_flow *p_flow;
+	struct iavf_flow_parser_node *p_parser;
+	void *temp;
+
+	TAILQ_FOREACH_SAFE(engine, &engine_list, node, temp) {
+		if (engine->uninit)
+			engine->uninit(ad);
+	}
+
+	/* Remove all flows */
+	while ((p_flow = TAILQ_FIRST(&vf->flow_list))) {
+		TAILQ_REMOVE(&vf->flow_list, p_flow, node);
+		if (p_flow->engine->free)
+			p_flow->engine->free(p_flow);
+		rte_free(p_flow);
+	}
+
+	/* Cleanup parser list */
+	while ((p_parser = TAILQ_FIRST(&vf->rss_parser_list))) {
+		TAILQ_REMOVE(&vf->rss_parser_list, p_parser, node);
+		rte_free(p_parser);
+	}
+
+	while ((p_parser = TAILQ_FIRST(&vf->dist_parser_list))) {
+		TAILQ_REMOVE(&vf->dist_parser_list, p_parser, node);
+		rte_free(p_parser);
+	}
+}
+
+int
+iavf_register_parser(struct iavf_flow_parser *parser,
+		     struct iavf_adapter *ad)
+{
+	struct iavf_parser_list *list = NULL;
+	struct iavf_flow_parser_node *parser_node;
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
+
+	parser_node = rte_zmalloc("iavf_parser", sizeof(*parser_node), 0);
+	if (parser_node == NULL) {
+		PMD_DRV_LOG(ERR, "Failed to allocate memory.");
+		return -ENOMEM;
+	}
+	parser_node->parser = parser;
+
+	if (parser->engine->type == IAVF_FLOW_ENGINE_HASH) {
+		list = &vf->rss_parser_list;
+		TAILQ_INSERT_TAIL(list, parser_node, node);
+	} else if (parser->engine->type == IAVF_FLOW_ENGINE_FDIR) {
+		list = &vf->dist_parser_list;
+		TAILQ_INSERT_HEAD(list, parser_node, node);
+	} else
+		return -EINVAL;
+
+	return 0;
+}
+
+void
+iavf_unregister_parser(struct iavf_flow_parser *parser,
+		       struct iavf_adapter *ad)
+{
+	struct iavf_parser_list *list = NULL;
+	struct iavf_flow_parser_node *p_parser;
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
+	void *temp;
+
+	if (parser->engine->type == IAVF_FLOW_ENGINE_HASH)
+		list = &vf->rss_parser_list;
+	else if (parser->engine->type == IAVF_FLOW_ENGINE_FDIR)
+		list = &vf->dist_parser_list;
+
+	if (list == NULL)
+		return;
+
+	TAILQ_FOREACH_SAFE(p_parser, list, node, temp) {
+		if (p_parser->parser->engine->type == parser->engine->type) {
+			TAILQ_REMOVE(list, p_parser, node);
+			rte_free(p_parser);
+		}
+	}
+}
+
+static int
+iavf_flow_valid_attr(const struct rte_flow_attr *attr,
+		     struct rte_flow_error *error)
+{
+	/* Must be input direction */
+	if (!attr->ingress) {
+		rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
+				attr, "Only support ingress.");
+		return -rte_errno;
+	}
+
+	/* Not supported */
+	if (attr->egress) {
+		rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
+				attr, "Not support egress.");
+		return -rte_errno;
+	}
+
+	/* Not supported */
+	if (attr->priority) {
+		rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
+				attr, "Not support priority.");
+		return -rte_errno;
+	}
+
+	/* Not supported */
+	if (attr->group) {
+		rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
+				attr, "Not support group.");
+		return -rte_errno;
+	}
+
+	return 0;
+}
+
+/* Find the first VOID or non-VOID item pointer */
+static const struct rte_flow_item *
+iavf_find_first_item(const struct rte_flow_item *item, bool is_void)
+{
+	bool is_find;
+
+	while (item->type != RTE_FLOW_ITEM_TYPE_END) {
+		if (is_void)
+			is_find = item->type == RTE_FLOW_ITEM_TYPE_VOID;
+		else
+			is_find = item->type != RTE_FLOW_ITEM_TYPE_VOID;
+		if (is_find)
+			break;
+		item++;
+	}
+	return item;
+}
+
+/* Skip all VOID items of the pattern */
+static void
+iavf_pattern_skip_void_item(struct rte_flow_item *items,
+			const struct rte_flow_item *pattern)
+{
+	uint32_t cpy_count = 0;
+	const struct rte_flow_item *pb = pattern, *pe = pattern;
+
+	for (;;) {
+		/* Find a non-void item first */
+		pb = iavf_find_first_item(pb, false);
+		if (pb->type == RTE_FLOW_ITEM_TYPE_END) {
+			pe = pb;
+			break;
+		}
+
+		/* Find a void item */
+		pe = iavf_find_first_item(pb + 1, true);
+
+		cpy_count = pe - pb;
+		rte_memcpy(items, pb, sizeof(struct rte_flow_item) * cpy_count);
+
+		items += cpy_count;
+
+		if (pe->type == RTE_FLOW_ITEM_TYPE_END)
+			break;
+
+		pb = pe + 1;
+	}
+	/* Copy the END item. */
+	rte_memcpy(items, pe, sizeof(struct rte_flow_item));
+}
+
+/* Check if the pattern matches a supported item type array */
+static bool
+iavf_match_pattern(enum rte_flow_item_type *item_array,
+		   const struct rte_flow_item *pattern)
+{
+	const struct rte_flow_item *item = pattern;
+
+	while ((*item_array == item->type) &&
+	       (*item_array != RTE_FLOW_ITEM_TYPE_END)) {
+		item_array++;
+		item++;
+	}
+
+	return (*item_array == RTE_FLOW_ITEM_TYPE_END &&
+		item->type == RTE_FLOW_ITEM_TYPE_END);
+}
+
+struct iavf_pattern_match_item *
+iavf_search_pattern_match_item(const struct rte_flow_item pattern[],
+		struct iavf_pattern_match_item *array,
+		uint32_t array_len,
+		struct rte_flow_error *error)
+{
+	uint16_t i = 0;
+	struct iavf_pattern_match_item *pattern_match_item;
+	/* need free by each filter */
+	struct rte_flow_item *items; /* used for pattern without VOID items */
+	uint32_t item_num = 0; /* non-void item number */
+
+	/* Get the non-void item number of pattern */
+	while ((pattern + i)->type != RTE_FLOW_ITEM_TYPE_END) {
+		if ((pattern + i)->type != RTE_FLOW_ITEM_TYPE_VOID)
+			item_num++;
+		i++;
+	}
+	item_num++;
+
+	items = rte_zmalloc("iavf_pattern",
+			    item_num * sizeof(struct rte_flow_item), 0);
+	if (!items) {
+		rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_ITEM_NUM,
+				   NULL, "No memory for PMD internal items.");
+		return NULL;
+	}
+	pattern_match_item = rte_zmalloc("iavf_pattern_match_item",
+				sizeof(struct iavf_pattern_match_item), 0);
+	if (!pattern_match_item) {
+		rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
+				   NULL, "Failed to allocate memory.");
+		return NULL;
+	}
+
+	iavf_pattern_skip_void_item(items, pattern);
+
+	for (i = 0; i < array_len; i++)
+		if (iavf_match_pattern(array[i].pattern_list,
+				       items)) {
+			pattern_match_item->input_set_mask =
+				array[i].input_set_mask;
+			pattern_match_item->pattern_list =
+				array[i].pattern_list;
+			pattern_match_item->meta = array[i].meta;
+			rte_free(items);
+			return pattern_match_item;
+		}
+	rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
+			   pattern, "Unsupported pattern");
+
+	rte_free(items);
+	rte_free(pattern_match_item);
+	return NULL;
+}
+
+static struct iavf_flow_engine *
+iavf_parse_engine_create(struct iavf_adapter *ad,
+		struct rte_flow *flow,
+		struct iavf_parser_list *parser_list,
+		const struct rte_flow_item pattern[],
+		const struct rte_flow_action actions[],
+		struct rte_flow_error *error)
+{
+	struct iavf_flow_engine *engine = NULL;
+	struct iavf_flow_parser_node *parser_node;
+	void *temp;
+	void *meta = NULL;
+
+	TAILQ_FOREACH_SAFE(parser_node, parser_list, node, temp) {
+		if (parser_node->parser->parse_pattern_action(ad,
+				parser_node->parser->array,
+				parser_node->parser->array_len,
+				pattern, actions, &meta, error) < 0)
+			continue;
+
+		engine = parser_node->parser->engine;
+
+		RTE_ASSERT(engine->create != NULL);
+		if (!(engine->create(ad, flow, meta, error)))
+			return engine;
+	}
+	return NULL;
+}
+
+static struct iavf_flow_engine *
+iavf_parse_engine_validate(struct iavf_adapter *ad,
+		struct rte_flow *flow,
+		struct iavf_parser_list *parser_list,
+		const struct rte_flow_item pattern[],
+		const struct rte_flow_action actions[],
+		struct rte_flow_error *error)
+{
+	struct iavf_flow_engine *engine = NULL;
+	struct iavf_flow_parser_node *parser_node;
+	void *temp;
+	void *meta = NULL;
+
+	TAILQ_FOREACH_SAFE(parser_node, parser_list, node, temp) {
+		if (parser_node->parser->parse_pattern_action(ad,
+				parser_node->parser->array,
+				parser_node->parser->array_len,
+				pattern, actions, &meta,  error) < 0)
+			continue;
+
+		engine = parser_node->parser->engine;
+		if (engine->validation == NULL) {
+			rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_HANDLE,
+				NULL, "Validation not support");
+			continue;
+		}
+
+		if (engine->validation(ad, flow, meta, error)) {
+			rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_HANDLE,
+				NULL, "Validation failed");
+			break;
+		}
+	}
+	return engine;
+}
+
+
+static int
+iavf_flow_process_filter(struct rte_eth_dev *dev,
+		struct rte_flow *flow,
+		const struct rte_flow_attr *attr,
+		const struct rte_flow_item pattern[],
+		const struct rte_flow_action actions[],
+		struct iavf_flow_engine **engine,
+		parse_engine_t iavf_parse_engine,
+		struct rte_flow_error *error)
+{
+	int ret = IAVF_ERR_CONFIG;
+	struct iavf_adapter *ad =
+		IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
+
+	if (!pattern) {
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_NUM,
+				   NULL, "NULL pattern.");
+		return -rte_errno;
+	}
+
+	if (!actions) {
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_ACTION_NUM,
+				   NULL, "NULL action.");
+		return -rte_errno;
+	}
+
+	if (!attr) {
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_ATTR,
+				   NULL, "NULL attribute.");
+		return -rte_errno;
+	}
+
+	ret = iavf_flow_valid_attr(attr, error);
+	if (ret)
+		return ret;
+
+	*engine = iavf_parse_engine(ad, flow, &vf->rss_parser_list, pattern,
+				    actions, error);
+	if (*engine != NULL)
+		return 0;
+
+	*engine = iavf_parse_engine(ad, flow, &vf->dist_parser_list, pattern,
+				    actions, error);
+
+	if (*engine == NULL)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int
+iavf_flow_validate(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)
+{
+	struct iavf_flow_engine *engine;
+
+	return iavf_flow_process_filter(dev, NULL, attr, pattern, actions,
+			&engine, iavf_parse_engine_validate, error);
+}
+
+static struct rte_flow *
+iavf_flow_create(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)
+{
+	struct iavf_adapter *ad =
+		IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
+	struct iavf_flow_engine *engine = NULL;
+	struct rte_flow *flow = NULL;
+	int ret;
+
+	flow = rte_zmalloc("iavf_flow", sizeof(struct rte_flow), 0);
+	if (!flow) {
+		rte_flow_error_set(error, ENOMEM,
+				   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+				   "Failed to allocate memory");
+		return flow;
+	}
+
+	ret = iavf_flow_process_filter(dev, flow, attr, pattern, actions,
+			&engine, iavf_parse_engine_create, error);
+	if (ret < 0) {
+		PMD_DRV_LOG(ERR, "Failed to create flow");
+		rte_free(flow);
+		flow = NULL;
+		goto free_flow;
+	}
+
+	flow->engine = engine;
+	TAILQ_INSERT_TAIL(&vf->flow_list, flow, node);
+	PMD_DRV_LOG(INFO, "Succeeded to create (%d) flow", engine->type);
+
+free_flow:
+	rte_spinlock_unlock(&vf->flow_ops_lock);
+	return flow;
+}
+
+static int
+iavf_flow_destroy(struct rte_eth_dev *dev,
+		  struct rte_flow *flow,
+		  struct rte_flow_error *error)
+{
+	struct iavf_adapter *ad =
+		IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
+	int ret = 0;
+
+	if (!flow || !flow->engine || !flow->engine->destroy) {
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_HANDLE,
+				   NULL, "Invalid flow");
+		return -rte_errno;
+	}
+
+	rte_spinlock_lock(&vf->flow_ops_lock);
+
+	ret = flow->engine->destroy(ad, flow, error);
+
+	if (!ret) {
+		TAILQ_REMOVE(&vf->flow_list, flow, node);
+		rte_free(flow);
+	} else {
+		PMD_DRV_LOG(ERR, "Failed to destroy flow");
+	}
+
+	rte_spinlock_unlock(&vf->flow_ops_lock);
+
+	return ret;
+}
+
+static int
+iavf_flow_flush(struct rte_eth_dev *dev,
+		struct rte_flow_error *error)
+{
+	struct iavf_adapter *ad =
+		IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
+	struct rte_flow *p_flow;
+	void *temp;
+	int ret = 0;
+
+	TAILQ_FOREACH_SAFE(p_flow, &vf->flow_list, node, temp) {
+		ret = iavf_flow_destroy(dev, p_flow, error);
+		if (ret) {
+			PMD_DRV_LOG(ERR, "Failed to flush flows");
+			return -EINVAL;
+		}
+	}
+
+	return ret;
+}
+
+static int
+iavf_flow_query(struct rte_eth_dev *dev,
+		struct rte_flow *flow,
+		const struct rte_flow_action *actions,
+		void *data,
+		struct rte_flow_error *error)
+{
+	int ret = -EINVAL;
+	struct iavf_adapter *ad =
+		IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+	struct rte_flow_query_count *count = data;
+
+	if (!flow || !flow->engine || !flow->engine->query_count) {
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_HANDLE,
+				   NULL, "Invalid flow");
+		return -rte_errno;
+	}
+
+	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
+		switch (actions->type) {
+		case RTE_FLOW_ACTION_TYPE_VOID:
+			break;
+		case RTE_FLOW_ACTION_TYPE_COUNT:
+			ret = flow->engine->query_count(ad, flow, count, error);
+			break;
+		default:
+			return rte_flow_error_set(error, ENOTSUP,
+					RTE_FLOW_ERROR_TYPE_ACTION,
+					actions,
+					"action not supported");
+		}
+	}
+	return ret;
+}
+
diff --git a/drivers/net/iavf/iavf_generic_flow.h b/drivers/net/iavf/iavf_generic_flow.h
new file mode 100644
index 0000000..1e69863
--- /dev/null
+++ b/drivers/net/iavf/iavf_generic_flow.h
@@ -0,0 +1,279 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#ifndef _IAVF_GENERIC_FLOW_H_
+#define _IAVF_GENERIC_FLOW_H_
+
+#include <rte_flow_driver.h>
+
+/* protocol */
+
+#define IAVF_PROT_MAC_INNER         (1ULL << 1)
+#define IAVF_PROT_MAC_OUTER         (1ULL << 2)
+#define IAVF_PROT_VLAN_INNER        (1ULL << 3)
+#define IAVF_PROT_VLAN_OUTER        (1ULL << 4)
+#define IAVF_PROT_IPV4_INNER        (1ULL << 5)
+#define IAVF_PROT_IPV4_OUTER        (1ULL << 6)
+#define IAVF_PROT_IPV6_INNER        (1ULL << 7)
+#define IAVF_PROT_IPV6_OUTER        (1ULL << 8)
+#define IAVF_PROT_TCP_INNER         (1ULL << 9)
+#define IAVF_PROT_TCP_OUTER         (1ULL << 10)
+#define IAVF_PROT_UDP_INNER         (1ULL << 11)
+#define IAVF_PROT_UDP_OUTER         (1ULL << 12)
+#define IAVF_PROT_SCTP_INNER        (1ULL << 13)
+#define IAVF_PROT_SCTP_OUTER        (1ULL << 14)
+#define IAVF_PROT_ICMP4_INNER       (1ULL << 15)
+#define IAVF_PROT_ICMP4_OUTER       (1ULL << 16)
+#define IAVF_PROT_ICMP6_INNER       (1ULL << 17)
+#define IAVF_PROT_ICMP6_OUTER       (1ULL << 18)
+#define IAVF_PROT_VXLAN             (1ULL << 19)
+#define IAVF_PROT_NVGRE             (1ULL << 20)
+#define IAVF_PROT_GTPU              (1ULL << 21)
+
+
+/* field */
+
+#define IAVF_SMAC                   (1ULL << 63)
+#define IAVF_DMAC                   (1ULL << 62)
+#define IAVF_ETHERTYPE              (1ULL << 61)
+#define IAVF_IP_SRC                 (1ULL << 60)
+#define IAVF_IP_DST                 (1ULL << 59)
+#define IAVF_IP_PROTO               (1ULL << 58)
+#define IAVF_IP_TTL                 (1ULL << 57)
+#define IAVF_IP_TOS                 (1ULL << 56)
+#define IAVF_SPORT                  (1ULL << 55)
+#define IAVF_DPORT                  (1ULL << 54)
+#define IAVF_ICMP_TYPE              (1ULL << 53)
+#define IAVF_ICMP_CODE              (1ULL << 52)
+#define IAVF_VXLAN_VNI              (1ULL << 51)
+#define IAVF_NVGRE_TNI              (1ULL << 50)
+#define IAVF_GTPU_TEID              (1ULL << 49)
+#define IAVF_GTPU_QFI               (1ULL << 48)
+
+/* input set */
+
+#define IAVF_INSET_NONE             0ULL
+
+/* non-tunnel */
+
+#define IAVF_INSET_SMAC         (IAVF_PROT_MAC_OUTER | IAVF_SMAC)
+#define IAVF_INSET_DMAC         (IAVF_PROT_MAC_OUTER | IAVF_DMAC)
+#define IAVF_INSET_VLAN_INNER   (IAVF_PROT_VLAN_INNER)
+#define IAVF_INSET_VLAN_OUTER   (IAVF_PROT_VLAN_OUTER)
+#define IAVF_INSET_ETHERTYPE    (IAVF_ETHERTYPE)
+
+#define IAVF_INSET_IPV4_SRC \
+	(IAVF_PROT_IPV4_OUTER | IAVF_IP_SRC)
+#define IAVF_INSET_IPV4_DST \
+	(IAVF_PROT_IPV4_OUTER | IAVF_IP_DST)
+#define IAVF_INSET_IPV4_TOS \
+	(IAVF_PROT_IPV4_OUTER | IAVF_IP_TOS)
+#define IAVF_INSET_IPV4_PROTO \
+	(IAVF_PROT_IPV4_OUTER | IAVF_IP_PROTO)
+#define IAVF_INSET_IPV4_TTL \
+	(IAVF_PROT_IPV4_OUTER | IAVF_IP_TTL)
+#define IAVF_INSET_IPV6_SRC \
+	(IAVF_PROT_IPV6_OUTER | IAVF_IP_SRC)
+#define IAVF_INSET_IPV6_DST \
+	(IAVF_PROT_IPV6_OUTER | IAVF_IP_DST)
+#define IAVF_INSET_IPV6_NEXT_HDR \
+	(IAVF_PROT_IPV6_OUTER | IAVF_IP_PROTO)
+#define IAVF_INSET_IPV6_HOP_LIMIT \
+	(IAVF_PROT_IPV6_OUTER | IAVF_IP_TTL)
+#define IAVF_INSET_IPV6_TC \
+	(IAVF_PROT_IPV6_OUTER | IAVF_IP_TOS)
+
+#define IAVF_INSET_TCP_SRC_PORT \
+	(IAVF_PROT_TCP_OUTER | IAVF_SPORT)
+#define IAVF_INSET_TCP_DST_PORT \
+	(IAVF_PROT_TCP_OUTER | IAVF_DPORT)
+#define IAVF_INSET_UDP_SRC_PORT \
+	(IAVF_PROT_UDP_OUTER | IAVF_SPORT)
+#define IAVF_INSET_UDP_DST_PORT \
+	(IAVF_PROT_UDP_OUTER | IAVF_DPORT)
+#define IAVF_INSET_SCTP_SRC_PORT \
+	(IAVF_PROT_SCTP_OUTER | IAVF_SPORT)
+#define IAVF_INSET_SCTP_DST_PORT \
+	(IAVF_PROT_SCTP_OUTER | IAVF_DPORT)
+#define IAVF_INSET_ICMP4_SRC_PORT \
+	(IAVF_PROT_ICMP4_OUTER | IAVF_SPORT)
+#define IAVF_INSET_ICMP4_DST_PORT \
+	(IAVF_PROT_ICMP4_OUTER | IAVF_DPORT)
+#define IAVF_INSET_ICMP6_SRC_PORT \
+	(IAVF_PROT_ICMP6_OUTER | IAVF_SPORT)
+#define IAVF_INSET_ICMP6_DST_PORT \
+	(IAVF_PROT_ICMP6_OUTER | IAVF_DPORT)
+#define IAVF_INSET_ICMP4_TYPE \
+	(IAVF_PROT_ICMP4_OUTER | IAVF_ICMP_TYPE)
+#define IAVF_INSET_ICMP4_CODE \
+	(IAVF_PROT_ICMP4_OUTER | IAVF_ICMP_CODE)
+#define IAVF_INSET_ICMP6_TYPE \
+	(IAVF_PROT_ICMP6_OUTER | IAVF_ICMP_TYPE)
+#define IAVF_INSET_ICMP6_CODE \
+	(IAVF_PROT_ICMP6_OUTER | IAVF_ICMP_CODE)
+#define IAVF_INSET_GTPU_TEID \
+	(IAVF_PROT_GTPU | IAVF_GTPU_TEID)
+#define IAVF_INSET_GTPU_QFI \
+	(IAVF_PROT_GTPU | IAVF_GTPU_QFI)
+
+
+/* empty pattern */
+extern enum rte_flow_item_type iavf_pattern_empty[];
+
+/* L2 */
+extern enum rte_flow_item_type iavf_pattern_ethertype[];
+extern enum rte_flow_item_type iavf_pattern_ethertype_vlan[];
+extern enum rte_flow_item_type iavf_pattern_ethertype_qinq[];
+
+/* ARP */
+extern enum rte_flow_item_type iavf_pattern_eth_arp[];
+
+/* non-tunnel IPv4 */
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_udp[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_udp[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_udp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_tcp[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_tcp[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_tcp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_sctp[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_sctp[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_sctp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_icmp[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_icmp[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_icmp[];
+
+/* non-tunnel IPv6 */
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6_udp[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_udp[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_udp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6_tcp[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_tcp[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_tcp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6_sctp[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_sctp[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_sctp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6_icmp6[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_icmp6[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_icmp6[];
+
+/* GTPU */
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_ipv4[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_udp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_tcp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_icmp[];
+
+
+extern const struct rte_flow_ops iavf_flow_ops;
+
+/* pattern structure */
+struct iavf_pattern_match_item {
+	enum rte_flow_item_type *pattern_list;
+	/* pattern_list must end with RTE_FLOW_ITEM_TYPE_END */
+	uint64_t input_set_mask;
+	void *meta;
+};
+
+typedef int (*engine_init_t)(struct iavf_adapter *ad);
+typedef void (*engine_uninit_t)(struct iavf_adapter *ad);
+typedef int (*engine_validation_t)(struct iavf_adapter *ad,
+		struct rte_flow *flow,
+		void *meta,
+		struct rte_flow_error *error);
+typedef int (*engine_create_t)(struct iavf_adapter *ad,
+		struct rte_flow *flow,
+		void *meta,
+		struct rte_flow_error *error);
+typedef int (*engine_destroy_t)(struct iavf_adapter *ad,
+		struct rte_flow *flow,
+		struct rte_flow_error *error);
+typedef int (*engine_query_t)(struct iavf_adapter *ad,
+		struct rte_flow *flow,
+		struct rte_flow_query_count *count,
+		struct rte_flow_error *error);
+typedef void (*engine_free_t) (struct rte_flow *flow);
+typedef int (*parse_pattern_action_t)(struct iavf_adapter *ad,
+		struct iavf_pattern_match_item *array,
+		uint32_t array_len,
+		const struct rte_flow_item pattern[],
+		const struct rte_flow_action actions[],
+		void **meta,
+		struct rte_flow_error *error);
+
+/* engine types. */
+enum iavf_flow_engine_type {
+	IAVF_FLOW_ENGINE_NONE = 0,
+	IAVF_FLOW_ENGINE_FDIR,
+	IAVF_FLOW_ENGINE_HASH,
+	IAVF_FLOW_ENGINE_MAX,
+};
+
+/**
+ * classification stages.
+ * for non-pipeline mode, we have two classification stages: Distributor/RSS
+ * for pipeline-mode we have three classification stages:
+ * Permission/Distributor/RSS
+ */
+enum iavf_flow_classification_stage {
+	IAVF_FLOW_STAGE_NONE = 0,
+	IAVF_FLOW_STAGE_RSS,
+	IAVF_FLOW_STAGE_DISTRIBUTOR,
+	IAVF_FLOW_STAGE_MAX,
+};
+
+/* Struct to store engine created. */
+struct iavf_flow_engine {
+	TAILQ_ENTRY(iavf_flow_engine) node;
+	engine_init_t init;
+	engine_uninit_t uninit;
+	engine_validation_t validation;
+	engine_create_t create;
+	engine_destroy_t destroy;
+	engine_query_t query_count;
+	engine_free_t free;
+	enum iavf_flow_engine_type type;
+};
+
+TAILQ_HEAD(iavf_engine_list, iavf_flow_engine);
+
+/* Struct to store flow created. */
+struct rte_flow {
+	TAILQ_ENTRY(rte_flow) node;
+	struct iavf_flow_engine *engine;
+	void *rule;
+};
+
+struct iavf_flow_parser {
+	struct iavf_flow_engine *engine;
+	struct iavf_pattern_match_item *array;
+	uint32_t array_len;
+	parse_pattern_action_t parse_pattern_action;
+	enum iavf_flow_classification_stage stage;
+};
+
+/* Struct to store parser created. */
+struct iavf_flow_parser_node {
+	TAILQ_ENTRY(iavf_flow_parser_node) node;
+	struct iavf_flow_parser *parser;
+};
+
+void iavf_register_flow_engine(struct iavf_flow_engine *engine);
+int iavf_flow_init(struct iavf_adapter *ad);
+void iavf_flow_uninit(struct iavf_adapter *ad);
+int iavf_register_parser(struct iavf_flow_parser *parser,
+			 struct iavf_adapter *ad);
+void iavf_unregister_parser(struct iavf_flow_parser *parser,
+			    struct iavf_adapter *ad);
+struct iavf_pattern_match_item *
+iavf_search_pattern_match_item(const struct rte_flow_item pattern[],
+		struct iavf_pattern_match_item *array,
+		uint32_t array_len,
+		struct rte_flow_error *error);
+#endif
diff --git a/drivers/net/iavf/meson.build b/drivers/net/iavf/meson.build
index dbd0b01..32eabca 100644
--- a/drivers/net/iavf/meson.build
+++ b/drivers/net/iavf/meson.build
@@ -12,6 +12,7 @@ sources = files(
 	'iavf_ethdev.c',
 	'iavf_rxtx.c',
 	'iavf_vchnl.c',
+	'iavf_generic_flow.c',
 )
 
 if arch_subdir == 'x86'
-- 
2.9.5


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

* [dpdk-dev] [PATCH v2 2/2] net/iavf: support more patterns
  2020-03-30  8:30 ` [dpdk-dev] [PATCH v2 0/2] add generic filter support for iavf Qiming Yang
  2020-03-30  8:30   ` [dpdk-dev] [PATCH v2 1/2] net/iavf: support generic flow Qiming Yang
@ 2020-03-30  8:30   ` Qiming Yang
  1 sibling, 0 replies; 14+ messages in thread
From: Qiming Yang @ 2020-03-30  8:30 UTC (permalink / raw)
  To: dev; +Cc: qi.z.zhang, Qiming Yang, Zhang Xiao

Add patterns support for AH/ESP/L2TPV3OIP/PFCP.
Added patterns are as follows:
/* GTPU */
    eth/ipv4/udp/gtpu
    eth/ipv4/udp/gtpu/gtp_psc
/* ESP */
    eth/ipv4/esp  eth/ipv4/udp/esp
    eth/ipv6/esp  eth/ipv6/udp/esp
/* AH */
    eth/ipv4/ah  eth/ipv6/ah
/* L2TPV3 */
    eth/ipv4/l2tpv3oip  eth/ipv6/l2tpv3oip
/* PFCP */
    eth/ipv4/udp/pfcp  eth/ipv6/udp/pfcp

Depends on patch: ethdev: add PFCP header to flow API

Signed-off-by: Zhang Xiao <xiao.zhang@intel.com>
---
 drivers/net/iavf/iavf_generic_flow.c | 95 ++++++++++++++++++++++++++++++++++++
 drivers/net/iavf/iavf_generic_flow.h | 39 +++++++++++++++
 2 files changed, 134 insertions(+)

diff --git a/drivers/net/iavf/iavf_generic_flow.c b/drivers/net/iavf/iavf_generic_flow.c
index 1e2231d..557021a 100644
--- a/drivers/net/iavf/iavf_generic_flow.c
+++ b/drivers/net/iavf/iavf_generic_flow.c
@@ -318,6 +318,23 @@ enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_icmp6[] = {
 };
 
 /* GTPU */
+enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_GTPU,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_GTPU,
+	RTE_FLOW_ITEM_TYPE_GTP_PSC,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
 enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_ipv4[] = {
 	RTE_FLOW_ITEM_TYPE_ETH,
 	RTE_FLOW_ITEM_TYPE_IPV4,
@@ -371,6 +388,84 @@ enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_icmp[] = {
 	RTE_FLOW_ITEM_TYPE_END,
 };
 
+/* ESP */
+enum rte_flow_item_type iavf_pattern_eth_ipv4_esp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_ESP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_udp_esp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_ESP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv6_esp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_ESP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv6_udp_esp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_ESP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+/* AH */
+enum rte_flow_item_type iavf_pattern_eth_ipv4_ah[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_AH,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv6_ah[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_AH,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+/* L2TPV3 */
+enum rte_flow_item_type iavf_pattern_eth_ipv4_l2tpv3[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_L2TPV3OIP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv6_l2tpv3[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_L2TPV3OIP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+/* PFCP */
+enum rte_flow_item_type iavf_pattern_eth_ipv4_pfcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_PFCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv6_pfcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_PFCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
 typedef struct iavf_flow_engine * (*parse_engine_t)(struct iavf_adapter *ad,
 		struct rte_flow *flow,
 		struct iavf_parser_list *parser_list,
diff --git a/drivers/net/iavf/iavf_generic_flow.h b/drivers/net/iavf/iavf_generic_flow.h
index 1e69863..c41ca1b 100644
--- a/drivers/net/iavf/iavf_generic_flow.h
+++ b/drivers/net/iavf/iavf_generic_flow.h
@@ -30,6 +30,10 @@
 #define IAVF_PROT_VXLAN             (1ULL << 19)
 #define IAVF_PROT_NVGRE             (1ULL << 20)
 #define IAVF_PROT_GTPU              (1ULL << 21)
+#define IAVF_PROT_ESP		    (1ULL << 22)
+#define IAVF_PROT_AH		    (1ULL << 23)
+#define IAVF_PROT_L2TPV3OIP	    (1ULL << 24)
+#define IAVF_PROT_PFCP		    (1ULL << 25)
 
 
 /* field */
@@ -50,6 +54,11 @@
 #define IAVF_NVGRE_TNI              (1ULL << 50)
 #define IAVF_GTPU_TEID              (1ULL << 49)
 #define IAVF_GTPU_QFI               (1ULL << 48)
+#define IAVF_ESP_SPI		    (1ULL << 47)
+#define IAVF_AH_SPI		    (1ULL << 46)
+#define IAVF_L2TPV3OIP_SESSION_ID   (1ULL << 45)
+#define IAVF_PFCP_S_FIELD	    (1ULL << 44)
+#define IAVF_PFCP_SEID		    (1ULL << 43)
 
 /* input set */
 
@@ -116,6 +125,16 @@
 	(IAVF_PROT_GTPU | IAVF_GTPU_TEID)
 #define IAVF_INSET_GTPU_QFI \
 	(IAVF_PROT_GTPU | IAVF_GTPU_QFI)
+#define IAVF_INSET_ESP_SPI \
+	(IAVF_PROT_ESP | IAVF_ESP_SPI)
+#define IAVF_INSET_AH_SPI \
+	(IAVF_PROT_AH | IAVF_AH_SPI)
+#define IAVF_INSET_L2TPV3OIP_SESSION_ID \
+	(IAVF_PROT_L2TPV3OIP | IAVF_L2TPV3OIP_SESSION_ID)
+#define IAVF_INSET_PFCP_S_FIELD \
+	(IAVF_PROT_PFCP | IAVF_PFCP_S_FIELD)
+#define IAVF_INSET_PFCP_SEID \
+	(IAVF_PROT_PFCP | IAVF_PFCP_S_FIELD | IAVF_PFCP_SEID)
 
 
 /* empty pattern */
@@ -164,12 +183,32 @@ extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_icmp6[];
 extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_icmp6[];
 
 /* GTPU */
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu[];
 extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_ipv4[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh[];
 extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4[];
 extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_udp[];
 extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_tcp[];
 extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_icmp[];
 
+/* ESP */
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_esp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_udp_esp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6_esp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6_udp_esp[];
+
+/* AH */
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_ah[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6_ah[];
+
+/* L2TPV3 */
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_l2tpv3[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6_l2tpv3[];
+
+/* PFCP */
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_pfcp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6_pfcp[];
+
 
 extern const struct rte_flow_ops iavf_flow_ops;
 
-- 
2.9.5


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

* Re: [dpdk-dev] [PATCH v2 1/2] net/iavf: support generic flow
  2020-03-30  8:30   ` [dpdk-dev] [PATCH v2 1/2] net/iavf: support generic flow Qiming Yang
@ 2020-04-01  2:48     ` Zhang, Qi Z
  0 siblings, 0 replies; 14+ messages in thread
From: Zhang, Qi Z @ 2020-04-01  2:48 UTC (permalink / raw)
  To: Yang, Qiming, dev



> -----Original Message-----
> From: Yang, Qiming <qiming.yang@intel.com>
> Sent: Monday, March 30, 2020 4:31 PM
> To: dev@dpdk.org
> Cc: Zhang, Qi Z <qi.z.zhang@intel.com>; Yang, Qiming
> <qiming.yang@intel.com>
> Subject: [PATCH v2 1/2] net/iavf: support generic flow
> 
> This patch added iavf_flow_create, iavf_flow_destroy, iavf_flow_flush and
> iavf_flow_validate support, these are used to handle all the generic filters.
> 
> This patch supported basic L2, L3, L4 and GTPU patterns.
> 
> Signed-off-by: Qiming Yang <qiming.yang@intel.com>
> ---
>  doc/guides/rel_notes/release_20_05.rst |   6 +
>  drivers/net/iavf/Makefile              |   1 +
>  drivers/net/iavf/iavf.h                |  10 +
>  drivers/net/iavf/iavf_ethdev.c         |  46 ++
>  drivers/net/iavf/iavf_generic_flow.c   | 930
> +++++++++++++++++++++++++++++++++
>  drivers/net/iavf/iavf_generic_flow.h   | 279 ++++++++++
>  drivers/net/iavf/meson.build           |   1 +

You may also need to add "Flow API = Y" into the doc/guides/nics/features/iavf.ini

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

* [dpdk-dev] [PATCH v3 0/2] add generic filter support for iavf
  2020-03-17  8:17 [dpdk-dev] [PATCH 0/2] add generic filter support for iavf Qiming Yang
                   ` (2 preceding siblings ...)
  2020-03-30  8:30 ` [dpdk-dev] [PATCH v2 0/2] add generic filter support for iavf Qiming Yang
@ 2020-04-03  5:42 ` Qiming Yang
  2020-04-03  5:42   ` [dpdk-dev] [PATCH v3 1/2] net/iavf: support generic flow Qiming Yang
                     ` (3 more replies)
  3 siblings, 4 replies; 14+ messages in thread
From: Qiming Yang @ 2020-04-03  5:42 UTC (permalink / raw)
  To: dev; +Cc: qi.z.zhang, Qiming Yang

This patch set added generic flow APIs and supported patterns includes:
/* L2 */
/* ARP */
/* IPv4 */
/* IPv6  */
/* GTPU */
/* ESP */
/* AH */
/* L2TPV3 */
/* PFCP */

---
v2 changes:
 - fixed document error.
 - fixed multiple thread not safe issue.
 - use RTE_ASSERT to replace runtime check for engine->create == NULL.
v3 changes:
 - add feature enable flag in iavf.ini

Qiming Yang (2):
  net/iavf: support generic flow
  net/iavf: support more patterns

 doc/guides/nics/features/iavf.ini      |    1 +
 doc/guides/rel_notes/release_20_05.rst |    5 +
 drivers/net/iavf/Makefile              |    1 +
 drivers/net/iavf/iavf.h                |   10 +
 drivers/net/iavf/iavf_ethdev.c         |   46 ++
 drivers/net/iavf/iavf_generic_flow.c   | 1025 ++++++++++++++++++++++++++++++++
 drivers/net/iavf/iavf_generic_flow.h   |  318 ++++++++++
 drivers/net/iavf/meson.build           |    1 +
 8 files changed, 1407 insertions(+)
 create mode 100644 drivers/net/iavf/iavf_generic_flow.c
 create mode 100644 drivers/net/iavf/iavf_generic_flow.h

-- 
2.9.5


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

* [dpdk-dev] [PATCH v3 1/2] net/iavf: support generic flow
  2020-04-03  5:42 ` [dpdk-dev] [PATCH v3 0/2] add generic filter support for iavf Qiming Yang
@ 2020-04-03  5:42   ` Qiming Yang
  2020-04-03  5:42   ` [dpdk-dev] [PATCH v3 2/2] net/iavf: support more patterns Qiming Yang
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 14+ messages in thread
From: Qiming Yang @ 2020-04-03  5:42 UTC (permalink / raw)
  To: dev; +Cc: qi.z.zhang, Qiming Yang

This patch added iavf_flow_create, iavf_flow_destroy,
iavf_flow_flush and iavf_flow_validate support,
these are used to handle all the generic filters.

This patch supported basic L2, L3, L4 and GTPU patterns.

Signed-off-by: Qiming Yang <qiming.yang@intel.com>
---
 doc/guides/nics/features/iavf.ini      |   1 +
 doc/guides/rel_notes/release_20_05.rst |   5 +
 drivers/net/iavf/Makefile              |   1 +
 drivers/net/iavf/iavf.h                |  10 +
 drivers/net/iavf/iavf_ethdev.c         |  46 ++
 drivers/net/iavf/iavf_generic_flow.c   | 930 +++++++++++++++++++++++++++++++++
 drivers/net/iavf/iavf_generic_flow.h   | 279 ++++++++++
 drivers/net/iavf/meson.build           |   1 +
 8 files changed, 1273 insertions(+)
 create mode 100644 drivers/net/iavf/iavf_generic_flow.c
 create mode 100644 drivers/net/iavf/iavf_generic_flow.h

diff --git a/doc/guides/nics/features/iavf.ini b/doc/guides/nics/features/iavf.ini
index 94d9f88..17f7928 100644
--- a/doc/guides/nics/features/iavf.ini
+++ b/doc/guides/nics/features/iavf.ini
@@ -19,6 +19,7 @@ Multicast MAC filter = Y
 RSS hash             = Y
 RSS key update       = Y
 RSS reta update      = Y
+Flow API             = Y
 VLAN filter          = Y
 CRC offload          = Y
 VLAN offload         = Y
diff --git a/doc/guides/rel_notes/release_20_05.rst b/doc/guides/rel_notes/release_20_05.rst
index 9bc6472..e9fd88e 100644
--- a/doc/guides/rel_notes/release_20_05.rst
+++ b/doc/guides/rel_notes/release_20_05.rst
@@ -69,6 +69,11 @@ New Features
 
   * Added support for DCF (Device Config Function) feature.
 
+* **Updated the Intel iavf driver.**
+
+  Update the Intel iavf driver with new features and improvements, including:
+
+  * Added generic filter support.
 
 Removed Items
 -------------
diff --git a/drivers/net/iavf/Makefile b/drivers/net/iavf/Makefile
index 514073d..1bf0f26 100644
--- a/drivers/net/iavf/Makefile
+++ b/drivers/net/iavf/Makefile
@@ -23,6 +23,7 @@ EXPORT_MAP := rte_pmd_iavf_version.map
 SRCS-$(CONFIG_RTE_LIBRTE_IAVF_PMD) += iavf_ethdev.c
 SRCS-$(CONFIG_RTE_LIBRTE_IAVF_PMD) += iavf_vchnl.c
 SRCS-$(CONFIG_RTE_LIBRTE_IAVF_PMD) += iavf_rxtx.c
+SRCS-$(CONFIG_RTE_LIBRTE_IAVF_PMD) += iavf_generic_flow.c
 ifeq ($(CONFIG_RTE_ARCH_X86), y)
 SRCS-$(CONFIG_RTE_LIBRTE_IAVF_PMD) += iavf_rxtx_vec_sse.c
 endif
diff --git a/drivers/net/iavf/iavf.h b/drivers/net/iavf/iavf.h
index 526040c..368ddf6 100644
--- a/drivers/net/iavf/iavf.h
+++ b/drivers/net/iavf/iavf.h
@@ -83,6 +83,12 @@ struct iavf_vsi {
 	struct virtchnl_eth_stats eth_stats_offset;
 };
 
+struct rte_flow;
+TAILQ_HEAD(iavf_flow_list, rte_flow);
+
+struct iavf_flow_parser_node;
+TAILQ_HEAD(iavf_parser_list, iavf_flow_parser_node);
+
 /* TODO: is that correct to assume the max number to be 16 ?*/
 #define IAVF_MAX_MSIX_VECTORS   16
 
@@ -117,6 +123,10 @@ struct iavf_info {
 	uint16_t msix_base; /* msix vector base from */
 	/* queue bitmask for each vector */
 	uint16_t rxq_map[IAVF_MAX_MSIX_VECTORS];
+	struct iavf_flow_list flow_list;
+	rte_spinlock_t flow_ops_lock;
+	struct iavf_parser_list rss_parser_list;
+	struct iavf_parser_list dist_parser_list;
 };
 
 #define IAVF_MAX_PKT_TYPE 1024
diff --git a/drivers/net/iavf/iavf_ethdev.c b/drivers/net/iavf/iavf_ethdev.c
index 7a8bec9..a5f492d 100644
--- a/drivers/net/iavf/iavf_ethdev.c
+++ b/drivers/net/iavf/iavf_ethdev.c
@@ -27,6 +27,7 @@
 
 #include "iavf.h"
 #include "iavf_rxtx.h"
+#include "iavf_generic_flow.h"
 
 static int iavf_dev_configure(struct rte_eth_dev *dev);
 static int iavf_dev_start(struct rte_eth_dev *dev);
@@ -67,6 +68,11 @@ static int iavf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev,
 					uint16_t queue_id);
 static int iavf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev,
 					 uint16_t queue_id);
+static int iavf_dev_filter_ctrl(struct rte_eth_dev *dev,
+		     enum rte_filter_type filter_type,
+		     enum rte_filter_op filter_op,
+		     void *arg);
+
 
 int iavf_logtype_init;
 int iavf_logtype_driver;
@@ -125,6 +131,7 @@ static const struct eth_dev_ops iavf_eth_dev_ops = {
 	.mtu_set                    = iavf_dev_mtu_set,
 	.rx_queue_intr_enable       = iavf_dev_rx_queue_intr_enable,
 	.rx_queue_intr_disable      = iavf_dev_rx_queue_intr_disable,
+	.filter_ctrl                = iavf_dev_filter_ctrl,
 };
 
 static int
@@ -1291,12 +1298,41 @@ iavf_dev_interrupt_handler(void *param)
 }
 
 static int
+iavf_dev_filter_ctrl(struct rte_eth_dev *dev,
+		     enum rte_filter_type filter_type,
+		     enum rte_filter_op filter_op,
+		     void *arg)
+{
+	int ret = 0;
+
+	if (!dev)
+		return -EINVAL;
+
+	switch (filter_type) {
+	case RTE_ETH_FILTER_GENERIC:
+		if (filter_op != RTE_ETH_FILTER_GET)
+			return -EINVAL;
+		*(const void **)arg = &iavf_flow_ops;
+		break;
+	default:
+		PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
+			    filter_type);
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+
+static int
 iavf_dev_init(struct rte_eth_dev *eth_dev)
 {
 	struct iavf_adapter *adapter =
 		IAVF_DEV_PRIVATE_TO_ADAPTER(eth_dev->data->dev_private);
 	struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(adapter);
 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
+	int ret = 0;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -1366,6 +1402,12 @@ iavf_dev_init(struct rte_eth_dev *eth_dev)
 	/* configure and enable device interrupt */
 	iavf_enable_irq0(hw);
 
+	ret = iavf_flow_init(adapter);
+	if (ret) {
+		PMD_INIT_LOG(ERR, "Failed to initialize flow");
+		return ret;
+	}
+
 	return 0;
 }
 
@@ -1375,6 +1417,8 @@ iavf_dev_close(struct rte_eth_dev *dev)
 	struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
 	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
+	struct iavf_adapter *adapter =
+		IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
 
 	iavf_dev_stop(dev);
 	iavf_shutdown_adminq(hw);
@@ -1385,6 +1429,8 @@ iavf_dev_close(struct rte_eth_dev *dev)
 	rte_intr_callback_unregister(intr_handle,
 				     iavf_dev_interrupt_handler, dev);
 	iavf_disable_irq0(hw);
+
+	iavf_flow_uninit(adapter);
 }
 
 static int
diff --git a/drivers/net/iavf/iavf_generic_flow.c b/drivers/net/iavf/iavf_generic_flow.c
new file mode 100644
index 0000000..1e2231d
--- /dev/null
+++ b/drivers/net/iavf/iavf_generic_flow.c
@@ -0,0 +1,930 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#include <sys/queue.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+#include <rte_ether.h>
+#include <rte_ethdev_driver.h>
+#include <rte_malloc.h>
+#include <rte_tailq.h>
+
+#include "iavf.h"
+#include "iavf_generic_flow.h"
+
+static struct iavf_engine_list engine_list =
+		TAILQ_HEAD_INITIALIZER(engine_list);
+
+static int iavf_flow_validate(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);
+static struct rte_flow *iavf_flow_create(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);
+static int iavf_flow_destroy(struct rte_eth_dev *dev,
+		struct rte_flow *flow,
+		struct rte_flow_error *error);
+static int iavf_flow_flush(struct rte_eth_dev *dev,
+		struct rte_flow_error *error);
+static int iavf_flow_query(struct rte_eth_dev *dev,
+		struct rte_flow *flow,
+		const struct rte_flow_action *actions,
+		void *data,
+		struct rte_flow_error *error);
+
+const struct rte_flow_ops iavf_flow_ops = {
+	.validate = iavf_flow_validate,
+	.create = iavf_flow_create,
+	.destroy = iavf_flow_destroy,
+	.flush = iavf_flow_flush,
+	.query = iavf_flow_query,
+};
+
+/* empty */
+enum rte_flow_item_type iavf_pattern_empty[] = {
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+/* L2 */
+enum rte_flow_item_type iavf_pattern_ethertype[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_ethertype_vlan[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_ethertype_qinq[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+/* ARP */
+enum rte_flow_item_type iavf_pattern_eth_arp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_ARP_ETH_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+/* non-tunnel IPv4 */
+enum rte_flow_item_type iavf_pattern_eth_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_sctp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_SCTP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_sctp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_SCTP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_sctp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_SCTP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_icmp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_ICMP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_icmp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_ICMP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_icmp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_ICMP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+/* non-tunnel IPv6 */
+enum rte_flow_item_type iavf_pattern_eth_ipv6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv6_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv6_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv6_sctp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_SCTP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_sctp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_SCTP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_sctp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_SCTP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv6_icmp6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_ICMP6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_icmp6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_ICMP6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_icmp6[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_VLAN,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_ICMP6,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+/* GTPU */
+enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_GTPU,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_GTPU,
+	RTE_FLOW_ITEM_TYPE_GTP_PSC,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_udp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_GTPU,
+	RTE_FLOW_ITEM_TYPE_GTP_PSC,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_tcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_GTPU,
+	RTE_FLOW_ITEM_TYPE_GTP_PSC,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_TCP,
+	RTE_FLOW_ITEM_TYPE_END,
+
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_icmp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_GTPU,
+	RTE_FLOW_ITEM_TYPE_GTP_PSC,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_ICMP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+typedef struct iavf_flow_engine * (*parse_engine_t)(struct iavf_adapter *ad,
+		struct rte_flow *flow,
+		struct iavf_parser_list *parser_list,
+		const struct rte_flow_item pattern[],
+		const struct rte_flow_action actions[],
+		struct rte_flow_error *error);
+
+void
+iavf_register_flow_engine(struct iavf_flow_engine *engine)
+{
+	TAILQ_INSERT_TAIL(&engine_list, engine, node);
+}
+
+int
+iavf_flow_init(struct iavf_adapter *ad)
+{
+	int ret;
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
+	void *temp;
+	struct iavf_flow_engine *engine;
+
+	TAILQ_INIT(&vf->flow_list);
+	TAILQ_INIT(&vf->rss_parser_list);
+	TAILQ_INIT(&vf->dist_parser_list);
+	rte_spinlock_init(&vf->flow_ops_lock);
+
+	TAILQ_FOREACH_SAFE(engine, &engine_list, node, temp) {
+		if (engine->init == NULL) {
+			PMD_INIT_LOG(ERR, "Invalid engine type (%d)",
+				     engine->type);
+			return -ENOTSUP;
+		}
+
+		ret = engine->init(ad);
+		if (ret && ret != -ENOTSUP) {
+			PMD_INIT_LOG(ERR, "Failed to initialize engine %d",
+				     engine->type);
+			return ret;
+		}
+	}
+	return 0;
+}
+
+void
+iavf_flow_uninit(struct iavf_adapter *ad)
+{
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
+	struct iavf_flow_engine *engine;
+	struct rte_flow *p_flow;
+	struct iavf_flow_parser_node *p_parser;
+	void *temp;
+
+	TAILQ_FOREACH_SAFE(engine, &engine_list, node, temp) {
+		if (engine->uninit)
+			engine->uninit(ad);
+	}
+
+	/* Remove all flows */
+	while ((p_flow = TAILQ_FIRST(&vf->flow_list))) {
+		TAILQ_REMOVE(&vf->flow_list, p_flow, node);
+		if (p_flow->engine->free)
+			p_flow->engine->free(p_flow);
+		rte_free(p_flow);
+	}
+
+	/* Cleanup parser list */
+	while ((p_parser = TAILQ_FIRST(&vf->rss_parser_list))) {
+		TAILQ_REMOVE(&vf->rss_parser_list, p_parser, node);
+		rte_free(p_parser);
+	}
+
+	while ((p_parser = TAILQ_FIRST(&vf->dist_parser_list))) {
+		TAILQ_REMOVE(&vf->dist_parser_list, p_parser, node);
+		rte_free(p_parser);
+	}
+}
+
+int
+iavf_register_parser(struct iavf_flow_parser *parser,
+		     struct iavf_adapter *ad)
+{
+	struct iavf_parser_list *list = NULL;
+	struct iavf_flow_parser_node *parser_node;
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
+
+	parser_node = rte_zmalloc("iavf_parser", sizeof(*parser_node), 0);
+	if (parser_node == NULL) {
+		PMD_DRV_LOG(ERR, "Failed to allocate memory.");
+		return -ENOMEM;
+	}
+	parser_node->parser = parser;
+
+	if (parser->engine->type == IAVF_FLOW_ENGINE_HASH) {
+		list = &vf->rss_parser_list;
+		TAILQ_INSERT_TAIL(list, parser_node, node);
+	} else if (parser->engine->type == IAVF_FLOW_ENGINE_FDIR) {
+		list = &vf->dist_parser_list;
+		TAILQ_INSERT_HEAD(list, parser_node, node);
+	} else
+		return -EINVAL;
+
+	return 0;
+}
+
+void
+iavf_unregister_parser(struct iavf_flow_parser *parser,
+		       struct iavf_adapter *ad)
+{
+	struct iavf_parser_list *list = NULL;
+	struct iavf_flow_parser_node *p_parser;
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
+	void *temp;
+
+	if (parser->engine->type == IAVF_FLOW_ENGINE_HASH)
+		list = &vf->rss_parser_list;
+	else if (parser->engine->type == IAVF_FLOW_ENGINE_FDIR)
+		list = &vf->dist_parser_list;
+
+	if (list == NULL)
+		return;
+
+	TAILQ_FOREACH_SAFE(p_parser, list, node, temp) {
+		if (p_parser->parser->engine->type == parser->engine->type) {
+			TAILQ_REMOVE(list, p_parser, node);
+			rte_free(p_parser);
+		}
+	}
+}
+
+static int
+iavf_flow_valid_attr(const struct rte_flow_attr *attr,
+		     struct rte_flow_error *error)
+{
+	/* Must be input direction */
+	if (!attr->ingress) {
+		rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
+				attr, "Only support ingress.");
+		return -rte_errno;
+	}
+
+	/* Not supported */
+	if (attr->egress) {
+		rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
+				attr, "Not support egress.");
+		return -rte_errno;
+	}
+
+	/* Not supported */
+	if (attr->priority) {
+		rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
+				attr, "Not support priority.");
+		return -rte_errno;
+	}
+
+	/* Not supported */
+	if (attr->group) {
+		rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
+				attr, "Not support group.");
+		return -rte_errno;
+	}
+
+	return 0;
+}
+
+/* Find the first VOID or non-VOID item pointer */
+static const struct rte_flow_item *
+iavf_find_first_item(const struct rte_flow_item *item, bool is_void)
+{
+	bool is_find;
+
+	while (item->type != RTE_FLOW_ITEM_TYPE_END) {
+		if (is_void)
+			is_find = item->type == RTE_FLOW_ITEM_TYPE_VOID;
+		else
+			is_find = item->type != RTE_FLOW_ITEM_TYPE_VOID;
+		if (is_find)
+			break;
+		item++;
+	}
+	return item;
+}
+
+/* Skip all VOID items of the pattern */
+static void
+iavf_pattern_skip_void_item(struct rte_flow_item *items,
+			const struct rte_flow_item *pattern)
+{
+	uint32_t cpy_count = 0;
+	const struct rte_flow_item *pb = pattern, *pe = pattern;
+
+	for (;;) {
+		/* Find a non-void item first */
+		pb = iavf_find_first_item(pb, false);
+		if (pb->type == RTE_FLOW_ITEM_TYPE_END) {
+			pe = pb;
+			break;
+		}
+
+		/* Find a void item */
+		pe = iavf_find_first_item(pb + 1, true);
+
+		cpy_count = pe - pb;
+		rte_memcpy(items, pb, sizeof(struct rte_flow_item) * cpy_count);
+
+		items += cpy_count;
+
+		if (pe->type == RTE_FLOW_ITEM_TYPE_END)
+			break;
+
+		pb = pe + 1;
+	}
+	/* Copy the END item. */
+	rte_memcpy(items, pe, sizeof(struct rte_flow_item));
+}
+
+/* Check if the pattern matches a supported item type array */
+static bool
+iavf_match_pattern(enum rte_flow_item_type *item_array,
+		   const struct rte_flow_item *pattern)
+{
+	const struct rte_flow_item *item = pattern;
+
+	while ((*item_array == item->type) &&
+	       (*item_array != RTE_FLOW_ITEM_TYPE_END)) {
+		item_array++;
+		item++;
+	}
+
+	return (*item_array == RTE_FLOW_ITEM_TYPE_END &&
+		item->type == RTE_FLOW_ITEM_TYPE_END);
+}
+
+struct iavf_pattern_match_item *
+iavf_search_pattern_match_item(const struct rte_flow_item pattern[],
+		struct iavf_pattern_match_item *array,
+		uint32_t array_len,
+		struct rte_flow_error *error)
+{
+	uint16_t i = 0;
+	struct iavf_pattern_match_item *pattern_match_item;
+	/* need free by each filter */
+	struct rte_flow_item *items; /* used for pattern without VOID items */
+	uint32_t item_num = 0; /* non-void item number */
+
+	/* Get the non-void item number of pattern */
+	while ((pattern + i)->type != RTE_FLOW_ITEM_TYPE_END) {
+		if ((pattern + i)->type != RTE_FLOW_ITEM_TYPE_VOID)
+			item_num++;
+		i++;
+	}
+	item_num++;
+
+	items = rte_zmalloc("iavf_pattern",
+			    item_num * sizeof(struct rte_flow_item), 0);
+	if (!items) {
+		rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_ITEM_NUM,
+				   NULL, "No memory for PMD internal items.");
+		return NULL;
+	}
+	pattern_match_item = rte_zmalloc("iavf_pattern_match_item",
+				sizeof(struct iavf_pattern_match_item), 0);
+	if (!pattern_match_item) {
+		rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
+				   NULL, "Failed to allocate memory.");
+		return NULL;
+	}
+
+	iavf_pattern_skip_void_item(items, pattern);
+
+	for (i = 0; i < array_len; i++)
+		if (iavf_match_pattern(array[i].pattern_list,
+				       items)) {
+			pattern_match_item->input_set_mask =
+				array[i].input_set_mask;
+			pattern_match_item->pattern_list =
+				array[i].pattern_list;
+			pattern_match_item->meta = array[i].meta;
+			rte_free(items);
+			return pattern_match_item;
+		}
+	rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
+			   pattern, "Unsupported pattern");
+
+	rte_free(items);
+	rte_free(pattern_match_item);
+	return NULL;
+}
+
+static struct iavf_flow_engine *
+iavf_parse_engine_create(struct iavf_adapter *ad,
+		struct rte_flow *flow,
+		struct iavf_parser_list *parser_list,
+		const struct rte_flow_item pattern[],
+		const struct rte_flow_action actions[],
+		struct rte_flow_error *error)
+{
+	struct iavf_flow_engine *engine = NULL;
+	struct iavf_flow_parser_node *parser_node;
+	void *temp;
+	void *meta = NULL;
+
+	TAILQ_FOREACH_SAFE(parser_node, parser_list, node, temp) {
+		if (parser_node->parser->parse_pattern_action(ad,
+				parser_node->parser->array,
+				parser_node->parser->array_len,
+				pattern, actions, &meta, error) < 0)
+			continue;
+
+		engine = parser_node->parser->engine;
+
+		RTE_ASSERT(engine->create != NULL);
+		if (!(engine->create(ad, flow, meta, error)))
+			return engine;
+	}
+	return NULL;
+}
+
+static struct iavf_flow_engine *
+iavf_parse_engine_validate(struct iavf_adapter *ad,
+		struct rte_flow *flow,
+		struct iavf_parser_list *parser_list,
+		const struct rte_flow_item pattern[],
+		const struct rte_flow_action actions[],
+		struct rte_flow_error *error)
+{
+	struct iavf_flow_engine *engine = NULL;
+	struct iavf_flow_parser_node *parser_node;
+	void *temp;
+	void *meta = NULL;
+
+	TAILQ_FOREACH_SAFE(parser_node, parser_list, node, temp) {
+		if (parser_node->parser->parse_pattern_action(ad,
+				parser_node->parser->array,
+				parser_node->parser->array_len,
+				pattern, actions, &meta,  error) < 0)
+			continue;
+
+		engine = parser_node->parser->engine;
+		if (engine->validation == NULL) {
+			rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_HANDLE,
+				NULL, "Validation not support");
+			continue;
+		}
+
+		if (engine->validation(ad, flow, meta, error)) {
+			rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_HANDLE,
+				NULL, "Validation failed");
+			break;
+		}
+	}
+	return engine;
+}
+
+
+static int
+iavf_flow_process_filter(struct rte_eth_dev *dev,
+		struct rte_flow *flow,
+		const struct rte_flow_attr *attr,
+		const struct rte_flow_item pattern[],
+		const struct rte_flow_action actions[],
+		struct iavf_flow_engine **engine,
+		parse_engine_t iavf_parse_engine,
+		struct rte_flow_error *error)
+{
+	int ret = IAVF_ERR_CONFIG;
+	struct iavf_adapter *ad =
+		IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
+
+	if (!pattern) {
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_NUM,
+				   NULL, "NULL pattern.");
+		return -rte_errno;
+	}
+
+	if (!actions) {
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_ACTION_NUM,
+				   NULL, "NULL action.");
+		return -rte_errno;
+	}
+
+	if (!attr) {
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_ATTR,
+				   NULL, "NULL attribute.");
+		return -rte_errno;
+	}
+
+	ret = iavf_flow_valid_attr(attr, error);
+	if (ret)
+		return ret;
+
+	*engine = iavf_parse_engine(ad, flow, &vf->rss_parser_list, pattern,
+				    actions, error);
+	if (*engine != NULL)
+		return 0;
+
+	*engine = iavf_parse_engine(ad, flow, &vf->dist_parser_list, pattern,
+				    actions, error);
+
+	if (*engine == NULL)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int
+iavf_flow_validate(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)
+{
+	struct iavf_flow_engine *engine;
+
+	return iavf_flow_process_filter(dev, NULL, attr, pattern, actions,
+			&engine, iavf_parse_engine_validate, error);
+}
+
+static struct rte_flow *
+iavf_flow_create(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)
+{
+	struct iavf_adapter *ad =
+		IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
+	struct iavf_flow_engine *engine = NULL;
+	struct rte_flow *flow = NULL;
+	int ret;
+
+	flow = rte_zmalloc("iavf_flow", sizeof(struct rte_flow), 0);
+	if (!flow) {
+		rte_flow_error_set(error, ENOMEM,
+				   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+				   "Failed to allocate memory");
+		return flow;
+	}
+
+	ret = iavf_flow_process_filter(dev, flow, attr, pattern, actions,
+			&engine, iavf_parse_engine_create, error);
+	if (ret < 0) {
+		PMD_DRV_LOG(ERR, "Failed to create flow");
+		rte_free(flow);
+		flow = NULL;
+		goto free_flow;
+	}
+
+	flow->engine = engine;
+	TAILQ_INSERT_TAIL(&vf->flow_list, flow, node);
+	PMD_DRV_LOG(INFO, "Succeeded to create (%d) flow", engine->type);
+
+free_flow:
+	rte_spinlock_unlock(&vf->flow_ops_lock);
+	return flow;
+}
+
+static int
+iavf_flow_destroy(struct rte_eth_dev *dev,
+		  struct rte_flow *flow,
+		  struct rte_flow_error *error)
+{
+	struct iavf_adapter *ad =
+		IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
+	int ret = 0;
+
+	if (!flow || !flow->engine || !flow->engine->destroy) {
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_HANDLE,
+				   NULL, "Invalid flow");
+		return -rte_errno;
+	}
+
+	rte_spinlock_lock(&vf->flow_ops_lock);
+
+	ret = flow->engine->destroy(ad, flow, error);
+
+	if (!ret) {
+		TAILQ_REMOVE(&vf->flow_list, flow, node);
+		rte_free(flow);
+	} else {
+		PMD_DRV_LOG(ERR, "Failed to destroy flow");
+	}
+
+	rte_spinlock_unlock(&vf->flow_ops_lock);
+
+	return ret;
+}
+
+static int
+iavf_flow_flush(struct rte_eth_dev *dev,
+		struct rte_flow_error *error)
+{
+	struct iavf_adapter *ad =
+		IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
+	struct rte_flow *p_flow;
+	void *temp;
+	int ret = 0;
+
+	TAILQ_FOREACH_SAFE(p_flow, &vf->flow_list, node, temp) {
+		ret = iavf_flow_destroy(dev, p_flow, error);
+		if (ret) {
+			PMD_DRV_LOG(ERR, "Failed to flush flows");
+			return -EINVAL;
+		}
+	}
+
+	return ret;
+}
+
+static int
+iavf_flow_query(struct rte_eth_dev *dev,
+		struct rte_flow *flow,
+		const struct rte_flow_action *actions,
+		void *data,
+		struct rte_flow_error *error)
+{
+	int ret = -EINVAL;
+	struct iavf_adapter *ad =
+		IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+	struct rte_flow_query_count *count = data;
+
+	if (!flow || !flow->engine || !flow->engine->query_count) {
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_HANDLE,
+				   NULL, "Invalid flow");
+		return -rte_errno;
+	}
+
+	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
+		switch (actions->type) {
+		case RTE_FLOW_ACTION_TYPE_VOID:
+			break;
+		case RTE_FLOW_ACTION_TYPE_COUNT:
+			ret = flow->engine->query_count(ad, flow, count, error);
+			break;
+		default:
+			return rte_flow_error_set(error, ENOTSUP,
+					RTE_FLOW_ERROR_TYPE_ACTION,
+					actions,
+					"action not supported");
+		}
+	}
+	return ret;
+}
+
diff --git a/drivers/net/iavf/iavf_generic_flow.h b/drivers/net/iavf/iavf_generic_flow.h
new file mode 100644
index 0000000..1e69863
--- /dev/null
+++ b/drivers/net/iavf/iavf_generic_flow.h
@@ -0,0 +1,279 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#ifndef _IAVF_GENERIC_FLOW_H_
+#define _IAVF_GENERIC_FLOW_H_
+
+#include <rte_flow_driver.h>
+
+/* protocol */
+
+#define IAVF_PROT_MAC_INNER         (1ULL << 1)
+#define IAVF_PROT_MAC_OUTER         (1ULL << 2)
+#define IAVF_PROT_VLAN_INNER        (1ULL << 3)
+#define IAVF_PROT_VLAN_OUTER        (1ULL << 4)
+#define IAVF_PROT_IPV4_INNER        (1ULL << 5)
+#define IAVF_PROT_IPV4_OUTER        (1ULL << 6)
+#define IAVF_PROT_IPV6_INNER        (1ULL << 7)
+#define IAVF_PROT_IPV6_OUTER        (1ULL << 8)
+#define IAVF_PROT_TCP_INNER         (1ULL << 9)
+#define IAVF_PROT_TCP_OUTER         (1ULL << 10)
+#define IAVF_PROT_UDP_INNER         (1ULL << 11)
+#define IAVF_PROT_UDP_OUTER         (1ULL << 12)
+#define IAVF_PROT_SCTP_INNER        (1ULL << 13)
+#define IAVF_PROT_SCTP_OUTER        (1ULL << 14)
+#define IAVF_PROT_ICMP4_INNER       (1ULL << 15)
+#define IAVF_PROT_ICMP4_OUTER       (1ULL << 16)
+#define IAVF_PROT_ICMP6_INNER       (1ULL << 17)
+#define IAVF_PROT_ICMP6_OUTER       (1ULL << 18)
+#define IAVF_PROT_VXLAN             (1ULL << 19)
+#define IAVF_PROT_NVGRE             (1ULL << 20)
+#define IAVF_PROT_GTPU              (1ULL << 21)
+
+
+/* field */
+
+#define IAVF_SMAC                   (1ULL << 63)
+#define IAVF_DMAC                   (1ULL << 62)
+#define IAVF_ETHERTYPE              (1ULL << 61)
+#define IAVF_IP_SRC                 (1ULL << 60)
+#define IAVF_IP_DST                 (1ULL << 59)
+#define IAVF_IP_PROTO               (1ULL << 58)
+#define IAVF_IP_TTL                 (1ULL << 57)
+#define IAVF_IP_TOS                 (1ULL << 56)
+#define IAVF_SPORT                  (1ULL << 55)
+#define IAVF_DPORT                  (1ULL << 54)
+#define IAVF_ICMP_TYPE              (1ULL << 53)
+#define IAVF_ICMP_CODE              (1ULL << 52)
+#define IAVF_VXLAN_VNI              (1ULL << 51)
+#define IAVF_NVGRE_TNI              (1ULL << 50)
+#define IAVF_GTPU_TEID              (1ULL << 49)
+#define IAVF_GTPU_QFI               (1ULL << 48)
+
+/* input set */
+
+#define IAVF_INSET_NONE             0ULL
+
+/* non-tunnel */
+
+#define IAVF_INSET_SMAC         (IAVF_PROT_MAC_OUTER | IAVF_SMAC)
+#define IAVF_INSET_DMAC         (IAVF_PROT_MAC_OUTER | IAVF_DMAC)
+#define IAVF_INSET_VLAN_INNER   (IAVF_PROT_VLAN_INNER)
+#define IAVF_INSET_VLAN_OUTER   (IAVF_PROT_VLAN_OUTER)
+#define IAVF_INSET_ETHERTYPE    (IAVF_ETHERTYPE)
+
+#define IAVF_INSET_IPV4_SRC \
+	(IAVF_PROT_IPV4_OUTER | IAVF_IP_SRC)
+#define IAVF_INSET_IPV4_DST \
+	(IAVF_PROT_IPV4_OUTER | IAVF_IP_DST)
+#define IAVF_INSET_IPV4_TOS \
+	(IAVF_PROT_IPV4_OUTER | IAVF_IP_TOS)
+#define IAVF_INSET_IPV4_PROTO \
+	(IAVF_PROT_IPV4_OUTER | IAVF_IP_PROTO)
+#define IAVF_INSET_IPV4_TTL \
+	(IAVF_PROT_IPV4_OUTER | IAVF_IP_TTL)
+#define IAVF_INSET_IPV6_SRC \
+	(IAVF_PROT_IPV6_OUTER | IAVF_IP_SRC)
+#define IAVF_INSET_IPV6_DST \
+	(IAVF_PROT_IPV6_OUTER | IAVF_IP_DST)
+#define IAVF_INSET_IPV6_NEXT_HDR \
+	(IAVF_PROT_IPV6_OUTER | IAVF_IP_PROTO)
+#define IAVF_INSET_IPV6_HOP_LIMIT \
+	(IAVF_PROT_IPV6_OUTER | IAVF_IP_TTL)
+#define IAVF_INSET_IPV6_TC \
+	(IAVF_PROT_IPV6_OUTER | IAVF_IP_TOS)
+
+#define IAVF_INSET_TCP_SRC_PORT \
+	(IAVF_PROT_TCP_OUTER | IAVF_SPORT)
+#define IAVF_INSET_TCP_DST_PORT \
+	(IAVF_PROT_TCP_OUTER | IAVF_DPORT)
+#define IAVF_INSET_UDP_SRC_PORT \
+	(IAVF_PROT_UDP_OUTER | IAVF_SPORT)
+#define IAVF_INSET_UDP_DST_PORT \
+	(IAVF_PROT_UDP_OUTER | IAVF_DPORT)
+#define IAVF_INSET_SCTP_SRC_PORT \
+	(IAVF_PROT_SCTP_OUTER | IAVF_SPORT)
+#define IAVF_INSET_SCTP_DST_PORT \
+	(IAVF_PROT_SCTP_OUTER | IAVF_DPORT)
+#define IAVF_INSET_ICMP4_SRC_PORT \
+	(IAVF_PROT_ICMP4_OUTER | IAVF_SPORT)
+#define IAVF_INSET_ICMP4_DST_PORT \
+	(IAVF_PROT_ICMP4_OUTER | IAVF_DPORT)
+#define IAVF_INSET_ICMP6_SRC_PORT \
+	(IAVF_PROT_ICMP6_OUTER | IAVF_SPORT)
+#define IAVF_INSET_ICMP6_DST_PORT \
+	(IAVF_PROT_ICMP6_OUTER | IAVF_DPORT)
+#define IAVF_INSET_ICMP4_TYPE \
+	(IAVF_PROT_ICMP4_OUTER | IAVF_ICMP_TYPE)
+#define IAVF_INSET_ICMP4_CODE \
+	(IAVF_PROT_ICMP4_OUTER | IAVF_ICMP_CODE)
+#define IAVF_INSET_ICMP6_TYPE \
+	(IAVF_PROT_ICMP6_OUTER | IAVF_ICMP_TYPE)
+#define IAVF_INSET_ICMP6_CODE \
+	(IAVF_PROT_ICMP6_OUTER | IAVF_ICMP_CODE)
+#define IAVF_INSET_GTPU_TEID \
+	(IAVF_PROT_GTPU | IAVF_GTPU_TEID)
+#define IAVF_INSET_GTPU_QFI \
+	(IAVF_PROT_GTPU | IAVF_GTPU_QFI)
+
+
+/* empty pattern */
+extern enum rte_flow_item_type iavf_pattern_empty[];
+
+/* L2 */
+extern enum rte_flow_item_type iavf_pattern_ethertype[];
+extern enum rte_flow_item_type iavf_pattern_ethertype_vlan[];
+extern enum rte_flow_item_type iavf_pattern_ethertype_qinq[];
+
+/* ARP */
+extern enum rte_flow_item_type iavf_pattern_eth_arp[];
+
+/* non-tunnel IPv4 */
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_udp[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_udp[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_udp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_tcp[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_tcp[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_tcp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_sctp[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_sctp[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_sctp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_icmp[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_icmp[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_icmp[];
+
+/* non-tunnel IPv6 */
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6_udp[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_udp[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_udp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6_tcp[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_tcp[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_tcp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6_sctp[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_sctp[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_sctp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6_icmp6[];
+extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_icmp6[];
+extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_icmp6[];
+
+/* GTPU */
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_ipv4[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_udp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_tcp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_icmp[];
+
+
+extern const struct rte_flow_ops iavf_flow_ops;
+
+/* pattern structure */
+struct iavf_pattern_match_item {
+	enum rte_flow_item_type *pattern_list;
+	/* pattern_list must end with RTE_FLOW_ITEM_TYPE_END */
+	uint64_t input_set_mask;
+	void *meta;
+};
+
+typedef int (*engine_init_t)(struct iavf_adapter *ad);
+typedef void (*engine_uninit_t)(struct iavf_adapter *ad);
+typedef int (*engine_validation_t)(struct iavf_adapter *ad,
+		struct rte_flow *flow,
+		void *meta,
+		struct rte_flow_error *error);
+typedef int (*engine_create_t)(struct iavf_adapter *ad,
+		struct rte_flow *flow,
+		void *meta,
+		struct rte_flow_error *error);
+typedef int (*engine_destroy_t)(struct iavf_adapter *ad,
+		struct rte_flow *flow,
+		struct rte_flow_error *error);
+typedef int (*engine_query_t)(struct iavf_adapter *ad,
+		struct rte_flow *flow,
+		struct rte_flow_query_count *count,
+		struct rte_flow_error *error);
+typedef void (*engine_free_t) (struct rte_flow *flow);
+typedef int (*parse_pattern_action_t)(struct iavf_adapter *ad,
+		struct iavf_pattern_match_item *array,
+		uint32_t array_len,
+		const struct rte_flow_item pattern[],
+		const struct rte_flow_action actions[],
+		void **meta,
+		struct rte_flow_error *error);
+
+/* engine types. */
+enum iavf_flow_engine_type {
+	IAVF_FLOW_ENGINE_NONE = 0,
+	IAVF_FLOW_ENGINE_FDIR,
+	IAVF_FLOW_ENGINE_HASH,
+	IAVF_FLOW_ENGINE_MAX,
+};
+
+/**
+ * classification stages.
+ * for non-pipeline mode, we have two classification stages: Distributor/RSS
+ * for pipeline-mode we have three classification stages:
+ * Permission/Distributor/RSS
+ */
+enum iavf_flow_classification_stage {
+	IAVF_FLOW_STAGE_NONE = 0,
+	IAVF_FLOW_STAGE_RSS,
+	IAVF_FLOW_STAGE_DISTRIBUTOR,
+	IAVF_FLOW_STAGE_MAX,
+};
+
+/* Struct to store engine created. */
+struct iavf_flow_engine {
+	TAILQ_ENTRY(iavf_flow_engine) node;
+	engine_init_t init;
+	engine_uninit_t uninit;
+	engine_validation_t validation;
+	engine_create_t create;
+	engine_destroy_t destroy;
+	engine_query_t query_count;
+	engine_free_t free;
+	enum iavf_flow_engine_type type;
+};
+
+TAILQ_HEAD(iavf_engine_list, iavf_flow_engine);
+
+/* Struct to store flow created. */
+struct rte_flow {
+	TAILQ_ENTRY(rte_flow) node;
+	struct iavf_flow_engine *engine;
+	void *rule;
+};
+
+struct iavf_flow_parser {
+	struct iavf_flow_engine *engine;
+	struct iavf_pattern_match_item *array;
+	uint32_t array_len;
+	parse_pattern_action_t parse_pattern_action;
+	enum iavf_flow_classification_stage stage;
+};
+
+/* Struct to store parser created. */
+struct iavf_flow_parser_node {
+	TAILQ_ENTRY(iavf_flow_parser_node) node;
+	struct iavf_flow_parser *parser;
+};
+
+void iavf_register_flow_engine(struct iavf_flow_engine *engine);
+int iavf_flow_init(struct iavf_adapter *ad);
+void iavf_flow_uninit(struct iavf_adapter *ad);
+int iavf_register_parser(struct iavf_flow_parser *parser,
+			 struct iavf_adapter *ad);
+void iavf_unregister_parser(struct iavf_flow_parser *parser,
+			    struct iavf_adapter *ad);
+struct iavf_pattern_match_item *
+iavf_search_pattern_match_item(const struct rte_flow_item pattern[],
+		struct iavf_pattern_match_item *array,
+		uint32_t array_len,
+		struct rte_flow_error *error);
+#endif
diff --git a/drivers/net/iavf/meson.build b/drivers/net/iavf/meson.build
index dbd0b01..32eabca 100644
--- a/drivers/net/iavf/meson.build
+++ b/drivers/net/iavf/meson.build
@@ -12,6 +12,7 @@ sources = files(
 	'iavf_ethdev.c',
 	'iavf_rxtx.c',
 	'iavf_vchnl.c',
+	'iavf_generic_flow.c',
 )
 
 if arch_subdir == 'x86'
-- 
2.9.5


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

* [dpdk-dev] [PATCH v3 2/2] net/iavf: support more patterns
  2020-04-03  5:42 ` [dpdk-dev] [PATCH v3 0/2] add generic filter support for iavf Qiming Yang
  2020-04-03  5:42   ` [dpdk-dev] [PATCH v3 1/2] net/iavf: support generic flow Qiming Yang
@ 2020-04-03  5:42   ` Qiming Yang
  2020-04-03  6:03   ` [dpdk-dev] [PATCH v3 0/2] add generic filter support for iavf Zhang, Qi Z
  2020-04-09  5:02   ` Ye Xiaolong
  3 siblings, 0 replies; 14+ messages in thread
From: Qiming Yang @ 2020-04-03  5:42 UTC (permalink / raw)
  To: dev; +Cc: qi.z.zhang, Qiming Yang, Zhang Xiao

Add patterns support for AH/ESP/L2TPV3OIP/PFCP.
Added patterns are as follows:
/* GTPU */
    eth/ipv4/udp/gtpu
    eth/ipv4/udp/gtpu/gtp_psc
/* ESP */
    eth/ipv4/esp  eth/ipv4/udp/esp
    eth/ipv6/esp  eth/ipv6/udp/esp
/* AH */
    eth/ipv4/ah  eth/ipv6/ah
/* L2TPV3 */
    eth/ipv4/l2tpv3oip  eth/ipv6/l2tpv3oip
/* PFCP */
    eth/ipv4/udp/pfcp  eth/ipv6/udp/pfcp

Depends on patch: ethdev: add PFCP header to flow API

Signed-off-by: Zhang Xiao <xiao.zhang@intel.com>
---
 drivers/net/iavf/iavf_generic_flow.c | 95 ++++++++++++++++++++++++++++++++++++
 drivers/net/iavf/iavf_generic_flow.h | 39 +++++++++++++++
 2 files changed, 134 insertions(+)

diff --git a/drivers/net/iavf/iavf_generic_flow.c b/drivers/net/iavf/iavf_generic_flow.c
index 1e2231d..557021a 100644
--- a/drivers/net/iavf/iavf_generic_flow.c
+++ b/drivers/net/iavf/iavf_generic_flow.c
@@ -318,6 +318,23 @@ enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_icmp6[] = {
 };
 
 /* GTPU */
+enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_GTPU,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_GTPU,
+	RTE_FLOW_ITEM_TYPE_GTP_PSC,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
 enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_ipv4[] = {
 	RTE_FLOW_ITEM_TYPE_ETH,
 	RTE_FLOW_ITEM_TYPE_IPV4,
@@ -371,6 +388,84 @@ enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_icmp[] = {
 	RTE_FLOW_ITEM_TYPE_END,
 };
 
+/* ESP */
+enum rte_flow_item_type iavf_pattern_eth_ipv4_esp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_ESP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv4_udp_esp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_ESP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv6_esp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_ESP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv6_udp_esp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_ESP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+/* AH */
+enum rte_flow_item_type iavf_pattern_eth_ipv4_ah[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_AH,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv6_ah[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_AH,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+/* L2TPV3 */
+enum rte_flow_item_type iavf_pattern_eth_ipv4_l2tpv3[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_L2TPV3OIP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv6_l2tpv3[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_L2TPV3OIP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+/* PFCP */
+enum rte_flow_item_type iavf_pattern_eth_ipv4_pfcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_PFCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
+enum rte_flow_item_type iavf_pattern_eth_ipv6_pfcp[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV6,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_PFCP,
+	RTE_FLOW_ITEM_TYPE_END,
+};
+
 typedef struct iavf_flow_engine * (*parse_engine_t)(struct iavf_adapter *ad,
 		struct rte_flow *flow,
 		struct iavf_parser_list *parser_list,
diff --git a/drivers/net/iavf/iavf_generic_flow.h b/drivers/net/iavf/iavf_generic_flow.h
index 1e69863..c41ca1b 100644
--- a/drivers/net/iavf/iavf_generic_flow.h
+++ b/drivers/net/iavf/iavf_generic_flow.h
@@ -30,6 +30,10 @@
 #define IAVF_PROT_VXLAN             (1ULL << 19)
 #define IAVF_PROT_NVGRE             (1ULL << 20)
 #define IAVF_PROT_GTPU              (1ULL << 21)
+#define IAVF_PROT_ESP		    (1ULL << 22)
+#define IAVF_PROT_AH		    (1ULL << 23)
+#define IAVF_PROT_L2TPV3OIP	    (1ULL << 24)
+#define IAVF_PROT_PFCP		    (1ULL << 25)
 
 
 /* field */
@@ -50,6 +54,11 @@
 #define IAVF_NVGRE_TNI              (1ULL << 50)
 #define IAVF_GTPU_TEID              (1ULL << 49)
 #define IAVF_GTPU_QFI               (1ULL << 48)
+#define IAVF_ESP_SPI		    (1ULL << 47)
+#define IAVF_AH_SPI		    (1ULL << 46)
+#define IAVF_L2TPV3OIP_SESSION_ID   (1ULL << 45)
+#define IAVF_PFCP_S_FIELD	    (1ULL << 44)
+#define IAVF_PFCP_SEID		    (1ULL << 43)
 
 /* input set */
 
@@ -116,6 +125,16 @@
 	(IAVF_PROT_GTPU | IAVF_GTPU_TEID)
 #define IAVF_INSET_GTPU_QFI \
 	(IAVF_PROT_GTPU | IAVF_GTPU_QFI)
+#define IAVF_INSET_ESP_SPI \
+	(IAVF_PROT_ESP | IAVF_ESP_SPI)
+#define IAVF_INSET_AH_SPI \
+	(IAVF_PROT_AH | IAVF_AH_SPI)
+#define IAVF_INSET_L2TPV3OIP_SESSION_ID \
+	(IAVF_PROT_L2TPV3OIP | IAVF_L2TPV3OIP_SESSION_ID)
+#define IAVF_INSET_PFCP_S_FIELD \
+	(IAVF_PROT_PFCP | IAVF_PFCP_S_FIELD)
+#define IAVF_INSET_PFCP_SEID \
+	(IAVF_PROT_PFCP | IAVF_PFCP_S_FIELD | IAVF_PFCP_SEID)
 
 
 /* empty pattern */
@@ -164,12 +183,32 @@ extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_icmp6[];
 extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_icmp6[];
 
 /* GTPU */
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu[];
 extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_ipv4[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh[];
 extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4[];
 extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_udp[];
 extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_tcp[];
 extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_icmp[];
 
+/* ESP */
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_esp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_udp_esp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6_esp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6_udp_esp[];
+
+/* AH */
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_ah[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6_ah[];
+
+/* L2TPV3 */
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_l2tpv3[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6_l2tpv3[];
+
+/* PFCP */
+extern enum rte_flow_item_type iavf_pattern_eth_ipv4_pfcp[];
+extern enum rte_flow_item_type iavf_pattern_eth_ipv6_pfcp[];
+
 
 extern const struct rte_flow_ops iavf_flow_ops;
 
-- 
2.9.5


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

* Re: [dpdk-dev] [PATCH v3 0/2] add generic filter support for iavf
  2020-04-03  5:42 ` [dpdk-dev] [PATCH v3 0/2] add generic filter support for iavf Qiming Yang
  2020-04-03  5:42   ` [dpdk-dev] [PATCH v3 1/2] net/iavf: support generic flow Qiming Yang
  2020-04-03  5:42   ` [dpdk-dev] [PATCH v3 2/2] net/iavf: support more patterns Qiming Yang
@ 2020-04-03  6:03   ` Zhang, Qi Z
  2020-04-09  5:02   ` Ye Xiaolong
  3 siblings, 0 replies; 14+ messages in thread
From: Zhang, Qi Z @ 2020-04-03  6:03 UTC (permalink / raw)
  To: Yang, Qiming, dev



> -----Original Message-----
> From: Yang, Qiming <qiming.yang@intel.com>
> Sent: Friday, April 3, 2020 1:43 PM
> To: dev@dpdk.org
> Cc: Zhang, Qi Z <qi.z.zhang@intel.com>; Yang, Qiming <qiming.yang@intel.com>
> Subject: [PATCH v3 0/2] add generic filter support for iavf
> 
> This patch set added generic flow APIs and supported patterns includes:
> /* L2 */
> /* ARP */
> /* IPv4 */
> /* IPv6  */
> /* GTPU */
> /* ESP */
> /* AH */
> /* L2TPV3 */
> /* PFCP */
> 
> ---
> v2 changes:
>  - fixed document error.
>  - fixed multiple thread not safe issue.
>  - use RTE_ASSERT to replace runtime check for engine->create == NULL.
> v3 changes:
>  - add feature enable flag in iavf.ini
> 
> Qiming Yang (2):
>   net/iavf: support generic flow
>   net/iavf: support more patterns
> 
>  doc/guides/nics/features/iavf.ini      |    1 +
>  doc/guides/rel_notes/release_20_05.rst |    5 +
>  drivers/net/iavf/Makefile              |    1 +
>  drivers/net/iavf/iavf.h                |   10 +
>  drivers/net/iavf/iavf_ethdev.c         |   46 ++
>  drivers/net/iavf/iavf_generic_flow.c   | 1025
> ++++++++++++++++++++++++++++++++
>  drivers/net/iavf/iavf_generic_flow.h   |  318 ++++++++++
>  drivers/net/iavf/meson.build           |    1 +
>  8 files changed, 1407 insertions(+)
>  create mode 100644 drivers/net/iavf/iavf_generic_flow.c
>  create mode 100644 drivers/net/iavf/iavf_generic_flow.h
> 
> --
> 2.9.5

Acked-by: Qi Zhang <qi.z.zhang@intel.com>

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

* Re: [dpdk-dev] [PATCH v3 0/2] add generic filter support for iavf
  2020-04-03  5:42 ` [dpdk-dev] [PATCH v3 0/2] add generic filter support for iavf Qiming Yang
                     ` (2 preceding siblings ...)
  2020-04-03  6:03   ` [dpdk-dev] [PATCH v3 0/2] add generic filter support for iavf Zhang, Qi Z
@ 2020-04-09  5:02   ` Ye Xiaolong
  3 siblings, 0 replies; 14+ messages in thread
From: Ye Xiaolong @ 2020-04-09  5:02 UTC (permalink / raw)
  To: Qiming Yang; +Cc: dev, qi.z.zhang

On 04/03, Qiming Yang wrote:
>This patch set added generic flow APIs and supported patterns includes:
>/* L2 */
>/* ARP */
>/* IPv4 */
>/* IPv6  */
>/* GTPU */
>/* ESP */
>/* AH */
>/* L2TPV3 */
>/* PFCP */
>
>---
>v2 changes:
> - fixed document error.
> - fixed multiple thread not safe issue.
> - use RTE_ASSERT to replace runtime check for engine->create == NULL.
>v3 changes:
> - add feature enable flag in iavf.ini
>
>Qiming Yang (2):
>  net/iavf: support generic flow
>  net/iavf: support more patterns
>
> doc/guides/nics/features/iavf.ini      |    1 +
> doc/guides/rel_notes/release_20_05.rst |    5 +
> drivers/net/iavf/Makefile              |    1 +
> drivers/net/iavf/iavf.h                |   10 +
> drivers/net/iavf/iavf_ethdev.c         |   46 ++
> drivers/net/iavf/iavf_generic_flow.c   | 1025 ++++++++++++++++++++++++++++++++
> drivers/net/iavf/iavf_generic_flow.h   |  318 ++++++++++
> drivers/net/iavf/meson.build           |    1 +
> 8 files changed, 1407 insertions(+)
> create mode 100644 drivers/net/iavf/iavf_generic_flow.c
> create mode 100644 drivers/net/iavf/iavf_generic_flow.h
>
>-- 
>2.9.5
>

Applied to dpdk-next-net-intel, Thanks.

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

end of thread, other threads:[~2020-04-09  5:06 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-17  8:17 [dpdk-dev] [PATCH 0/2] add generic filter support for iavf Qiming Yang
2020-03-17  8:17 ` [dpdk-dev] [PATCH 1/2] net/iavf: support generic flow Qiming Yang
2020-03-19  2:01   ` Zhang, Qi Z
2020-03-20  1:20     ` Yang, Qiming
2020-03-17  8:17 ` [dpdk-dev] [PATCH 2/2] net/iavf: support more patterns Qiming Yang
2020-03-30  8:30 ` [dpdk-dev] [PATCH v2 0/2] add generic filter support for iavf Qiming Yang
2020-03-30  8:30   ` [dpdk-dev] [PATCH v2 1/2] net/iavf: support generic flow Qiming Yang
2020-04-01  2:48     ` Zhang, Qi Z
2020-03-30  8:30   ` [dpdk-dev] [PATCH v2 2/2] net/iavf: support more patterns Qiming Yang
2020-04-03  5:42 ` [dpdk-dev] [PATCH v3 0/2] add generic filter support for iavf Qiming Yang
2020-04-03  5:42   ` [dpdk-dev] [PATCH v3 1/2] net/iavf: support generic flow Qiming Yang
2020-04-03  5:42   ` [dpdk-dev] [PATCH v3 2/2] net/iavf: support more patterns Qiming Yang
2020-04-03  6:03   ` [dpdk-dev] [PATCH v3 0/2] add generic filter support for iavf Zhang, Qi Z
2020-04-09  5:02   ` Ye Xiaolong

DPDK patches and discussions

This inbox may be cloned and mirrored by anyone:

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

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

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


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