All of lore.kernel.org
 help / color / mirror / Atom feed
From: Rosen Xu <rosen.xu@intel.com>
To: dev@dpdk.org
Cc: ferruh.yigit@intel.com, tianfei.zhang@intel.com,
	dan.wei@intel.com, rosen.xu@intel.com, andy.pei@intel.com,
	qiming.yang@intel.com, haiyue.wang@intel.com,
	santos.chen@intel.com, zhang.zhang@intel.com
Subject: [PATCH v2 06/15] drivers/net/ipn3ke: add IPN3KE Flow of PMD driver
Date: Fri, 29 Mar 2019 23:58:10 +0800	[thread overview]
Message-ID: <1553875099-166351-7-git-send-email-rosen.xu@intel.com> (raw)
In-Reply-To: <1553875099-166351-1-git-send-email-rosen.xu@intel.com>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 37859 bytes --]

Add Intel FPGA Acceleration NIC IPN3KE Flow of PMD driver.

Signed-off-by: Rosen Xu <rosen.xu@intel.com>
Signed-off-by: Andy Pei <andy.pei@intel.com>
Signed-off-by: Dan Wei <dan.wei@intel.com>
---
 drivers/net/ipn3ke/Makefile             |    1 +
 drivers/net/ipn3ke/ipn3ke_ethdev.c      |    5 +
 drivers/net/ipn3ke/ipn3ke_ethdev.h      |    1 +
 drivers/net/ipn3ke/ipn3ke_flow.c        | 1400 +++++++++++++++++++++++++++++++
 drivers/net/ipn3ke/ipn3ke_flow.h        |   86 ++
 drivers/net/ipn3ke/ipn3ke_representor.c |    3 +-
 drivers/net/ipn3ke/ipn3ke_tm.c          |    1 +
 drivers/net/ipn3ke/meson.build          |    3 +-
 8 files changed, 1498 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/ipn3ke/ipn3ke_flow.c
 create mode 100644 drivers/net/ipn3ke/ipn3ke_flow.h

diff --git a/drivers/net/ipn3ke/Makefile b/drivers/net/ipn3ke/Makefile
index 903ec39..aaffede 100644
--- a/drivers/net/ipn3ke/Makefile
+++ b/drivers/net/ipn3ke/Makefile
@@ -34,5 +34,6 @@ LIBABIVER := 1
 SRCS-$(CONFIG_RTE_LIBRTE_IPN3KE_PMD) += ipn3ke_ethdev.c
 SRCS-$(CONFIG_RTE_LIBRTE_IPN3KE_PMD) += ipn3ke_representor.c
 SRCS-$(CONFIG_RTE_LIBRTE_IPN3KE_PMD) += ipn3ke_tm.c
+SRCS-$(CONFIG_RTE_LIBRTE_IPN3KE_PMD) += ipn3ke_flow.c
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/net/ipn3ke/ipn3ke_ethdev.c b/drivers/net/ipn3ke/ipn3ke_ethdev.c
index 2b4bb4a..eb5d522 100644
--- a/drivers/net/ipn3ke/ipn3ke_ethdev.c
+++ b/drivers/net/ipn3ke/ipn3ke_ethdev.c
@@ -21,6 +21,7 @@
 #include <ifpga_logs.h>
 
 #include "ipn3ke_rawdev_api.h"
+#include "ipn3ke_flow.h"
 #include "ipn3ke_logs.h"
 #include "ipn3ke_ethdev.h"
 
@@ -332,6 +333,10 @@ static int ipn3ke_indirect_mac_write(struct ipn3ke_hw *hw,
 			return ret;
 		hw->tm_hw_enable = 1;
 
+		ret = ipn3ke_flow_init(hw);
+		if (ret)
+			return ret;
+		hw->flow_hw_enable = 1;
 	}
 
 	hw->acc_tm = 0;
diff --git a/drivers/net/ipn3ke/ipn3ke_ethdev.h b/drivers/net/ipn3ke/ipn3ke_ethdev.h
index f6344c9..0c49d39 100644
--- a/drivers/net/ipn3ke/ipn3ke_ethdev.h
+++ b/drivers/net/ipn3ke/ipn3ke_ethdev.h
@@ -303,6 +303,7 @@ struct ipn3ke_hw {
 	uint32_t acc_tm;
 	uint32_t acc_flow;
 
+	struct ipn3ke_flow_list flow_list;
 	uint32_t flow_max_entries;
 	uint32_t flow_num_entries;
 
diff --git a/drivers/net/ipn3ke/ipn3ke_flow.c b/drivers/net/ipn3ke/ipn3ke_flow.c
new file mode 100644
index 0000000..6795bcd
--- /dev/null
+++ b/drivers/net/ipn3ke/ipn3ke_flow.c
@@ -0,0 +1,1400 @@
+/* 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_io.h>
+#include <rte_debug.h>
+#include <rte_ether.h>
+#include <rte_ethdev_driver.h>
+#include <rte_log.h>
+#include <rte_malloc.h>
+#include <rte_eth_ctrl.h>
+#include <rte_tailq.h>
+
+#include "ipn3ke_rawdev_api.h"
+#include "ipn3ke_flow.h"
+#include "ipn3ke_logs.h"
+#include "ipn3ke_ethdev.h"
+
+/** Static initializer for items. */
+#define FLOW_PATTERNS(...) \
+	((const enum rte_flow_item_type []) { \
+		__VA_ARGS__, RTE_FLOW_ITEM_TYPE_END, \
+	})
+
+enum IPN3KE_HASH_KEY_TYPE {
+	IPN3KE_HASH_KEY_VXLAN,
+	IPN3KE_HASH_KEY_MAC,
+	IPN3KE_HASH_KEY_QINQ,
+	IPN3KE_HASH_KEY_MPLS,
+	IPN3KE_HASH_KEY_IP_TCP,
+	IPN3KE_HASH_KEY_IP_UDP,
+	IPN3KE_HASH_KEY_IP_NVGRE,
+	IPN3KE_HASH_KEY_VXLAN_IP_UDP,
+};
+
+struct ipn3ke_flow_parse {
+	uint32_t mark:1; /**< Set if the flow is marked. */
+	uint32_t drop:1; /**< ACL drop. */
+	uint32_t key_type:IPN3KE_FLOW_KEY_ID_BITS;
+	uint32_t mark_id:IPN3KE_FLOW_RESULT_UID_BITS; /**< Mark identifier. */
+	uint8_t key_len; /**< Length in bit. */
+	uint8_t key[BITS_TO_BYTES(IPN3KE_FLOW_KEY_DATA_BITS)];
+		/**< key1, key2 */
+};
+
+typedef int (*pattern_filter_t)(const struct rte_flow_item patterns[],
+					struct rte_flow_error *error,
+					struct ipn3ke_flow_parse *parser);
+
+
+struct ipn3ke_flow_pattern {
+	const enum rte_flow_item_type *const items;
+
+	pattern_filter_t filter;
+};
+
+/*
+ * @ RTL definition:
+ * typedef struct packed {
+ * logic [47:0]    vxlan_inner_mac;
+ * logic [23:0]    vxlan_vni;
+ * } Hash_Key_Vxlan_t;
+ *
+ * @ flow items:
+ * RTE_FLOW_ITEM_TYPE_VXLAN
+ * RTE_FLOW_ITEM_TYPE_ETH
+ */
+static int
+ipn3ke_pattern_vxlan(const struct rte_flow_item patterns[],
+		struct rte_flow_error *error,
+		struct ipn3ke_flow_parse *parser)
+{
+	const struct rte_flow_item_vxlan *vxlan = NULL;
+	const struct rte_flow_item_eth *eth = NULL;
+	const struct rte_flow_item *item;
+
+	for (item = patterns; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+		if (/*!item->spec || item->mask || */item->last) {
+			rte_flow_error_set(error,
+					EINVAL,
+					RTE_FLOW_ERROR_TYPE_ITEM,
+					item,
+					"Only support item with 'spec'");
+			return -rte_errno;
+		}
+
+		switch (item->type) {
+		case RTE_FLOW_ITEM_TYPE_ETH:
+			eth = item->spec;
+
+			rte_memcpy(&parser->key[0],
+					eth->src.addr_bytes,
+					ETHER_ADDR_LEN);
+			break;
+
+		case RTE_FLOW_ITEM_TYPE_VXLAN:
+			vxlan = item->spec;
+
+			rte_memcpy(&parser->key[6], vxlan->vni, 3);
+			break;
+
+		default:
+			rte_flow_error_set(error,
+					EINVAL,
+					RTE_FLOW_ERROR_TYPE_ITEM,
+					item,
+					"Not support item type");
+			return -rte_errno;
+		}
+	}
+
+	if (vxlan != NULL && eth != NULL) {
+		parser->key_len = 48 + 24;
+		return 0;
+	}
+
+	rte_flow_error_set(error,
+			EINVAL,
+			RTE_FLOW_ERROR_TYPE_ITEM,
+			patterns,
+			"Missed some patterns");
+	return -rte_errno;
+}
+
+/*
+ * @ RTL definition:
+ * typedef struct packed {
+ * logic [47:0]    eth_smac;
+ * } Hash_Key_Mac_t;
+ *
+ * @ flow items:
+ * RTE_FLOW_ITEM_TYPE_ETH
+ */
+static int
+ipn3ke_pattern_mac(const struct rte_flow_item patterns[],
+		 struct rte_flow_error *error,
+		 struct ipn3ke_flow_parse *parser)
+{
+	const struct rte_flow_item_eth *eth = NULL;
+	const struct rte_flow_item *item;
+
+	for (item = patterns; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+		if (!item->spec || item->mask || item->last) {
+			rte_flow_error_set(error,
+					EINVAL,
+					RTE_FLOW_ERROR_TYPE_ITEM,
+					item,
+					"Only support item with 'spec'");
+			return -rte_errno;
+		}
+
+		switch (item->type) {
+		case RTE_FLOW_ITEM_TYPE_ETH:
+			eth = item->spec;
+
+			rte_memcpy(parser->key,
+					eth->src.addr_bytes,
+					ETHER_ADDR_LEN);
+			break;
+
+		default:
+			rte_flow_error_set(error,
+					EINVAL,
+					RTE_FLOW_ERROR_TYPE_ITEM,
+					item,
+					"Not support item type");
+			return -rte_errno;
+		}
+	}
+
+	if (eth != NULL) {
+		parser->key_len = 48;
+		return 0;
+	}
+
+	rte_flow_error_set(error,
+			EINVAL,
+			RTE_FLOW_ERROR_TYPE_ITEM,
+			patterns,
+			"Missed some patterns");
+	return -rte_errno;
+}
+
+/*
+ * @ RTL definition:
+ * typedef struct packed {
+ * logic [11:0]    outer_vlan_id;
+ * logic [11:0]    inner_vlan_id;
+ * } Hash_Key_QinQ_t;
+ *
+ * @ flow items:
+ * RTE_FLOW_ITEM_TYPE_VLAN
+ * RTE_FLOW_ITEM_TYPE_VLAN
+ */
+static int
+ipn3ke_pattern_qinq(const struct rte_flow_item patterns[],
+		struct rte_flow_error *error,
+		struct ipn3ke_flow_parse *parser)
+{
+	const struct rte_flow_item_vlan *outer_vlan = NULL;
+	const struct rte_flow_item_vlan *inner_vlan = NULL;
+	const struct rte_flow_item *item;
+	uint16_t tci;
+
+	for (item = patterns; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+		if (!item->spec || item->mask || item->last) {
+			rte_flow_error_set(error,
+					EINVAL,
+					RTE_FLOW_ERROR_TYPE_ITEM,
+					item,
+					"Only support item with 'spec'");
+			return -rte_errno;
+		}
+
+		switch (item->type) {
+		case RTE_FLOW_ITEM_TYPE_VLAN:
+			if (!outer_vlan) {
+				outer_vlan = item->spec;
+
+				tci = rte_be_to_cpu_16(outer_vlan->tci);
+				parser->key[0]  = (tci & 0xff0) >> 4;
+				parser->key[1] |= (tci & 0x00f) << 4;
+			} else {
+				inner_vlan = item->spec;
+
+				tci = rte_be_to_cpu_16(inner_vlan->tci);
+				parser->key[1] |= (tci & 0xf00) >> 8;
+				parser->key[2]  = (tci & 0x0ff);
+			}
+			break;
+
+		default:
+			rte_flow_error_set(error,
+					EINVAL,
+					RTE_FLOW_ERROR_TYPE_ITEM,
+					item,
+					"Not support item type");
+			return -rte_errno;
+		}
+	}
+
+	if (outer_vlan != NULL && inner_vlan != NULL) {
+		parser->key_len = 12 + 12;
+		return 0;
+	}
+
+	rte_flow_error_set(error,
+			EINVAL,
+			RTE_FLOW_ERROR_TYPE_ITEM,
+			patterns,
+			"Missed some patterns");
+	return -rte_errno;
+}
+
+/*
+ * @ RTL definition:
+ * typedef struct packed {
+ * logic [19:0]    mpls_label1;
+ * logic [19:0]    mpls_label2;
+ * } Hash_Key_Mpls_t;
+ *
+ * @ flow items:
+ * RTE_FLOW_ITEM_TYPE_MPLS
+ * RTE_FLOW_ITEM_TYPE_MPLS
+ */
+static int
+ipn3ke_pattern_mpls(const struct rte_flow_item patterns[],
+		struct rte_flow_error *error,
+		struct ipn3ke_flow_parse *parser)
+{
+	const struct rte_flow_item_mpls *mpls1 = NULL;
+	const struct rte_flow_item_mpls *mpls2 = NULL;
+	const struct rte_flow_item *item;
+
+	for (item = patterns; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+		if (!item->spec || item->mask || item->last) {
+			rte_flow_error_set(error,
+					EINVAL,
+					RTE_FLOW_ERROR_TYPE_ITEM,
+					item,
+					"Only support item with 'spec'");
+			return -rte_errno;
+		}
+
+		switch (item->type) {
+		case RTE_FLOW_ITEM_TYPE_MPLS:
+			if (!mpls1) {
+				mpls1 = item->spec;
+
+				parser->key[0] = mpls1->label_tc_s[0];
+				parser->key[1] = mpls1->label_tc_s[1];
+				parser->key[2] = mpls1->label_tc_s[2] & 0xf0;
+			} else {
+				mpls2 = item->spec;
+
+				parser->key[2] |=
+					((mpls2->label_tc_s[0] & 0xf0) >> 4);
+				parser->key[3] =
+					((mpls2->label_tc_s[0] & 0xf) << 4) |
+					((mpls2->label_tc_s[1] & 0xf0) >> 4);
+				parser->key[4] =
+					((mpls2->label_tc_s[1] & 0xf) << 4) |
+					((mpls2->label_tc_s[2] & 0xf0) >> 4);
+			}
+			break;
+
+		default:
+			rte_flow_error_set(error,
+					EINVAL,
+					RTE_FLOW_ERROR_TYPE_ITEM,
+					item,
+					"Not support item type");
+			return -rte_errno;
+		}
+	}
+
+	if (mpls1 != NULL && mpls2 != NULL) {
+		parser->key_len = 20 + 20;
+		return 0;
+	}
+
+	rte_flow_error_set(error,
+			EINVAL,
+			RTE_FLOW_ERROR_TYPE_ITEM,
+			patterns,
+			"Missed some patterns");
+	return -rte_errno;
+}
+
+/*
+ * @ RTL definition:
+ * typedef struct packed {
+ * logic [31:0]    ip_sa;
+ * logic [15:0]    tcp_sport;
+ * } Hash_Key_Ip_Tcp_t;
+ *
+ * @ flow items:
+ * RTE_FLOW_ITEM_TYPE_IPV4
+ * RTE_FLOW_ITEM_TYPE_TCP
+ */
+static int
+ipn3ke_pattern_ip_tcp(const struct rte_flow_item patterns[],
+		struct rte_flow_error *error,
+		struct ipn3ke_flow_parse *parser)
+{
+	const struct rte_flow_item_ipv4 *ipv4 = NULL;
+	const struct rte_flow_item_tcp *tcp = NULL;
+	const struct rte_flow_item *item;
+
+	for (item = patterns; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+		if (!item->spec || item->mask || item->last) {
+			rte_flow_error_set(error,
+					EINVAL,
+					RTE_FLOW_ERROR_TYPE_ITEM,
+					item,
+					"Only support item with 'spec'");
+			return -rte_errno;
+		}
+
+		switch (item->type) {
+		case RTE_FLOW_ITEM_TYPE_IPV4:
+			ipv4 = item->spec;
+
+			rte_memcpy(&parser->key[0], &ipv4->hdr.src_addr, 4);
+			break;
+
+		case RTE_FLOW_ITEM_TYPE_TCP:
+			tcp = item->spec;
+
+			rte_memcpy(&parser->key[4], &tcp->hdr.src_port, 2);
+			break;
+
+		default:
+			rte_flow_error_set(error,
+					EINVAL,
+					RTE_FLOW_ERROR_TYPE_ITEM,
+					item,
+					"Not support item type");
+			return -rte_errno;
+		}
+	}
+
+	if (ipv4 != NULL && tcp != NULL) {
+		parser->key_len = 32 + 16;
+		return 0;
+	}
+
+	rte_flow_error_set(error,
+			EINVAL,
+			RTE_FLOW_ERROR_TYPE_ITEM,
+			patterns,
+			"Missed some patterns");
+	return -rte_errno;
+}
+
+/*
+ * @ RTL definition:
+ * typedef struct packed {
+ * logic [31:0]    ip_sa;
+ * logic [15:0]    udp_sport;
+ * } Hash_Key_Ip_Udp_t;
+ *
+ * @ flow items:
+ * RTE_FLOW_ITEM_TYPE_IPV4
+ * RTE_FLOW_ITEM_TYPE_UDP
+ */
+static int
+ipn3ke_pattern_ip_udp(const struct rte_flow_item patterns[],
+		struct rte_flow_error *error,
+		struct ipn3ke_flow_parse *parser)
+{
+	const struct rte_flow_item_ipv4 *ipv4 = NULL;
+	const struct rte_flow_item_udp *udp = NULL;
+	const struct rte_flow_item *item;
+
+	for (item = patterns; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+		if (!item->spec || item->mask || item->last) {
+			rte_flow_error_set(error,
+					EINVAL,
+					RTE_FLOW_ERROR_TYPE_ITEM,
+					item,
+					"Only support item with 'spec'");
+			return -rte_errno;
+		}
+
+		switch (item->type) {
+		case RTE_FLOW_ITEM_TYPE_IPV4:
+			ipv4 = item->spec;
+
+			rte_memcpy(&parser->key[0], &ipv4->hdr.src_addr, 4);
+			break;
+
+		case RTE_FLOW_ITEM_TYPE_UDP:
+			udp = item->spec;
+
+			rte_memcpy(&parser->key[4], &udp->hdr.src_port, 2);
+			break;
+
+		default:
+			rte_flow_error_set(error,
+					EINVAL,
+					RTE_FLOW_ERROR_TYPE_ITEM,
+					item,
+					"Not support item type");
+			return -rte_errno;
+		}
+	}
+
+	if (ipv4 != NULL && udp != NULL) {
+		parser->key_len = 32 + 16;
+		return 0;
+	}
+
+	rte_flow_error_set(error,
+			EINVAL,
+			RTE_FLOW_ERROR_TYPE_ITEM,
+			patterns,
+			"Missed some patterns");
+	return -rte_errno;
+}
+
+/*
+ * @ RTL definition:
+ * typedef struct packed {
+ * logic [31:0]    ip_sa;
+ * logic [15:0]    udp_sport;
+ * logic [23:0]    vsid;
+ * } Hash_Key_Ip_Nvgre_t;
+ *
+ * @ flow items:
+ * RTE_FLOW_ITEM_TYPE_IPV4
+ * RTE_FLOW_ITEM_TYPE_UDP
+ * RTE_FLOW_ITEM_TYPE_NVGRE
+ */
+static int
+ipn3ke_pattern_ip_nvgre(const struct rte_flow_item patterns[],
+		struct rte_flow_error *error,
+		struct ipn3ke_flow_parse *parser)
+{
+	const struct rte_flow_item_nvgre *nvgre = NULL;
+	const struct rte_flow_item_ipv4 *ipv4 = NULL;
+	const struct rte_flow_item_udp *udp = NULL;
+	const struct rte_flow_item *item;
+
+	for (item = patterns; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+		if (!item->spec || item->mask || item->last) {
+			rte_flow_error_set(error,
+					EINVAL,
+					RTE_FLOW_ERROR_TYPE_ITEM,
+					item,
+					"Only support item with 'spec'");
+			return -rte_errno;
+		}
+
+		switch (item->type) {
+		case RTE_FLOW_ITEM_TYPE_IPV4:
+			ipv4 = item->spec;
+
+			rte_memcpy(&parser->key[0], &ipv4->hdr.src_addr, 4);
+			break;
+
+		case RTE_FLOW_ITEM_TYPE_UDP:
+			udp = item->spec;
+
+			rte_memcpy(&parser->key[4], &udp->hdr.src_port, 2);
+			break;
+
+		case RTE_FLOW_ITEM_TYPE_NVGRE:
+			nvgre = item->spec;
+
+			rte_memcpy(&parser->key[6], nvgre->tni, 3);
+			break;
+
+		default:
+			rte_flow_error_set(error,
+					EINVAL,
+					RTE_FLOW_ERROR_TYPE_ITEM,
+					item,
+					"Not support item type");
+			return -rte_errno;
+		}
+	}
+
+	if (ipv4 != NULL && udp != NULL && nvgre != NULL) {
+		parser->key_len = 32 + 16 + 24;
+		return 0;
+	}
+
+	rte_flow_error_set(error,
+			EINVAL,
+			RTE_FLOW_ERROR_TYPE_ITEM,
+			patterns,
+			"Missed some patterns");
+	return -rte_errno;
+}
+
+/*
+ * @ RTL definition:
+ * typedef struct packed{
+ * logic [23:0]    vxlan_vni;
+ * logic [31:0]    ip_sa;
+ * logic [15:0]    udp_sport;
+ * } Hash_Key_Vxlan_Ip_Udp_t;
+ *
+ * @ flow items:
+ * RTE_FLOW_ITEM_TYPE_VXLAN
+ * RTE_FLOW_ITEM_TYPE_IPV4
+ * RTE_FLOW_ITEM_TYPE_UDP
+ */
+static int
+ipn3ke_pattern_vxlan_ip_udp(const struct rte_flow_item patterns[],
+				struct rte_flow_error *error,
+				struct ipn3ke_flow_parse *parser)
+{
+	const struct rte_flow_item_vxlan *vxlan = NULL;
+	const struct rte_flow_item_ipv4 *ipv4 = NULL;
+	const struct rte_flow_item_udp *udp = NULL;
+	const struct rte_flow_item *item;
+
+	for (item = patterns; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+		if (!item->spec || item->mask || item->last) {
+			rte_flow_error_set(error,
+					EINVAL,
+					RTE_FLOW_ERROR_TYPE_ITEM,
+					item,
+					"Only support item with 'spec'");
+			return -rte_errno;
+		}
+
+		switch (item->type) {
+		case RTE_FLOW_ITEM_TYPE_VXLAN:
+			vxlan = item->spec;
+
+			rte_memcpy(&parser->key[0], vxlan->vni, 3);
+			break;
+
+		case RTE_FLOW_ITEM_TYPE_IPV4:
+			ipv4 = item->spec;
+
+			rte_memcpy(&parser->key[3], &ipv4->hdr.src_addr, 4);
+			break;
+
+		case RTE_FLOW_ITEM_TYPE_UDP:
+			udp = item->spec;
+
+			rte_memcpy(&parser->key[7], &udp->hdr.src_port, 2);
+			break;
+
+		default:
+			rte_flow_error_set(error,
+					EINVAL,
+					RTE_FLOW_ERROR_TYPE_ITEM,
+					item,
+					"Not support item type");
+			return -rte_errno;
+		}
+	}
+
+	if (vxlan != NULL && ipv4 != NULL && udp != NULL) {
+		parser->key_len = 24 + 32 + 16;
+		return 0;
+	}
+
+	rte_flow_error_set(error,
+			EINVAL,
+			RTE_FLOW_ERROR_TYPE_ITEM,
+			patterns,
+			"Missed some patterns");
+	return -rte_errno;
+}
+
+static const struct ipn3ke_flow_pattern ipn3ke_supported_patterns[] = {
+	[IPN3KE_HASH_KEY_VXLAN] = {
+		.items = FLOW_PATTERNS(RTE_FLOW_ITEM_TYPE_VXLAN,
+					RTE_FLOW_ITEM_TYPE_ETH),
+		.filter = ipn3ke_pattern_vxlan,
+	},
+
+	[IPN3KE_HASH_KEY_MAC] = {
+		.items = FLOW_PATTERNS(RTE_FLOW_ITEM_TYPE_ETH),
+		.filter = ipn3ke_pattern_mac,
+	},
+
+	[IPN3KE_HASH_KEY_QINQ] = {
+		.items = FLOW_PATTERNS(RTE_FLOW_ITEM_TYPE_VLAN,
+					RTE_FLOW_ITEM_TYPE_VLAN),
+		.filter = ipn3ke_pattern_qinq,
+	},
+
+	[IPN3KE_HASH_KEY_MPLS] = {
+		.items = FLOW_PATTERNS(RTE_FLOW_ITEM_TYPE_MPLS,
+					RTE_FLOW_ITEM_TYPE_MPLS),
+		.filter = ipn3ke_pattern_mpls,
+	},
+
+	[IPN3KE_HASH_KEY_IP_TCP] = {
+		.items = FLOW_PATTERNS(RTE_FLOW_ITEM_TYPE_IPV4,
+					RTE_FLOW_ITEM_TYPE_TCP),
+		.filter = ipn3ke_pattern_ip_tcp,
+	},
+
+	[IPN3KE_HASH_KEY_IP_UDP] = {
+		.items = FLOW_PATTERNS(RTE_FLOW_ITEM_TYPE_IPV4,
+					RTE_FLOW_ITEM_TYPE_UDP),
+		.filter = ipn3ke_pattern_ip_udp,
+	},
+
+	[IPN3KE_HASH_KEY_IP_NVGRE] = {
+		.items = FLOW_PATTERNS(RTE_FLOW_ITEM_TYPE_IPV4,
+					RTE_FLOW_ITEM_TYPE_UDP,
+					RTE_FLOW_ITEM_TYPE_NVGRE),
+		.filter = ipn3ke_pattern_ip_nvgre,
+	},
+
+	[IPN3KE_HASH_KEY_VXLAN_IP_UDP] = {
+		.items = FLOW_PATTERNS(RTE_FLOW_ITEM_TYPE_VXLAN,
+					RTE_FLOW_ITEM_TYPE_IPV4,
+					RTE_FLOW_ITEM_TYPE_UDP),
+		.filter = ipn3ke_pattern_vxlan_ip_udp,
+	},
+};
+
+static int
+ipn3ke_flow_convert_attributes(const struct rte_flow_attr *attr,
+				struct rte_flow_error *error)
+{
+	if (!attr) {
+		rte_flow_error_set(error,
+				EINVAL,
+				RTE_FLOW_ERROR_TYPE_ATTR,
+				NULL,
+				"NULL attribute.");
+		return -rte_errno;
+	}
+
+	if (attr->group) {
+		rte_flow_error_set(error,
+				ENOTSUP,
+				RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
+				NULL,
+				"groups are not supported");
+		return -rte_errno;
+	}
+
+	if (attr->egress) {
+		rte_flow_error_set(error,
+				ENOTSUP,
+				RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
+				NULL,
+				"egress is not supported");
+		return -rte_errno;
+	}
+
+	if (attr->transfer) {
+		rte_flow_error_set(error,
+				ENOTSUP,
+				RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER,
+				NULL,
+				"transfer is not supported");
+		return -rte_errno;
+	}
+
+	if (!attr->ingress) {
+		rte_flow_error_set(error,
+				ENOTSUP,
+				RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
+				NULL,
+				"only ingress is supported");
+		return -rte_errno;
+	}
+
+	return 0;
+}
+
+static int
+ipn3ke_flow_convert_actions(const struct rte_flow_action actions[],
+				struct rte_flow_error *error,
+				struct ipn3ke_flow_parse *parser)
+{
+	const struct rte_flow_action_mark *mark = NULL;
+
+	if (!actions) {
+		rte_flow_error_set(error,
+				EINVAL,
+				RTE_FLOW_ERROR_TYPE_ACTION_NUM,
+				NULL,
+				"NULL action.");
+		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_MARK:
+			if (mark) {
+				rte_flow_error_set(error,
+						ENOTSUP,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						actions,
+						"duplicated mark");
+				return -rte_errno;
+			}
+
+			mark = actions->conf;
+			if (!mark) {
+				rte_flow_error_set(error,
+						EINVAL,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						actions,
+						"mark must be defined");
+				return -rte_errno;
+			} else if (mark->id > IPN3KE_FLOW_RESULT_UID_MAX) {
+				rte_flow_error_set(error,
+						ENOTSUP,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						actions,
+						"mark id is out of range");
+				return -rte_errno;
+			}
+
+			parser->mark = 1;
+			parser->mark_id = mark->id;
+			break;
+
+		case RTE_FLOW_ACTION_TYPE_DROP:
+			parser->drop = 1;
+			break;
+
+		default:
+			rte_flow_error_set(error,
+					ENOTSUP,
+					RTE_FLOW_ERROR_TYPE_ACTION,
+					actions,
+					"invalid action");
+			return -rte_errno;
+		}
+	}
+
+	if (!parser->drop && !parser->mark) {
+		rte_flow_error_set(error,
+				EINVAL,
+				RTE_FLOW_ERROR_TYPE_ACTION,
+				actions,
+				"no valid actions");
+		return -rte_errno;
+	}
+
+	return 0;
+}
+
+static bool
+ipn3ke_match_pattern(const enum rte_flow_item_type *patterns,
+				const struct rte_flow_item *input)
+{
+	const struct rte_flow_item *item = input;
+
+	while ((*patterns == item->type) &&
+		(*patterns != RTE_FLOW_ITEM_TYPE_END)) {
+		patterns++;
+		item++;
+	}
+
+	return (*patterns == RTE_FLOW_ITEM_TYPE_END &&
+		item->type == RTE_FLOW_ITEM_TYPE_END);
+}
+
+static pattern_filter_t
+ipn3ke_find_filter_func(const struct rte_flow_item *input,
+				uint32_t *idx)
+{
+	pattern_filter_t filter = NULL;
+	uint32_t i;
+
+	for (i = 0; i < RTE_DIM(ipn3ke_supported_patterns); i++) {
+		if (ipn3ke_match_pattern(ipn3ke_supported_patterns[i].items,
+					input)) {
+			filter = ipn3ke_supported_patterns[i].filter;
+			*idx = i;
+			break;
+		}
+	}
+
+	return filter;
+}
+
+static int
+ipn3ke_flow_convert_items(const struct rte_flow_item items[],
+			struct rte_flow_error *error,
+			struct ipn3ke_flow_parse *parser)
+{
+	pattern_filter_t filter = NULL;
+	uint32_t idx;
+
+	if (!items) {
+		rte_flow_error_set(error,
+				EINVAL,
+				RTE_FLOW_ERROR_TYPE_ITEM_NUM,
+				NULL,
+				"NULL pattern.");
+		return -rte_errno;
+	}
+
+	filter = ipn3ke_find_filter_func(items, &idx);
+
+	if (!filter) {
+		rte_flow_error_set(error,
+				EINVAL,
+				RTE_FLOW_ERROR_TYPE_ITEM,
+				items,
+				"Unsupported pattern");
+		return -rte_errno;
+	}
+
+	parser->key_type = idx;
+
+	return filter(items, error, parser);
+}
+
+/* Put the least @nbits of @data into @offset of @dst bits stream, and
+ * the @offset starts from MSB to LSB in each byte.
+ *
+ * MSB    LSB
+ *  +------+------+------+------+
+ *  |      |      |      |      |
+ *  +------+------+------+------+
+ *       ^                 ^
+ *       |<- data: nbits ->|
+ *       |
+ *     offset
+ */
+static void
+copy_data_bits(uint8_t *dst, uint64_t data,
+		uint32_t offset, uint8_t nbits)
+{
+	uint8_t set, *p = &dst[offset / BITS_PER_BYTE];
+	uint8_t bits_to_set = BITS_PER_BYTE - (offset % BITS_PER_BYTE);
+	uint8_t mask_to_set = 0xff >> (offset % BITS_PER_BYTE);
+	uint32_t size = offset + nbits;
+
+	if (nbits > (sizeof(data) * BITS_PER_BYTE)) {
+		IPN3KE_AFU_PMD_ERR("nbits is out of range");
+		return;
+	}
+
+	while (nbits - bits_to_set >= 0) {
+		set = data >> (nbits - bits_to_set);
+
+		*p &= ~mask_to_set;
+		*p |= (set & mask_to_set);
+
+		nbits -= bits_to_set;
+		bits_to_set = BITS_PER_BYTE;
+		mask_to_set = 0xff;
+		p++;
+	}
+
+	if (nbits) {
+		uint8_t shift = BITS_PER_BYTE - (size % BITS_PER_BYTE);
+
+		set = data << shift;
+		mask_to_set = 0xff << shift;
+
+		*p &= ~mask_to_set;
+		*p |= (set & mask_to_set);
+	}
+}
+
+static void
+ipn3ke_flow_key_generation(struct ipn3ke_flow_parse *parser,
+				struct rte_flow *flow)
+{
+	uint32_t i, shift_bytes, len_in_bytes, offset;
+	uint64_t key;
+	uint8_t *dst;
+
+	dst = flow->rule.key;
+
+	copy_data_bits(dst,
+			parser->key_type,
+			IPN3KE_FLOW_KEY_ID_OFFSET,
+			IPN3KE_FLOW_KEY_ID_BITS);
+
+	/* The MSb of key is filled to 0 when it is less than
+	 * IPN3KE_FLOW_KEY_DATA_BITS bit. And the parsed key data is
+	 * save as MSB byte first in the array, it needs to move
+	 * the bits before formatting them.
+	 */
+	key = 0;
+	shift_bytes = 0;
+	len_in_bytes = BITS_TO_BYTES(parser->key_len);
+	offset = (IPN3KE_FLOW_KEY_DATA_OFFSET +
+		IPN3KE_FLOW_KEY_DATA_BITS -
+		parser->key_len);
+
+	for (i = 0; i < len_in_bytes; i++) {
+		key = (key << 8) | parser->key[i];
+
+		if (++shift_bytes == sizeof(key)) {
+			shift_bytes = 0;
+
+			copy_data_bits(dst, key, offset,
+					sizeof(key) * BITS_PER_BYTE);
+			offset += sizeof(key) * BITS_PER_BYTE;
+			key = 0;
+		}
+	}
+
+	if (shift_bytes != 0) {
+		uint32_t rem_bits;
+
+		rem_bits = parser->key_len % (sizeof(key) * BITS_PER_BYTE);
+		key >>= (shift_bytes * 8 - rem_bits);
+		copy_data_bits(dst, key, offset, rem_bits);
+	}
+}
+
+static void
+ipn3ke_flow_result_generation(struct ipn3ke_flow_parse *parser,
+				struct rte_flow *flow)
+{
+	uint8_t *dst;
+
+	if (parser->drop)
+		return;
+
+	dst = flow->rule.result;
+
+	copy_data_bits(dst,
+			1,
+			IPN3KE_FLOW_RESULT_ACL_OFFSET,
+			IPN3KE_FLOW_RESULT_ACL_BITS);
+
+	copy_data_bits(dst,
+			parser->mark_id,
+			IPN3KE_FLOW_RESULT_UID_OFFSET,
+			IPN3KE_FLOW_RESULT_UID_BITS);
+}
+
+#define	__SWAP16(_x)				\
+	((((_x) & 0xff) << 8) |			\
+	(((_x) >> 8) & 0xff))
+
+#define	__SWAP32(_x)				\
+	((__SWAP16((_x) & 0xffff) << 16) |	\
+	__SWAP16(((_x) >> 16) & 0xffff))
+
+#define MHL_COMMAND_TIME_COUNT        0xFFFF
+#define MHL_COMMAND_TIME_INTERVAL_US  10
+
+static int
+ipn3ke_flow_hw_update(struct ipn3ke_hw *hw,
+			struct rte_flow *flow, uint32_t is_add)
+{
+	uint32_t *pdata = NULL;
+	uint32_t data;
+	uint32_t time_out = MHL_COMMAND_TIME_COUNT;
+	uint32_t i;
+
+	IPN3KE_AFU_PMD_DEBUG("IPN3KE flow dump start\n");
+
+	pdata = (uint32_t *)flow->rule.key;
+	IPN3KE_AFU_PMD_DEBUG(" - key   :");
+
+	for (i = 0; i < RTE_DIM(flow->rule.key); i++)
+		IPN3KE_AFU_PMD_DEBUG(" %02x", flow->rule.key[i]);
+
+	for (i = 0; i < 4; i++)
+		IPN3KE_AFU_PMD_DEBUG(" %02x", __SWAP32(pdata[3 - i]));
+	IPN3KE_AFU_PMD_DEBUG("\n");
+
+	pdata = (uint32_t *)flow->rule.result;
+	IPN3KE_AFU_PMD_DEBUG(" - result:");
+
+	for (i = 0; i < RTE_DIM(flow->rule.result); i++)
+		IPN3KE_AFU_PMD_DEBUG(" %02x", flow->rule.result[i]);
+
+	for (i = 0; i < 1; i++)
+		IPN3KE_AFU_PMD_DEBUG(" %02x", pdata[i]);
+	IPN3KE_AFU_PMD_DEBUG("IPN3KE flow dump end\n");
+
+	pdata = (uint32_t *)flow->rule.key;
+
+	IPN3KE_MASK_WRITE_REG(hw,
+			IPN3KE_CLF_MHL_KEY_0,
+			0,
+			__SWAP32(pdata[3]),
+			IPN3KE_CLF_MHL_KEY_MASK);
+
+	IPN3KE_MASK_WRITE_REG(hw,
+			IPN3KE_CLF_MHL_KEY_1,
+			0,
+			__SWAP32(pdata[2]),
+			IPN3KE_CLF_MHL_KEY_MASK);
+
+	IPN3KE_MASK_WRITE_REG(hw,
+			IPN3KE_CLF_MHL_KEY_2,
+			0,
+			__SWAP32(pdata[1]),
+			IPN3KE_CLF_MHL_KEY_MASK);
+
+	IPN3KE_MASK_WRITE_REG(hw,
+			IPN3KE_CLF_MHL_KEY_3,
+			0,
+			__SWAP32(pdata[0]),
+			IPN3KE_CLF_MHL_KEY_MASK);
+
+	pdata = (uint32_t *)flow->rule.result;
+	IPN3KE_MASK_WRITE_REG(hw,
+			IPN3KE_CLF_MHL_RES,
+			0,
+			__SWAP32(pdata[0]),
+			IPN3KE_CLF_MHL_RES_MASK);
+
+	/* insert/delete the key and result */
+	data = 0;
+	data = IPN3KE_MASK_READ_REG(hw,
+				IPN3KE_CLF_MHL_MGMT_CTRL,
+				0,
+				0x80000000);
+	time_out = MHL_COMMAND_TIME_COUNT;
+	while (IPN3KE_BIT_ISSET(data, IPN3KE_CLF_MHL_MGMT_CTRL_BIT_BUSY) &&
+		(time_out > 0)) {
+		data = IPN3KE_MASK_READ_REG(hw,
+					IPN3KE_CLF_MHL_MGMT_CTRL,
+					0,
+					0x80000000);
+		time_out--;
+		rte_delay_us(MHL_COMMAND_TIME_INTERVAL_US);
+	}
+	if (!time_out)
+		return -1;
+	if (is_add)
+		IPN3KE_MASK_WRITE_REG(hw,
+				IPN3KE_CLF_MHL_MGMT_CTRL,
+				0,
+				IPN3KE_CLF_MHL_MGMT_CTRL_INSERT,
+				0x3);
+	else
+		IPN3KE_MASK_WRITE_REG(hw,
+				IPN3KE_CLF_MHL_MGMT_CTRL,
+				0,
+				IPN3KE_CLF_MHL_MGMT_CTRL_DELETE,
+				0x3);
+
+	return 0;
+}
+
+static int
+ipn3ke_flow_hw_flush(struct ipn3ke_hw *hw)
+{
+	uint32_t data;
+	uint32_t time_out = MHL_COMMAND_TIME_COUNT;
+
+	/* flush the MHL lookup table */
+	data = 0;
+	data = IPN3KE_MASK_READ_REG(hw,
+				IPN3KE_CLF_MHL_MGMT_CTRL,
+				0,
+				0x80000000);
+	time_out = MHL_COMMAND_TIME_COUNT;
+	while (IPN3KE_BIT_ISSET(data, IPN3KE_CLF_MHL_MGMT_CTRL_BIT_BUSY) &&
+		(time_out > 0)) {
+		data = IPN3KE_MASK_READ_REG(hw,
+					IPN3KE_CLF_MHL_MGMT_CTRL,
+					0,
+					0x80000000);
+		time_out--;
+		rte_delay_us(MHL_COMMAND_TIME_INTERVAL_US);
+	}
+	if (!time_out)
+		return -1;
+	IPN3KE_MASK_WRITE_REG(hw,
+			IPN3KE_CLF_MHL_MGMT_CTRL,
+			0,
+			IPN3KE_CLF_MHL_MGMT_CTRL_FLUSH,
+			0x3);
+
+	return 0;
+}
+
+static void
+ipn3ke_flow_convert_finalise(struct ipn3ke_hw *hw,
+				struct ipn3ke_flow_parse *parser,
+				struct rte_flow *flow)
+{
+	ipn3ke_flow_key_generation(parser, flow);
+	ipn3ke_flow_result_generation(parser, flow);
+	ipn3ke_flow_hw_update(hw, flow, 1);
+}
+
+static int
+ipn3ke_flow_convert(const struct rte_flow_attr *attr,
+		const struct rte_flow_item items[],
+		const struct rte_flow_action actions[],
+		struct rte_flow_error *error,
+		struct ipn3ke_flow_parse *parser)
+{
+	int ret;
+
+	ret = ipn3ke_flow_convert_attributes(attr, error);
+	if (ret)
+		return ret;
+
+	ret = ipn3ke_flow_convert_actions(actions, error, parser);
+	if (ret)
+		return ret;
+
+	ret = ipn3ke_flow_convert_items(items, error, parser);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int
+ipn3ke_flow_validate(__rte_unused 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 ipn3ke_flow_parse parser = {0};
+	return ipn3ke_flow_convert(attr, pattern, actions, error, &parser);
+}
+
+static struct rte_flow *
+ipn3ke_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 ipn3ke_hw *hw = IPN3KE_DEV_PRIVATE_TO_HW(dev);
+	struct ipn3ke_flow_parse parser = {0};
+	struct rte_flow *flow;
+	int ret;
+
+	if (hw->flow_num_entries == hw->flow_max_entries) {
+		rte_flow_error_set(error,
+				ENOBUFS,
+				RTE_FLOW_ERROR_TYPE_HANDLE,
+				NULL,
+				"The flow table is full.");
+		return NULL;
+	}
+
+	ret = ipn3ke_flow_convert(attr, pattern, actions, error, &parser);
+	if (ret < 0) {
+		rte_flow_error_set(error,
+				-ret,
+				RTE_FLOW_ERROR_TYPE_HANDLE,
+				NULL,
+				"Failed to create flow.");
+		return NULL;
+	}
+
+	flow = rte_zmalloc("ipn3ke_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;
+	}
+
+	ipn3ke_flow_convert_finalise(hw, &parser, flow);
+
+	TAILQ_INSERT_TAIL(&hw->flow_list, flow, next);
+
+	return flow;
+}
+
+static int
+ipn3ke_flow_destroy(struct rte_eth_dev *dev,
+		struct rte_flow *flow,
+		struct rte_flow_error *error)
+{
+	struct ipn3ke_hw *hw = IPN3KE_DEV_PRIVATE_TO_HW(dev);
+	int ret = 0;
+
+	ret = ipn3ke_flow_hw_update(hw, flow, 0);
+	if (!ret) {
+		TAILQ_REMOVE(&hw->flow_list, flow, next);
+		rte_free(flow);
+	} else {
+		rte_flow_error_set(error,
+				-ret,
+				RTE_FLOW_ERROR_TYPE_HANDLE,
+				NULL,
+				"Failed to destroy flow.");
+	}
+
+	return ret;
+}
+
+static int
+ipn3ke_flow_flush(struct rte_eth_dev *dev,
+		__rte_unused struct rte_flow_error *error)
+{
+	struct ipn3ke_hw *hw = IPN3KE_DEV_PRIVATE_TO_HW(dev);
+	struct rte_flow *flow, *temp;
+
+	TAILQ_FOREACH_SAFE(flow, &hw->flow_list, next, temp) {
+		TAILQ_REMOVE(&hw->flow_list, flow, next);
+		rte_free(flow);
+	}
+
+	return ipn3ke_flow_hw_flush(hw);
+}
+
+int ipn3ke_flow_init(void *dev)
+{
+	struct ipn3ke_hw *hw = (struct ipn3ke_hw *)dev;
+	uint32_t data;
+
+	/* disable rx classifier bypass */
+	IPN3KE_MASK_WRITE_REG(hw,
+			IPN3KE_CLF_RX_TEST,
+			0, 0, 0x1);
+
+	data = 0;
+	data = IPN3KE_MASK_READ_REG(hw,
+				IPN3KE_CLF_RX_TEST,
+				0,
+				0x1);
+	IPN3KE_AFU_PMD_DEBUG("IPN3KE_CLF_RX_TEST: %x\n", data);
+
+	/* configure base mac address */
+	IPN3KE_MASK_WRITE_REG(hw,
+			IPN3KE_CLF_BASE_DST_MAC_ADDR_HI,
+			0,
+			0x2457,
+			0xFFFF);
+
+	data = 0;
+	data = IPN3KE_MASK_READ_REG(hw,
+				IPN3KE_CLF_BASE_DST_MAC_ADDR_HI,
+				0,
+				0xFFFF);
+	IPN3KE_AFU_PMD_DEBUG("IPN3KE_CLF_BASE_DST_MAC_ADDR_HI: %x\n", data);
+
+	IPN3KE_MASK_WRITE_REG(hw,
+			IPN3KE_CLF_BASE_DST_MAC_ADDR_LOW,
+			0,
+			0x9bdf1000,
+			0xFFFFFFFF);
+
+	data = 0;
+	data = IPN3KE_MASK_READ_REG(hw,
+				IPN3KE_CLF_BASE_DST_MAC_ADDR_LOW,
+				0,
+				0xFFFFFFFF);
+	IPN3KE_AFU_PMD_DEBUG("IPN3KE_CLF_BASE_DST_MAC_ADDR_LOW: %x\n", data);
+
+
+	/* configure hash lookup rules enable */
+	IPN3KE_MASK_WRITE_REG(hw,
+			IPN3KE_CLF_LKUP_ENABLE,
+			0,
+			0xFD,
+			0xFF);
+
+	data = 0;
+	data = IPN3KE_MASK_READ_REG(hw,
+				IPN3KE_CLF_LKUP_ENABLE,
+				0,
+				0xFF);
+	IPN3KE_AFU_PMD_DEBUG("IPN3KE_CLF_LKUP_ENABLE: %x\n", data);
+
+
+	/* configure rx parse config, settings associatied with VxLAN */
+	IPN3KE_MASK_WRITE_REG(hw,
+			IPN3KE_CLF_RX_PARSE_CFG,
+			0,
+			0x212b5,
+			0x3FFFF);
+
+	data = 0;
+	data = IPN3KE_MASK_READ_REG(hw,
+				IPN3KE_CLF_RX_PARSE_CFG,
+				0,
+				0x3FFFF);
+	IPN3KE_AFU_PMD_DEBUG("IPN3KE_CLF_RX_PARSE_CFG: %x\n", data);
+
+
+	/* configure QinQ S-Tag */
+	IPN3KE_MASK_WRITE_REG(hw,
+			IPN3KE_CLF_QINQ_STAG,
+			0,
+			0x88a8,
+			0xFFFF);
+
+	data = 0;
+	data = IPN3KE_MASK_READ_REG(hw,
+				IPN3KE_CLF_QINQ_STAG,
+				0,
+				0xFFFF);
+	IPN3KE_AFU_PMD_DEBUG("IPN3KE_CLF_QINQ_STAG: %x\n", data);
+
+
+	/* configure gen ctrl */
+	IPN3KE_MASK_WRITE_REG(hw,
+			IPN3KE_CLF_MHL_GEN_CTRL,
+			0,
+			0x3,
+			0x3);
+
+	data = 0;
+	data = IPN3KE_MASK_READ_REG(hw,
+				IPN3KE_CLF_MHL_GEN_CTRL,
+				0,
+				0x1F);
+	IPN3KE_AFU_PMD_DEBUG("IPN3KE_CLF_MHL_GEN_CTRL: %x\n", data);
+
+
+	/* clear monitoring register */
+	IPN3KE_MASK_WRITE_REG(hw,
+			IPN3KE_CLF_MHL_MON_0,
+			0,
+			0xFFFFFFFF,
+			0xFFFFFFFF);
+
+	data = 0;
+	data = IPN3KE_MASK_READ_REG(hw,
+				IPN3KE_CLF_MHL_MON_0,
+				0,
+				0xFFFFFFFF);
+	IPN3KE_AFU_PMD_DEBUG("IPN3KE_CLF_MHL_MON_0: %x\n", data);
+
+
+	ipn3ke_flow_hw_flush(hw);
+
+	TAILQ_INIT(&hw->flow_list);
+	hw->flow_max_entries = IPN3KE_MASK_READ_REG(hw,
+						IPN3KE_CLF_EM_NUM,
+						0,
+						0xFFFFFFFF);
+	hw->flow_num_entries = 0;
+
+	return 0;
+}
+
+const struct rte_flow_ops ipn3ke_flow_ops = {
+	.validate = ipn3ke_flow_validate,
+	.create = ipn3ke_flow_create,
+	.destroy = ipn3ke_flow_destroy,
+	.flush = ipn3ke_flow_flush,
+};
+
diff --git a/drivers/net/ipn3ke/ipn3ke_flow.h b/drivers/net/ipn3ke/ipn3ke_flow.h
new file mode 100644
index 0000000..ff97f94
--- /dev/null
+++ b/drivers/net/ipn3ke/ipn3ke_flow.h
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#ifndef _IPN3KE_FLOW_H_
+#define _IPN3KE_FLOW_H_
+
+/**
+ * Expand the length to DWORD alignment with 'Unused' field.
+ *
+ * FLOW KEY:
+ *  | Unused |Ruler id (id)  | Key1 Key2 … (data) |
+ *  |--------+---------------+--------------------|
+ *  | 17bits |    3 bits     |   Total 108 bits   |
+ * MSB                 --->                      LSB
+ *
+ * Note: And the MSb of key data is filled to 0 when it is less
+ *       than 108 bit.
+ */
+#define IPN3KE_FLOW_KEY_UNUSED_BITS  17
+#define IPN3KE_FLOW_KEY_ID_BITS      3
+#define IPN3KE_FLOW_KEY_DATA_BITS    108
+
+#define IPN3KE_FLOW_KEY_TOTAL_BITS \
+		(IPN3KE_FLOW_KEY_UNUSED_BITS + \
+		IPN3KE_FLOW_KEY_ID_BITS + \
+		IPN3KE_FLOW_KEY_DATA_BITS)
+
+#define IPN3KE_FLOW_KEY_ID_OFFSET \
+		(IPN3KE_FLOW_KEY_UNUSED_BITS)
+
+#define IPN3KE_FLOW_KEY_DATA_OFFSET \
+		(IPN3KE_FLOW_KEY_ID_OFFSET + IPN3KE_FLOW_KEY_ID_BITS)
+
+/**
+ * Expand the length to DWORD alignment with 'Unused' field.
+ *
+ * FLOW RESULT:
+ *  |  Unused | enable (acl) |    uid       |
+ *  |---------+--------------+--------------|
+ *  | 15 bits |    1 bit     |   16 bits    |
+ * MSB              --->                   LSB
+ */
+
+#define IPN3KE_FLOW_RESULT_UNUSED_BITS 15
+#define IPN3KE_FLOW_RESULT_ACL_BITS    1
+#define IPN3KE_FLOW_RESULT_UID_BITS    16
+
+#define IPN3KE_FLOW_RESULT_TOTAL_BITS \
+		(IPN3KE_FLOW_RESULT_UNUSED_BITS + \
+		IPN3KE_FLOW_RESULT_ACL_BITS + \
+		IPN3KE_FLOW_RESULT_UID_BITS)
+
+#define IPN3KE_FLOW_RESULT_ACL_OFFSET \
+		(IPN3KE_FLOW_RESULT_UNUSED_BITS)
+
+#define IPN3KE_FLOW_RESULT_UID_OFFSET \
+		(IPN3KE_FLOW_RESULT_ACL_OFFSET + IPN3KE_FLOW_RESULT_ACL_BITS)
+
+#define IPN3KE_FLOW_RESULT_UID_MAX \
+		((1UL << IPN3KE_FLOW_RESULT_UID_BITS) - 1)
+
+#ifndef BITS_PER_BYTE
+#define BITS_PER_BYTE    8
+#endif
+#define BITS_TO_BYTES(bits) \
+	(((bits) + BITS_PER_BYTE - 1) / BITS_PER_BYTE)
+
+struct ipn3ke_flow_rule {
+	uint8_t key[BITS_TO_BYTES(IPN3KE_FLOW_KEY_TOTAL_BITS)];
+	uint8_t result[BITS_TO_BYTES(IPN3KE_FLOW_RESULT_TOTAL_BITS)];
+};
+
+struct rte_flow {
+	TAILQ_ENTRY(rte_flow) next; /**< Pointer to the next flow structure. */
+
+	struct ipn3ke_flow_rule rule;
+};
+
+TAILQ_HEAD(ipn3ke_flow_list, rte_flow);
+
+extern const struct rte_flow_ops ipn3ke_flow_ops;
+
+int ipn3ke_flow_init(void *dev);
+
+#endif /* _IPN3KE_FLOW_H_ */
diff --git a/drivers/net/ipn3ke/ipn3ke_representor.c b/drivers/net/ipn3ke/ipn3ke_representor.c
index 32f75fb..6c218a1 100644
--- a/drivers/net/ipn3ke/ipn3ke_representor.c
+++ b/drivers/net/ipn3ke/ipn3ke_representor.c
@@ -21,6 +21,7 @@
 #include <ifpga_logs.h>
 
 #include "ipn3ke_rawdev_api.h"
+#include "ipn3ke_flow.h"
 #include "ipn3ke_logs.h"
 #include "ipn3ke_ethdev.h"
 
@@ -813,7 +814,7 @@ static int ipn3ke_rpst_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 		case RTE_ETH_FILTER_GENERIC:
 			if (filter_op != RTE_ETH_FILTER_GET)
 				return -EINVAL;
-			*(const void **)arg = NULL;
+			*(const void **)arg = &ipn3ke_flow_ops;
 			break;
 		default:
 			IPN3KE_AFU_PMD_WARN("Filter type (%d) not supported",
diff --git a/drivers/net/ipn3ke/ipn3ke_tm.c b/drivers/net/ipn3ke/ipn3ke_tm.c
index 3aaa61e..0b9be57 100644
--- a/drivers/net/ipn3ke/ipn3ke_tm.c
+++ b/drivers/net/ipn3ke/ipn3ke_tm.c
@@ -23,6 +23,7 @@
 #include <ifpga_logs.h>
 
 #include "ipn3ke_rawdev_api.h"
+#include "ipn3ke_flow.h"
 #include "ipn3ke_logs.h"
 #include "ipn3ke_ethdev.h"
 
diff --git a/drivers/net/ipn3ke/meson.build b/drivers/net/ipn3ke/meson.build
index 093ddbc..c35e667 100644
--- a/drivers/net/ipn3ke/meson.build
+++ b/drivers/net/ipn3ke/meson.build
@@ -4,5 +4,6 @@
 allow_experimental_apis = true
 sources += files('ipn3ke_ethdev.c',
 	'ipn3ke_representor.c',
-	'ipn3ke_tm.c')
+	'ipn3ke_tm.c',
+	'ipn3ke_flow.c')
 deps += ['bus_ifpga', 'sched']
-- 
1.8.3.1

  parent reply	other threads:[~2019-03-29 16:00 UTC|newest]

Thread overview: 193+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-02-28  7:13 [PATCH v1 00/11] Add patch set for IPN3KE Rosen Xu
2019-02-28  7:13 ` [PATCH v1 01/11] drivers/bus/ifpga: add AFU shared data Rosen Xu
2019-02-28  7:13 ` [PATCH v1 02/11] drivers/bus/ifpga: add function for AFU search by name Rosen Xu
2019-03-06 12:44   ` Ferruh Yigit
2019-03-11 13:10     ` Xu, Rosen
2019-02-28  7:13 ` [PATCH v1 03/11] drivers/raw/ifpga_rawdev: add OPAE share code for IPN3KE Rosen Xu
2019-03-06 12:27   ` Ferruh Yigit
2019-03-06 13:59     ` Zhang, Tianfei
2019-03-06 17:54       ` Ferruh Yigit
2019-03-06 23:59         ` Zhang, Tianfei
2019-02-28  7:13 ` [PATCH v1 04/11] drivers/raw/ifpga_rawdev: add IPN3KE support for IFPGA Rawdev Rosen Xu
2019-03-06 12:31   ` Ferruh Yigit
2019-03-07  7:16     ` Xu, Rosen
2019-02-28  7:13 ` [PATCH v1 05/11] drivers/net/ipn3ke: add IPN3KE PMD driver Rosen Xu
2019-02-28  8:32   ` David Marchand
2019-02-28  8:44     ` Xu, Rosen
2019-03-06 12:44   ` Ferruh Yigit
2019-03-11 13:09     ` Xu, Rosen
2019-03-09 19:34   ` Luca Boccassi
2019-03-11  3:05     ` Xu, Rosen
2019-02-28  7:13 ` [PATCH v1 06/11] config: add build enablement for IPN3KE Rosen Xu
2019-03-06 12:45   ` Yigit, Ferruh
2019-03-08  0:58     ` Xu, Rosen
2019-03-09  9:36     ` Xu, Rosen
2019-02-28  7:13 ` [PATCH v1 07/11] mk: add link " Rosen Xu
2019-03-06 12:45   ` Yigit, Ferruh
2019-03-08  0:56     ` Xu, Rosen
2019-02-28  7:13 ` [PATCH v1 08/11] app/test-pmd: add IPN3KE support for testpmd Rosen Xu
2019-02-28  8:37   ` David Marchand
2019-02-28  8:45     ` Xu, Rosen
2019-02-28  8:47       ` David Marchand
2019-03-01  5:56         ` Xu, Rosen
2019-03-06 12:45   ` Yigit, Ferruh
2019-03-08  0:55     ` Xu, Rosen
2019-02-28  7:13 ` [PATCH v1 09/11] usertools: add IPN3KE device bind Rosen Xu
2019-02-28  7:13 ` [PATCH v1 10/11] doc: add IPN3KE document Rosen Xu
2019-03-06 12:45   ` Ferruh Yigit
2019-03-08  2:41     ` Xu, Rosen
2019-02-28  7:13 ` [PATCH v1 11/11] MAINTAINERS: add MAINTAINERS for IPN3KE Rosen Xu
2019-03-06 12:46   ` Ferruh Yigit
2019-03-08  0:55     ` Xu, Rosen
2019-03-29 15:58 ` [PATCH v2 00/15] Add patch set " Rosen Xu
2019-03-29 15:58   ` [PATCH v2 01/15] drivers/bus/ifpga: add AFU shared data Rosen Xu
2019-03-29 15:58   ` [PATCH v2 02/15] drivers/bus/ifpga: add function for AFU search by name Rosen Xu
2019-03-29 15:58   ` [PATCH v2 03/15] drivers/net/ipn3ke: add IPN3KE ethdev PMD driver Rosen Xu
2019-03-29 15:58   ` [PATCH v2 04/15] drivers/net/ipn3ke: add IPN3KE representor of " Rosen Xu
2019-03-29 15:58   ` [PATCH v2 05/15] drivers/net/ipn3ke: add IPN3KE TM " Rosen Xu
2019-03-29 15:58   ` Rosen Xu [this message]
2019-03-29 15:58   ` [PATCH v2 07/15] raw/ifpga/base: clean up code for ifpga share code Rosen Xu
2019-03-29 15:58   ` [PATCH v2 08/15] raw/ifpga/base: store private features in FME and Port list Rosen Xu
2019-03-29 15:58   ` [PATCH v2 09/15] raw/ifpga/base: add SPI and MAX10 device driver Rosen Xu
2019-03-29 15:58   ` [PATCH v2 10/15] raw/ifpga/base: add I2C and at24 EEPROM driver Rosen Xu
2019-03-29 15:58   ` [PATCH v2 11/15] raw/ifpga/base: add eth group driver Rosen Xu
2019-03-29 15:58   ` [PATCH v2 12/15] raw/ifpga/base: add device tree support Rosen Xu
2019-03-29 15:58   ` [PATCH v2 13/15] raw/ifpga/base: add version description on README Rosen Xu
2019-03-29 15:58   ` [PATCH v2 14/15] raw/ifpga/base: using prefix name "ifpga_" for feature and feature_ops data struct Rosen Xu
2019-03-29 15:58   ` [PATCH v2 15/15] drivers/raw/ifpga_rawdev: add IPN3KE support for IFPGA Rawdev Rosen Xu
2019-03-29 18:59   ` [PATCH v2 00/15] Add patch set for IPN3KE Ferruh Yigit
2019-03-31 14:19     ` Xu, Rosen
2019-04-02 13:57 ` [PATCH v3 00/14] " Xu, Rosen
2019-04-02 13:57   ` [PATCH v3 01/14] drivers/bus/ifpga: add AFU shared data Xu, Rosen
2019-04-02 13:57   ` [PATCH v3 02/14] drivers/bus/ifpga: add function for AFU search by name Xu, Rosen
2019-04-02 13:57   ` [PATCH v3 03/14] drivers/net/ipn3ke: add IPN3KE ethdev PMD driver Xu, Rosen
2019-04-02 13:57   ` [PATCH v3 04/14] drivers/net/ipn3ke: add IPN3KE representor of " Xu, Rosen
2019-04-02 13:57   ` [PATCH v3 05/14] drivers/net/ipn3ke: add IPN3KE TM " Xu, Rosen
2019-04-02 13:57   ` [PATCH v3 06/14] drivers/net/ipn3ke: add IPN3KE Flow " Xu, Rosen
2019-04-02 13:57   ` [PATCH v3 07/14] raw/ifpga/base: clean up code for ifpga share code Xu, Rosen
2019-04-02 13:57   ` [PATCH v3 08/14] raw/ifpga/base: store private features in FME and Port list Xu, Rosen
2019-04-02 13:57   ` [PATCH v3 09/14] raw/ifpga/base: add SPI and MAX10 device driver Xu, Rosen
2019-04-02 13:57   ` [PATCH v3 10/14] raw/ifpga/base: add I2C and at24 EEPROM driver Xu, Rosen
2019-04-02 13:57   ` [PATCH v3 11/14] raw/ifpga/base: add eth group driver Xu, Rosen
2019-04-02 13:57   ` [PATCH v3 12/14] raw/ifpga/base: add version description on README Xu, Rosen
2019-04-02 13:57   ` [PATCH v3 13/14] raw/ifpga/base: using prefix name "ifpga_" for feature and feature_ops data struct Xu, Rosen
2019-04-02 13:57   ` [PATCH v3 14/14] drivers/raw/ifpga_rawdev: add IPN3KE support for IFPGA Rawdev Xu, Rosen
2019-04-03  8:46 ` [PATCH v4 00/14] Add patch set for IPN3KE Rosen Xu
2019-04-03  8:46   ` [PATCH v4 01/14] drivers/bus/ifpga: add AFU shared data Rosen Xu
2019-04-03  8:46   ` [PATCH v4 02/14] drivers/bus/ifpga: add function for AFU search by name Rosen Xu
2019-04-03  8:46   ` [PATCH v4 03/14] drivers/net/ipn3ke: add IPN3KE ethdev PMD driver Rosen Xu
2019-04-03  8:46   ` [PATCH v4 04/14] drivers/net/ipn3ke: add IPN3KE representor of " Rosen Xu
2019-04-03  8:46   ` [PATCH v4 05/14] drivers/net/ipn3ke: add IPN3KE TM " Rosen Xu
2019-04-03  8:46   ` [PATCH v4 06/14] drivers/net/ipn3ke: add IPN3KE Flow " Rosen Xu
2019-04-03  8:46   ` [PATCH v4 07/14] raw/ifpga/base: clean up code for ifpga share code Rosen Xu
2019-04-03  8:46   ` [PATCH v4 08/14] raw/ifpga/base: store private features in FME and Port list Rosen Xu
2019-04-03  8:46   ` [PATCH v4 09/14] raw/ifpga/base: add SPI and MAX10 device driver Rosen Xu
2019-04-03  8:46   ` [PATCH v4 10/14] raw/ifpga/base: add I2C and at24 EEPROM driver Rosen Xu
2019-04-03  8:46   ` [PATCH v4 11/14] raw/ifpga/base: add eth group driver Rosen Xu
2019-04-03  8:46   ` [PATCH v4 12/14] raw/ifpga/base: add version description on README Rosen Xu
2019-04-03  8:46   ` [PATCH v4 13/14] raw/ifpga/base: using prefix name "ifpga_" for feature and feature_ops data struct Rosen Xu
2019-04-03  8:46   ` [PATCH v4 14/14] drivers/raw/ifpga_rawdev: add IPN3KE support for IFPGA Rawdev Rosen Xu
2019-04-03 11:47 ` [PATCH v5 00/14] Add patch set for IPN3KE Rosen Xu
2019-04-03 11:47   ` [PATCH v5 01/14] drivers/bus/ifpga: add AFU shared data Rosen Xu
2019-04-03 11:47   ` [PATCH v5 02/14] drivers/bus/ifpga: add function for AFU search by name Rosen Xu
2019-04-03 11:47   ` [PATCH v5 03/14] drivers/net/ipn3ke: add IPN3KE ethdev PMD driver Rosen Xu
2019-04-04 19:38     ` Ferruh Yigit
2019-04-08  7:29       ` [dpdk-dev] " Xu, Rosen
2019-04-03 11:47   ` [PATCH v5 04/14] drivers/net/ipn3ke: add IPN3KE representor of " Rosen Xu
2019-04-04 19:02     ` Ferruh Yigit
2019-04-08  7:40       ` [dpdk-dev] " Xu, Rosen
2019-04-03 11:47   ` [PATCH v5 05/14] drivers/net/ipn3ke: add IPN3KE TM " Rosen Xu
2019-04-03 11:47   ` [PATCH v5 06/14] drivers/net/ipn3ke: add IPN3KE Flow " Rosen Xu
2019-04-03 11:47   ` [PATCH v5 07/14] raw/ifpga/base: clean up code for ifpga share code Rosen Xu
2019-04-03 11:47   ` [PATCH v5 08/14] raw/ifpga/base: store private features in FME and Port list Rosen Xu
2019-04-03 11:47   ` [PATCH v5 09/14] raw/ifpga/base: add SPI and MAX10 device driver Rosen Xu
2019-04-03 11:47   ` [PATCH v5 10/14] raw/ifpga/base: add I2C and at24 EEPROM driver Rosen Xu
2019-04-03 11:47   ` [PATCH v5 11/14] raw/ifpga/base: add eth group driver Rosen Xu
2019-04-03 11:47   ` [PATCH v5 12/14] raw/ifpga/base: add version description on README Rosen Xu
2019-04-03 11:47   ` [PATCH v5 13/14] raw/ifpga/base: using prefix name "ifpga_" for feature and feature_ops data struct Rosen Xu
2019-04-03 11:47   ` [PATCH v5 14/14] drivers/raw/ifpga_rawdev: add IPN3KE support for IFPGA Rawdev Rosen Xu
2019-04-04 18:37   ` [PATCH v5 00/14] Add patch set for IPN3KE Ferruh Yigit
2019-04-08  7:19     ` [dpdk-dev] " Xu, Rosen
2019-04-09 12:41 ` [dpdk-dev] [PATCH v6 " Rosen Xu
2019-04-09 12:41   ` [dpdk-dev] [PATCH v6 01/14] bus/ifpga: add AFU shared data Rosen Xu
2019-04-09 12:41   ` [dpdk-dev] [PATCH v6 02/14] bus/ifpga: add function for AFU search by name Rosen Xu
2019-04-09 12:41   ` [dpdk-dev] [PATCH v6 03/14] net/ipn3ke: add IPN3KE ethdev PMD driver Rosen Xu
2019-04-09 15:18     ` Stephen Hemminger
2019-04-10  6:03       ` Xu, Rosen
2019-04-09 12:41   ` [dpdk-dev] [PATCH v6 04/14] net/ipn3ke: add IPN3KE representor of " Rosen Xu
2019-04-09 12:41   ` [dpdk-dev] [PATCH v6 05/14] net/ipn3ke: add IPN3KE TM " Rosen Xu
2019-04-09 12:41   ` [dpdk-dev] [PATCH v6 06/14] net/ipn3ke: add IPN3KE Flow " Rosen Xu
2019-04-09 12:41   ` [dpdk-dev] [PATCH v6 07/14] raw/ifpga_rawdev: clean up code for ifpga share code Rosen Xu
2019-04-09 12:41   ` [dpdk-dev] [PATCH v6 08/14] raw/ifpga_rawdev: store private features in FME and Port Rosen Xu
2019-04-09 12:41   ` [dpdk-dev] [PATCH v6 09/14] raw/ifpga_rawdev: add SPI and MAX10 device driver Rosen Xu
2019-04-09 12:41   ` [dpdk-dev] [PATCH v6 10/14] raw/ifpga_rawdev: add I2C and at24 EEPROM driver Rosen Xu
2019-04-09 12:41   ` [dpdk-dev] [PATCH v6 11/14] raw/ifpga_rawdev: add eth group driver Rosen Xu
2019-04-09 12:41   ` [dpdk-dev] [PATCH v6 12/14] raw/ifpga_rawdev: add version description on README Rosen Xu
2019-04-09 12:41   ` [dpdk-dev] [PATCH v6 13/14] raw/ifpga_rawdev: using prefix name for feature and its ops Rosen Xu
2019-04-09 12:41   ` [dpdk-dev] [PATCH v6 14/14] raw/ifpga_rawdev: add IPN3KE support for IFPGA Rawdev Rosen Xu
2019-04-10  6:27 ` [dpdk-dev] [PATCH v7 00/14] Add patch set for IPN3KE Rosen Xu
2019-04-10  6:27   ` [dpdk-dev] [PATCH v7 01/14] bus/ifpga: add AFU shared data Rosen Xu
2019-04-10  6:27   ` [dpdk-dev] [PATCH v7 02/14] bus/ifpga: add function for AFU search by name Rosen Xu
2019-04-10  6:27   ` [dpdk-dev] [PATCH v7 03/14] net/ipn3ke: add IPN3KE ethdev PMD driver Rosen Xu
2019-04-10  6:27   ` [dpdk-dev] [PATCH v7 04/14] net/ipn3ke: add IPN3KE representor of " Rosen Xu
2019-04-10  6:27   ` [dpdk-dev] [PATCH v7 05/14] net/ipn3ke: add IPN3KE TM " Rosen Xu
2019-04-10  6:27   ` [dpdk-dev] [PATCH v7 06/14] net/ipn3ke: add IPN3KE Flow " Rosen Xu
2019-04-10  6:27   ` [dpdk-dev] [PATCH v7 07/14] raw/ifpga_rawdev: clean up code for ifpga share code Rosen Xu
2019-04-10  6:27   ` [dpdk-dev] [PATCH v7 08/14] raw/ifpga_rawdev: store private features in FME and Port Rosen Xu
2019-04-10  6:27   ` [dpdk-dev] [PATCH v7 09/14] raw/ifpga_rawdev: add SPI and MAX10 device driver Rosen Xu
2019-04-10  6:27   ` [dpdk-dev] [PATCH v7 10/14] raw/ifpga_rawdev: add I2C and at24 EEPROM driver Rosen Xu
2019-04-10  6:27   ` [dpdk-dev] [PATCH v7 11/14] raw/ifpga_rawdev: add eth group driver Rosen Xu
2019-04-10  6:27   ` [dpdk-dev] [PATCH v7 12/14] raw/ifpga_rawdev: add version description on README Rosen Xu
2019-04-10  6:27   ` [dpdk-dev] [PATCH v7 13/14] raw/ifpga_rawdev: using prefix name for feature and its ops Rosen Xu
2019-04-10  6:27   ` [dpdk-dev] [PATCH v7 14/14] raw/ifpga_rawdev: add IPN3KE support for IFPGA Rawdev Rosen Xu
2019-04-12 16:52   ` [dpdk-dev] [PATCH v7 00/14] Add patch set for IPN3KE Ferruh Yigit
2019-04-15  5:07     ` Xu, Rosen
2019-04-15  5:06 ` [dpdk-dev] [PATCH v8 " Rosen Xu
2019-04-15  5:06   ` [dpdk-dev] [PATCH v8 01/14] bus/ifpga: add AFU shared data Rosen Xu
2019-04-15  5:06   ` [dpdk-dev] [PATCH v8 02/14] bus/ifpga: add function for AFU search by name Rosen Xu
2019-04-15 12:28     ` Ferruh Yigit
2019-04-15 12:37       ` Xu, Rosen
2019-04-16  2:50       ` Xu, Rosen
2019-04-16  8:09         ` Thomas Monjalon
2019-04-16  8:15           ` Xu, Rosen
2019-04-15  5:06   ` [dpdk-dev] [PATCH v8 03/14] net/ipn3ke: add IPN3KE ethdev PMD driver Rosen Xu
2019-04-15 12:28     ` Ferruh Yigit
2019-04-15 12:43       ` Xu, Rosen
2019-04-15  5:06   ` [dpdk-dev] [PATCH v8 04/14] net/ipn3ke: add IPN3KE representor of " Rosen Xu
2019-04-15  5:06   ` [dpdk-dev] [PATCH v8 05/14] net/ipn3ke: add IPN3KE TM " Rosen Xu
2019-04-15  5:06   ` [dpdk-dev] [PATCH v8 06/14] net/ipn3ke: add IPN3KE Flow " Rosen Xu
2019-04-15  5:06   ` [dpdk-dev] [PATCH v8 07/14] raw/ifpga_rawdev: clean up code for ifpga share code Rosen Xu
2019-04-15  5:06   ` [dpdk-dev] [PATCH v8 08/14] raw/ifpga_rawdev: store private features in FME and Port Rosen Xu
2019-04-15  5:06   ` [dpdk-dev] [PATCH v8 09/14] raw/ifpga_rawdev: add SPI and MAX10 device driver Rosen Xu
2019-04-15  5:06   ` [dpdk-dev] [PATCH v8 10/14] raw/ifpga_rawdev: add I2C and at24 EEPROM driver Rosen Xu
2019-04-15  5:07   ` [dpdk-dev] [PATCH v8 11/14] raw/ifpga_rawdev: add eth group driver Rosen Xu
2019-04-15  5:07   ` [dpdk-dev] [PATCH v8 12/14] raw/ifpga_rawdev: add version description on README Rosen Xu
2019-04-15  5:07   ` [dpdk-dev] [PATCH v8 13/14] raw/ifpga_rawdev: using prefix name for feature and its ops Rosen Xu
2019-04-15  5:07   ` [dpdk-dev] [PATCH v8 14/14] raw/ifpga_rawdev: add IPN3KE support for IFPGA Rawdev Rosen Xu
2019-04-15 12:28     ` Ferruh Yigit
2019-04-15 12:55       ` Xu, Rosen
2019-04-15 12:28   ` [dpdk-dev] [PATCH v8 00/14] Add patch set for IPN3KE Ferruh Yigit
2019-04-15 12:34     ` Xu, Rosen
2019-04-16  3:17 ` [dpdk-dev] [PATCH v9 " Rosen Xu
2019-04-16  3:17   ` [dpdk-dev] [PATCH v9 01/14] bus/ifpga: add AFU shared data Rosen Xu
2019-04-16  3:17   ` [dpdk-dev] [PATCH v9 02/14] bus/ifpga: add function for AFU search by name Rosen Xu
2019-04-16  8:48     ` Ferruh Yigit
2019-04-16 11:18       ` Xu, Rosen
2019-04-16  3:17   ` [dpdk-dev] [PATCH v9 03/14] net/ipn3ke: add IPN3KE ethdev PMD driver Rosen Xu
2023-03-21 20:19     ` Ferruh Yigit
2023-03-22  1:37       ` Xu, Rosen
2019-04-16  3:17   ` [dpdk-dev] [PATCH v9 04/14] net/ipn3ke: add IPN3KE representor of " Rosen Xu
2019-04-16  3:17   ` [dpdk-dev] [PATCH v9 05/14] net/ipn3ke: add IPN3KE TM " Rosen Xu
2019-04-16  3:17   ` [dpdk-dev] [PATCH v9 06/14] net/ipn3ke: add IPN3KE Flow " Rosen Xu
2019-04-16  3:17   ` [dpdk-dev] [PATCH v9 07/14] raw/ifpga_rawdev: clean up code for ifpga share code Rosen Xu
2019-04-16  3:17   ` [dpdk-dev] [PATCH v9 08/14] raw/ifpga_rawdev: store private features in FME and Port Rosen Xu
2019-04-16  3:17   ` [dpdk-dev] [PATCH v9 09/14] raw/ifpga_rawdev: add SPI and MAX10 device driver Rosen Xu
2019-04-16  3:17   ` [dpdk-dev] [PATCH v9 10/14] raw/ifpga_rawdev: add I2C and at24 EEPROM driver Rosen Xu
2019-04-16  3:17   ` [dpdk-dev] [PATCH v9 11/14] raw/ifpga_rawdev: add eth group driver Rosen Xu
2019-04-16  3:17   ` [dpdk-dev] [PATCH v9 12/14] raw/ifpga_rawdev: add version description on README Rosen Xu
2019-04-16  3:17   ` [dpdk-dev] [PATCH v9 13/14] raw/ifpga_rawdev: using prefix name for feature and its ops Rosen Xu
2019-04-16  3:17   ` [dpdk-dev] [PATCH v9 14/14] raw/ifpga_rawdev: add IPN3KE support for IFPGA Rawdev Rosen Xu
2019-04-16  9:00   ` [dpdk-dev] [PATCH v9 00/14] Add patch set for IPN3KE Ferruh Yigit
2019-04-16  9:05     ` Ferruh Yigit
2019-04-16  9:06       ` Xu, Rosen
2019-04-16  9:06     ` Xu, Rosen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1553875099-166351-7-git-send-email-rosen.xu@intel.com \
    --to=rosen.xu@intel.com \
    --cc=andy.pei@intel.com \
    --cc=dan.wei@intel.com \
    --cc=dev@dpdk.org \
    --cc=ferruh.yigit@intel.com \
    --cc=haiyue.wang@intel.com \
    --cc=qiming.yang@intel.com \
    --cc=santos.chen@intel.com \
    --cc=tianfei.zhang@intel.com \
    --cc=zhang.zhang@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.