[v5,23/42] net/dpaa2: flow API refactor

Message ID 20241023115955.1207617-24-vanshika.shukla@nxp.com (mailing list archive)
State Accepted, archived
Delegated to: Thomas Monjalon
Headers
Series DPAA2 specific patches |

Checks

Context Check Description
ci/checkpatch warning coding style issues

Commit Message

Vanshika Shukla Oct. 23, 2024, 11:59 a.m. UTC
From: Jun Yang <jun.yang@nxp.com>

1) Gather redundant code with same logic from various protocol
   handlers to create common functions.
2) struct dpaa2_key_profile is used to describe each extract's
   offset of rule and size. It's easy to insert new extract previous
   IP address extract.
3) IP address profile is used to describe ipv4/v6 addresses extracts
   located at end of rule.
4) L4 ports profile is used to describe the ports positions and offsets
   of rule.
5) Once the extracts of QoS/FS table are update, go through all
   the existing flows of this table to update the rule data.

Signed-off-by: Jun Yang <jun.yang@nxp.com>
---
 drivers/net/dpaa2/dpaa2_ethdev.c |   27 +-
 drivers/net/dpaa2/dpaa2_ethdev.h |   90 +-
 drivers/net/dpaa2/dpaa2_flow.c   | 4839 ++++++++++++------------------
 3 files changed, 2030 insertions(+), 2926 deletions(-)
  

Comments

Thomas Monjalon Nov. 9, 2024, 7:01 p.m. UTC | #1
23/10/2024 13:59, vanshika.shukla@nxp.com:
> +static inline int
> +dpaa2_fs_action_supported(enum rte_flow_action_type action)
> +{
> +       int i;
> +       int action_num = sizeof(dpaa2_supported_fs_action_type) /
> +               sizeof(enum rte_flow_action_type);
>  
> -               curr = LIST_NEXT(curr, next);
> +       for (i = 0; i < action_num; i++) {
> +               if (action == dpaa2_supported_fs_action_type[i])
> +                       return true;
>         }
>  
> -       return 0;
> +       return false;
>  }

One more compilation error:

unused function 'dpaa2_fs_action_supported'
  

Patch

diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index bd6a578e30..e55de5b614 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -2808,39 +2808,20 @@  dpaa2_dev_init(struct rte_eth_dev *eth_dev)
 	/* Init fields w.r.t. classification */
 	memset(&priv->extract.qos_key_extract, 0,
 		sizeof(struct dpaa2_key_extract));
-	priv->extract.qos_extract_param = (size_t)rte_malloc(NULL, 256, 64);
+	priv->extract.qos_extract_param = rte_malloc(NULL, 256, 64);
 	if (!priv->extract.qos_extract_param) {
-		DPAA2_PMD_ERR(" Error(%d) in allocation resources for flow "
-			    " classification ", ret);
+		DPAA2_PMD_ERR("Memory alloc failed");
 		goto init_err;
 	}
-	priv->extract.qos_key_extract.key_info.ipv4_src_offset =
-		IP_ADDRESS_OFFSET_INVALID;
-	priv->extract.qos_key_extract.key_info.ipv4_dst_offset =
-		IP_ADDRESS_OFFSET_INVALID;
-	priv->extract.qos_key_extract.key_info.ipv6_src_offset =
-		IP_ADDRESS_OFFSET_INVALID;
-	priv->extract.qos_key_extract.key_info.ipv6_dst_offset =
-		IP_ADDRESS_OFFSET_INVALID;
 
 	for (i = 0; i < MAX_TCS; i++) {
 		memset(&priv->extract.tc_key_extract[i], 0,
 			sizeof(struct dpaa2_key_extract));
-		priv->extract.tc_extract_param[i] =
-			(size_t)rte_malloc(NULL, 256, 64);
+		priv->extract.tc_extract_param[i] = rte_malloc(NULL, 256, 64);
 		if (!priv->extract.tc_extract_param[i]) {
-			DPAA2_PMD_ERR(" Error(%d) in allocation resources for flow classification",
-				     ret);
+			DPAA2_PMD_ERR("Memory alloc failed");
 			goto init_err;
 		}
-		priv->extract.tc_key_extract[i].key_info.ipv4_src_offset =
-			IP_ADDRESS_OFFSET_INVALID;
-		priv->extract.tc_key_extract[i].key_info.ipv4_dst_offset =
-			IP_ADDRESS_OFFSET_INVALID;
-		priv->extract.tc_key_extract[i].key_info.ipv6_src_offset =
-			IP_ADDRESS_OFFSET_INVALID;
-		priv->extract.tc_key_extract[i].key_info.ipv6_dst_offset =
-			IP_ADDRESS_OFFSET_INVALID;
 	}
 
 	ret = dpni_set_max_frame_length(dpni_dev, CMD_PRI_LOW, priv->token,
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h
index 6625afaba3..ea1c1b5117 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.h
+++ b/drivers/net/dpaa2/dpaa2_ethdev.h
@@ -145,14 +145,6 @@  extern bool dpaa2_enable_ts[];
 extern uint64_t dpaa2_timestamp_rx_dynflag;
 extern int dpaa2_timestamp_dynfield_offset;
 
-#define DPAA2_QOS_TABLE_RECONFIGURE	1
-#define DPAA2_FS_TABLE_RECONFIGURE	2
-
-#define DPAA2_QOS_TABLE_IPADDR_EXTRACT 4
-#define DPAA2_FS_TABLE_IPADDR_EXTRACT 8
-
-#define DPAA2_FLOW_MAX_KEY_SIZE		16
-
 /* Externally defined */
 extern const struct rte_flow_ops dpaa2_flow_ops;
 
@@ -160,29 +152,85 @@  extern const struct rte_tm_ops dpaa2_tm_ops;
 
 extern bool dpaa2_enable_err_queue;
 
-#define IP_ADDRESS_OFFSET_INVALID (-1)
+struct ipv4_sd_addr_extract_rule {
+	uint32_t ipv4_src;
+	uint32_t ipv4_dst;
+};
+
+struct ipv6_sd_addr_extract_rule {
+	uint8_t ipv6_src[NH_FLD_IPV6_ADDR_SIZE];
+	uint8_t ipv6_dst[NH_FLD_IPV6_ADDR_SIZE];
+};
 
-struct dpaa2_key_info {
+struct ipv4_ds_addr_extract_rule {
+	uint32_t ipv4_dst;
+	uint32_t ipv4_src;
+};
+
+struct ipv6_ds_addr_extract_rule {
+	uint8_t ipv6_dst[NH_FLD_IPV6_ADDR_SIZE];
+	uint8_t ipv6_src[NH_FLD_IPV6_ADDR_SIZE];
+};
+
+union ip_addr_extract_rule {
+	struct ipv4_sd_addr_extract_rule ipv4_sd_addr;
+	struct ipv6_sd_addr_extract_rule ipv6_sd_addr;
+	struct ipv4_ds_addr_extract_rule ipv4_ds_addr;
+	struct ipv6_ds_addr_extract_rule ipv6_ds_addr;
+};
+
+union ip_src_addr_extract_rule {
+	uint32_t ipv4_src;
+	uint8_t ipv6_src[NH_FLD_IPV6_ADDR_SIZE];
+};
+
+union ip_dst_addr_extract_rule {
+	uint32_t ipv4_dst;
+	uint8_t ipv6_dst[NH_FLD_IPV6_ADDR_SIZE];
+};
+
+enum ip_addr_extract_type {
+	IP_NONE_ADDR_EXTRACT,
+	IP_SRC_EXTRACT,
+	IP_DST_EXTRACT,
+	IP_SRC_DST_EXTRACT,
+	IP_DST_SRC_EXTRACT
+};
+
+struct key_prot_field {
+	enum net_prot prot;
+	uint32_t key_field;
+};
+
+struct dpaa2_key_profile {
+	uint8_t num;
 	uint8_t key_offset[DPKG_MAX_NUM_OF_EXTRACTS];
 	uint8_t key_size[DPKG_MAX_NUM_OF_EXTRACTS];
-	/* Special for IP address. */
-	int ipv4_src_offset;
-	int ipv4_dst_offset;
-	int ipv6_src_offset;
-	int ipv6_dst_offset;
-	uint8_t key_total_size;
+
+	enum ip_addr_extract_type ip_addr_type;
+	uint8_t ip_addr_extract_pos;
+	uint8_t ip_addr_extract_off;
+
+	uint8_t l4_src_port_present;
+	uint8_t l4_src_port_pos;
+	uint8_t l4_src_port_offset;
+	uint8_t l4_dst_port_present;
+	uint8_t l4_dst_port_pos;
+	uint8_t l4_dst_port_offset;
+	struct key_prot_field prot_field[DPKG_MAX_NUM_OF_EXTRACTS];
+	uint16_t key_max_size;
 };
 
 struct dpaa2_key_extract {
 	struct dpkg_profile_cfg dpkg;
-	struct dpaa2_key_info key_info;
+	struct dpaa2_key_profile key_profile;
 };
 
 struct extract_s {
 	struct dpaa2_key_extract qos_key_extract;
 	struct dpaa2_key_extract tc_key_extract[MAX_TCS];
-	uint64_t qos_extract_param;
-	uint64_t tc_extract_param[MAX_TCS];
+	uint8_t *qos_extract_param;
+	uint8_t *tc_extract_param[MAX_TCS];
 };
 
 struct dpaa2_dev_priv {
@@ -233,7 +281,8 @@  struct dpaa2_dev_priv {
 	/* Stores correction offset for one step timestamping */
 	uint16_t ptp_correction_offset;
 
-	LIST_HEAD(, rte_flow) flows; /**< Configured flow rule handles. */
+	struct dpaa2_dev_flow *curr;
+	LIST_HEAD(, dpaa2_dev_flow) flows;
 	LIST_HEAD(nodes, dpaa2_tm_node) nodes;
 	LIST_HEAD(shaper_profiles, dpaa2_tm_shaper_profile) shaper_profiles;
 };
@@ -292,7 +341,6 @@  uint16_t dpaa2_dev_tx_multi_txq_ordered(void **queue,
 void dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci, struct dpaa2_queue *dpaa2_q);
 void dpaa2_flow_clean(struct rte_eth_dev *dev);
 uint16_t dpaa2_dev_tx_conf(void *queue)  __rte_unused;
-int dpaa2_dev_is_dpaa2(struct rte_eth_dev *dev);
 
 int dpaa2_timesync_enable(struct rte_eth_dev *dev);
 int dpaa2_timesync_disable(struct rte_eth_dev *dev);
diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c
index b7f1f974c6..9e03ad5401 100644
--- a/drivers/net/dpaa2/dpaa2_flow.c
+++ b/drivers/net/dpaa2/dpaa2_flow.c
@@ -1,5 +1,5 @@ 
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2018-2021 NXP
+ * Copyright 2018-2022 NXP
  */
 
 #include <sys/queue.h>
@@ -27,41 +27,40 @@ 
  * MC/WRIOP are not able to identify
  * the l4 protocol with l4 ports.
  */
-int mc_l4_port_identification;
+static int mc_l4_port_identification;
 
 static char *dpaa2_flow_control_log;
 static uint16_t dpaa2_flow_miss_flow_id; /* Default miss flow id is 0. */
 
-#define FIXED_ENTRY_SIZE DPNI_MAX_KEY_SIZE
-
-enum flow_rule_ipaddr_type {
-	FLOW_NONE_IPADDR,
-	FLOW_IPV4_ADDR,
-	FLOW_IPV6_ADDR
+enum dpaa2_flow_entry_size {
+	DPAA2_FLOW_ENTRY_MIN_SIZE = (DPNI_MAX_KEY_SIZE / 2),
+	DPAA2_FLOW_ENTRY_MAX_SIZE = DPNI_MAX_KEY_SIZE
 };
 
-struct flow_rule_ipaddr {
-	enum flow_rule_ipaddr_type ipaddr_type;
-	int qos_ipsrc_offset;
-	int qos_ipdst_offset;
-	int fs_ipsrc_offset;
-	int fs_ipdst_offset;
+enum dpaa2_flow_dist_type {
+	DPAA2_FLOW_QOS_TYPE = 1 << 0,
+	DPAA2_FLOW_FS_TYPE = 1 << 1
 };
 
-struct rte_flow {
-	LIST_ENTRY(rte_flow) next; /**< Pointer to the next flow structure. */
+#define DPAA2_FLOW_RAW_OFFSET_FIELD_SHIFT	16
+#define DPAA2_FLOW_MAX_KEY_SIZE			16
+
+struct dpaa2_dev_flow {
+	LIST_ENTRY(dpaa2_dev_flow) next;
 	struct dpni_rule_cfg qos_rule;
+	uint8_t *qos_key_addr;
+	uint8_t *qos_mask_addr;
+	uint16_t qos_rule_size;
 	struct dpni_rule_cfg fs_rule;
 	uint8_t qos_real_key_size;
 	uint8_t fs_real_key_size;
+	uint8_t *fs_key_addr;
+	uint8_t *fs_mask_addr;
+	uint16_t fs_rule_size;
 	uint8_t tc_id; /** Traffic Class ID. */
 	uint8_t tc_index; /** index within this Traffic Class. */
-	enum rte_flow_action_type action;
-	/* Special for IP address to specify the offset
-	 * in key/mask.
-	 */
-	struct flow_rule_ipaddr ipaddr_rule;
-	struct dpni_fs_action_cfg action_cfg;
+	enum rte_flow_action_type action_type;
+	struct dpni_fs_action_cfg fs_action_cfg;
 };
 
 static const
@@ -94,9 +93,6 @@  enum rte_flow_action_type dpaa2_supported_fs_action_type[] = {
 	RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT,
 };
 
-/* Max of enum rte_flow_item_type + 1, for both IPv4 and IPv6*/
-#define DPAA2_FLOW_ITEM_TYPE_GENERIC_IP (RTE_FLOW_ITEM_TYPE_META + 1)
-
 #ifndef __cplusplus
 static const struct rte_flow_item_eth dpaa2_flow_item_eth_mask = {
 	.hdr.dst_addr.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
@@ -151,11 +147,12 @@  static const struct rte_flow_item_sctp dpaa2_flow_item_sctp_mask = {
 static const struct rte_flow_item_gre dpaa2_flow_item_gre_mask = {
 	.protocol = RTE_BE16(0xffff),
 };
-
 #endif
 
-static inline void dpaa2_prot_field_string(
-	enum net_prot prot, uint32_t field,
+#define DPAA2_FLOW_DUMP printf
+
+static inline void
+dpaa2_prot_field_string(uint32_t prot, uint32_t field,
 	char *string)
 {
 	if (!dpaa2_flow_control_log)
@@ -230,60 +227,84 @@  static inline void dpaa2_prot_field_string(
 	}
 }
 
-static inline void dpaa2_flow_qos_table_extracts_log(
-	const struct dpaa2_dev_priv *priv, FILE *f)
+static inline void
+dpaa2_flow_qos_extracts_log(const struct dpaa2_dev_priv *priv)
 {
 	int idx;
 	char string[32];
+	const struct dpkg_profile_cfg *dpkg =
+		&priv->extract.qos_key_extract.dpkg;
+	const struct dpkg_extract *extract;
+	enum dpkg_extract_type type;
+	enum net_prot prot;
+	uint32_t field;
 
 	if (!dpaa2_flow_control_log)
 		return;
 
-	fprintf(f, "Setup QoS table: number of extracts: %d\r\n",
-			priv->extract.qos_key_extract.dpkg.num_extracts);
-	for (idx = 0; idx < priv->extract.qos_key_extract.dpkg.num_extracts;
-		idx++) {
-		dpaa2_prot_field_string(priv->extract.qos_key_extract.dpkg
-			.extracts[idx].extract.from_hdr.prot,
-			priv->extract.qos_key_extract.dpkg.extracts[idx]
-			.extract.from_hdr.field,
-			string);
-		fprintf(f, "%s", string);
-		if ((idx + 1) < priv->extract.qos_key_extract.dpkg.num_extracts)
-			fprintf(f, " / ");
-	}
-	fprintf(f, "\r\n");
+	DPAA2_FLOW_DUMP("QoS table: %d extracts\r\n",
+		dpkg->num_extracts);
+	for (idx = 0; idx < dpkg->num_extracts; idx++) {
+		extract = &dpkg->extracts[idx];
+		type = extract->type;
+		if (type == DPKG_EXTRACT_FROM_HDR) {
+			prot = extract->extract.from_hdr.prot;
+			field = extract->extract.from_hdr.field;
+			dpaa2_prot_field_string(prot, field,
+				string);
+		} else if (type == DPKG_EXTRACT_FROM_DATA) {
+			sprintf(string, "raw offset/len: %d/%d",
+				extract->extract.from_data.offset,
+				extract->extract.from_data.size);
+		}
+		DPAA2_FLOW_DUMP("%s", string);
+		if ((idx + 1) < dpkg->num_extracts)
+			DPAA2_FLOW_DUMP(" / ");
+	}
+	DPAA2_FLOW_DUMP("\r\n");
 }
 
-static inline void dpaa2_flow_fs_table_extracts_log(
-	const struct dpaa2_dev_priv *priv, int tc_id, FILE *f)
+static inline void
+dpaa2_flow_fs_extracts_log(const struct dpaa2_dev_priv *priv,
+	int tc_id)
 {
 	int idx;
 	char string[32];
+	const struct dpkg_profile_cfg *dpkg =
+		&priv->extract.tc_key_extract[tc_id].dpkg;
+	const struct dpkg_extract *extract;
+	enum dpkg_extract_type type;
+	enum net_prot prot;
+	uint32_t field;
 
 	if (!dpaa2_flow_control_log)
 		return;
 
-	fprintf(f, "Setup FS table: number of extracts of TC[%d]: %d\r\n",
-			tc_id, priv->extract.tc_key_extract[tc_id]
-			.dpkg.num_extracts);
-	for (idx = 0; idx < priv->extract.tc_key_extract[tc_id]
-		.dpkg.num_extracts; idx++) {
-		dpaa2_prot_field_string(priv->extract.tc_key_extract[tc_id]
-			.dpkg.extracts[idx].extract.from_hdr.prot,
-			priv->extract.tc_key_extract[tc_id].dpkg.extracts[idx]
-			.extract.from_hdr.field,
-			string);
-		fprintf(f, "%s", string);
-		if ((idx + 1) < priv->extract.tc_key_extract[tc_id]
-			.dpkg.num_extracts)
-			fprintf(f, " / ");
-	}
-	fprintf(f, "\r\n");
+	DPAA2_FLOW_DUMP("FS table: %d extracts in TC[%d]\r\n",
+		dpkg->num_extracts, tc_id);
+	for (idx = 0; idx < dpkg->num_extracts; idx++) {
+		extract = &dpkg->extracts[idx];
+		type = extract->type;
+		if (type == DPKG_EXTRACT_FROM_HDR) {
+			prot = extract->extract.from_hdr.prot;
+			field = extract->extract.from_hdr.field;
+			dpaa2_prot_field_string(prot, field,
+				string);
+		} else if (type == DPKG_EXTRACT_FROM_DATA) {
+			sprintf(string, "raw offset/len: %d/%d",
+				extract->extract.from_data.offset,
+				extract->extract.from_data.size);
+		}
+		DPAA2_FLOW_DUMP("%s", string);
+		if ((idx + 1) < dpkg->num_extracts)
+			DPAA2_FLOW_DUMP(" / ");
+	}
+	DPAA2_FLOW_DUMP("\r\n");
 }
 
-static inline void dpaa2_flow_qos_entry_log(
-	const char *log_info, const struct rte_flow *flow, int qos_index, FILE *f)
+static inline void
+dpaa2_flow_qos_entry_log(const char *log_info,
+	const struct dpaa2_dev_flow *flow, int qos_index)
 {
 	int idx;
 	uint8_t *key, *mask;
@@ -291,27 +312,34 @@  static inline void dpaa2_flow_qos_entry_log(
 	if (!dpaa2_flow_control_log)
 		return;
 
-	fprintf(f, "\r\n%s QoS entry[%d] for TC[%d], extracts size is %d\r\n",
-		log_info, qos_index, flow->tc_id, flow->qos_real_key_size);
-
-	key = (uint8_t *)(size_t)flow->qos_rule.key_iova;
-	mask = (uint8_t *)(size_t)flow->qos_rule.mask_iova;
+	if (qos_index >= 0) {
+		DPAA2_FLOW_DUMP("%s QoS entry[%d](size %d/%d) for TC[%d]\r\n",
+			log_info, qos_index, flow->qos_rule_size,
+			flow->qos_rule.key_size,
+			flow->tc_id);
+	} else {
+		DPAA2_FLOW_DUMP("%s QoS entry(size %d/%d) for TC[%d]\r\n",
+			log_info, flow->qos_rule_size,
+			flow->qos_rule.key_size,
+			flow->tc_id);
+	}
 
-	fprintf(f, "key:\r\n");
-	for (idx = 0; idx < flow->qos_real_key_size; idx++)
-		fprintf(f, "%02x ", key[idx]);
+	key = flow->qos_key_addr;
+	mask = flow->qos_mask_addr;
 
-	fprintf(f, "\r\nmask:\r\n");
-	for (idx = 0; idx < flow->qos_real_key_size; idx++)
-		fprintf(f, "%02x ", mask[idx]);
+	DPAA2_FLOW_DUMP("key:\r\n");
+	for (idx = 0; idx < flow->qos_rule_size; idx++)
+		DPAA2_FLOW_DUMP("%02x ", key[idx]);
 
-	fprintf(f, "\r\n%s QoS ipsrc: %d, ipdst: %d\r\n", log_info,
-		flow->ipaddr_rule.qos_ipsrc_offset,
-		flow->ipaddr_rule.qos_ipdst_offset);
+	DPAA2_FLOW_DUMP("\r\nmask:\r\n");
+	for (idx = 0; idx < flow->qos_rule_size; idx++)
+		DPAA2_FLOW_DUMP("%02x ", mask[idx]);
+	DPAA2_FLOW_DUMP("\r\n");
 }
 
-static inline void dpaa2_flow_fs_entry_log(
-	const char *log_info, const struct rte_flow *flow, FILE *f)
+static inline void
+dpaa2_flow_fs_entry_log(const char *log_info,
+	const struct dpaa2_dev_flow *flow)
 {
 	int idx;
 	uint8_t *key, *mask;
@@ -319,187 +347,432 @@  static inline void dpaa2_flow_fs_entry_log(
 	if (!dpaa2_flow_control_log)
 		return;
 
-	fprintf(f, "\r\n%s FS/TC entry[%d] of TC[%d], extracts size is %d\r\n",
-		log_info, flow->tc_index, flow->tc_id, flow->fs_real_key_size);
+	DPAA2_FLOW_DUMP("%s FS/TC entry[%d](size %d/%d) of TC[%d]\r\n",
+		log_info, flow->tc_index,
+		flow->fs_rule_size, flow->fs_rule.key_size,
+		flow->tc_id);
+
+	key = flow->fs_key_addr;
+	mask = flow->fs_mask_addr;
+
+	DPAA2_FLOW_DUMP("key:\r\n");
+	for (idx = 0; idx < flow->fs_rule_size; idx++)
+		DPAA2_FLOW_DUMP("%02x ", key[idx]);
+
+	DPAA2_FLOW_DUMP("\r\nmask:\r\n");
+	for (idx = 0; idx < flow->fs_rule_size; idx++)
+		DPAA2_FLOW_DUMP("%02x ", mask[idx]);
+	DPAA2_FLOW_DUMP("\r\n");
+}
 
-	key = (uint8_t *)(size_t)flow->fs_rule.key_iova;
-	mask = (uint8_t *)(size_t)flow->fs_rule.mask_iova;
+static int
+dpaa2_flow_ip_address_extract(enum net_prot prot,
+	uint32_t field)
+{
+	if (prot == NET_PROT_IPV4 &&
+		(field == NH_FLD_IPV4_SRC_IP ||
+		field == NH_FLD_IPV4_DST_IP))
+		return true;
+	else if (prot == NET_PROT_IPV6 &&
+		(field == NH_FLD_IPV6_SRC_IP ||
+		field == NH_FLD_IPV6_DST_IP))
+		return true;
+	else if (prot == NET_PROT_IP &&
+		(field == NH_FLD_IP_SRC ||
+		field == NH_FLD_IP_DST))
+		return true;
 
-	fprintf(f, "key:\r\n");
-	for (idx = 0; idx < flow->fs_real_key_size; idx++)
-		fprintf(f, "%02x ", key[idx]);
+	return false;
+}
 
-	fprintf(f, "\r\nmask:\r\n");
-	for (idx = 0; idx < flow->fs_real_key_size; idx++)
-		fprintf(f, "%02x ", mask[idx]);
+static int
+dpaa2_flow_l4_src_port_extract(enum net_prot prot,
+	uint32_t field)
+{
+	if (prot == NET_PROT_TCP &&
+		field == NH_FLD_TCP_PORT_SRC)
+		return true;
+	else if (prot == NET_PROT_UDP &&
+		field == NH_FLD_UDP_PORT_SRC)
+		return true;
+	else if (prot == NET_PROT_SCTP &&
+		field == NH_FLD_SCTP_PORT_SRC)
+		return true;
+
+	return false;
+}
 
-	fprintf(f, "\r\n%s FS ipsrc: %d, ipdst: %d\r\n", log_info,
-		flow->ipaddr_rule.fs_ipsrc_offset,
-		flow->ipaddr_rule.fs_ipdst_offset);
+static int
+dpaa2_flow_l4_dst_port_extract(enum net_prot prot,
+	uint32_t field)
+{
+	if (prot == NET_PROT_TCP &&
+		field == NH_FLD_TCP_PORT_DST)
+		return true;
+	else if (prot == NET_PROT_UDP &&
+		field == NH_FLD_UDP_PORT_DST)
+		return true;
+	else if (prot == NET_PROT_SCTP &&
+		field == NH_FLD_SCTP_PORT_DST)
+		return true;
+
+	return false;
 }
 
-static inline void dpaa2_flow_extract_key_set(
-	struct dpaa2_key_info *key_info, int index, uint8_t size)
+static int
+dpaa2_flow_add_qos_rule(struct dpaa2_dev_priv *priv,
+	struct dpaa2_dev_flow *flow)
 {
-	key_info->key_size[index] = size;
-	if (index > 0) {
-		key_info->key_offset[index] =
-			key_info->key_offset[index - 1] +
-			key_info->key_size[index - 1];
-	} else {
-		key_info->key_offset[index] = 0;
+	uint16_t qos_index;
+	int ret;
+	struct fsl_mc_io *dpni = priv->hw;
+
+	if (priv->num_rx_tc <= 1 &&
+		flow->action_type != RTE_FLOW_ACTION_TYPE_RSS) {
+		DPAA2_PMD_WARN("No QoS Table for FS");
+		return -EINVAL;
 	}
-	key_info->key_total_size += size;
+
+	/* QoS entry added is only effective for multiple TCs.*/
+	qos_index = flow->tc_id * priv->fs_entries + flow->tc_index;
+	if (qos_index >= priv->qos_entries) {
+		DPAA2_PMD_ERR("QoS table full(%d >= %d)",
+			qos_index, priv->qos_entries);
+		return -EINVAL;
+	}
+
+	dpaa2_flow_qos_entry_log("Start add", flow, qos_index);
+
+	ret = dpni_add_qos_entry(dpni, CMD_PRI_LOW,
+			priv->token, &flow->qos_rule,
+			flow->tc_id, qos_index,
+			0, 0);
+	if (ret < 0) {
+		DPAA2_PMD_ERR("Add entry(%d) to table(%d) failed",
+			qos_index, flow->tc_id);
+		return ret;
+	}
+
+	return 0;
 }
 
-static int dpaa2_flow_extract_add(
-	struct dpaa2_key_extract *key_extract,
-	enum net_prot prot,
-	uint32_t field, uint8_t field_size)
+static int
+dpaa2_flow_add_fs_rule(struct dpaa2_dev_priv *priv,
+	struct dpaa2_dev_flow *flow)
 {
-	int index, ip_src = -1, ip_dst = -1;
-	struct dpkg_profile_cfg *dpkg = &key_extract->dpkg;
-	struct dpaa2_key_info *key_info = &key_extract->key_info;
+	int ret;
+	struct fsl_mc_io *dpni = priv->hw;
 
-	if (dpkg->num_extracts >=
-		DPKG_MAX_NUM_OF_EXTRACTS) {
-		DPAA2_PMD_WARN("Number of extracts overflows");
-		return -1;
+	if (flow->tc_index >= priv->fs_entries) {
+		DPAA2_PMD_ERR("FS table full(%d >= %d)",
+			flow->tc_index, priv->fs_entries);
+		return -EINVAL;
 	}
-	/* Before reorder, the IP SRC and IP DST are already last
-	 * extract(s).
-	 */
-	for (index = 0; index < dpkg->num_extracts; index++) {
-		if (dpkg->extracts[index].extract.from_hdr.prot ==
-			NET_PROT_IP) {
-			if (dpkg->extracts[index].extract.from_hdr.field ==
-				NH_FLD_IP_SRC) {
-				ip_src = index;
-			}
-			if (dpkg->extracts[index].extract.from_hdr.field ==
-				NH_FLD_IP_DST) {
-				ip_dst = index;
+
+	dpaa2_flow_fs_entry_log("Start add", flow);
+
+	ret = dpni_add_fs_entry(dpni, CMD_PRI_LOW,
+			priv->token, flow->tc_id,
+			flow->tc_index, &flow->fs_rule,
+			&flow->fs_action_cfg);
+	if (ret < 0) {
+		DPAA2_PMD_ERR("Add rule(%d) to FS table(%d) failed",
+			flow->tc_index, flow->tc_id);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int
+dpaa2_flow_rule_insert_hole(struct dpaa2_dev_flow *flow,
+	int offset, int size,
+	enum dpaa2_flow_dist_type dist_type)
+{
+	int end;
+
+	if (dist_type & DPAA2_FLOW_QOS_TYPE) {
+		end = flow->qos_rule_size;
+		if (end > offset) {
+			memmove(flow->qos_key_addr + offset + size,
+					flow->qos_key_addr + offset,
+					end - offset);
+			memset(flow->qos_key_addr + offset,
+					0, size);
+
+			memmove(flow->qos_mask_addr + offset + size,
+					flow->qos_mask_addr + offset,
+					end - offset);
+			memset(flow->qos_mask_addr + offset,
+					0, size);
+		}
+		flow->qos_rule_size += size;
+	}
+
+	if (dist_type & DPAA2_FLOW_FS_TYPE) {
+		end = flow->fs_rule_size;
+		if (end > offset) {
+			memmove(flow->fs_key_addr + offset + size,
+					flow->fs_key_addr + offset,
+					end - offset);
+			memset(flow->fs_key_addr + offset,
+					0, size);
+
+			memmove(flow->fs_mask_addr + offset + size,
+					flow->fs_mask_addr + offset,
+					end - offset);
+			memset(flow->fs_mask_addr + offset,
+					0, size);
+		}
+		flow->fs_rule_size += size;
+	}
+
+	return 0;
+}
+
+static int
+dpaa2_flow_rule_add_all(struct dpaa2_dev_priv *priv,
+	enum dpaa2_flow_dist_type dist_type,
+	uint16_t entry_size, uint8_t tc_id)
+{
+	struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows);
+	int ret;
+
+	while (curr) {
+		if (dist_type & DPAA2_FLOW_QOS_TYPE) {
+			if (priv->num_rx_tc > 1 ||
+				curr->action_type ==
+				RTE_FLOW_ACTION_TYPE_RSS) {
+				curr->qos_rule.key_size = entry_size;
+				ret = dpaa2_flow_add_qos_rule(priv, curr);
+				if (ret)
+					return ret;
 			}
 		}
+		if (dist_type & DPAA2_FLOW_FS_TYPE &&
+			curr->tc_id == tc_id) {
+			curr->fs_rule.key_size = entry_size;
+			ret = dpaa2_flow_add_fs_rule(priv, curr);
+			if (ret)
+				return ret;
+		}
+		curr = LIST_NEXT(curr, next);
 	}
 
-	if (ip_src >= 0)
-		RTE_ASSERT((ip_src + 2) >= dpkg->num_extracts);
+	return 0;
+}
 
-	if (ip_dst >= 0)
-		RTE_ASSERT((ip_dst + 2) >= dpkg->num_extracts);
+static int
+dpaa2_flow_qos_rule_insert_hole(struct dpaa2_dev_priv *priv,
+	int offset, int size)
+{
+	struct dpaa2_dev_flow *curr;
+	int ret;
 
-	if (prot == NET_PROT_IP &&
-		(field == NH_FLD_IP_SRC ||
-		field == NH_FLD_IP_DST)) {
-		index = dpkg->num_extracts;
+	curr = priv->curr;
+	if (!curr) {
+		DPAA2_PMD_ERR("Current qos flow insert hole failed.");
+		return -EINVAL;
 	} else {
-		if (ip_src >= 0 && ip_dst >= 0)
-			index = dpkg->num_extracts - 2;
-		else if (ip_src >= 0 || ip_dst >= 0)
-			index = dpkg->num_extracts - 1;
-		else
-			index = dpkg->num_extracts;
+		ret = dpaa2_flow_rule_insert_hole(curr, offset, size,
+				DPAA2_FLOW_QOS_TYPE);
+		if (ret)
+			return ret;
 	}
 
-	dpkg->extracts[index].type =	DPKG_EXTRACT_FROM_HDR;
-	dpkg->extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
-	dpkg->extracts[index].extract.from_hdr.prot = prot;
-	dpkg->extracts[index].extract.from_hdr.field = field;
-	if (prot == NET_PROT_IP &&
-		(field == NH_FLD_IP_SRC ||
-		field == NH_FLD_IP_DST)) {
-		dpaa2_flow_extract_key_set(key_info, index, 0);
+	curr = LIST_FIRST(&priv->flows);
+	while (curr) {
+		ret = dpaa2_flow_rule_insert_hole(curr, offset, size,
+				DPAA2_FLOW_QOS_TYPE);
+		if (ret)
+			return ret;
+		curr = LIST_NEXT(curr, next);
+	}
+
+	return 0;
+}
+
+static int
+dpaa2_flow_fs_rule_insert_hole(struct dpaa2_dev_priv *priv,
+	int offset, int size, int tc_id)
+{
+	struct dpaa2_dev_flow *curr;
+	int ret;
+
+	curr = priv->curr;
+	if (!curr || curr->tc_id != tc_id) {
+		DPAA2_PMD_ERR("Current flow insert hole failed.");
+		return -EINVAL;
 	} else {
-		dpaa2_flow_extract_key_set(key_info, index, field_size);
+		ret = dpaa2_flow_rule_insert_hole(curr, offset, size,
+				DPAA2_FLOW_FS_TYPE);
+		if (ret)
+			return ret;
 	}
 
-	if (prot == NET_PROT_IP) {
-		if (field == NH_FLD_IP_SRC) {
-			if (key_info->ipv4_dst_offset >= 0) {
-				key_info->ipv4_src_offset =
-					key_info->ipv4_dst_offset +
-					NH_FLD_IPV4_ADDR_SIZE;
-			} else {
-				key_info->ipv4_src_offset =
-					key_info->key_offset[index - 1] +
-						key_info->key_size[index - 1];
-			}
-			if (key_info->ipv6_dst_offset >= 0) {
-				key_info->ipv6_src_offset =
-					key_info->ipv6_dst_offset +
-					NH_FLD_IPV6_ADDR_SIZE;
-			} else {
-				key_info->ipv6_src_offset =
-					key_info->key_offset[index - 1] +
-						key_info->key_size[index - 1];
-			}
-		} else if (field == NH_FLD_IP_DST) {
-			if (key_info->ipv4_src_offset >= 0) {
-				key_info->ipv4_dst_offset =
-					key_info->ipv4_src_offset +
-					NH_FLD_IPV4_ADDR_SIZE;
-			} else {
-				key_info->ipv4_dst_offset =
-					key_info->key_offset[index - 1] +
-						key_info->key_size[index - 1];
-			}
-			if (key_info->ipv6_src_offset >= 0) {
-				key_info->ipv6_dst_offset =
-					key_info->ipv6_src_offset +
-					NH_FLD_IPV6_ADDR_SIZE;
-			} else {
-				key_info->ipv6_dst_offset =
-					key_info->key_offset[index - 1] +
-						key_info->key_size[index - 1];
-			}
+	curr = LIST_FIRST(&priv->flows);
+
+	while (curr) {
+		if (curr->tc_id != tc_id) {
+			curr = LIST_NEXT(curr, next);
+			continue;
 		}
+		ret = dpaa2_flow_rule_insert_hole(curr, offset, size,
+				DPAA2_FLOW_FS_TYPE);
+		if (ret)
+			return ret;
+		curr = LIST_NEXT(curr, next);
 	}
 
-	if (index == dpkg->num_extracts) {
-		dpkg->num_extracts++;
-		return 0;
+	return 0;
+}
+
+/* Move IPv4/IPv6 addresses to fill new extract previous IP address.
+ * Current MC/WRIOP only support generic IP extract but IP address
+ * is not fixed, so we have to put them at end of extracts, otherwise,
+ * the extracts position following them can't be identified.
+ */
+static int
+dpaa2_flow_key_profile_advance(enum net_prot prot,
+	uint32_t field, uint8_t field_size,
+	struct dpaa2_dev_priv *priv,
+	enum dpaa2_flow_dist_type dist_type, int tc_id,
+	int *insert_offset)
+{
+	int offset, ret;
+	struct dpaa2_key_profile *key_profile;
+	int num, pos;
+
+	if (dpaa2_flow_ip_address_extract(prot, field)) {
+		DPAA2_PMD_ERR("%s only for none IP address extract",
+			__func__);
+		return -EINVAL;
+	}
+
+	if (dist_type == DPAA2_FLOW_QOS_TYPE)
+		key_profile = &priv->extract.qos_key_extract.key_profile;
+	else
+		key_profile = &priv->extract.tc_key_extract[tc_id].key_profile;
+
+	num = key_profile->num;
+
+	if (num >= DPKG_MAX_NUM_OF_EXTRACTS) {
+		DPAA2_PMD_ERR("Number of extracts overflows");
+		return -EINVAL;
+	}
+
+	if (key_profile->ip_addr_type != IP_NONE_ADDR_EXTRACT) {
+		offset = key_profile->ip_addr_extract_off;
+		pos = key_profile->ip_addr_extract_pos;
+		key_profile->ip_addr_extract_pos++;
+		key_profile->ip_addr_extract_off += field_size;
+		if (dist_type == DPAA2_FLOW_QOS_TYPE) {
+			ret = dpaa2_flow_qos_rule_insert_hole(priv,
+					offset, field_size);
+		} else {
+			ret = dpaa2_flow_fs_rule_insert_hole(priv,
+				offset, field_size, tc_id);
+		}
+		if (ret)
+			return ret;
+	} else {
+		pos = num;
+	}
+
+	if (pos > 0) {
+		key_profile->key_offset[pos] =
+			key_profile->key_offset[pos - 1] +
+			key_profile->key_size[pos - 1];
+	} else {
+		key_profile->key_offset[pos] = 0;
+	}
+
+	key_profile->key_size[pos] = field_size;
+	key_profile->prot_field[pos].prot = prot;
+	key_profile->prot_field[pos].key_field = field;
+	key_profile->num++;
+
+	if (insert_offset)
+		*insert_offset = key_profile->key_offset[pos];
+
+	if (dpaa2_flow_l4_src_port_extract(prot, field)) {
+		key_profile->l4_src_port_present = 1;
+		key_profile->l4_src_port_pos = pos;
+		key_profile->l4_src_port_offset =
+			key_profile->key_offset[pos];
+	} else if (dpaa2_flow_l4_dst_port_extract(prot, field)) {
+		key_profile->l4_dst_port_present = 1;
+		key_profile->l4_dst_port_pos = pos;
+		key_profile->l4_dst_port_offset =
+			key_profile->key_offset[pos];
+	}
+	key_profile->key_max_size += field_size;
+
+	return pos;
+}
+
+static int
+dpaa2_flow_extract_add_hdr(enum net_prot prot,
+	uint32_t field, uint8_t field_size,
+	struct dpaa2_dev_priv *priv,
+	enum dpaa2_flow_dist_type dist_type, int tc_id,
+	int *insert_offset)
+{
+	int pos, i;
+	struct dpaa2_key_extract *key_extract;
+	struct dpkg_profile_cfg *dpkg;
+	struct dpkg_extract *extracts;
+
+	if (dist_type == DPAA2_FLOW_QOS_TYPE)
+		key_extract = &priv->extract.qos_key_extract;
+	else
+		key_extract = &priv->extract.tc_key_extract[tc_id];
+
+	dpkg = &key_extract->dpkg;
+	extracts = dpkg->extracts;
+
+	if (dpaa2_flow_ip_address_extract(prot, field)) {
+		DPAA2_PMD_ERR("%s only for none IP address extract",
+			__func__);
+		return -EINVAL;
+	}
+
+	if (dpkg->num_extracts >= DPKG_MAX_NUM_OF_EXTRACTS) {
+		DPAA2_PMD_ERR("Number of extracts overflows");
+		return -EINVAL;
 	}
 
-	if (ip_src >= 0) {
-		ip_src++;
-		dpkg->extracts[ip_src].type =
-			DPKG_EXTRACT_FROM_HDR;
-		dpkg->extracts[ip_src].extract.from_hdr.type =
-			DPKG_FULL_FIELD;
-		dpkg->extracts[ip_src].extract.from_hdr.prot =
-			NET_PROT_IP;
-		dpkg->extracts[ip_src].extract.from_hdr.field =
-			NH_FLD_IP_SRC;
-		dpaa2_flow_extract_key_set(key_info, ip_src, 0);
-		key_info->ipv4_src_offset += field_size;
-		key_info->ipv6_src_offset += field_size;
-	}
-	if (ip_dst >= 0) {
-		ip_dst++;
-		dpkg->extracts[ip_dst].type =
-			DPKG_EXTRACT_FROM_HDR;
-		dpkg->extracts[ip_dst].extract.from_hdr.type =
-			DPKG_FULL_FIELD;
-		dpkg->extracts[ip_dst].extract.from_hdr.prot =
-			NET_PROT_IP;
-		dpkg->extracts[ip_dst].extract.from_hdr.field =
-			NH_FLD_IP_DST;
-		dpaa2_flow_extract_key_set(key_info, ip_dst, 0);
-		key_info->ipv4_dst_offset += field_size;
-		key_info->ipv6_dst_offset += field_size;
+	pos = dpaa2_flow_key_profile_advance(prot,
+			field, field_size, priv,
+			dist_type, tc_id,
+			insert_offset);
+	if (pos < 0)
+		return pos;
+
+	if (pos != dpkg->num_extracts) {
+		/* Not the last pos, must have IP address extract.*/
+		for (i = dpkg->num_extracts - 1; i >= pos; i--) {
+			memcpy(&extracts[i + 1],
+				&extracts[i], sizeof(struct dpkg_extract));
+		}
 	}
 
+	extracts[pos].type = DPKG_EXTRACT_FROM_HDR;
+	extracts[pos].extract.from_hdr.prot = prot;
+	extracts[pos].extract.from_hdr.type = DPKG_FULL_FIELD;
+	extracts[pos].extract.from_hdr.field = field;
+
 	dpkg->num_extracts++;
 
 	return 0;
 }
 
-static int dpaa2_flow_extract_add_raw(struct dpaa2_key_extract *key_extract,
-				      int size)
+static int
+dpaa2_flow_extract_add_raw(struct dpaa2_key_extract *key_extract,
+	int size)
 {
 	struct dpkg_profile_cfg *dpkg = &key_extract->dpkg;
-	struct dpaa2_key_info *key_info = &key_extract->key_info;
+	struct dpaa2_key_profile *key_info = &key_extract->key_profile;
 	int last_extract_size, index;
 
 	if (dpkg->num_extracts != 0 && dpkg->extracts[0].type !=
@@ -527,83 +800,58 @@  static int dpaa2_flow_extract_add_raw(struct dpaa2_key_extract *key_extract,
 			DPAA2_FLOW_MAX_KEY_SIZE * index;
 	}
 
-	key_info->key_total_size = size;
+	key_info->key_max_size = size;
 	return 0;
 }
 
-/* Protocol discrimination.
- * Discriminate IPv4/IPv6/vLan by Eth type.
- * Discriminate UDP/TCP/ICMP by next proto of IP.
- */
 static inline int
-dpaa2_flow_proto_discrimination_extract(
-	struct dpaa2_key_extract *key_extract,
-	enum rte_flow_item_type type)
+dpaa2_flow_extract_search(struct dpaa2_key_profile *key_profile,
+	enum net_prot prot, uint32_t key_field)
 {
-	if (type == RTE_FLOW_ITEM_TYPE_ETH) {
-		return dpaa2_flow_extract_add(
-				key_extract, NET_PROT_ETH,
-				NH_FLD_ETH_TYPE,
-				sizeof(rte_be16_t));
-	} else if (type == (enum rte_flow_item_type)
-		DPAA2_FLOW_ITEM_TYPE_GENERIC_IP) {
-		return dpaa2_flow_extract_add(
-				key_extract, NET_PROT_IP,
-				NH_FLD_IP_PROTO,
-				NH_FLD_IP_PROTO_SIZE);
-	}
-
-	return -1;
-}
+	int pos;
+	struct key_prot_field *prot_field;
 
-static inline int dpaa2_flow_extract_search(
-	struct dpkg_profile_cfg *dpkg,
-	enum net_prot prot, uint32_t field)
-{
-	int i;
+	if (dpaa2_flow_ip_address_extract(prot, key_field)) {
+		DPAA2_PMD_ERR("%s only for none IP address extract",
+			__func__);
+		return -EINVAL;
+	}
 
-	for (i = 0; i < dpkg->num_extracts; i++) {
-		if (dpkg->extracts[i].extract.from_hdr.prot == prot &&
-			dpkg->extracts[i].extract.from_hdr.field == field) {
-			return i;
+	prot_field = key_profile->prot_field;
+	for (pos = 0; pos < key_profile->num; pos++) {
+		if (prot_field[pos].prot == prot &&
+			prot_field[pos].key_field == key_field) {
+			return pos;
 		}
 	}
 
-	return -1;
+	if (dpaa2_flow_l4_src_port_extract(prot, key_field)) {
+		if (key_profile->l4_src_port_present)
+			return key_profile->l4_src_port_pos;
+	} else if (dpaa2_flow_l4_dst_port_extract(prot, key_field)) {
+		if (key_profile->l4_dst_port_present)
+			return key_profile->l4_dst_port_pos;
+	}
+
+	return -ENXIO;
 }
 
-static inline int dpaa2_flow_extract_key_offset(
-	struct dpaa2_key_extract *key_extract,
-	enum net_prot prot, uint32_t field)
+static inline int
+dpaa2_flow_extract_key_offset(struct dpaa2_key_profile *key_profile,
+	enum net_prot prot, uint32_t key_field)
 {
 	int i;
-	struct dpkg_profile_cfg *dpkg = &key_extract->dpkg;
-	struct dpaa2_key_info *key_info = &key_extract->key_info;
 
-	if (prot == NET_PROT_IPV4 ||
-		prot == NET_PROT_IPV6)
-		i = dpaa2_flow_extract_search(dpkg, NET_PROT_IP, field);
+	i = dpaa2_flow_extract_search(key_profile, prot, key_field);
+
+	if (i >= 0)
+		return key_profile->key_offset[i];
 	else
-		i = dpaa2_flow_extract_search(dpkg, prot, field);
-
-	if (i >= 0) {
-		if (prot == NET_PROT_IPV4 && field == NH_FLD_IP_SRC)
-			return key_info->ipv4_src_offset;
-		else if (prot == NET_PROT_IPV4 && field == NH_FLD_IP_DST)
-			return key_info->ipv4_dst_offset;
-		else if (prot == NET_PROT_IPV6 && field == NH_FLD_IP_SRC)
-			return key_info->ipv6_src_offset;
-		else if (prot == NET_PROT_IPV6 && field == NH_FLD_IP_DST)
-			return key_info->ipv6_dst_offset;
-		else
-			return key_info->key_offset[i];
-	} else {
-		return -1;
-	}
+		return i;
 }
 
-struct proto_discrimination {
-	enum rte_flow_item_type type;
+struct prev_proto_field_id {
+	enum net_prot prot;
 	union {
 		rte_be16_t eth_type;
 		uint8_t ip_proto;
@@ -611,103 +859,134 @@  struct proto_discrimination {
 };
 
 static int
-dpaa2_flow_proto_discrimination_rule(
-	struct dpaa2_dev_priv *priv, struct rte_flow *flow,
-	struct proto_discrimination proto, int group)
+dpaa2_flow_prev_proto_rule(struct dpaa2_dev_priv *priv,
+	struct dpaa2_dev_flow *flow,
+	const struct prev_proto_field_id *prev_proto,
+	int group,
+	enum dpaa2_flow_dist_type dist_type)
 {
-	enum net_prot prot;
-	uint32_t field;
 	int offset;
-	size_t key_iova;
-	size_t mask_iova;
+	uint8_t *key_addr;
+	uint8_t *mask_addr;
+	uint32_t field = 0;
 	rte_be16_t eth_type;
 	uint8_t ip_proto;
+	struct dpaa2_key_extract *key_extract;
+	struct dpaa2_key_profile *key_profile;
 
-	if (proto.type == RTE_FLOW_ITEM_TYPE_ETH) {
-		prot = NET_PROT_ETH;
+	if (prev_proto->prot == NET_PROT_ETH) {
 		field = NH_FLD_ETH_TYPE;
-	} else if (proto.type == DPAA2_FLOW_ITEM_TYPE_GENERIC_IP) {
-		prot = NET_PROT_IP;
+	} else if (prev_proto->prot == NET_PROT_IP) {
 		field = NH_FLD_IP_PROTO;
 	} else {
-		DPAA2_PMD_ERR(
-			"Only Eth and IP support to discriminate next proto.");
-		return -1;
-	}
-
-	offset = dpaa2_flow_extract_key_offset(&priv->extract.qos_key_extract,
-			prot, field);
-	if (offset < 0) {
-		DPAA2_PMD_ERR("QoS prot %d field %d extract failed",
-				prot, field);
-		return -1;
-	}
-	key_iova = flow->qos_rule.key_iova + offset;
-	mask_iova = flow->qos_rule.mask_iova + offset;
-	if (proto.type == RTE_FLOW_ITEM_TYPE_ETH) {
-		eth_type = proto.eth_type;
-		memcpy((void *)key_iova, (const void *)(&eth_type),
-			sizeof(rte_be16_t));
-		eth_type = 0xffff;
-		memcpy((void *)mask_iova, (const void *)(&eth_type),
-			sizeof(rte_be16_t));
-	} else {
-		ip_proto = proto.ip_proto;
-		memcpy((void *)key_iova, (const void *)(&ip_proto),
-			sizeof(uint8_t));
-		ip_proto = 0xff;
-		memcpy((void *)mask_iova, (const void *)(&ip_proto),
-			sizeof(uint8_t));
-	}
-
-	offset = dpaa2_flow_extract_key_offset(
-			&priv->extract.tc_key_extract[group],
-			prot, field);
-	if (offset < 0) {
-		DPAA2_PMD_ERR("FS prot %d field %d extract failed",
-				prot, field);
-		return -1;
+		DPAA2_PMD_ERR("Prev proto(%d) not support!",
+			prev_proto->prot);
+		return -EINVAL;
 	}
-	key_iova = flow->fs_rule.key_iova + offset;
-	mask_iova = flow->fs_rule.mask_iova + offset;
 
-	if (proto.type == RTE_FLOW_ITEM_TYPE_ETH) {
-		eth_type = proto.eth_type;
-		memcpy((void *)key_iova, (const void *)(&eth_type),
-			sizeof(rte_be16_t));
-		eth_type = 0xffff;
-		memcpy((void *)mask_iova, (const void *)(&eth_type),
-			sizeof(rte_be16_t));
-	} else {
-		ip_proto = proto.ip_proto;
-		memcpy((void *)key_iova, (const void *)(&ip_proto),
-			sizeof(uint8_t));
-		ip_proto = 0xff;
-		memcpy((void *)mask_iova, (const void *)(&ip_proto),
-			sizeof(uint8_t));
+	if (dist_type & DPAA2_FLOW_QOS_TYPE) {
+		key_extract = &priv->extract.qos_key_extract;
+		key_profile = &key_extract->key_profile;
+
+		offset = dpaa2_flow_extract_key_offset(key_profile,
+				prev_proto->prot, field);
+		if (offset < 0) {
+			DPAA2_PMD_ERR("%s QoS key extract failed", __func__);
+			return -EINVAL;
+		}
+		key_addr = flow->qos_key_addr + offset;
+		mask_addr = flow->qos_mask_addr + offset;
+		if (prev_proto->prot == NET_PROT_ETH) {
+			eth_type = prev_proto->eth_type;
+			memcpy(key_addr, &eth_type, sizeof(rte_be16_t));
+			eth_type = 0xffff;
+			memcpy(mask_addr, &eth_type, sizeof(rte_be16_t));
+			flow->qos_rule_size += sizeof(rte_be16_t);
+		} else if (prev_proto->prot == NET_PROT_IP) {
+			ip_proto = prev_proto->ip_proto;
+			memcpy(key_addr, &ip_proto, sizeof(uint8_t));
+			ip_proto = 0xff;
+			memcpy(mask_addr, &ip_proto, sizeof(uint8_t));
+			flow->qos_rule_size += sizeof(uint8_t);
+		} else {
+			DPAA2_PMD_ERR("Invalid Prev proto(%d)",
+				prev_proto->prot);
+			return -EINVAL;
+		}
+	}
+
+	if (dist_type & DPAA2_FLOW_FS_TYPE) {
+		key_extract = &priv->extract.tc_key_extract[group];
+		key_profile = &key_extract->key_profile;
+
+		offset = dpaa2_flow_extract_key_offset(key_profile,
+				prev_proto->prot, field);
+		if (offset < 0) {
+			DPAA2_PMD_ERR("%s TC[%d] key extract failed",
+				__func__, group);
+			return -EINVAL;
+		}
+		key_addr = flow->fs_key_addr + offset;
+		mask_addr = flow->fs_mask_addr + offset;
+
+		if (prev_proto->prot == NET_PROT_ETH) {
+			eth_type = prev_proto->eth_type;
+			memcpy(key_addr, &eth_type, sizeof(rte_be16_t));
+			eth_type = 0xffff;
+			memcpy(mask_addr, &eth_type, sizeof(rte_be16_t));
+			flow->fs_rule_size += sizeof(rte_be16_t);
+		} else if (prev_proto->prot == NET_PROT_IP) {
+			ip_proto = prev_proto->ip_proto;
+			memcpy(key_addr, &ip_proto, sizeof(uint8_t));
+			ip_proto = 0xff;
+			memcpy(mask_addr, &ip_proto, sizeof(uint8_t));
+			flow->fs_rule_size += sizeof(uint8_t);
+		} else {
+			DPAA2_PMD_ERR("Invalid Prev proto(%d)",
+				prev_proto->prot);
+			return -EINVAL;
+		}
 	}
 
 	return 0;
 }
 
 static inline int
-dpaa2_flow_rule_data_set(
-	struct dpaa2_key_extract *key_extract,
-	struct dpni_rule_cfg *rule,
-	enum net_prot prot, uint32_t field,
-	const void *key, const void *mask, int size)
+dpaa2_flow_hdr_rule_data_set(struct dpaa2_dev_flow *flow,
+	struct dpaa2_key_profile *key_profile,
+	enum net_prot prot, uint32_t field, int size,
+	const void *key, const void *mask,
+	enum dpaa2_flow_dist_type dist_type)
 {
-	int offset = dpaa2_flow_extract_key_offset(key_extract,
-				prot, field);
+	int offset;
 
+	if (dpaa2_flow_ip_address_extract(prot, field)) {
+		DPAA2_PMD_ERR("%s only for none IP address extract",
+			__func__);
+		return -EINVAL;
+	}
+
+	offset = dpaa2_flow_extract_key_offset(key_profile,
+			prot, field);
 	if (offset < 0) {
-		DPAA2_PMD_ERR("prot %d, field %d extract failed",
+		DPAA2_PMD_ERR("P(%d)/F(%d) does not exist!",
 			prot, field);
-		return -1;
+		return -EINVAL;
 	}
 
-	memcpy((void *)(size_t)(rule->key_iova + offset), key, size);
-	memcpy((void *)(size_t)(rule->mask_iova + offset), mask, size);
+	if (dist_type & DPAA2_FLOW_QOS_TYPE) {
+		memcpy((flow->qos_key_addr + offset), key, size);
+		memcpy((flow->qos_mask_addr + offset), mask, size);
+		if (key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT)
+			flow->qos_rule_size = offset + size;
+	}
+
+	if (dist_type & DPAA2_FLOW_FS_TYPE) {
+		memcpy((flow->fs_key_addr + offset), key, size);
+		memcpy((flow->fs_mask_addr + offset), mask, size);
+		if (key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT)
+			flow->fs_rule_size = offset + size;
+	}
 
 	return 0;
 }
@@ -724,145 +1003,13 @@  dpaa2_flow_rule_data_set_raw(struct dpni_rule_cfg *rule,
 	return 0;
 }
 
-static inline int
-_dpaa2_flow_rule_move_ipaddr_tail(
-	struct dpaa2_key_extract *key_extract,
-	struct dpni_rule_cfg *rule, int src_offset,
-	uint32_t field, bool ipv4)
-{
-	size_t key_src;
-	size_t mask_src;
-	size_t key_dst;
-	size_t mask_dst;
-	int dst_offset, len;
-	enum net_prot prot;
-	char tmp[NH_FLD_IPV6_ADDR_SIZE];
-
-	if (field != NH_FLD_IP_SRC &&
-		field != NH_FLD_IP_DST) {
-		DPAA2_PMD_ERR("Field of IP addr reorder must be IP SRC/DST");
-		return -1;
-	}
-	if (ipv4)
-		prot = NET_PROT_IPV4;
-	else
-		prot = NET_PROT_IPV6;
-	dst_offset = dpaa2_flow_extract_key_offset(key_extract,
-				prot, field);
-	if (dst_offset < 0) {
-		DPAA2_PMD_ERR("Field %d reorder extract failed", field);
-		return -1;
-	}
-	key_src = rule->key_iova + src_offset;
-	mask_src = rule->mask_iova + src_offset;
-	key_dst = rule->key_iova + dst_offset;
-	mask_dst = rule->mask_iova + dst_offset;
-	if (ipv4)
-		len = sizeof(rte_be32_t);
-	else
-		len = NH_FLD_IPV6_ADDR_SIZE;
-
-	memcpy(tmp, (char *)key_src, len);
-	memset((char *)key_src, 0, len);
-	memcpy((char *)key_dst, tmp, len);
-
-	memcpy(tmp, (char *)mask_src, len);
-	memset((char *)mask_src, 0, len);
-	memcpy((char *)mask_dst, tmp, len);
-
-	return 0;
-}
-
-static inline int
-dpaa2_flow_rule_move_ipaddr_tail(
-	struct rte_flow *flow, struct dpaa2_dev_priv *priv,
-	int fs_group)
+static int
+dpaa2_flow_extract_support(const uint8_t *mask_src,
+	enum rte_flow_item_type type)
 {
-	int ret;
-	enum net_prot prot;
-
-	if (flow->ipaddr_rule.ipaddr_type == FLOW_NONE_IPADDR)
-		return 0;
-
-	if (flow->ipaddr_rule.ipaddr_type == FLOW_IPV4_ADDR)
-		prot = NET_PROT_IPV4;
-	else
-		prot = NET_PROT_IPV6;
-
-	if (flow->ipaddr_rule.qos_ipsrc_offset >= 0) {
-		ret = _dpaa2_flow_rule_move_ipaddr_tail(
-				&priv->extract.qos_key_extract,
-				&flow->qos_rule,
-				flow->ipaddr_rule.qos_ipsrc_offset,
-				NH_FLD_IP_SRC, prot == NET_PROT_IPV4);
-		if (ret) {
-			DPAA2_PMD_ERR("QoS src address reorder failed");
-			return -1;
-		}
-		flow->ipaddr_rule.qos_ipsrc_offset =
-			dpaa2_flow_extract_key_offset(
-				&priv->extract.qos_key_extract,
-				prot, NH_FLD_IP_SRC);
-	}
-
-	if (flow->ipaddr_rule.qos_ipdst_offset >= 0) {
-		ret = _dpaa2_flow_rule_move_ipaddr_tail(
-				&priv->extract.qos_key_extract,
-				&flow->qos_rule,
-				flow->ipaddr_rule.qos_ipdst_offset,
-				NH_FLD_IP_DST, prot == NET_PROT_IPV4);
-		if (ret) {
-			DPAA2_PMD_ERR("QoS dst address reorder failed");
-			return -1;
-		}
-		flow->ipaddr_rule.qos_ipdst_offset =
-			dpaa2_flow_extract_key_offset(
-				&priv->extract.qos_key_extract,
-				prot, NH_FLD_IP_DST);
-	}
-
-	if (flow->ipaddr_rule.fs_ipsrc_offset >= 0) {
-		ret = _dpaa2_flow_rule_move_ipaddr_tail(
-				&priv->extract.tc_key_extract[fs_group],
-				&flow->fs_rule,
-				flow->ipaddr_rule.fs_ipsrc_offset,
-				NH_FLD_IP_SRC, prot == NET_PROT_IPV4);
-		if (ret) {
-			DPAA2_PMD_ERR("FS src address reorder failed");
-			return -1;
-		}
-		flow->ipaddr_rule.fs_ipsrc_offset =
-			dpaa2_flow_extract_key_offset(
-				&priv->extract.tc_key_extract[fs_group],
-				prot, NH_FLD_IP_SRC);
-	}
-	if (flow->ipaddr_rule.fs_ipdst_offset >= 0) {
-		ret = _dpaa2_flow_rule_move_ipaddr_tail(
-				&priv->extract.tc_key_extract[fs_group],
-				&flow->fs_rule,
-				flow->ipaddr_rule.fs_ipdst_offset,
-				NH_FLD_IP_DST, prot == NET_PROT_IPV4);
-		if (ret) {
-			DPAA2_PMD_ERR("FS dst address reorder failed");
-			return -1;
-		}
-		flow->ipaddr_rule.fs_ipdst_offset =
-			dpaa2_flow_extract_key_offset(
-				&priv->extract.tc_key_extract[fs_group],
-				prot, NH_FLD_IP_DST);
-	}
-
-	return 0;
-}
-
-static int
-dpaa2_flow_extract_support(
-	const uint8_t *mask_src,
-	enum rte_flow_item_type type)
-{
-	char mask[64];
-	int i, size = 0;
-	const char *mask_support = 0;
+	char mask[64];
+	int i, size = 0;
+	const char *mask_support = 0;
 
 	switch (type) {
 	case RTE_FLOW_ITEM_TYPE_ETH:
@@ -902,7 +1049,7 @@  dpaa2_flow_extract_support(
 		size = sizeof(struct rte_flow_item_gre);
 		break;
 	default:
-		return -1;
+		return -EINVAL;
 	}
 
 	memcpy(mask, mask_support, size);
@@ -917,491 +1064,444 @@  dpaa2_flow_extract_support(
 }
 
 static int
-dpaa2_configure_flow_eth(struct rte_flow *flow,
-			 struct rte_eth_dev *dev,
-			 const struct rte_flow_attr *attr,
-			 const struct rte_flow_item *pattern,
-			 const struct rte_flow_action actions[] __rte_unused,
-			 struct rte_flow_error *error __rte_unused,
-			 int *device_configured)
+dpaa2_flow_identify_by_prev_prot(struct dpaa2_dev_priv *priv,
+	struct dpaa2_dev_flow *flow,
+	const struct prev_proto_field_id *prev_prot,
+	enum dpaa2_flow_dist_type dist_type,
+	int group, int *recfg)
 {
-	int index, ret;
-	int local_cfg = 0;
-	uint32_t group;
-	const struct rte_flow_item_eth *spec, *mask;
-
-	/* TODO: Currently upper bound of range parameter is not implemented */
-	const struct rte_flow_item_eth *last __rte_unused;
-	struct dpaa2_dev_priv *priv = dev->data->dev_private;
-	const char zero_cmp[RTE_ETHER_ADDR_LEN] = {0};
-
-	group = attr->group;
-
-	/* Parse pattern list to get the matching parameters */
-	spec    = (const struct rte_flow_item_eth *)pattern->spec;
-	last    = (const struct rte_flow_item_eth *)pattern->last;
-	mask    = (const struct rte_flow_item_eth *)
-		(pattern->mask ? pattern->mask : &dpaa2_flow_item_eth_mask);
-	if (!spec) {
-		/* Don't care any field of eth header,
-		 * only care eth protocol.
-		 */
-		DPAA2_PMD_WARN("No pattern spec for Eth flow, just skip");
-		return 0;
-	}
-
-	/* Get traffic class index and flow id to be configured */
-	flow->tc_id = group;
-	flow->tc_index = attr->priority;
-
-	if (dpaa2_flow_extract_support((const uint8_t *)mask,
-		RTE_FLOW_ITEM_TYPE_ETH)) {
-		DPAA2_PMD_WARN("Extract field(s) of ethernet not support.");
-
-		return -1;
-	}
-
-	if (memcmp((const char *)&mask->hdr.src_addr, zero_cmp, RTE_ETHER_ADDR_LEN)) {
-		index = dpaa2_flow_extract_search(
-				&priv->extract.qos_key_extract.dpkg,
-				NET_PROT_ETH, NH_FLD_ETH_SA);
-		if (index < 0) {
-			ret = dpaa2_flow_extract_add(
-					&priv->extract.qos_key_extract,
-					NET_PROT_ETH, NH_FLD_ETH_SA,
-					RTE_ETHER_ADDR_LEN);
-			if (ret) {
-				DPAA2_PMD_ERR("QoS Extract add ETH_SA failed.");
-
-				return -1;
-			}
-			local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
-		}
-		index = dpaa2_flow_extract_search(
-				&priv->extract.tc_key_extract[group].dpkg,
-				NET_PROT_ETH, NH_FLD_ETH_SA);
-		if (index < 0) {
-			ret = dpaa2_flow_extract_add(
-					&priv->extract.tc_key_extract[group],
-					NET_PROT_ETH, NH_FLD_ETH_SA,
-					RTE_ETHER_ADDR_LEN);
-			if (ret) {
-				DPAA2_PMD_ERR("FS Extract add ETH_SA failed.");
-				return -1;
-			}
-			local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
-		}
+	int ret, index, local_cfg = 0, size = 0;
+	struct dpaa2_key_extract *extract;
+	struct dpaa2_key_profile *key_profile;
+	enum net_prot prot = prev_prot->prot;
+	uint32_t key_field = 0;
 
-		ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"Move ipaddr before ETH_SA rule set failed");
-			return -1;
-		}
-
-		ret = dpaa2_flow_rule_data_set(
-				&priv->extract.qos_key_extract,
-				&flow->qos_rule,
-				NET_PROT_ETH,
-				NH_FLD_ETH_SA,
-				&spec->hdr.src_addr.addr_bytes,
-				&mask->hdr.src_addr.addr_bytes,
-				sizeof(struct rte_ether_addr));
-		if (ret) {
-			DPAA2_PMD_ERR("QoS NH_FLD_ETH_SA rule data set failed");
-			return -1;
-		}
-
-		ret = dpaa2_flow_rule_data_set(
-				&priv->extract.tc_key_extract[group],
-				&flow->fs_rule,
-				NET_PROT_ETH,
-				NH_FLD_ETH_SA,
-				&spec->hdr.src_addr.addr_bytes,
-				&mask->hdr.src_addr.addr_bytes,
-				sizeof(struct rte_ether_addr));
-		if (ret) {
-			DPAA2_PMD_ERR("FS NH_FLD_ETH_SA rule data set failed");
-			return -1;
-		}
+	if (prot == NET_PROT_ETH) {
+		key_field = NH_FLD_ETH_TYPE;
+		size = sizeof(rte_be16_t);
+	} else if (prot == NET_PROT_IP) {
+		key_field = NH_FLD_IP_PROTO;
+		size = sizeof(uint8_t);
+	} else if (prot == NET_PROT_IPV4) {
+		prot = NET_PROT_IP;
+		key_field = NH_FLD_IP_PROTO;
+		size = sizeof(uint8_t);
+	} else if (prot == NET_PROT_IPV6) {
+		prot = NET_PROT_IP;
+		key_field = NH_FLD_IP_PROTO;
+		size = sizeof(uint8_t);
+	} else {
+		DPAA2_PMD_ERR("Invalid Prev prot(%d)", prot);
+		return -EINVAL;
 	}
 
-	if (memcmp((const char *)&mask->hdr.dst_addr, zero_cmp, RTE_ETHER_ADDR_LEN)) {
-		index = dpaa2_flow_extract_search(
-				&priv->extract.qos_key_extract.dpkg,
-				NET_PROT_ETH, NH_FLD_ETH_DA);
-		if (index < 0) {
-			ret = dpaa2_flow_extract_add(
-					&priv->extract.qos_key_extract,
-					NET_PROT_ETH, NH_FLD_ETH_DA,
-					RTE_ETHER_ADDR_LEN);
-			if (ret) {
-				DPAA2_PMD_ERR("QoS Extract add ETH_DA failed.");
-
-				return -1;
-			}
-			local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
-		}
+	if (dist_type & DPAA2_FLOW_QOS_TYPE) {
+		extract = &priv->extract.qos_key_extract;
+		key_profile = &extract->key_profile;
 
-		index = dpaa2_flow_extract_search(
-				&priv->extract.tc_key_extract[group].dpkg,
-				NET_PROT_ETH, NH_FLD_ETH_DA);
+		index = dpaa2_flow_extract_search(key_profile,
+				prot, key_field);
 		if (index < 0) {
-			ret = dpaa2_flow_extract_add(
-					&priv->extract.tc_key_extract[group],
-					NET_PROT_ETH, NH_FLD_ETH_DA,
-					RTE_ETHER_ADDR_LEN);
+			ret = dpaa2_flow_extract_add_hdr(prot,
+					key_field, size, priv,
+					DPAA2_FLOW_QOS_TYPE, group,
+					NULL);
 			if (ret) {
-				DPAA2_PMD_ERR("FS Extract add ETH_DA failed.");
+				DPAA2_PMD_ERR("QOS prev extract add failed");
 
-				return -1;
+				return -EINVAL;
 			}
-			local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
-		}
-
-		ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"Move ipaddr before ETH DA rule set failed");
-			return -1;
-		}
-
-		ret = dpaa2_flow_rule_data_set(
-				&priv->extract.qos_key_extract,
-				&flow->qos_rule,
-				NET_PROT_ETH,
-				NH_FLD_ETH_DA,
-				&spec->hdr.dst_addr.addr_bytes,
-				&mask->hdr.dst_addr.addr_bytes,
-				sizeof(struct rte_ether_addr));
-		if (ret) {
-			DPAA2_PMD_ERR("QoS NH_FLD_ETH_DA rule data set failed");
-			return -1;
+			local_cfg |= DPAA2_FLOW_QOS_TYPE;
 		}
 
-		ret = dpaa2_flow_rule_data_set(
-				&priv->extract.tc_key_extract[group],
-				&flow->fs_rule,
-				NET_PROT_ETH,
-				NH_FLD_ETH_DA,
-				&spec->hdr.dst_addr.addr_bytes,
-				&mask->hdr.dst_addr.addr_bytes,
-				sizeof(struct rte_ether_addr));
+		ret = dpaa2_flow_prev_proto_rule(priv, flow, prev_prot, group,
+				DPAA2_FLOW_QOS_TYPE);
 		if (ret) {
-			DPAA2_PMD_ERR("FS NH_FLD_ETH_DA rule data set failed");
-			return -1;
+			DPAA2_PMD_ERR("QoS prev rule set failed");
+			return -EINVAL;
 		}
 	}
 
-	if (memcmp((const char *)&mask->hdr.ether_type, zero_cmp, sizeof(rte_be16_t))) {
-		index = dpaa2_flow_extract_search(
-				&priv->extract.qos_key_extract.dpkg,
-				NET_PROT_ETH, NH_FLD_ETH_TYPE);
-		if (index < 0) {
-			ret = dpaa2_flow_extract_add(
-					&priv->extract.qos_key_extract,
-					NET_PROT_ETH, NH_FLD_ETH_TYPE,
-					RTE_ETHER_TYPE_LEN);
-			if (ret) {
-				DPAA2_PMD_ERR("QoS Extract add ETH_TYPE failed.");
+	if (dist_type & DPAA2_FLOW_FS_TYPE) {
+		extract = &priv->extract.tc_key_extract[group];
+		key_profile = &extract->key_profile;
 
-				return -1;
-			}
-			local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
-		}
-		index = dpaa2_flow_extract_search(
-				&priv->extract.tc_key_extract[group].dpkg,
-				NET_PROT_ETH, NH_FLD_ETH_TYPE);
+		index = dpaa2_flow_extract_search(key_profile,
+				prot, key_field);
 		if (index < 0) {
-			ret = dpaa2_flow_extract_add(
-					&priv->extract.tc_key_extract[group],
-					NET_PROT_ETH, NH_FLD_ETH_TYPE,
-					RTE_ETHER_TYPE_LEN);
+			ret = dpaa2_flow_extract_add_hdr(prot,
+					key_field, size, priv,
+					DPAA2_FLOW_FS_TYPE, group,
+					NULL);
 			if (ret) {
-				DPAA2_PMD_ERR("FS Extract add ETH_TYPE failed.");
+				DPAA2_PMD_ERR("FS[%d] prev extract add failed",
+					group);
 
-				return -1;
+				return -EINVAL;
 			}
-			local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
-		}
-
-		ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"Move ipaddr before ETH TYPE rule set failed");
-				return -1;
-		}
-
-		ret = dpaa2_flow_rule_data_set(
-				&priv->extract.qos_key_extract,
-				&flow->qos_rule,
-				NET_PROT_ETH,
-				NH_FLD_ETH_TYPE,
-				&spec->hdr.ether_type,
-				&mask->hdr.ether_type,
-				sizeof(rte_be16_t));
-		if (ret) {
-			DPAA2_PMD_ERR("QoS NH_FLD_ETH_TYPE rule data set failed");
-			return -1;
+			local_cfg |= DPAA2_FLOW_FS_TYPE;
 		}
 
-		ret = dpaa2_flow_rule_data_set(
-				&priv->extract.tc_key_extract[group],
-				&flow->fs_rule,
-				NET_PROT_ETH,
-				NH_FLD_ETH_TYPE,
-				&spec->hdr.ether_type,
-				&mask->hdr.ether_type,
-				sizeof(rte_be16_t));
+		ret = dpaa2_flow_prev_proto_rule(priv, flow, prev_prot, group,
+				DPAA2_FLOW_FS_TYPE);
 		if (ret) {
-			DPAA2_PMD_ERR("FS NH_FLD_ETH_TYPE rule data set failed");
-			return -1;
+			DPAA2_PMD_ERR("FS[%d] prev rule set failed",
+				group);
+			return -EINVAL;
 		}
 	}
 
-	(*device_configured) |= local_cfg;
+	if (recfg)
+		*recfg = local_cfg;
 
 	return 0;
 }
 
 static int
-dpaa2_configure_flow_vlan(struct rte_flow *flow,
-			  struct rte_eth_dev *dev,
-			  const struct rte_flow_attr *attr,
-			  const struct rte_flow_item *pattern,
-			  const struct rte_flow_action actions[] __rte_unused,
-			  struct rte_flow_error *error __rte_unused,
-			  int *device_configured)
+dpaa2_flow_add_hdr_extract_rule(struct dpaa2_dev_flow *flow,
+	enum net_prot prot, uint32_t field,
+	const void *key, const void *mask, int size,
+	struct dpaa2_dev_priv *priv, int tc_id, int *recfg,
+	enum dpaa2_flow_dist_type dist_type)
 {
-	int index, ret;
-	int local_cfg = 0;
-	uint32_t group;
-	const struct rte_flow_item_vlan *spec, *mask;
-
-	const struct rte_flow_item_vlan *last __rte_unused;
-	struct dpaa2_dev_priv *priv = dev->data->dev_private;
-
-	group = attr->group;
+	int index, ret, local_cfg = 0;
+	struct dpaa2_key_extract *key_extract;
+	struct dpaa2_key_profile *key_profile;
 
-	/* Parse pattern list to get the matching parameters */
-	spec    = (const struct rte_flow_item_vlan *)pattern->spec;
-	last    = (const struct rte_flow_item_vlan *)pattern->last;
-	mask    = (const struct rte_flow_item_vlan *)
-		(pattern->mask ? pattern->mask : &dpaa2_flow_item_vlan_mask);
+	if (dpaa2_flow_ip_address_extract(prot, field))
+		return -EINVAL;
 
-	/* Get traffic class index and flow id to be configured */
-	flow->tc_id = group;
-	flow->tc_index = attr->priority;
+	if (dist_type == DPAA2_FLOW_QOS_TYPE)
+		key_extract = &priv->extract.qos_key_extract;
+	else
+		key_extract = &priv->extract.tc_key_extract[tc_id];
 
-	if (!spec) {
-		/* Don't care any field of vlan header,
-		 * only care vlan protocol.
-		 */
-		/* Eth type is actually used for vLan classification.
-		 */
-		struct proto_discrimination proto;
+	key_profile = &key_extract->key_profile;
 
-		index = dpaa2_flow_extract_search(
-				&priv->extract.qos_key_extract.dpkg,
-				NET_PROT_ETH, NH_FLD_ETH_TYPE);
-		if (index < 0) {
-			ret = dpaa2_flow_proto_discrimination_extract(
-						&priv->extract.qos_key_extract,
-						RTE_FLOW_ITEM_TYPE_ETH);
-			if (ret) {
-				DPAA2_PMD_ERR(
-				"QoS Ext ETH_TYPE to discriminate vLan failed");
+	index = dpaa2_flow_extract_search(key_profile,
+			prot, field);
+	if (index < 0) {
+		ret = dpaa2_flow_extract_add_hdr(prot,
+				field, size, priv,
+				dist_type, tc_id, NULL);
+		if (ret) {
+			DPAA2_PMD_ERR("QoS Extract P(%d)/F(%d) failed",
+				prot, field);
 
-				return -1;
-			}
-			local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
+			return ret;
 		}
+		local_cfg |= dist_type;
+	}
 
-		index = dpaa2_flow_extract_search(
-				&priv->extract.tc_key_extract[group].dpkg,
-				NET_PROT_ETH, NH_FLD_ETH_TYPE);
-		if (index < 0) {
-			ret = dpaa2_flow_proto_discrimination_extract(
-					&priv->extract.tc_key_extract[group],
-					RTE_FLOW_ITEM_TYPE_ETH);
-			if (ret) {
-				DPAA2_PMD_ERR(
-				"FS Ext ETH_TYPE to discriminate vLan failed.");
+	ret = dpaa2_flow_hdr_rule_data_set(flow, key_profile,
+			prot, field, size, key, mask, dist_type);
+	if (ret) {
+		DPAA2_PMD_ERR("QoS P(%d)/F(%d) rule data set failed",
+			prot, field);
 
-				return -1;
-			}
-			local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
-		}
+		return ret;
+	}
 
-		ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
-		if (ret) {
-			DPAA2_PMD_ERR(
-			"Move ipaddr before vLan discrimination set failed");
-			return -1;
-		}
+	if (recfg)
+		*recfg |= local_cfg;
 
-		proto.type = RTE_FLOW_ITEM_TYPE_ETH;
-		proto.eth_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
-		ret = dpaa2_flow_proto_discrimination_rule(priv, flow,
-							proto, group);
-		if (ret) {
-			DPAA2_PMD_ERR("vLan discrimination rule set failed");
-			return -1;
-		}
+	return 0;
+}
 
-		(*device_configured) |= local_cfg;
+static int
+dpaa2_flow_add_ipaddr_extract_rule(struct dpaa2_dev_flow *flow,
+	enum net_prot prot, uint32_t field,
+	const void *key, const void *mask, int size,
+	struct dpaa2_dev_priv *priv, int tc_id, int *recfg,
+	enum dpaa2_flow_dist_type dist_type)
+{
+	int local_cfg = 0, num, ipaddr_extract_len = 0;
+	struct dpaa2_key_extract *key_extract;
+	struct dpaa2_key_profile *key_profile;
+	struct dpkg_profile_cfg *dpkg;
+	uint8_t *key_addr, *mask_addr;
+	union ip_addr_extract_rule *ip_addr_data;
+	union ip_addr_extract_rule *ip_addr_mask;
+	enum net_prot orig_prot;
+	uint32_t orig_field;
+
+	if (prot != NET_PROT_IPV4 && prot != NET_PROT_IPV6)
+		return -EINVAL;
 
-		return 0;
+	if (prot == NET_PROT_IPV4 && field != NH_FLD_IPV4_SRC_IP &&
+		field != NH_FLD_IPV4_DST_IP) {
+		return -EINVAL;
 	}
 
-	if (dpaa2_flow_extract_support((const uint8_t *)mask,
-		RTE_FLOW_ITEM_TYPE_VLAN)) {
-		DPAA2_PMD_WARN("Extract field(s) of vlan not support.");
-
-		return -1;
+	if (prot == NET_PROT_IPV6 && field != NH_FLD_IPV6_SRC_IP &&
+		field != NH_FLD_IPV6_DST_IP) {
+		return -EINVAL;
 	}
 
-	if (!mask->hdr.vlan_tci)
-		return 0;
-
-	index = dpaa2_flow_extract_search(
-				&priv->extract.qos_key_extract.dpkg,
-				NET_PROT_VLAN, NH_FLD_VLAN_TCI);
-	if (index < 0) {
-		ret = dpaa2_flow_extract_add(
-						&priv->extract.qos_key_extract,
-						NET_PROT_VLAN,
-						NH_FLD_VLAN_TCI,
-						sizeof(rte_be16_t));
-		if (ret) {
-			DPAA2_PMD_ERR("QoS Extract add VLAN_TCI failed.");
+	orig_prot = prot;
+	orig_field = field;
 
-			return -1;
-		}
-		local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
+	if (prot == NET_PROT_IPV4 &&
+		field == NH_FLD_IPV4_SRC_IP) {
+		prot = NET_PROT_IP;
+		field = NH_FLD_IP_SRC;
+	} else if (prot == NET_PROT_IPV4 &&
+		field == NH_FLD_IPV4_DST_IP) {
+		prot = NET_PROT_IP;
+		field = NH_FLD_IP_DST;
+	} else if (prot == NET_PROT_IPV6 &&
+		field == NH_FLD_IPV6_SRC_IP) {
+		prot = NET_PROT_IP;
+		field = NH_FLD_IP_SRC;
+	} else if (prot == NET_PROT_IPV6 &&
+		field == NH_FLD_IPV6_DST_IP) {
+		prot = NET_PROT_IP;
+		field = NH_FLD_IP_DST;
+	} else {
+		DPAA2_PMD_ERR("Inval P(%d)/F(%d) to extract ip address",
+			prot, field);
+		return -EINVAL;
 	}
 
-	index = dpaa2_flow_extract_search(
-			&priv->extract.tc_key_extract[group].dpkg,
-			NET_PROT_VLAN, NH_FLD_VLAN_TCI);
-	if (index < 0) {
-		ret = dpaa2_flow_extract_add(
-				&priv->extract.tc_key_extract[group],
-				NET_PROT_VLAN,
-				NH_FLD_VLAN_TCI,
-				sizeof(rte_be16_t));
-		if (ret) {
-			DPAA2_PMD_ERR("FS Extract add VLAN_TCI failed.");
-
-			return -1;
-		}
-		local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
+	if (dist_type == DPAA2_FLOW_QOS_TYPE) {
+		key_extract = &priv->extract.qos_key_extract;
+		key_profile = &key_extract->key_profile;
+		dpkg = &key_extract->dpkg;
+		num = key_profile->num;
+		key_addr = flow->qos_key_addr;
+		mask_addr = flow->qos_mask_addr;
+	} else {
+		key_extract = &priv->extract.tc_key_extract[tc_id];
+		key_profile = &key_extract->key_profile;
+		dpkg = &key_extract->dpkg;
+		num = key_profile->num;
+		key_addr = flow->fs_key_addr;
+		mask_addr = flow->fs_mask_addr;
 	}
 
-	ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
-	if (ret) {
-		DPAA2_PMD_ERR(
-			"Move ipaddr before VLAN TCI rule set failed");
-		return -1;
+	if (num >= DPKG_MAX_NUM_OF_EXTRACTS) {
+		DPAA2_PMD_ERR("Number of extracts overflows");
+		return -EINVAL;
 	}
 
-	ret = dpaa2_flow_rule_data_set(&priv->extract.qos_key_extract,
-				&flow->qos_rule,
-				NET_PROT_VLAN,
-				NH_FLD_VLAN_TCI,
-				&spec->hdr.vlan_tci,
-				&mask->hdr.vlan_tci,
-				sizeof(rte_be16_t));
-	if (ret) {
-		DPAA2_PMD_ERR("QoS NH_FLD_VLAN_TCI rule data set failed");
-		return -1;
+	if (key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT) {
+		if (field == NH_FLD_IP_SRC)
+			key_profile->ip_addr_type = IP_SRC_EXTRACT;
+		else
+			key_profile->ip_addr_type = IP_DST_EXTRACT;
+		ipaddr_extract_len = size;
+
+		key_profile->ip_addr_extract_pos = num;
+		if (num > 0) {
+			key_profile->ip_addr_extract_off =
+				key_profile->key_offset[num - 1] +
+				key_profile->key_size[num - 1];
+		} else {
+			key_profile->ip_addr_extract_off = 0;
+		}
+		key_profile->key_max_size += NH_FLD_IPV6_ADDR_SIZE;
+	} else if (key_profile->ip_addr_type == IP_SRC_EXTRACT) {
+		if (field == NH_FLD_IP_SRC) {
+			ipaddr_extract_len = size;
+			goto rule_configure;
+		}
+		key_profile->ip_addr_type = IP_SRC_DST_EXTRACT;
+		ipaddr_extract_len = size * 2;
+		key_profile->key_max_size += NH_FLD_IPV6_ADDR_SIZE;
+	} else if (key_profile->ip_addr_type == IP_DST_EXTRACT) {
+		if (field == NH_FLD_IP_DST) {
+			ipaddr_extract_len = size;
+			goto rule_configure;
+		}
+		key_profile->ip_addr_type = IP_DST_SRC_EXTRACT;
+		ipaddr_extract_len = size * 2;
+		key_profile->key_max_size += NH_FLD_IPV6_ADDR_SIZE;
+	}
+	key_profile->num++;
+
+	dpkg->extracts[num].extract.from_hdr.prot = prot;
+	dpkg->extracts[num].extract.from_hdr.field = field;
+	dpkg->extracts[num].extract.from_hdr.type = DPKG_FULL_FIELD;
+	dpkg->num_extracts++;
+
+	if (dist_type == DPAA2_FLOW_QOS_TYPE)
+		local_cfg = DPAA2_FLOW_QOS_TYPE;
+	else
+		local_cfg = DPAA2_FLOW_FS_TYPE;
+
+rule_configure:
+	key_addr += key_profile->ip_addr_extract_off;
+	ip_addr_data = (union ip_addr_extract_rule *)key_addr;
+	mask_addr += key_profile->ip_addr_extract_off;
+	ip_addr_mask = (union ip_addr_extract_rule *)mask_addr;
+
+	if (orig_prot == NET_PROT_IPV4 &&
+		orig_field == NH_FLD_IPV4_SRC_IP) {
+		if (key_profile->ip_addr_type == IP_SRC_EXTRACT ||
+			key_profile->ip_addr_type == IP_SRC_DST_EXTRACT) {
+			memcpy(&ip_addr_data->ipv4_sd_addr.ipv4_src,
+				key, size);
+			memcpy(&ip_addr_mask->ipv4_sd_addr.ipv4_src,
+				mask, size);
+		} else {
+			memcpy(&ip_addr_data->ipv4_ds_addr.ipv4_src,
+				key, size);
+			memcpy(&ip_addr_mask->ipv4_ds_addr.ipv4_src,
+				mask, size);
+		}
+	} else if (orig_prot == NET_PROT_IPV4 &&
+		orig_field == NH_FLD_IPV4_DST_IP) {
+		if (key_profile->ip_addr_type == IP_DST_EXTRACT ||
+			key_profile->ip_addr_type == IP_DST_SRC_EXTRACT) {
+			memcpy(&ip_addr_data->ipv4_ds_addr.ipv4_dst,
+				key, size);
+			memcpy(&ip_addr_mask->ipv4_ds_addr.ipv4_dst,
+				mask, size);
+		} else {
+			memcpy(&ip_addr_data->ipv4_sd_addr.ipv4_dst,
+				key, size);
+			memcpy(&ip_addr_mask->ipv4_sd_addr.ipv4_dst,
+				mask, size);
+		}
+	} else if (orig_prot == NET_PROT_IPV6 &&
+		orig_field == NH_FLD_IPV6_SRC_IP) {
+		if (key_profile->ip_addr_type == IP_SRC_EXTRACT ||
+			key_profile->ip_addr_type == IP_SRC_DST_EXTRACT) {
+			memcpy(ip_addr_data->ipv6_sd_addr.ipv6_src,
+				key, size);
+			memcpy(ip_addr_mask->ipv6_sd_addr.ipv6_src,
+				mask, size);
+		} else {
+			memcpy(ip_addr_data->ipv6_ds_addr.ipv6_src,
+				key, size);
+			memcpy(ip_addr_mask->ipv6_ds_addr.ipv6_src,
+				mask, size);
+		}
+	} else if (orig_prot == NET_PROT_IPV6 &&
+		orig_field == NH_FLD_IPV6_DST_IP) {
+		if (key_profile->ip_addr_type == IP_DST_EXTRACT ||
+			key_profile->ip_addr_type == IP_DST_SRC_EXTRACT) {
+			memcpy(ip_addr_data->ipv6_ds_addr.ipv6_dst,
+				key, size);
+			memcpy(ip_addr_mask->ipv6_ds_addr.ipv6_dst,
+				mask, size);
+		} else {
+			memcpy(ip_addr_data->ipv6_sd_addr.ipv6_dst,
+				key, size);
+			memcpy(ip_addr_mask->ipv6_sd_addr.ipv6_dst,
+				mask, size);
+		}
 	}
 
-	ret = dpaa2_flow_rule_data_set(
-			&priv->extract.tc_key_extract[group],
-			&flow->fs_rule,
-			NET_PROT_VLAN,
-			NH_FLD_VLAN_TCI,
-			&spec->hdr.vlan_tci,
-			&mask->hdr.vlan_tci,
-			sizeof(rte_be16_t));
-	if (ret) {
-		DPAA2_PMD_ERR("FS NH_FLD_VLAN_TCI rule data set failed");
-		return -1;
+	if (dist_type == DPAA2_FLOW_QOS_TYPE) {
+		flow->qos_rule_size =
+			key_profile->ip_addr_extract_off + ipaddr_extract_len;
+	} else {
+		flow->fs_rule_size =
+			key_profile->ip_addr_extract_off + ipaddr_extract_len;
 	}
 
-	(*device_configured) |= local_cfg;
+	if (recfg)
+		*recfg |= local_cfg;
 
 	return 0;
 }
 
 static int
-dpaa2_configure_flow_ip_discrimation(
-	struct dpaa2_dev_priv *priv, struct rte_flow *flow,
+dpaa2_configure_flow_eth(struct dpaa2_dev_flow *flow,
+	struct rte_eth_dev *dev,
+	const struct rte_flow_attr *attr,
 	const struct rte_flow_item *pattern,
-	int *local_cfg,	int *device_configured,
-	uint32_t group)
+	const struct rte_flow_action actions[] __rte_unused,
+	struct rte_flow_error *error __rte_unused,
+	int *device_configured)
 {
-	int index, ret;
-	struct proto_discrimination proto;
+	int ret, local_cfg = 0;
+	uint32_t group;
+	const struct rte_flow_item_eth *spec, *mask;
+	struct dpaa2_dev_priv *priv = dev->data->dev_private;
+	const char zero_cmp[RTE_ETHER_ADDR_LEN] = {0};
 
-	index = dpaa2_flow_extract_search(
-			&priv->extract.qos_key_extract.dpkg,
-			NET_PROT_ETH, NH_FLD_ETH_TYPE);
-	if (index < 0) {
-		ret = dpaa2_flow_proto_discrimination_extract(
-				&priv->extract.qos_key_extract,
-				RTE_FLOW_ITEM_TYPE_ETH);
-		if (ret) {
-			DPAA2_PMD_ERR(
-			"QoS Extract ETH_TYPE to discriminate IP failed.");
-			return -1;
-		}
-		(*local_cfg) |= DPAA2_QOS_TABLE_RECONFIGURE;
-	}
+	group = attr->group;
 
-	index = dpaa2_flow_extract_search(
-			&priv->extract.tc_key_extract[group].dpkg,
-			NET_PROT_ETH, NH_FLD_ETH_TYPE);
-	if (index < 0) {
-		ret = dpaa2_flow_proto_discrimination_extract(
-				&priv->extract.tc_key_extract[group],
-				RTE_FLOW_ITEM_TYPE_ETH);
-		if (ret) {
-			DPAA2_PMD_ERR(
-			"FS Extract ETH_TYPE to discriminate IP failed.");
-			return -1;
-		}
-		(*local_cfg) |= DPAA2_FS_TABLE_RECONFIGURE;
+	/* Parse pattern list to get the matching parameters */
+	spec = pattern->spec;
+	mask = pattern->mask ?
+			pattern->mask : &dpaa2_flow_item_eth_mask;
+	if (!spec) {
+		DPAA2_PMD_WARN("No pattern spec for Eth flow");
+		return -EINVAL;
 	}
 
-	ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
-	if (ret) {
-		DPAA2_PMD_ERR(
-			"Move ipaddr before IP discrimination set failed");
-		return -1;
+	/* Get traffic class index and flow id to be configured */
+	flow->tc_id = group;
+	flow->tc_index = attr->priority;
+
+	if (dpaa2_flow_extract_support((const uint8_t *)mask,
+		RTE_FLOW_ITEM_TYPE_ETH)) {
+		DPAA2_PMD_WARN("Extract field(s) of ethernet failed");
+
+		return -EINVAL;
 	}
 
-	proto.type = RTE_FLOW_ITEM_TYPE_ETH;
-	if (pattern->type == RTE_FLOW_ITEM_TYPE_IPV4)
-		proto.eth_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
-	else
-		proto.eth_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
-	ret = dpaa2_flow_proto_discrimination_rule(priv, flow, proto, group);
-	if (ret) {
-		DPAA2_PMD_ERR("IP discrimination rule set failed");
-		return -1;
+	if (memcmp((const char *)&mask->src,
+		zero_cmp, RTE_ETHER_ADDR_LEN)) {
+		ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH,
+			NH_FLD_ETH_SA, &spec->src.addr_bytes,
+			&mask->src.addr_bytes, RTE_ETHER_ADDR_LEN,
+			priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
+		if (ret)
+			return ret;
+
+		ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH,
+			NH_FLD_ETH_SA, &spec->src.addr_bytes,
+			&mask->src.addr_bytes, RTE_ETHER_ADDR_LEN,
+			priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+		if (ret)
+			return ret;
+	}
+
+	if (memcmp((const char *)&mask->dst,
+		zero_cmp, RTE_ETHER_ADDR_LEN)) {
+		ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH,
+			NH_FLD_ETH_DA, &spec->dst.addr_bytes,
+			&mask->dst.addr_bytes, RTE_ETHER_ADDR_LEN,
+			priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
+		if (ret)
+			return ret;
+
+		ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH,
+			NH_FLD_ETH_DA, &spec->dst.addr_bytes,
+			&mask->dst.addr_bytes, RTE_ETHER_ADDR_LEN,
+			priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+		if (ret)
+			return ret;
+	}
+
+	if (memcmp((const char *)&mask->type,
+		zero_cmp, sizeof(rte_be16_t))) {
+		ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH,
+			NH_FLD_ETH_TYPE, &spec->type,
+			&mask->type, sizeof(rte_be16_t),
+			priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
+		if (ret)
+			return ret;
+
+		ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH,
+			NH_FLD_ETH_TYPE, &spec->type,
+			&mask->type, sizeof(rte_be16_t),
+			priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+		if (ret)
+			return ret;
 	}
 
-	(*device_configured) |= (*local_cfg);
+	(*device_configured) |= local_cfg;
 
 	return 0;
 }
 
-
 static int
-dpaa2_configure_flow_generic_ip(
-	struct rte_flow *flow,
+dpaa2_configure_flow_vlan(struct dpaa2_dev_flow *flow,
 	struct rte_eth_dev *dev,
 	const struct rte_flow_attr *attr,
 	const struct rte_flow_item *pattern,
@@ -1409,419 +1509,338 @@  dpaa2_configure_flow_generic_ip(
 	struct rte_flow_error *error __rte_unused,
 	int *device_configured)
 {
-	int index, ret;
-	int local_cfg = 0;
+	int ret, local_cfg = 0;
 	uint32_t group;
-	const struct rte_flow_item_ipv4 *spec_ipv4 = 0,
-		*mask_ipv4 = 0;
-	const struct rte_flow_item_ipv6 *spec_ipv6 = 0,
-		*mask_ipv6 = 0;
-	const void *key, *mask;
-	enum net_prot prot;
-
+	const struct rte_flow_item_vlan *spec, *mask;
 	struct dpaa2_dev_priv *priv = dev->data->dev_private;
-	const char zero_cmp[NH_FLD_IPV6_ADDR_SIZE] = {0};
-	int size;
 
 	group = attr->group;
 
 	/* Parse pattern list to get the matching parameters */
-	if (pattern->type == RTE_FLOW_ITEM_TYPE_IPV4) {
-		spec_ipv4 = (const struct rte_flow_item_ipv4 *)pattern->spec;
-		mask_ipv4 = (const struct rte_flow_item_ipv4 *)
-			(pattern->mask ? pattern->mask :
-					&dpaa2_flow_item_ipv4_mask);
-	} else {
-		spec_ipv6 = (const struct rte_flow_item_ipv6 *)pattern->spec;
-		mask_ipv6 = (const struct rte_flow_item_ipv6 *)
-			(pattern->mask ? pattern->mask :
-					&dpaa2_flow_item_ipv6_mask);
-	}
+	spec = pattern->spec;
+	mask = pattern->mask ? pattern->mask : &dpaa2_flow_item_vlan_mask;
 
 	/* Get traffic class index and flow id to be configured */
 	flow->tc_id = group;
 	flow->tc_index = attr->priority;
 
-	ret = dpaa2_configure_flow_ip_discrimation(priv,
-			flow, pattern, &local_cfg,
-			device_configured, group);
-	if (ret) {
-		DPAA2_PMD_ERR("IP discrimination failed!");
-		return -1;
+	if (!spec) {
+		struct prev_proto_field_id prev_proto;
+
+		prev_proto.prot = NET_PROT_ETH;
+		prev_proto.eth_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
+		ret = dpaa2_flow_identify_by_prev_prot(priv, flow, &prev_proto,
+				DPAA2_FLOW_QOS_TYPE | DPAA2_FLOW_FS_TYPE,
+				group, &local_cfg);
+		if (ret)
+			return ret;
+		(*device_configured) |= local_cfg;
+		return 0;
+	}
+
+	if (dpaa2_flow_extract_support((const uint8_t *)mask,
+				       RTE_FLOW_ITEM_TYPE_VLAN)) {
+		DPAA2_PMD_WARN("Extract field(s) of vlan not support.");
+		return -EINVAL;
 	}
 
-	if (!spec_ipv4 && !spec_ipv6)
+	if (!mask->tci)
 		return 0;
 
-	if (mask_ipv4) {
-		if (dpaa2_flow_extract_support((const uint8_t *)mask_ipv4,
-			RTE_FLOW_ITEM_TYPE_IPV4)) {
-			DPAA2_PMD_WARN("Extract field(s) of IPv4 not support.");
+	ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_VLAN,
+					      NH_FLD_VLAN_TCI, &spec->tci,
+					      &mask->tci, sizeof(rte_be16_t),
+					      priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
+	if (ret)
+		return ret;
 
-			return -1;
-		}
-	}
-
-	if (mask_ipv6) {
-		if (dpaa2_flow_extract_support((const uint8_t *)mask_ipv6,
-			RTE_FLOW_ITEM_TYPE_IPV6)) {
-			DPAA2_PMD_WARN("Extract field(s) of IPv6 not support.");
-
-			return -1;
-		}
-	}
+	ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_VLAN,
+					      NH_FLD_VLAN_TCI, &spec->tci,
+					      &mask->tci, sizeof(rte_be16_t),
+					      priv, group, &local_cfg,
+					      DPAA2_FLOW_FS_TYPE);
+	if (ret)
+		return ret;
 
-	if (mask_ipv4 && (mask_ipv4->hdr.src_addr ||
-		mask_ipv4->hdr.dst_addr)) {
-		flow->ipaddr_rule.ipaddr_type = FLOW_IPV4_ADDR;
-	} else if (mask_ipv6 &&
-		(memcmp(&mask_ipv6->hdr.src_addr,
-				zero_cmp, NH_FLD_IPV6_ADDR_SIZE) ||
-		memcmp(&mask_ipv6->hdr.dst_addr,
-				zero_cmp, NH_FLD_IPV6_ADDR_SIZE))) {
-		flow->ipaddr_rule.ipaddr_type = FLOW_IPV6_ADDR;
-	}
-
-	if ((mask_ipv4 && mask_ipv4->hdr.src_addr) ||
-		(mask_ipv6 &&
-			memcmp(&mask_ipv6->hdr.src_addr,
-				zero_cmp, NH_FLD_IPV6_ADDR_SIZE))) {
-		index = dpaa2_flow_extract_search(
-				&priv->extract.qos_key_extract.dpkg,
-				NET_PROT_IP, NH_FLD_IP_SRC);
-		if (index < 0) {
-			ret = dpaa2_flow_extract_add(
-					&priv->extract.qos_key_extract,
-					NET_PROT_IP,
-					NH_FLD_IP_SRC,
-					0);
-			if (ret) {
-				DPAA2_PMD_ERR("QoS Extract add IP_SRC failed.");
+	(*device_configured) |= local_cfg;
+	return 0;
+}
 
-				return -1;
-			}
-			local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
-		}
+static int
+dpaa2_configure_flow_ipv4(struct dpaa2_dev_flow *flow, struct rte_eth_dev *dev,
+			  const struct rte_flow_attr *attr,
+			  const struct rte_flow_item *pattern,
+			  const struct rte_flow_action actions[] __rte_unused,
+			  struct rte_flow_error *error __rte_unused,
+			  int *device_configured)
+{
+	int ret, local_cfg = 0;
+	uint32_t group;
+	const struct rte_flow_item_ipv4 *spec_ipv4 = 0, *mask_ipv4 = 0;
+	const void *key, *mask;
+	struct dpaa2_dev_priv *priv = dev->data->dev_private;
+	int size;
+	struct prev_proto_field_id prev_prot;
 
-		index = dpaa2_flow_extract_search(
-				&priv->extract.tc_key_extract[group].dpkg,
-				NET_PROT_IP, NH_FLD_IP_SRC);
-		if (index < 0) {
-			ret = dpaa2_flow_extract_add(
-					&priv->extract.tc_key_extract[group],
-					NET_PROT_IP,
-					NH_FLD_IP_SRC,
-					0);
-			if (ret) {
-				DPAA2_PMD_ERR("FS Extract add IP_SRC failed.");
+	group = attr->group;
 
-				return -1;
-			}
-			local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
-		}
+	/* Parse pattern list to get the matching parameters */
+	spec_ipv4 = pattern->spec;
+	mask_ipv4 = pattern->mask ?
+		    pattern->mask : &dpaa2_flow_item_ipv4_mask;
 
-		if (spec_ipv4)
-			key = &spec_ipv4->hdr.src_addr;
-		else
-			key = &spec_ipv6->hdr.src_addr;
-		if (mask_ipv4) {
-			mask = &mask_ipv4->hdr.src_addr;
-			size = NH_FLD_IPV4_ADDR_SIZE;
-			prot = NET_PROT_IPV4;
-		} else {
-			mask = &mask_ipv6->hdr.src_addr;
-			size = NH_FLD_IPV6_ADDR_SIZE;
-			prot = NET_PROT_IPV6;
-		}
+	/* Get traffic class index and flow id to be configured */
+	flow->tc_id = group;
+	flow->tc_index = attr->priority;
 
-		ret = dpaa2_flow_rule_data_set(
-				&priv->extract.qos_key_extract,
-				&flow->qos_rule,
-				prot, NH_FLD_IP_SRC,
-				key,	mask, size);
-		if (ret) {
-			DPAA2_PMD_ERR("QoS NH_FLD_IP_SRC rule data set failed");
-			return -1;
-		}
+	prev_prot.prot = NET_PROT_ETH;
+	prev_prot.eth_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
 
-		ret = dpaa2_flow_rule_data_set(
-				&priv->extract.tc_key_extract[group],
-				&flow->fs_rule,
-				prot, NH_FLD_IP_SRC,
-				key,	mask, size);
-		if (ret) {
-			DPAA2_PMD_ERR("FS NH_FLD_IP_SRC rule data set failed");
-			return -1;
-		}
+	ret = dpaa2_flow_identify_by_prev_prot(priv, flow, &prev_prot,
+			DPAA2_FLOW_QOS_TYPE | DPAA2_FLOW_FS_TYPE, group,
+			&local_cfg);
+	if (ret) {
+		DPAA2_PMD_ERR("IPv4 identification failed!");
+		return ret;
+	}
 
-		flow->ipaddr_rule.qos_ipsrc_offset =
-			dpaa2_flow_extract_key_offset(
-				&priv->extract.qos_key_extract,
-				prot, NH_FLD_IP_SRC);
-		flow->ipaddr_rule.fs_ipsrc_offset =
-			dpaa2_flow_extract_key_offset(
-				&priv->extract.tc_key_extract[group],
-				prot, NH_FLD_IP_SRC);
-	}
-
-	if ((mask_ipv4 && mask_ipv4->hdr.dst_addr) ||
-		(mask_ipv6 &&
-			memcmp(&mask_ipv6->hdr.dst_addr,
-				zero_cmp, NH_FLD_IPV6_ADDR_SIZE))) {
-		index = dpaa2_flow_extract_search(
-				&priv->extract.qos_key_extract.dpkg,
-				NET_PROT_IP, NH_FLD_IP_DST);
-		if (index < 0) {
-			if (mask_ipv4)
-				size = NH_FLD_IPV4_ADDR_SIZE;
-			else
-				size = NH_FLD_IPV6_ADDR_SIZE;
-			ret = dpaa2_flow_extract_add(
-					&priv->extract.qos_key_extract,
-					NET_PROT_IP,
-					NH_FLD_IP_DST,
-					size);
-			if (ret) {
-				DPAA2_PMD_ERR("QoS Extract add IP_DST failed.");
+	if (!spec_ipv4)
+		return 0;
 
-				return -1;
-			}
-			local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
-		}
+	if (dpaa2_flow_extract_support((const uint8_t *)mask_ipv4,
+				       RTE_FLOW_ITEM_TYPE_IPV4)) {
+		DPAA2_PMD_WARN("Extract field(s) of IPv4 not support.");
+		return -EINVAL;
+	}
 
-		index = dpaa2_flow_extract_search(
-				&priv->extract.tc_key_extract[group].dpkg,
-				NET_PROT_IP, NH_FLD_IP_DST);
-		if (index < 0) {
-			if (mask_ipv4)
-				size = NH_FLD_IPV4_ADDR_SIZE;
-			else
-				size = NH_FLD_IPV6_ADDR_SIZE;
-			ret = dpaa2_flow_extract_add(
-					&priv->extract.tc_key_extract[group],
-					NET_PROT_IP,
-					NH_FLD_IP_DST,
-					size);
-			if (ret) {
-				DPAA2_PMD_ERR("FS Extract add IP_DST failed.");
+	if (mask_ipv4->hdr.src_addr) {
+		key = &spec_ipv4->hdr.src_addr;
+		mask = &mask_ipv4->hdr.src_addr;
+		size = sizeof(rte_be32_t);
+
+		ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV4,
+							 NH_FLD_IPV4_SRC_IP,
+							 key, mask, size, priv,
+							 group, &local_cfg,
+							 DPAA2_FLOW_QOS_TYPE);
+		if (ret)
+			return ret;
+
+		ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV4,
+							 NH_FLD_IPV4_SRC_IP,
+							 key, mask, size, priv,
+							 group, &local_cfg,
+							 DPAA2_FLOW_FS_TYPE);
+		if (ret)
+			return ret;
+	}
+
+	if (mask_ipv4->hdr.dst_addr) {
+		key = &spec_ipv4->hdr.dst_addr;
+		mask = &mask_ipv4->hdr.dst_addr;
+		size = sizeof(rte_be32_t);
+
+		ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV4,
+							 NH_FLD_IPV4_DST_IP,
+							 key, mask, size, priv,
+							 group, &local_cfg,
+							 DPAA2_FLOW_QOS_TYPE);
+		if (ret)
+			return ret;
+		ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV4,
+							 NH_FLD_IPV4_DST_IP,
+							 key, mask, size, priv,
+							 group, &local_cfg,
+							 DPAA2_FLOW_FS_TYPE);
+		if (ret)
+			return ret;
+	}
+
+	if (mask_ipv4->hdr.next_proto_id) {
+		key = &spec_ipv4->hdr.next_proto_id;
+		mask = &mask_ipv4->hdr.next_proto_id;
+		size = sizeof(uint8_t);
+
+		ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IP,
+						      NH_FLD_IP_PROTO, key,
+						      mask, size, priv, group,
+						      &local_cfg,
+						      DPAA2_FLOW_QOS_TYPE);
+		if (ret)
+			return ret;
+
+		ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IP,
+						      NH_FLD_IP_PROTO, key,
+						      mask, size, priv, group,
+						      &local_cfg,
+						      DPAA2_FLOW_FS_TYPE);
+		if (ret)
+			return ret;
+	}
 
-				return -1;
-			}
-			local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
-		}
+	(*device_configured) |= local_cfg;
+	return 0;
+}
 
-		if (spec_ipv4)
-			key = &spec_ipv4->hdr.dst_addr;
-		else
-			key = &spec_ipv6->hdr.dst_addr;
-		if (mask_ipv4) {
-			mask = &mask_ipv4->hdr.dst_addr;
-			size = NH_FLD_IPV4_ADDR_SIZE;
-			prot = NET_PROT_IPV4;
-		} else {
-			mask = &mask_ipv6->hdr.dst_addr;
-			size = NH_FLD_IPV6_ADDR_SIZE;
-			prot = NET_PROT_IPV6;
-		}
+static int
+dpaa2_configure_flow_ipv6(struct dpaa2_dev_flow *flow, struct rte_eth_dev *dev,
+			  const struct rte_flow_attr *attr,
+			  const struct rte_flow_item *pattern,
+			  const struct rte_flow_action actions[] __rte_unused,
+			  struct rte_flow_error *error __rte_unused,
+			  int *device_configured)
+{
+	int ret, local_cfg = 0;
+	uint32_t group;
+	const struct rte_flow_item_ipv6 *spec_ipv6 = 0, *mask_ipv6 = 0;
+	const void *key, *mask;
+	struct dpaa2_dev_priv *priv = dev->data->dev_private;
+	const char zero_cmp[NH_FLD_IPV6_ADDR_SIZE] = {0};
+	int size;
+	struct prev_proto_field_id prev_prot;
 
-		ret = dpaa2_flow_rule_data_set(
-				&priv->extract.qos_key_extract,
-				&flow->qos_rule,
-				prot, NH_FLD_IP_DST,
-				key,	mask, size);
-		if (ret) {
-			DPAA2_PMD_ERR("QoS NH_FLD_IP_DST rule data set failed");
-			return -1;
-		}
+	group = attr->group;
 
-		ret = dpaa2_flow_rule_data_set(
-				&priv->extract.tc_key_extract[group],
-				&flow->fs_rule,
-				prot, NH_FLD_IP_DST,
-				key,	mask, size);
-		if (ret) {
-			DPAA2_PMD_ERR("FS NH_FLD_IP_DST rule data set failed");
-			return -1;
-		}
-		flow->ipaddr_rule.qos_ipdst_offset =
-			dpaa2_flow_extract_key_offset(
-				&priv->extract.qos_key_extract,
-				prot, NH_FLD_IP_DST);
-		flow->ipaddr_rule.fs_ipdst_offset =
-			dpaa2_flow_extract_key_offset(
-				&priv->extract.tc_key_extract[group],
-				prot, NH_FLD_IP_DST);
-	}
-
-	if ((mask_ipv4 && mask_ipv4->hdr.next_proto_id) ||
-		(mask_ipv6 && mask_ipv6->hdr.proto)) {
-		index = dpaa2_flow_extract_search(
-				&priv->extract.qos_key_extract.dpkg,
-				NET_PROT_IP, NH_FLD_IP_PROTO);
-		if (index < 0) {
-			ret = dpaa2_flow_extract_add(
-				&priv->extract.qos_key_extract,
-				NET_PROT_IP,
-				NH_FLD_IP_PROTO,
-				NH_FLD_IP_PROTO_SIZE);
-			if (ret) {
-				DPAA2_PMD_ERR("QoS Extract add IP_DST failed.");
+	/* Parse pattern list to get the matching parameters */
+	spec_ipv6 = pattern->spec;
+	mask_ipv6 = pattern->mask ? pattern->mask : &dpaa2_flow_item_ipv6_mask;
 
-				return -1;
-			}
-			local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
-		}
+	/* Get traffic class index and flow id to be configured */
+	flow->tc_id = group;
+	flow->tc_index = attr->priority;
 
-		index = dpaa2_flow_extract_search(
-				&priv->extract.tc_key_extract[group].dpkg,
-				NET_PROT_IP, NH_FLD_IP_PROTO);
-		if (index < 0) {
-			ret = dpaa2_flow_extract_add(
-					&priv->extract.tc_key_extract[group],
-					NET_PROT_IP,
-					NH_FLD_IP_PROTO,
-					NH_FLD_IP_PROTO_SIZE);
-			if (ret) {
-				DPAA2_PMD_ERR("FS Extract add IP_DST failed.");
+	prev_prot.prot = NET_PROT_ETH;
+	prev_prot.eth_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
 
-				return -1;
-			}
-			local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
-		}
+	ret = dpaa2_flow_identify_by_prev_prot(priv, flow, &prev_prot,
+			DPAA2_FLOW_QOS_TYPE | DPAA2_FLOW_FS_TYPE,
+			group, &local_cfg);
+	if (ret) {
+		DPAA2_PMD_ERR("IPv6 identification failed!");
+		return ret;
+	}
 
-		ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"Move ipaddr after NH_FLD_IP_PROTO rule set failed");
-			return -1;
-		}
+	if (!spec_ipv6)
+		return 0;
 
-		if (spec_ipv4)
-			key = &spec_ipv4->hdr.next_proto_id;
-		else
-			key = &spec_ipv6->hdr.proto;
-		if (mask_ipv4)
-			mask = &mask_ipv4->hdr.next_proto_id;
-		else
-			mask = &mask_ipv6->hdr.proto;
-
-		ret = dpaa2_flow_rule_data_set(
-				&priv->extract.qos_key_extract,
-				&flow->qos_rule,
-				NET_PROT_IP,
-				NH_FLD_IP_PROTO,
-				key,	mask, NH_FLD_IP_PROTO_SIZE);
-		if (ret) {
-			DPAA2_PMD_ERR("QoS NH_FLD_IP_PROTO rule data set failed");
-			return -1;
-		}
+	if (dpaa2_flow_extract_support((const uint8_t *)mask_ipv6,
+				       RTE_FLOW_ITEM_TYPE_IPV6)) {
+		DPAA2_PMD_WARN("Extract field(s) of IPv6 not support.");
+		return -EINVAL;
+	}
 
-		ret = dpaa2_flow_rule_data_set(
-				&priv->extract.tc_key_extract[group],
-				&flow->fs_rule,
-				NET_PROT_IP,
-				NH_FLD_IP_PROTO,
-				key,	mask, NH_FLD_IP_PROTO_SIZE);
-		if (ret) {
-			DPAA2_PMD_ERR("FS NH_FLD_IP_PROTO rule data set failed");
-			return -1;
-		}
+	if (memcmp((const char *)&mask_ipv6->hdr.src_addr, zero_cmp, NH_FLD_IPV6_ADDR_SIZE)) {
+		key = &spec_ipv6->hdr.src_addr;
+		mask = &mask_ipv6->hdr.src_addr;
+		size = NH_FLD_IPV6_ADDR_SIZE;
+
+		ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV6,
+							 NH_FLD_IPV6_SRC_IP,
+							 key, mask, size, priv,
+							 group, &local_cfg,
+							 DPAA2_FLOW_QOS_TYPE);
+		if (ret)
+			return ret;
+
+		ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV6,
+							 NH_FLD_IPV6_SRC_IP,
+							 key, mask, size, priv,
+							 group, &local_cfg,
+							 DPAA2_FLOW_FS_TYPE);
+		if (ret)
+			return ret;
+	}
+
+	if (memcmp((const char *)&mask_ipv6->hdr.dst_addr, zero_cmp, NH_FLD_IPV6_ADDR_SIZE)) {
+		key = &spec_ipv6->hdr.dst_addr;
+		mask = &mask_ipv6->hdr.dst_addr;
+		size = NH_FLD_IPV6_ADDR_SIZE;
+
+		ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV6,
+							 NH_FLD_IPV6_DST_IP,
+							 key, mask, size, priv,
+							 group, &local_cfg,
+							 DPAA2_FLOW_QOS_TYPE);
+		if (ret)
+			return ret;
+
+		ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV6,
+							 NH_FLD_IPV6_DST_IP,
+							 key, mask, size, priv,
+							 group, &local_cfg,
+							 DPAA2_FLOW_FS_TYPE);
+		if (ret)
+			return ret;
+	}
+
+	if (mask_ipv6->hdr.proto) {
+		key = &spec_ipv6->hdr.proto;
+		mask = &mask_ipv6->hdr.proto;
+		size = sizeof(uint8_t);
+
+		ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IP,
+						      NH_FLD_IP_PROTO, key,
+						      mask, size, priv, group,
+						      &local_cfg,
+						      DPAA2_FLOW_QOS_TYPE);
+		if (ret)
+			return ret;
+
+		ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IP,
+						      NH_FLD_IP_PROTO, key,
+						      mask, size, priv, group,
+						      &local_cfg,
+						      DPAA2_FLOW_FS_TYPE);
+		if (ret)
+			return ret;
 	}
 
 	(*device_configured) |= local_cfg;
-
 	return 0;
 }
 
 static int
-dpaa2_configure_flow_icmp(struct rte_flow *flow,
-			  struct rte_eth_dev *dev,
-			  const struct rte_flow_attr *attr,
-			  const struct rte_flow_item *pattern,
-			  const struct rte_flow_action actions[] __rte_unused,
-			  struct rte_flow_error *error __rte_unused,
-			  int *device_configured)
+dpaa2_configure_flow_icmp(struct dpaa2_dev_flow *flow,
+	struct rte_eth_dev *dev,
+	const struct rte_flow_attr *attr,
+	const struct rte_flow_item *pattern,
+	const struct rte_flow_action actions[] __rte_unused,
+	struct rte_flow_error *error __rte_unused,
+	int *device_configured)
 {
-	int index, ret;
-	int local_cfg = 0;
+	int ret, local_cfg = 0;
 	uint32_t group;
 	const struct rte_flow_item_icmp *spec, *mask;
-
-	const struct rte_flow_item_icmp *last __rte_unused;
 	struct dpaa2_dev_priv *priv = dev->data->dev_private;
 
 	group = attr->group;
 
 	/* Parse pattern list to get the matching parameters */
-	spec    = (const struct rte_flow_item_icmp *)pattern->spec;
-	last    = (const struct rte_flow_item_icmp *)pattern->last;
-	mask    = (const struct rte_flow_item_icmp *)
-		(pattern->mask ? pattern->mask : &dpaa2_flow_item_icmp_mask);
+	spec = pattern->spec;
+	mask = pattern->mask ?
+		pattern->mask : &dpaa2_flow_item_icmp_mask;
 
 	/* Get traffic class index and flow id to be configured */
 	flow->tc_id = group;
 	flow->tc_index = attr->priority;
 
 	if (!spec) {
-		/* Don't care any field of ICMP header,
-		 * only care ICMP protocol.
-		 * Example: flow create 0 ingress pattern icmp /
-		 */
 		/* Next proto of Generical IP is actually used
 		 * for ICMP identification.
+		 * Example: flow create 0 ingress pattern icmp
 		 */
-		struct proto_discrimination proto;
-
-		index = dpaa2_flow_extract_search(
-				&priv->extract.qos_key_extract.dpkg,
-				NET_PROT_IP, NH_FLD_IP_PROTO);
-		if (index < 0) {
-			ret = dpaa2_flow_proto_discrimination_extract(
-					&priv->extract.qos_key_extract,
-					DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
-			if (ret) {
-				DPAA2_PMD_ERR(
-					"QoS Extract IP protocol to discriminate ICMP failed.");
-
-				return -1;
-			}
-			local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
-		}
-
-		index = dpaa2_flow_extract_search(
-				&priv->extract.tc_key_extract[group].dpkg,
-				NET_PROT_IP, NH_FLD_IP_PROTO);
-		if (index < 0) {
-			ret = dpaa2_flow_proto_discrimination_extract(
-					&priv->extract.tc_key_extract[group],
-					DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
-			if (ret) {
-				DPAA2_PMD_ERR(
-					"FS Extract IP protocol to discriminate ICMP failed.");
-
-				return -1;
-			}
-			local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
-		}
-
-		ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"Move IP addr before ICMP discrimination set failed");
-			return -1;
-		}
+		struct prev_proto_field_id prev_proto;
 
-		proto.type = DPAA2_FLOW_ITEM_TYPE_GENERIC_IP;
-		proto.ip_proto = IPPROTO_ICMP;
-		ret = dpaa2_flow_proto_discrimination_rule(priv, flow,
-							proto, group);
-		if (ret) {
-			DPAA2_PMD_ERR("ICMP discrimination rule set failed");
-			return -1;
-		}
+		prev_proto.prot = NET_PROT_IP;
+		prev_proto.ip_proto = IPPROTO_ICMP;
+		ret = dpaa2_flow_identify_by_prev_prot(priv,
+			flow, &prev_proto,
+			DPAA2_FLOW_QOS_TYPE | DPAA2_FLOW_FS_TYPE,
+			group, &local_cfg);
+		if (ret)
+			return ret;
 
 		(*device_configured) |= local_cfg;
-
 		return 0;
 	}
 
@@ -1829,145 +1848,39 @@  dpaa2_configure_flow_icmp(struct rte_flow *flow,
 		RTE_FLOW_ITEM_TYPE_ICMP)) {
 		DPAA2_PMD_WARN("Extract field(s) of ICMP not support.");
 
-		return -1;
+		return -EINVAL;
 	}
 
 	if (mask->hdr.icmp_type) {
-		index = dpaa2_flow_extract_search(
-				&priv->extract.qos_key_extract.dpkg,
-				NET_PROT_ICMP, NH_FLD_ICMP_TYPE);
-		if (index < 0) {
-			ret = dpaa2_flow_extract_add(
-					&priv->extract.qos_key_extract,
-					NET_PROT_ICMP,
-					NH_FLD_ICMP_TYPE,
-					NH_FLD_ICMP_TYPE_SIZE);
-			if (ret) {
-				DPAA2_PMD_ERR("QoS Extract add ICMP_TYPE failed.");
-
-				return -1;
-			}
-			local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
-		}
-
-		index = dpaa2_flow_extract_search(
-				&priv->extract.tc_key_extract[group].dpkg,
-				NET_PROT_ICMP, NH_FLD_ICMP_TYPE);
-		if (index < 0) {
-			ret = dpaa2_flow_extract_add(
-					&priv->extract.tc_key_extract[group],
-					NET_PROT_ICMP,
-					NH_FLD_ICMP_TYPE,
-					NH_FLD_ICMP_TYPE_SIZE);
-			if (ret) {
-				DPAA2_PMD_ERR("FS Extract add ICMP_TYPE failed.");
-
-				return -1;
-			}
-			local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
-		}
-
-		ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"Move ipaddr before ICMP TYPE set failed");
-			return -1;
-		}
+		ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ICMP,
+			NH_FLD_ICMP_TYPE, &spec->hdr.icmp_type,
+			&mask->hdr.icmp_type, sizeof(uint8_t),
+			priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
+		if (ret)
+			return ret;
 
-		ret = dpaa2_flow_rule_data_set(
-				&priv->extract.qos_key_extract,
-				&flow->qos_rule,
-				NET_PROT_ICMP,
-				NH_FLD_ICMP_TYPE,
-				&spec->hdr.icmp_type,
-				&mask->hdr.icmp_type,
-				NH_FLD_ICMP_TYPE_SIZE);
-		if (ret) {
-			DPAA2_PMD_ERR("QoS NH_FLD_ICMP_TYPE rule data set failed");
-			return -1;
-		}
-
-		ret = dpaa2_flow_rule_data_set(
-				&priv->extract.tc_key_extract[group],
-				&flow->fs_rule,
-				NET_PROT_ICMP,
-				NH_FLD_ICMP_TYPE,
-				&spec->hdr.icmp_type,
-				&mask->hdr.icmp_type,
-				NH_FLD_ICMP_TYPE_SIZE);
-		if (ret) {
-			DPAA2_PMD_ERR("FS NH_FLD_ICMP_TYPE rule data set failed");
-			return -1;
-		}
+		ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ICMP,
+			NH_FLD_ICMP_TYPE, &spec->hdr.icmp_type,
+			&mask->hdr.icmp_type, sizeof(uint8_t),
+			priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+		if (ret)
+			return ret;
 	}
 
 	if (mask->hdr.icmp_code) {
-		index = dpaa2_flow_extract_search(
-				&priv->extract.qos_key_extract.dpkg,
-				NET_PROT_ICMP, NH_FLD_ICMP_CODE);
-		if (index < 0) {
-			ret = dpaa2_flow_extract_add(
-					&priv->extract.qos_key_extract,
-					NET_PROT_ICMP,
-					NH_FLD_ICMP_CODE,
-					NH_FLD_ICMP_CODE_SIZE);
-			if (ret) {
-				DPAA2_PMD_ERR("QoS Extract add ICMP_CODE failed.");
-
-				return -1;
-			}
-			local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
-		}
-
-		index = dpaa2_flow_extract_search(
-				&priv->extract.tc_key_extract[group].dpkg,
-				NET_PROT_ICMP, NH_FLD_ICMP_CODE);
-		if (index < 0) {
-			ret = dpaa2_flow_extract_add(
-					&priv->extract.tc_key_extract[group],
-					NET_PROT_ICMP,
-					NH_FLD_ICMP_CODE,
-					NH_FLD_ICMP_CODE_SIZE);
-			if (ret) {
-				DPAA2_PMD_ERR("FS Extract add ICMP_CODE failed.");
+		ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ICMP,
+			NH_FLD_ICMP_CODE, &spec->hdr.icmp_code,
+			&mask->hdr.icmp_code, sizeof(uint8_t),
+			priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
+		if (ret)
+			return ret;
 
-				return -1;
-			}
-			local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
-		}
-
-		ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"Move ipaddr after ICMP CODE set failed");
-			return -1;
-		}
-
-		ret = dpaa2_flow_rule_data_set(
-				&priv->extract.qos_key_extract,
-				&flow->qos_rule,
-				NET_PROT_ICMP,
-				NH_FLD_ICMP_CODE,
-				&spec->hdr.icmp_code,
-				&mask->hdr.icmp_code,
-				NH_FLD_ICMP_CODE_SIZE);
-		if (ret) {
-			DPAA2_PMD_ERR("QoS NH_FLD_ICMP_CODE rule data set failed");
-			return -1;
-		}
-
-		ret = dpaa2_flow_rule_data_set(
-				&priv->extract.tc_key_extract[group],
-				&flow->fs_rule,
-				NET_PROT_ICMP,
-				NH_FLD_ICMP_CODE,
-				&spec->hdr.icmp_code,
-				&mask->hdr.icmp_code,
-				NH_FLD_ICMP_CODE_SIZE);
-		if (ret) {
-			DPAA2_PMD_ERR("FS NH_FLD_ICMP_CODE rule data set failed");
-			return -1;
-		}
+		ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ICMP,
+			NH_FLD_ICMP_CODE, &spec->hdr.icmp_code,
+			&mask->hdr.icmp_code, sizeof(uint8_t),
+			priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+		if (ret)
+			return ret;
 	}
 
 	(*device_configured) |= local_cfg;
@@ -1976,84 +1889,41 @@  dpaa2_configure_flow_icmp(struct rte_flow *flow,
 }
 
 static int
-dpaa2_configure_flow_udp(struct rte_flow *flow,
-			 struct rte_eth_dev *dev,
-			  const struct rte_flow_attr *attr,
-			  const struct rte_flow_item *pattern,
-			  const struct rte_flow_action actions[] __rte_unused,
-			  struct rte_flow_error *error __rte_unused,
-			  int *device_configured)
+dpaa2_configure_flow_udp(struct dpaa2_dev_flow *flow,
+	struct rte_eth_dev *dev,
+	const struct rte_flow_attr *attr,
+	const struct rte_flow_item *pattern,
+	const struct rte_flow_action actions[] __rte_unused,
+	struct rte_flow_error *error __rte_unused,
+	int *device_configured)
 {
-	int index, ret;
-	int local_cfg = 0;
+	int ret, local_cfg = 0;
 	uint32_t group;
 	const struct rte_flow_item_udp *spec, *mask;
-
-	const struct rte_flow_item_udp *last __rte_unused;
 	struct dpaa2_dev_priv *priv = dev->data->dev_private;
 
 	group = attr->group;
 
 	/* Parse pattern list to get the matching parameters */
-	spec    = (const struct rte_flow_item_udp *)pattern->spec;
-	last    = (const struct rte_flow_item_udp *)pattern->last;
-	mask    = (const struct rte_flow_item_udp *)
-		(pattern->mask ? pattern->mask : &dpaa2_flow_item_udp_mask);
+	spec = pattern->spec;
+	mask = pattern->mask ?
+		pattern->mask : &dpaa2_flow_item_udp_mask;
 
 	/* Get traffic class index and flow id to be configured */
 	flow->tc_id = group;
 	flow->tc_index = attr->priority;
 
 	if (!spec || !mc_l4_port_identification) {
-		struct proto_discrimination proto;
-
-		index = dpaa2_flow_extract_search(
-				&priv->extract.qos_key_extract.dpkg,
-				NET_PROT_IP, NH_FLD_IP_PROTO);
-		if (index < 0) {
-			ret = dpaa2_flow_proto_discrimination_extract(
-					&priv->extract.qos_key_extract,
-					DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
-			if (ret) {
-				DPAA2_PMD_ERR(
-					"QoS Extract IP protocol to discriminate UDP failed.");
-
-				return -1;
-			}
-			local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
-		}
-
-		index = dpaa2_flow_extract_search(
-				&priv->extract.tc_key_extract[group].dpkg,
-				NET_PROT_IP, NH_FLD_IP_PROTO);
-		if (index < 0) {
-			ret = dpaa2_flow_proto_discrimination_extract(
-				&priv->extract.tc_key_extract[group],
-				DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
-			if (ret) {
-				DPAA2_PMD_ERR(
-					"FS Extract IP protocol to discriminate UDP failed.");
-
-				return -1;
-			}
-			local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
-		}
-
-		ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"Move IP addr before UDP discrimination set failed");
-			return -1;
-		}
+		struct prev_proto_field_id prev_proto;
 
-		proto.type = DPAA2_FLOW_ITEM_TYPE_GENERIC_IP;
-		proto.ip_proto = IPPROTO_UDP;
-		ret = dpaa2_flow_proto_discrimination_rule(priv, flow,
-							proto, group);
-		if (ret) {
-			DPAA2_PMD_ERR("UDP discrimination rule set failed");
-			return -1;
-		}
+		prev_proto.prot = NET_PROT_IP;
+		prev_proto.ip_proto = IPPROTO_UDP;
+		ret = dpaa2_flow_identify_by_prev_prot(priv,
+			flow, &prev_proto,
+			DPAA2_FLOW_QOS_TYPE | DPAA2_FLOW_FS_TYPE,
+			group, &local_cfg);
+		if (ret)
+			return ret;
 
 		(*device_configured) |= local_cfg;
 
@@ -2065,149 +1935,40 @@  dpaa2_configure_flow_udp(struct rte_flow *flow,
 		RTE_FLOW_ITEM_TYPE_UDP)) {
 		DPAA2_PMD_WARN("Extract field(s) of UDP not support.");
 
-		return -1;
+		return -EINVAL;
 	}
 
 	if (mask->hdr.src_port) {
-		index = dpaa2_flow_extract_search(
-				&priv->extract.qos_key_extract.dpkg,
-				NET_PROT_UDP, NH_FLD_UDP_PORT_SRC);
-		if (index < 0) {
-			ret = dpaa2_flow_extract_add(
-					&priv->extract.qos_key_extract,
-				NET_PROT_UDP,
-				NH_FLD_UDP_PORT_SRC,
-				NH_FLD_UDP_PORT_SIZE);
-			if (ret) {
-				DPAA2_PMD_ERR("QoS Extract add UDP_SRC failed.");
+		ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_UDP,
+			NH_FLD_UDP_PORT_SRC, &spec->hdr.src_port,
+			&mask->hdr.src_port, sizeof(rte_be16_t),
+			priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
+		if (ret)
+			return ret;
 
-				return -1;
-			}
-			local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
-		}
+		ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_UDP,
+			NH_FLD_UDP_PORT_SRC, &spec->hdr.src_port,
+			&mask->hdr.src_port, sizeof(rte_be16_t),
+			priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+		if (ret)
+			return ret;
+	}
 
-		index = dpaa2_flow_extract_search(
-				&priv->extract.tc_key_extract[group].dpkg,
-				NET_PROT_UDP, NH_FLD_UDP_PORT_SRC);
-		if (index < 0) {
-			ret = dpaa2_flow_extract_add(
-					&priv->extract.tc_key_extract[group],
-					NET_PROT_UDP,
-					NH_FLD_UDP_PORT_SRC,
-					NH_FLD_UDP_PORT_SIZE);
-			if (ret) {
-				DPAA2_PMD_ERR("FS Extract add UDP_SRC failed.");
+	if (mask->hdr.dst_port) {
+		ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_UDP,
+			NH_FLD_UDP_PORT_DST, &spec->hdr.dst_port,
+			&mask->hdr.dst_port, sizeof(rte_be16_t),
+			priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
+		if (ret)
+			return ret;
 
-				return -1;
-			}
-			local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
-		}
-
-		ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"Move ipaddr before UDP_PORT_SRC set failed");
-			return -1;
-		}
-
-		ret = dpaa2_flow_rule_data_set(&priv->extract.qos_key_extract,
-				&flow->qos_rule,
-				NET_PROT_UDP,
-				NH_FLD_UDP_PORT_SRC,
-				&spec->hdr.src_port,
-				&mask->hdr.src_port,
-				NH_FLD_UDP_PORT_SIZE);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"QoS NH_FLD_UDP_PORT_SRC rule data set failed");
-			return -1;
-		}
-
-		ret = dpaa2_flow_rule_data_set(
-				&priv->extract.tc_key_extract[group],
-				&flow->fs_rule,
-				NET_PROT_UDP,
-				NH_FLD_UDP_PORT_SRC,
-				&spec->hdr.src_port,
-				&mask->hdr.src_port,
-				NH_FLD_UDP_PORT_SIZE);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"FS NH_FLD_UDP_PORT_SRC rule data set failed");
-			return -1;
-		}
-	}
-
-	if (mask->hdr.dst_port) {
-		index = dpaa2_flow_extract_search(
-				&priv->extract.qos_key_extract.dpkg,
-				NET_PROT_UDP, NH_FLD_UDP_PORT_DST);
-		if (index < 0) {
-			ret = dpaa2_flow_extract_add(
-					&priv->extract.qos_key_extract,
-					NET_PROT_UDP,
-					NH_FLD_UDP_PORT_DST,
-					NH_FLD_UDP_PORT_SIZE);
-			if (ret) {
-				DPAA2_PMD_ERR("QoS Extract add UDP_DST failed.");
-
-				return -1;
-			}
-			local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
-		}
-
-		index = dpaa2_flow_extract_search(
-				&priv->extract.tc_key_extract[group].dpkg,
-				NET_PROT_UDP, NH_FLD_UDP_PORT_DST);
-		if (index < 0) {
-			ret = dpaa2_flow_extract_add(
-					&priv->extract.tc_key_extract[group],
-					NET_PROT_UDP,
-					NH_FLD_UDP_PORT_DST,
-					NH_FLD_UDP_PORT_SIZE);
-			if (ret) {
-				DPAA2_PMD_ERR("FS Extract add UDP_DST failed.");
-
-				return -1;
-			}
-			local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
-		}
-
-		ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"Move ipaddr before UDP_PORT_DST set failed");
-			return -1;
-		}
-
-		ret = dpaa2_flow_rule_data_set(
-				&priv->extract.qos_key_extract,
-				&flow->qos_rule,
-				NET_PROT_UDP,
-				NH_FLD_UDP_PORT_DST,
-				&spec->hdr.dst_port,
-				&mask->hdr.dst_port,
-				NH_FLD_UDP_PORT_SIZE);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"QoS NH_FLD_UDP_PORT_DST rule data set failed");
-			return -1;
-		}
-
-		ret = dpaa2_flow_rule_data_set(
-				&priv->extract.tc_key_extract[group],
-				&flow->fs_rule,
-				NET_PROT_UDP,
-				NH_FLD_UDP_PORT_DST,
-				&spec->hdr.dst_port,
-				&mask->hdr.dst_port,
-				NH_FLD_UDP_PORT_SIZE);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"FS NH_FLD_UDP_PORT_DST rule data set failed");
-			return -1;
-		}
-	}
+		ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_UDP,
+			NH_FLD_UDP_PORT_DST, &spec->hdr.dst_port,
+			&mask->hdr.dst_port, sizeof(rte_be16_t),
+			priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+		if (ret)
+			return ret;
+	}
 
 	(*device_configured) |= local_cfg;
 
@@ -2215,84 +1976,41 @@  dpaa2_configure_flow_udp(struct rte_flow *flow,
 }
 
 static int
-dpaa2_configure_flow_tcp(struct rte_flow *flow,
-			 struct rte_eth_dev *dev,
-			 const struct rte_flow_attr *attr,
-			 const struct rte_flow_item *pattern,
-			 const struct rte_flow_action actions[] __rte_unused,
-			 struct rte_flow_error *error __rte_unused,
-			 int *device_configured)
+dpaa2_configure_flow_tcp(struct dpaa2_dev_flow *flow,
+	struct rte_eth_dev *dev,
+	const struct rte_flow_attr *attr,
+	const struct rte_flow_item *pattern,
+	const struct rte_flow_action actions[] __rte_unused,
+	struct rte_flow_error *error __rte_unused,
+	int *device_configured)
 {
-	int index, ret;
-	int local_cfg = 0;
+	int ret, local_cfg = 0;
 	uint32_t group;
 	const struct rte_flow_item_tcp *spec, *mask;
-
-	const struct rte_flow_item_tcp *last __rte_unused;
 	struct dpaa2_dev_priv *priv = dev->data->dev_private;
 
 	group = attr->group;
 
 	/* Parse pattern list to get the matching parameters */
-	spec    = (const struct rte_flow_item_tcp *)pattern->spec;
-	last    = (const struct rte_flow_item_tcp *)pattern->last;
-	mask    = (const struct rte_flow_item_tcp *)
-		(pattern->mask ? pattern->mask : &dpaa2_flow_item_tcp_mask);
+	spec = pattern->spec;
+	mask = pattern->mask ?
+		pattern->mask : &dpaa2_flow_item_tcp_mask;
 
 	/* Get traffic class index and flow id to be configured */
 	flow->tc_id = group;
 	flow->tc_index = attr->priority;
 
 	if (!spec || !mc_l4_port_identification) {
-		struct proto_discrimination proto;
+		struct prev_proto_field_id prev_proto;
 
-		index = dpaa2_flow_extract_search(
-				&priv->extract.qos_key_extract.dpkg,
-				NET_PROT_IP, NH_FLD_IP_PROTO);
-		if (index < 0) {
-			ret = dpaa2_flow_proto_discrimination_extract(
-					&priv->extract.qos_key_extract,
-					DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
-			if (ret) {
-				DPAA2_PMD_ERR(
-					"QoS Extract IP protocol to discriminate TCP failed.");
-
-				return -1;
-			}
-			local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
-		}
-
-		index = dpaa2_flow_extract_search(
-				&priv->extract.tc_key_extract[group].dpkg,
-				NET_PROT_IP, NH_FLD_IP_PROTO);
-		if (index < 0) {
-			ret = dpaa2_flow_proto_discrimination_extract(
-				&priv->extract.tc_key_extract[group],
-				DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
-			if (ret) {
-				DPAA2_PMD_ERR(
-					"FS Extract IP protocol to discriminate TCP failed.");
-
-				return -1;
-			}
-			local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
-		}
-
-		ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"Move IP addr before TCP discrimination set failed");
-			return -1;
-		}
-
-		proto.type = DPAA2_FLOW_ITEM_TYPE_GENERIC_IP;
-		proto.ip_proto = IPPROTO_TCP;
-		ret = dpaa2_flow_proto_discrimination_rule(priv, flow,
-							proto, group);
-		if (ret) {
-			DPAA2_PMD_ERR("TCP discrimination rule set failed");
-			return -1;
-		}
+		prev_proto.prot = NET_PROT_IP;
+		prev_proto.ip_proto = IPPROTO_TCP;
+		ret = dpaa2_flow_identify_by_prev_prot(priv,
+			flow, &prev_proto,
+			DPAA2_FLOW_QOS_TYPE | DPAA2_FLOW_FS_TYPE,
+			group, &local_cfg);
+		if (ret)
+			return ret;
 
 		(*device_configured) |= local_cfg;
 
@@ -2304,149 +2022,39 @@  dpaa2_configure_flow_tcp(struct rte_flow *flow,
 		RTE_FLOW_ITEM_TYPE_TCP)) {
 		DPAA2_PMD_WARN("Extract field(s) of TCP not support.");
 
-		return -1;
+		return -EINVAL;
 	}
 
 	if (mask->hdr.src_port) {
-		index = dpaa2_flow_extract_search(
-				&priv->extract.qos_key_extract.dpkg,
-				NET_PROT_TCP, NH_FLD_TCP_PORT_SRC);
-		if (index < 0) {
-			ret = dpaa2_flow_extract_add(
-					&priv->extract.qos_key_extract,
-					NET_PROT_TCP,
-					NH_FLD_TCP_PORT_SRC,
-					NH_FLD_TCP_PORT_SIZE);
-			if (ret) {
-				DPAA2_PMD_ERR("QoS Extract add TCP_SRC failed.");
-
-				return -1;
-			}
-			local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
-		}
-
-		index = dpaa2_flow_extract_search(
-				&priv->extract.tc_key_extract[group].dpkg,
-				NET_PROT_TCP, NH_FLD_TCP_PORT_SRC);
-		if (index < 0) {
-			ret = dpaa2_flow_extract_add(
-					&priv->extract.tc_key_extract[group],
-					NET_PROT_TCP,
-					NH_FLD_TCP_PORT_SRC,
-					NH_FLD_TCP_PORT_SIZE);
-			if (ret) {
-				DPAA2_PMD_ERR("FS Extract add TCP_SRC failed.");
-
-				return -1;
-			}
-			local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
-		}
+		ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_TCP,
+			NH_FLD_TCP_PORT_SRC, &spec->hdr.src_port,
+			&mask->hdr.src_port, sizeof(rte_be16_t),
+			priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
+		if (ret)
+			return ret;
 
-		ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"Move ipaddr before TCP_PORT_SRC set failed");
-			return -1;
-		}
-
-		ret = dpaa2_flow_rule_data_set(
-				&priv->extract.qos_key_extract,
-				&flow->qos_rule,
-				NET_PROT_TCP,
-				NH_FLD_TCP_PORT_SRC,
-				&spec->hdr.src_port,
-				&mask->hdr.src_port,
-				NH_FLD_TCP_PORT_SIZE);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"QoS NH_FLD_TCP_PORT_SRC rule data set failed");
-			return -1;
-		}
-
-		ret = dpaa2_flow_rule_data_set(
-				&priv->extract.tc_key_extract[group],
-				&flow->fs_rule,
-				NET_PROT_TCP,
-				NH_FLD_TCP_PORT_SRC,
-				&spec->hdr.src_port,
-				&mask->hdr.src_port,
-				NH_FLD_TCP_PORT_SIZE);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"FS NH_FLD_TCP_PORT_SRC rule data set failed");
-			return -1;
-		}
+		ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_TCP,
+			NH_FLD_TCP_PORT_SRC, &spec->hdr.src_port,
+			&mask->hdr.src_port, sizeof(rte_be16_t),
+			priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+		if (ret)
+			return ret;
 	}
 
 	if (mask->hdr.dst_port) {
-		index = dpaa2_flow_extract_search(
-				&priv->extract.qos_key_extract.dpkg,
-				NET_PROT_TCP, NH_FLD_TCP_PORT_DST);
-		if (index < 0) {
-			ret = dpaa2_flow_extract_add(
-					&priv->extract.qos_key_extract,
-					NET_PROT_TCP,
-					NH_FLD_TCP_PORT_DST,
-					NH_FLD_TCP_PORT_SIZE);
-			if (ret) {
-				DPAA2_PMD_ERR("QoS Extract add TCP_DST failed.");
-
-				return -1;
-			}
-			local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
-		}
-
-		index = dpaa2_flow_extract_search(
-				&priv->extract.tc_key_extract[group].dpkg,
-				NET_PROT_TCP, NH_FLD_TCP_PORT_DST);
-		if (index < 0) {
-			ret = dpaa2_flow_extract_add(
-					&priv->extract.tc_key_extract[group],
-					NET_PROT_TCP,
-					NH_FLD_TCP_PORT_DST,
-					NH_FLD_TCP_PORT_SIZE);
-			if (ret) {
-				DPAA2_PMD_ERR("FS Extract add TCP_DST failed.");
-
-				return -1;
-			}
-			local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
-		}
-
-		ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"Move ipaddr before TCP_PORT_DST set failed");
-			return -1;
-		}
-
-		ret = dpaa2_flow_rule_data_set(
-				&priv->extract.qos_key_extract,
-				&flow->qos_rule,
-				NET_PROT_TCP,
-				NH_FLD_TCP_PORT_DST,
-				&spec->hdr.dst_port,
-				&mask->hdr.dst_port,
-				NH_FLD_TCP_PORT_SIZE);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"QoS NH_FLD_TCP_PORT_DST rule data set failed");
-			return -1;
-		}
+		ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_TCP,
+			NH_FLD_TCP_PORT_DST, &spec->hdr.dst_port,
+			&mask->hdr.dst_port, sizeof(rte_be16_t),
+			priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
+		if (ret)
+			return ret;
 
-		ret = dpaa2_flow_rule_data_set(
-				&priv->extract.tc_key_extract[group],
-				&flow->fs_rule,
-				NET_PROT_TCP,
-				NH_FLD_TCP_PORT_DST,
-				&spec->hdr.dst_port,
-				&mask->hdr.dst_port,
-				NH_FLD_TCP_PORT_SIZE);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"FS NH_FLD_TCP_PORT_DST rule data set failed");
-			return -1;
-		}
+		ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_TCP,
+			NH_FLD_TCP_PORT_DST, &spec->hdr.dst_port,
+			&mask->hdr.dst_port, sizeof(rte_be16_t),
+			priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+		if (ret)
+			return ret;
 	}
 
 	(*device_configured) |= local_cfg;
@@ -2455,85 +2063,41 @@  dpaa2_configure_flow_tcp(struct rte_flow *flow,
 }
 
 static int
-dpaa2_configure_flow_sctp(struct rte_flow *flow,
-			  struct rte_eth_dev *dev,
-			  const struct rte_flow_attr *attr,
-			  const struct rte_flow_item *pattern,
-			  const struct rte_flow_action actions[] __rte_unused,
-			  struct rte_flow_error *error __rte_unused,
-			  int *device_configured)
+dpaa2_configure_flow_sctp(struct dpaa2_dev_flow *flow,
+	struct rte_eth_dev *dev,
+	const struct rte_flow_attr *attr,
+	const struct rte_flow_item *pattern,
+	const struct rte_flow_action actions[] __rte_unused,
+	struct rte_flow_error *error __rte_unused,
+	int *device_configured)
 {
-	int index, ret;
-	int local_cfg = 0;
+	int ret, local_cfg = 0;
 	uint32_t group;
 	const struct rte_flow_item_sctp *spec, *mask;
-
-	const struct rte_flow_item_sctp *last __rte_unused;
 	struct dpaa2_dev_priv *priv = dev->data->dev_private;
 
 	group = attr->group;
 
 	/* Parse pattern list to get the matching parameters */
-	spec    = (const struct rte_flow_item_sctp *)pattern->spec;
-	last    = (const struct rte_flow_item_sctp *)pattern->last;
-	mask    = (const struct rte_flow_item_sctp *)
-			(pattern->mask ? pattern->mask :
-				&dpaa2_flow_item_sctp_mask);
+	spec = pattern->spec;
+	mask = pattern->mask ?
+		pattern->mask : &dpaa2_flow_item_sctp_mask;
 
 	/* Get traffic class index and flow id to be configured */
 	flow->tc_id = group;
 	flow->tc_index = attr->priority;
 
 	if (!spec || !mc_l4_port_identification) {
-		struct proto_discrimination proto;
+		struct prev_proto_field_id prev_proto;
 
-		index = dpaa2_flow_extract_search(
-				&priv->extract.qos_key_extract.dpkg,
-				NET_PROT_IP, NH_FLD_IP_PROTO);
-		if (index < 0) {
-			ret = dpaa2_flow_proto_discrimination_extract(
-					&priv->extract.qos_key_extract,
-					DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
-			if (ret) {
-				DPAA2_PMD_ERR(
-					"QoS Extract IP protocol to discriminate SCTP failed.");
-
-				return -1;
-			}
-			local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
-		}
-
-		index = dpaa2_flow_extract_search(
-				&priv->extract.tc_key_extract[group].dpkg,
-				NET_PROT_IP, NH_FLD_IP_PROTO);
-		if (index < 0) {
-			ret = dpaa2_flow_proto_discrimination_extract(
-					&priv->extract.tc_key_extract[group],
-					DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
-			if (ret) {
-				DPAA2_PMD_ERR(
-					"FS Extract IP protocol to discriminate SCTP failed.");
-
-				return -1;
-			}
-			local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
-		}
-
-		ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"Move ipaddr before SCTP discrimination set failed");
-			return -1;
-		}
-
-		proto.type = DPAA2_FLOW_ITEM_TYPE_GENERIC_IP;
-		proto.ip_proto = IPPROTO_SCTP;
-		ret = dpaa2_flow_proto_discrimination_rule(priv, flow,
-							proto, group);
-		if (ret) {
-			DPAA2_PMD_ERR("SCTP discrimination rule set failed");
-			return -1;
-		}
+		prev_proto.prot = NET_PROT_IP;
+		prev_proto.ip_proto = IPPROTO_SCTP;
+		ret = dpaa2_flow_identify_by_prev_prot(priv,
+			flow, &prev_proto,
+			DPAA2_FLOW_QOS_TYPE | DPAA2_FLOW_FS_TYPE,
+			group, &local_cfg);
+		if (ret)
+			return ret;
 
 		(*device_configured) |= local_cfg;
 
@@ -2549,145 +2113,35 @@  dpaa2_configure_flow_sctp(struct rte_flow *flow,
 	}
 
 	if (mask->hdr.src_port) {
-		index = dpaa2_flow_extract_search(
-				&priv->extract.qos_key_extract.dpkg,
-				NET_PROT_SCTP, NH_FLD_SCTP_PORT_SRC);
-		if (index < 0) {
-			ret = dpaa2_flow_extract_add(
-					&priv->extract.qos_key_extract,
-					NET_PROT_SCTP,
-					NH_FLD_SCTP_PORT_SRC,
-					NH_FLD_SCTP_PORT_SIZE);
-			if (ret) {
-				DPAA2_PMD_ERR("QoS Extract add SCTP_SRC failed.");
-
-				return -1;
-			}
-			local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
-		}
-
-		index = dpaa2_flow_extract_search(
-				&priv->extract.tc_key_extract[group].dpkg,
-				NET_PROT_SCTP, NH_FLD_SCTP_PORT_SRC);
-		if (index < 0) {
-			ret = dpaa2_flow_extract_add(
-					&priv->extract.tc_key_extract[group],
-					NET_PROT_SCTP,
-					NH_FLD_SCTP_PORT_SRC,
-					NH_FLD_SCTP_PORT_SIZE);
-			if (ret) {
-				DPAA2_PMD_ERR("FS Extract add SCTP_SRC failed.");
-
-				return -1;
-			}
-			local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
-		}
+		ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_SCTP,
+			NH_FLD_SCTP_PORT_SRC, &spec->hdr.src_port,
+			&mask->hdr.src_port, sizeof(rte_be16_t),
+			priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
+		if (ret)
+			return ret;
 
-		ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"Move ipaddr before SCTP_PORT_SRC set failed");
-			return -1;
-		}
-
-		ret = dpaa2_flow_rule_data_set(
-				&priv->extract.qos_key_extract,
-				&flow->qos_rule,
-				NET_PROT_SCTP,
-				NH_FLD_SCTP_PORT_SRC,
-				&spec->hdr.src_port,
-				&mask->hdr.src_port,
-				NH_FLD_SCTP_PORT_SIZE);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"QoS NH_FLD_SCTP_PORT_SRC rule data set failed");
-			return -1;
-		}
-
-		ret = dpaa2_flow_rule_data_set(
-				&priv->extract.tc_key_extract[group],
-				&flow->fs_rule,
-				NET_PROT_SCTP,
-				NH_FLD_SCTP_PORT_SRC,
-				&spec->hdr.src_port,
-				&mask->hdr.src_port,
-				NH_FLD_SCTP_PORT_SIZE);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"FS NH_FLD_SCTP_PORT_SRC rule data set failed");
-			return -1;
-		}
+		ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_SCTP,
+			NH_FLD_SCTP_PORT_SRC, &spec->hdr.src_port,
+			&mask->hdr.src_port, sizeof(rte_be16_t),
+			priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+		if (ret)
+			return ret;
 	}
 
 	if (mask->hdr.dst_port) {
-		index = dpaa2_flow_extract_search(
-				&priv->extract.qos_key_extract.dpkg,
-				NET_PROT_SCTP, NH_FLD_SCTP_PORT_DST);
-		if (index < 0) {
-			ret = dpaa2_flow_extract_add(
-					&priv->extract.qos_key_extract,
-					NET_PROT_SCTP,
-					NH_FLD_SCTP_PORT_DST,
-					NH_FLD_SCTP_PORT_SIZE);
-			if (ret) {
-				DPAA2_PMD_ERR("QoS Extract add SCTP_DST failed.");
-
-				return -1;
-			}
-			local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
-		}
-
-		index = dpaa2_flow_extract_search(
-				&priv->extract.tc_key_extract[group].dpkg,
-				NET_PROT_SCTP, NH_FLD_SCTP_PORT_DST);
-		if (index < 0) {
-			ret = dpaa2_flow_extract_add(
-					&priv->extract.tc_key_extract[group],
-					NET_PROT_SCTP,
-					NH_FLD_SCTP_PORT_DST,
-					NH_FLD_SCTP_PORT_SIZE);
-			if (ret) {
-				DPAA2_PMD_ERR("FS Extract add SCTP_DST failed.");
-
-				return -1;
-			}
-			local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
-		}
-
-		ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"Move ipaddr before SCTP_PORT_DST set failed");
-			return -1;
-		}
-
-		ret = dpaa2_flow_rule_data_set(
-				&priv->extract.qos_key_extract,
-				&flow->qos_rule,
-				NET_PROT_SCTP,
-				NH_FLD_SCTP_PORT_DST,
-				&spec->hdr.dst_port,
-				&mask->hdr.dst_port,
-				NH_FLD_SCTP_PORT_SIZE);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"QoS NH_FLD_SCTP_PORT_DST rule data set failed");
-			return -1;
-		}
+		ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_SCTP,
+			NH_FLD_SCTP_PORT_DST, &spec->hdr.dst_port,
+			&mask->hdr.dst_port, sizeof(rte_be16_t),
+			priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
+		if (ret)
+			return ret;
 
-		ret = dpaa2_flow_rule_data_set(
-				&priv->extract.tc_key_extract[group],
-				&flow->fs_rule,
-				NET_PROT_SCTP,
-				NH_FLD_SCTP_PORT_DST,
-				&spec->hdr.dst_port,
-				&mask->hdr.dst_port,
-				NH_FLD_SCTP_PORT_SIZE);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"FS NH_FLD_SCTP_PORT_DST rule data set failed");
-			return -1;
-		}
+		ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_SCTP,
+			NH_FLD_SCTP_PORT_DST, &spec->hdr.dst_port,
+			&mask->hdr.dst_port, sizeof(rte_be16_t),
+			priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+		if (ret)
+			return ret;
 	}
 
 	(*device_configured) |= local_cfg;
@@ -2696,88 +2150,46 @@  dpaa2_configure_flow_sctp(struct rte_flow *flow,
 }
 
 static int
-dpaa2_configure_flow_gre(struct rte_flow *flow,
-			 struct rte_eth_dev *dev,
-			 const struct rte_flow_attr *attr,
-			 const struct rte_flow_item *pattern,
-			 const struct rte_flow_action actions[] __rte_unused,
-			 struct rte_flow_error *error __rte_unused,
-			 int *device_configured)
+dpaa2_configure_flow_gre(struct dpaa2_dev_flow *flow,
+	struct rte_eth_dev *dev,
+	const struct rte_flow_attr *attr,
+	const struct rte_flow_item *pattern,
+	const struct rte_flow_action actions[] __rte_unused,
+	struct rte_flow_error *error __rte_unused,
+	int *device_configured)
 {
-	int index, ret;
-	int local_cfg = 0;
+	int ret, local_cfg = 0;
 	uint32_t group;
 	const struct rte_flow_item_gre *spec, *mask;
-
-	const struct rte_flow_item_gre *last __rte_unused;
 	struct dpaa2_dev_priv *priv = dev->data->dev_private;
 
 	group = attr->group;
 
 	/* Parse pattern list to get the matching parameters */
-	spec    = (const struct rte_flow_item_gre *)pattern->spec;
-	last    = (const struct rte_flow_item_gre *)pattern->last;
-	mask    = (const struct rte_flow_item_gre *)
-		(pattern->mask ? pattern->mask : &dpaa2_flow_item_gre_mask);
+	spec = pattern->spec;
+	mask = pattern->mask ?
+		pattern->mask : &dpaa2_flow_item_gre_mask;
 
 	/* Get traffic class index and flow id to be configured */
 	flow->tc_id = group;
 	flow->tc_index = attr->priority;
 
 	if (!spec) {
-		struct proto_discrimination proto;
+		struct prev_proto_field_id prev_proto;
 
-		index = dpaa2_flow_extract_search(
-				&priv->extract.qos_key_extract.dpkg,
-				NET_PROT_IP, NH_FLD_IP_PROTO);
-		if (index < 0) {
-			ret = dpaa2_flow_proto_discrimination_extract(
-					&priv->extract.qos_key_extract,
-					DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
-			if (ret) {
-				DPAA2_PMD_ERR(
-					"QoS Extract IP protocol to discriminate GRE failed.");
-
-				return -1;
-			}
-			local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
-		}
-
-		index = dpaa2_flow_extract_search(
-				&priv->extract.tc_key_extract[group].dpkg,
-				NET_PROT_IP, NH_FLD_IP_PROTO);
-		if (index < 0) {
-			ret = dpaa2_flow_proto_discrimination_extract(
-					&priv->extract.tc_key_extract[group],
-					DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
-			if (ret) {
-				DPAA2_PMD_ERR(
-					"FS Extract IP protocol to discriminate GRE failed.");
-
-				return -1;
-			}
-			local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
-		}
-
-		ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
-		if (ret) {
-			DPAA2_PMD_ERR(
-				"Move IP addr before GRE discrimination set failed");
-			return -1;
-		}
-
-		proto.type = DPAA2_FLOW_ITEM_TYPE_GENERIC_IP;
-		proto.ip_proto = IPPROTO_GRE;
-		ret = dpaa2_flow_proto_discrimination_rule(priv, flow,
-							proto, group);
-		if (ret) {
-			DPAA2_PMD_ERR("GRE discrimination rule set failed");
-			return -1;
-		}
+		prev_proto.prot = NET_PROT_IP;
+		prev_proto.ip_proto = IPPROTO_GRE;
+		ret = dpaa2_flow_identify_by_prev_prot(priv,
+			flow, &prev_proto,
+			DPAA2_FLOW_QOS_TYPE | DPAA2_FLOW_FS_TYPE,
+			group, &local_cfg);
+		if (ret)
+			return ret;
 
 		(*device_configured) |= local_cfg;
 
-		return 0;
+		if (!spec)
+			return 0;
 	}
 
 	if (dpaa2_flow_extract_support((const uint8_t *)mask,
@@ -2790,74 +2202,19 @@  dpaa2_configure_flow_gre(struct rte_flow *flow,
 	if (!mask->protocol)
 		return 0;
 
-	index = dpaa2_flow_extract_search(
-			&priv->extract.qos_key_extract.dpkg,
-			NET_PROT_GRE, NH_FLD_GRE_TYPE);
-	if (index < 0) {
-		ret = dpaa2_flow_extract_add(
-				&priv->extract.qos_key_extract,
-				NET_PROT_GRE,
-				NH_FLD_GRE_TYPE,
-				sizeof(rte_be16_t));
-		if (ret) {
-			DPAA2_PMD_ERR("QoS Extract add GRE_TYPE failed.");
-
-			return -1;
-		}
-		local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
-	}
-
-	index = dpaa2_flow_extract_search(
-			&priv->extract.tc_key_extract[group].dpkg,
-			NET_PROT_GRE, NH_FLD_GRE_TYPE);
-	if (index < 0) {
-		ret = dpaa2_flow_extract_add(
-				&priv->extract.tc_key_extract[group],
-				NET_PROT_GRE,
-				NH_FLD_GRE_TYPE,
-				sizeof(rte_be16_t));
-		if (ret) {
-			DPAA2_PMD_ERR("FS Extract add GRE_TYPE failed.");
-
-			return -1;
-		}
-		local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
-	}
-
-	ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
-	if (ret) {
-		DPAA2_PMD_ERR(
-			"Move ipaddr before GRE_TYPE set failed");
-		return -1;
-	}
-
-	ret = dpaa2_flow_rule_data_set(
-				&priv->extract.qos_key_extract,
-				&flow->qos_rule,
-				NET_PROT_GRE,
-				NH_FLD_GRE_TYPE,
-				&spec->protocol,
-				&mask->protocol,
-				sizeof(rte_be16_t));
-	if (ret) {
-		DPAA2_PMD_ERR(
-			"QoS NH_FLD_GRE_TYPE rule data set failed");
-		return -1;
-	}
+	ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_GRE,
+			NH_FLD_GRE_TYPE, &spec->protocol,
+			&mask->protocol, sizeof(rte_be16_t),
+			priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE);
+	if (ret)
+		return ret;
 
-	ret = dpaa2_flow_rule_data_set(
-			&priv->extract.tc_key_extract[group],
-			&flow->fs_rule,
-			NET_PROT_GRE,
-			NH_FLD_GRE_TYPE,
-			&spec->protocol,
-			&mask->protocol,
-			sizeof(rte_be16_t));
-	if (ret) {
-		DPAA2_PMD_ERR(
-			"FS NH_FLD_GRE_TYPE rule data set failed");
-		return -1;
-	}
+	ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_GRE,
+			NH_FLD_GRE_TYPE, &spec->protocol,
+			&mask->protocol, sizeof(rte_be16_t),
+			priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE);
+	if (ret)
+		return ret;
 
 	(*device_configured) |= local_cfg;
 
@@ -2865,404 +2222,109 @@  dpaa2_configure_flow_gre(struct rte_flow *flow,
 }
 
 static int
-dpaa2_configure_flow_raw(struct rte_flow *flow,
-			 struct rte_eth_dev *dev,
-			 const struct rte_flow_attr *attr,
-			 const struct rte_flow_item *pattern,
-			 const struct rte_flow_action actions[] __rte_unused,
-			 struct rte_flow_error *error __rte_unused,
-			 int *device_configured)
+dpaa2_configure_flow_raw(struct dpaa2_dev_flow *flow,
+	struct rte_eth_dev *dev,
+	const struct rte_flow_attr *attr,
+	const struct rte_flow_item *pattern,
+	const struct rte_flow_action actions[] __rte_unused,
+	struct rte_flow_error *error __rte_unused,
+	int *device_configured)
 {
 	struct dpaa2_dev_priv *priv = dev->data->dev_private;
 	const struct rte_flow_item_raw *spec = pattern->spec;
 	const struct rte_flow_item_raw *mask = pattern->mask;
 	int prev_key_size =
-		priv->extract.qos_key_extract.key_info.key_total_size;
+		priv->extract.qos_key_extract.key_profile.key_max_size;
 	int local_cfg = 0, ret;
 	uint32_t group;
 
 	/* Need both spec and mask */
 	if (!spec || !mask) {
-		DPAA2_PMD_ERR("spec or mask not present.");
-		return -EINVAL;
-	}
-	/* Only supports non-relative with offset 0 */
-	if (spec->relative || spec->offset != 0 ||
-	    spec->search || spec->limit) {
-		DPAA2_PMD_ERR("relative and non zero offset not supported.");
-		return -EINVAL;
-	}
-	/* Spec len and mask len should be same */
-	if (spec->length != mask->length) {
-		DPAA2_PMD_ERR("Spec len and mask len mismatch.");
-		return -EINVAL;
-	}
-
-	/* Get traffic class index and flow id to be configured */
-	group = attr->group;
-	flow->tc_id = group;
-	flow->tc_index = attr->priority;
-
-	if (prev_key_size <= spec->length) {
-		ret = dpaa2_flow_extract_add_raw(&priv->extract.qos_key_extract,
-						 spec->length);
-		if (ret) {
-			DPAA2_PMD_ERR("QoS Extract RAW add failed.");
-			return -1;
-		}
-		local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
-
-		ret = dpaa2_flow_extract_add_raw(
-					&priv->extract.tc_key_extract[group],
-					spec->length);
-		if (ret) {
-			DPAA2_PMD_ERR("FS Extract RAW add failed.");
-			return -1;
-		}
-		local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
-	}
-
-	ret = dpaa2_flow_rule_data_set_raw(&flow->qos_rule, spec->pattern,
-					   mask->pattern, spec->length);
-	if (ret) {
-		DPAA2_PMD_ERR("QoS RAW rule data set failed");
-		return -1;
-	}
-
-	ret = dpaa2_flow_rule_data_set_raw(&flow->fs_rule, spec->pattern,
-					   mask->pattern, spec->length);
-	if (ret) {
-		DPAA2_PMD_ERR("FS RAW rule data set failed");
-		return -1;
-	}
-
-	(*device_configured) |= local_cfg;
-
-	return 0;
-}
-
-static inline int
-dpaa2_fs_action_supported(enum rte_flow_action_type action)
-{
-	int i;
-
-	for (i = 0; i < (int)(sizeof(dpaa2_supported_fs_action_type) /
-					sizeof(enum rte_flow_action_type)); i++) {
-		if (action == dpaa2_supported_fs_action_type[i])
-			return 1;
-	}
-
-	return 0;
-}
-/* The existing QoS/FS entry with IP address(es)
- * needs update after
- * new extract(s) are inserted before IP
- * address(es) extract(s).
- */
-static int
-dpaa2_flow_entry_update(
-	struct dpaa2_dev_priv *priv, uint8_t tc_id)
-{
-	struct rte_flow *curr = LIST_FIRST(&priv->flows);
-	struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
-	int ret;
-	int qos_ipsrc_offset = -1, qos_ipdst_offset = -1;
-	int fs_ipsrc_offset = -1, fs_ipdst_offset = -1;
-	struct dpaa2_key_extract *qos_key_extract =
-		&priv->extract.qos_key_extract;
-	struct dpaa2_key_extract *tc_key_extract =
-		&priv->extract.tc_key_extract[tc_id];
-	char ipsrc_key[NH_FLD_IPV6_ADDR_SIZE];
-	char ipdst_key[NH_FLD_IPV6_ADDR_SIZE];
-	char ipsrc_mask[NH_FLD_IPV6_ADDR_SIZE];
-	char ipdst_mask[NH_FLD_IPV6_ADDR_SIZE];
-	int extend = -1, extend1, size = -1;
-	uint16_t qos_index;
-
-	while (curr) {
-		if (curr->ipaddr_rule.ipaddr_type ==
-			FLOW_NONE_IPADDR) {
-			curr = LIST_NEXT(curr, next);
-			continue;
-		}
-
-		if (curr->ipaddr_rule.ipaddr_type ==
-			FLOW_IPV4_ADDR) {
-			qos_ipsrc_offset =
-				qos_key_extract->key_info.ipv4_src_offset;
-			qos_ipdst_offset =
-				qos_key_extract->key_info.ipv4_dst_offset;
-			fs_ipsrc_offset =
-				tc_key_extract->key_info.ipv4_src_offset;
-			fs_ipdst_offset =
-				tc_key_extract->key_info.ipv4_dst_offset;
-			size = NH_FLD_IPV4_ADDR_SIZE;
-		} else {
-			qos_ipsrc_offset =
-				qos_key_extract->key_info.ipv6_src_offset;
-			qos_ipdst_offset =
-				qos_key_extract->key_info.ipv6_dst_offset;
-			fs_ipsrc_offset =
-				tc_key_extract->key_info.ipv6_src_offset;
-			fs_ipdst_offset =
-				tc_key_extract->key_info.ipv6_dst_offset;
-			size = NH_FLD_IPV6_ADDR_SIZE;
-		}
-
-		qos_index = curr->tc_id * priv->fs_entries +
-			curr->tc_index;
-
-		dpaa2_flow_qos_entry_log("Before update", curr, qos_index, stdout);
-
-		if (priv->num_rx_tc > 1) {
-			ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW,
-					priv->token, &curr->qos_rule);
-			if (ret) {
-				DPAA2_PMD_ERR("Qos entry remove failed.");
-				return -1;
-			}
-		}
-
-		extend = -1;
-
-		if (curr->ipaddr_rule.qos_ipsrc_offset >= 0) {
-			RTE_ASSERT(qos_ipsrc_offset >=
-				curr->ipaddr_rule.qos_ipsrc_offset);
-			extend1 = qos_ipsrc_offset -
-				curr->ipaddr_rule.qos_ipsrc_offset;
-			if (extend >= 0)
-				RTE_ASSERT(extend == extend1);
-			else
-				extend = extend1;
-
-			RTE_ASSERT((size == NH_FLD_IPV4_ADDR_SIZE) ||
-				(size == NH_FLD_IPV6_ADDR_SIZE));
-
-			memcpy(ipsrc_key,
-				(char *)(size_t)curr->qos_rule.key_iova +
-				curr->ipaddr_rule.qos_ipsrc_offset,
-				size);
-			memset((char *)(size_t)curr->qos_rule.key_iova +
-				curr->ipaddr_rule.qos_ipsrc_offset,
-				0, size);
-
-			memcpy(ipsrc_mask,
-				(char *)(size_t)curr->qos_rule.mask_iova +
-				curr->ipaddr_rule.qos_ipsrc_offset,
-				size);
-			memset((char *)(size_t)curr->qos_rule.mask_iova +
-				curr->ipaddr_rule.qos_ipsrc_offset,
-				0, size);
-
-			curr->ipaddr_rule.qos_ipsrc_offset = qos_ipsrc_offset;
-		}
-
-		if (curr->ipaddr_rule.qos_ipdst_offset >= 0) {
-			RTE_ASSERT(qos_ipdst_offset >=
-				curr->ipaddr_rule.qos_ipdst_offset);
-			extend1 = qos_ipdst_offset -
-				curr->ipaddr_rule.qos_ipdst_offset;
-			if (extend >= 0)
-				RTE_ASSERT(extend == extend1);
-			else
-				extend = extend1;
-
-			RTE_ASSERT((size == NH_FLD_IPV4_ADDR_SIZE) ||
-				(size == NH_FLD_IPV6_ADDR_SIZE));
-
-			memcpy(ipdst_key,
-				(char *)(size_t)curr->qos_rule.key_iova +
-				curr->ipaddr_rule.qos_ipdst_offset,
-				size);
-			memset((char *)(size_t)curr->qos_rule.key_iova +
-				curr->ipaddr_rule.qos_ipdst_offset,
-				0, size);
-
-			memcpy(ipdst_mask,
-				(char *)(size_t)curr->qos_rule.mask_iova +
-				curr->ipaddr_rule.qos_ipdst_offset,
-				size);
-			memset((char *)(size_t)curr->qos_rule.mask_iova +
-				curr->ipaddr_rule.qos_ipdst_offset,
-				0, size);
-
-			curr->ipaddr_rule.qos_ipdst_offset = qos_ipdst_offset;
-		}
-
-		if (curr->ipaddr_rule.qos_ipsrc_offset >= 0) {
-			RTE_ASSERT((size == NH_FLD_IPV4_ADDR_SIZE) ||
-				(size == NH_FLD_IPV6_ADDR_SIZE));
-			memcpy((char *)(size_t)curr->qos_rule.key_iova +
-				curr->ipaddr_rule.qos_ipsrc_offset,
-				ipsrc_key,
-				size);
-			memcpy((char *)(size_t)curr->qos_rule.mask_iova +
-				curr->ipaddr_rule.qos_ipsrc_offset,
-				ipsrc_mask,
-				size);
-		}
-		if (curr->ipaddr_rule.qos_ipdst_offset >= 0) {
-			RTE_ASSERT((size == NH_FLD_IPV4_ADDR_SIZE) ||
-				(size == NH_FLD_IPV6_ADDR_SIZE));
-			memcpy((char *)(size_t)curr->qos_rule.key_iova +
-				curr->ipaddr_rule.qos_ipdst_offset,
-				ipdst_key,
-				size);
-			memcpy((char *)(size_t)curr->qos_rule.mask_iova +
-				curr->ipaddr_rule.qos_ipdst_offset,
-				ipdst_mask,
-				size);
-		}
-
-		if (extend >= 0)
-			curr->qos_real_key_size += extend;
-
-		curr->qos_rule.key_size = FIXED_ENTRY_SIZE;
-
-		dpaa2_flow_qos_entry_log("Start update", curr, qos_index, stdout);
-
-		if (priv->num_rx_tc > 1) {
-			ret = dpni_add_qos_entry(dpni, CMD_PRI_LOW,
-					priv->token, &curr->qos_rule,
-					curr->tc_id, qos_index,
-					0, 0);
-			if (ret) {
-				DPAA2_PMD_ERR("Qos entry update failed.");
-				return -1;
-			}
-		}
-
-		if (!dpaa2_fs_action_supported(curr->action)) {
-			curr = LIST_NEXT(curr, next);
-			continue;
-		}
+		DPAA2_PMD_ERR("spec or mask not present.");
+		return -EINVAL;
+	}
+	/* Only supports non-relative with offset 0 */
+	if (spec->relative || spec->offset != 0 ||
+	    spec->search || spec->limit) {
+		DPAA2_PMD_ERR("relative and non zero offset not supported.");
+		return -EINVAL;
+	}
+	/* Spec len and mask len should be same */
+	if (spec->length != mask->length) {
+		DPAA2_PMD_ERR("Spec len and mask len mismatch.");
+		return -EINVAL;
+	}
 
-		dpaa2_flow_fs_entry_log("Before update", curr, stdout);
-		extend = -1;
+	/* Get traffic class index and flow id to be configured */
+	group = attr->group;
+	flow->tc_id = group;
+	flow->tc_index = attr->priority;
 
-		ret = dpni_remove_fs_entry(dpni, CMD_PRI_LOW,
-				priv->token, curr->tc_id, &curr->fs_rule);
+	if (prev_key_size <= spec->length) {
+		ret = dpaa2_flow_extract_add_raw(&priv->extract.qos_key_extract,
+						 spec->length);
 		if (ret) {
-			DPAA2_PMD_ERR("FS entry remove failed.");
+			DPAA2_PMD_ERR("QoS Extract RAW add failed.");
 			return -1;
 		}
+		local_cfg |= DPAA2_FLOW_QOS_TYPE;
 
-		if (curr->ipaddr_rule.fs_ipsrc_offset >= 0 &&
-			tc_id == curr->tc_id) {
-			RTE_ASSERT(fs_ipsrc_offset >=
-				curr->ipaddr_rule.fs_ipsrc_offset);
-			extend1 = fs_ipsrc_offset -
-				curr->ipaddr_rule.fs_ipsrc_offset;
-			if (extend >= 0)
-				RTE_ASSERT(extend == extend1);
-			else
-				extend = extend1;
-
-			memcpy(ipsrc_key,
-				(char *)(size_t)curr->fs_rule.key_iova +
-				curr->ipaddr_rule.fs_ipsrc_offset,
-				size);
-			memset((char *)(size_t)curr->fs_rule.key_iova +
-				curr->ipaddr_rule.fs_ipsrc_offset,
-				0, size);
-
-			memcpy(ipsrc_mask,
-				(char *)(size_t)curr->fs_rule.mask_iova +
-				curr->ipaddr_rule.fs_ipsrc_offset,
-				size);
-			memset((char *)(size_t)curr->fs_rule.mask_iova +
-				curr->ipaddr_rule.fs_ipsrc_offset,
-				0, size);
-
-			curr->ipaddr_rule.fs_ipsrc_offset = fs_ipsrc_offset;
+		ret = dpaa2_flow_extract_add_raw(&priv->extract.tc_key_extract[group],
+					spec->length);
+		if (ret) {
+			DPAA2_PMD_ERR("FS Extract RAW add failed.");
+			return -1;
 		}
+		local_cfg |= DPAA2_FLOW_FS_TYPE;
+	}
 
-		if (curr->ipaddr_rule.fs_ipdst_offset >= 0 &&
-			tc_id == curr->tc_id) {
-			RTE_ASSERT(fs_ipdst_offset >=
-				curr->ipaddr_rule.fs_ipdst_offset);
-			extend1 = fs_ipdst_offset -
-				curr->ipaddr_rule.fs_ipdst_offset;
-			if (extend >= 0)
-				RTE_ASSERT(extend == extend1);
-			else
-				extend = extend1;
-
-			memcpy(ipdst_key,
-				(char *)(size_t)curr->fs_rule.key_iova +
-				curr->ipaddr_rule.fs_ipdst_offset,
-				size);
-			memset((char *)(size_t)curr->fs_rule.key_iova +
-				curr->ipaddr_rule.fs_ipdst_offset,
-				0, size);
-
-			memcpy(ipdst_mask,
-				(char *)(size_t)curr->fs_rule.mask_iova +
-				curr->ipaddr_rule.fs_ipdst_offset,
-				size);
-			memset((char *)(size_t)curr->fs_rule.mask_iova +
-				curr->ipaddr_rule.fs_ipdst_offset,
-				0, size);
-
-			curr->ipaddr_rule.fs_ipdst_offset = fs_ipdst_offset;
-		}
+	ret = dpaa2_flow_rule_data_set_raw(&flow->qos_rule, spec->pattern,
+					   mask->pattern, spec->length);
+	if (ret) {
+		DPAA2_PMD_ERR("QoS RAW rule data set failed");
+		return -1;
+	}
 
-		if (curr->ipaddr_rule.fs_ipsrc_offset >= 0) {
-			memcpy((char *)(size_t)curr->fs_rule.key_iova +
-				curr->ipaddr_rule.fs_ipsrc_offset,
-				ipsrc_key,
-				size);
-			memcpy((char *)(size_t)curr->fs_rule.mask_iova +
-				curr->ipaddr_rule.fs_ipsrc_offset,
-				ipsrc_mask,
-				size);
-		}
-		if (curr->ipaddr_rule.fs_ipdst_offset >= 0) {
-			memcpy((char *)(size_t)curr->fs_rule.key_iova +
-				curr->ipaddr_rule.fs_ipdst_offset,
-				ipdst_key,
-				size);
-			memcpy((char *)(size_t)curr->fs_rule.mask_iova +
-				curr->ipaddr_rule.fs_ipdst_offset,
-				ipdst_mask,
-				size);
-		}
+	ret = dpaa2_flow_rule_data_set_raw(&flow->fs_rule, spec->pattern,
+					   mask->pattern, spec->length);
+	if (ret) {
+		DPAA2_PMD_ERR("FS RAW rule data set failed");
+		return -1;
+	}
 
-		if (extend >= 0)
-			curr->fs_real_key_size += extend;
-		curr->fs_rule.key_size = FIXED_ENTRY_SIZE;
+	(*device_configured) |= local_cfg;
 
-		dpaa2_flow_fs_entry_log("Start update", curr, stdout);
+	return 0;
+}
 
-		ret = dpni_add_fs_entry(dpni, CMD_PRI_LOW,
-				priv->token, curr->tc_id, curr->tc_index,
-				&curr->fs_rule, &curr->action_cfg);
-		if (ret) {
-			DPAA2_PMD_ERR("FS entry update failed.");
-			return -1;
-		}
+static inline int
+dpaa2_fs_action_supported(enum rte_flow_action_type action)
+{
+	int i;
+	int action_num = sizeof(dpaa2_supported_fs_action_type) /
+		sizeof(enum rte_flow_action_type);
 
-		curr = LIST_NEXT(curr, next);
+	for (i = 0; i < action_num; i++) {
+		if (action == dpaa2_supported_fs_action_type[i])
+			return true;
 	}
 
-	return 0;
+	return false;
 }
 
 static inline int
-dpaa2_flow_verify_attr(
-	struct dpaa2_dev_priv *priv,
+dpaa2_flow_verify_attr(struct dpaa2_dev_priv *priv,
 	const struct rte_flow_attr *attr)
 {
-	struct rte_flow *curr = LIST_FIRST(&priv->flows);
+	struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows);
 
 	while (curr) {
 		if (curr->tc_id == attr->group &&
 			curr->tc_index == attr->priority) {
-			DPAA2_PMD_ERR(
-				"Flow with group %d and priority %d already exists.",
+			DPAA2_PMD_ERR("Flow(TC[%d].entry[%d] exists",
 				attr->group, attr->priority);
 
-			return -1;
+			return -EINVAL;
 		}
 		curr = LIST_NEXT(curr, next);
 	}
@@ -3275,18 +2337,16 @@  dpaa2_flow_redirect_dev(struct dpaa2_dev_priv *priv,
 	const struct rte_flow_action *action)
 {
 	const struct rte_flow_action_port_id *port_id;
+	const struct rte_flow_action_ethdev *ethdev;
 	int idx = -1;
 	struct rte_eth_dev *dest_dev;
 
 	if (action->type == RTE_FLOW_ACTION_TYPE_PORT_ID) {
-		port_id = (const struct rte_flow_action_port_id *)
-					action->conf;
+		port_id = action->conf;
 		if (!port_id->original)
 			idx = port_id->id;
 	} else if (action->type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) {
-		const struct rte_flow_action_ethdev *ethdev;
-
-		ethdev = (const struct rte_flow_action_ethdev *)action->conf;
+		ethdev = action->conf;
 		idx = ethdev->port_id;
 	} else {
 		return NULL;
@@ -3306,8 +2366,7 @@  dpaa2_flow_redirect_dev(struct dpaa2_dev_priv *priv,
 }
 
 static inline int
-dpaa2_flow_verify_action(
-	struct dpaa2_dev_priv *priv,
+dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv,
 	const struct rte_flow_attr *attr,
 	const struct rte_flow_action actions[])
 {
@@ -3319,15 +2378,14 @@  dpaa2_flow_verify_action(
 	while (!end_of_list) {
 		switch (actions[j].type) {
 		case RTE_FLOW_ACTION_TYPE_QUEUE:
-			dest_queue = (const struct rte_flow_action_queue *)
-					(actions[j].conf);
+			dest_queue = actions[j].conf;
 			rxq = priv->rx_vq[dest_queue->index];
 			if (attr->group != rxq->tc_index) {
-				DPAA2_PMD_ERR(
-					"RXQ[%d] does not belong to the group %d",
-					dest_queue->index, attr->group);
+				DPAA2_PMD_ERR("FSQ(%d.%d) not in TC[%d]",
+					rxq->tc_index, rxq->flow_id,
+					attr->group);
 
-				return -1;
+				return -ENOTSUP;
 			}
 			break;
 		case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
@@ -3341,20 +2399,17 @@  dpaa2_flow_verify_action(
 			rss_conf = (const struct rte_flow_action_rss *)
 					(actions[j].conf);
 			if (rss_conf->queue_num > priv->dist_queues) {
-				DPAA2_PMD_ERR(
-					"RSS number exceeds the distribution size");
+				DPAA2_PMD_ERR("RSS number too large");
 				return -ENOTSUP;
 			}
 			for (i = 0; i < (int)rss_conf->queue_num; i++) {
 				if (rss_conf->queue[i] >= priv->nb_rx_queues) {
-					DPAA2_PMD_ERR(
-						"RSS queue index exceeds the number of RXQs");
+					DPAA2_PMD_ERR("RSS queue not in range");
 					return -ENOTSUP;
 				}
 				rxq = priv->rx_vq[rss_conf->queue[i]];
 				if (rxq->tc_index != attr->group) {
-					DPAA2_PMD_ERR(
-						"Queue/Group combination are not supported");
+					DPAA2_PMD_ERR("RSS queue not in group");
 					return -ENOTSUP;
 				}
 			}
@@ -3374,28 +2429,248 @@  dpaa2_flow_verify_action(
 }
 
 static int
-dpaa2_generic_flow_set(struct rte_flow *flow,
-		       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)
+dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv,
+	struct dpaa2_dev_flow *flow,
+	const struct rte_flow_action *rte_action)
 {
+	struct rte_eth_dev *dest_dev;
+	struct dpaa2_dev_priv *dest_priv;
 	const struct rte_flow_action_queue *dest_queue;
+	struct dpaa2_queue *dest_q;
+
+	memset(&flow->fs_action_cfg, 0,
+		sizeof(struct dpni_fs_action_cfg));
+	flow->action_type = rte_action->type;
+
+	if (flow->action_type == RTE_FLOW_ACTION_TYPE_QUEUE) {
+		dest_queue = rte_action->conf;
+		dest_q = priv->rx_vq[dest_queue->index];
+		flow->fs_action_cfg.flow_id = dest_q->flow_id;
+	} else if (flow->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID ||
+		   flow->action_type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) {
+		dest_dev = dpaa2_flow_redirect_dev(priv, rte_action);
+		if (!dest_dev) {
+			DPAA2_PMD_ERR("Invalid device to redirect");
+			return -EINVAL;
+		}
+
+		dest_priv = dest_dev->data->dev_private;
+		dest_q = dest_priv->tx_vq[0];
+		flow->fs_action_cfg.options =
+			DPNI_FS_OPT_REDIRECT_TO_DPNI_TX;
+		flow->fs_action_cfg.redirect_obj_token =
+			dest_priv->token;
+		flow->fs_action_cfg.flow_id = dest_q->flow_id;
+	}
+
+	return 0;
+}
+
+static inline uint16_t
+dpaa2_flow_entry_size(uint16_t key_max_size)
+{
+	if (key_max_size > DPAA2_FLOW_ENTRY_MAX_SIZE) {
+		DPAA2_PMD_ERR("Key size(%d) > max(%d)",
+			key_max_size,
+			DPAA2_FLOW_ENTRY_MAX_SIZE);
+
+		return 0;
+	}
+
+	if (key_max_size > DPAA2_FLOW_ENTRY_MIN_SIZE)
+		return DPAA2_FLOW_ENTRY_MAX_SIZE;
+
+	/* Current MC only support fixed entry size(56)*/
+	return DPAA2_FLOW_ENTRY_MAX_SIZE;
+}
+
+static inline int
+dpaa2_flow_clear_fs_table(struct dpaa2_dev_priv *priv,
+	uint8_t tc_id)
+{
+	struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows);
+	int need_clear = 0, ret;
+	struct fsl_mc_io *dpni = priv->hw;
+
+	while (curr) {
+		if (curr->tc_id == tc_id) {
+			need_clear = 1;
+			break;
+		}
+		curr = LIST_NEXT(curr, next);
+	}
+
+	if (need_clear) {
+		ret = dpni_clear_fs_entries(dpni, CMD_PRI_LOW,
+				priv->token, tc_id);
+		if (ret) {
+			DPAA2_PMD_ERR("TC[%d] clear failed", tc_id);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int
+dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv,
+	uint8_t tc_id, uint16_t dist_size, int rss_dist)
+{
+	struct dpaa2_key_extract *tc_extract;
+	uint8_t *key_cfg_buf;
+	uint64_t key_cfg_iova;
+	int ret;
+	struct dpni_rx_dist_cfg tc_cfg;
+	struct fsl_mc_io *dpni = priv->hw;
+	uint16_t entry_size;
+	uint16_t key_max_size;
+
+	ret = dpaa2_flow_clear_fs_table(priv, tc_id);
+	if (ret < 0) {
+		DPAA2_PMD_ERR("TC[%d] clear failed", tc_id);
+		return ret;
+	}
+
+	tc_extract = &priv->extract.tc_key_extract[tc_id];
+	key_cfg_buf = priv->extract.tc_extract_param[tc_id];
+	key_cfg_iova = DPAA2_VADDR_TO_IOVA(key_cfg_buf);
+
+	key_max_size = tc_extract->key_profile.key_max_size;
+	entry_size = dpaa2_flow_entry_size(key_max_size);
+
+	dpaa2_flow_fs_extracts_log(priv, tc_id);
+	ret = dpkg_prepare_key_cfg(&tc_extract->dpkg,
+			key_cfg_buf);
+	if (ret < 0) {
+		DPAA2_PMD_ERR("TC[%d] prepare key failed", tc_id);
+		return ret;
+	}
+
+	memset(&tc_cfg, 0, sizeof(struct dpni_rx_dist_cfg));
+	tc_cfg.dist_size = dist_size;
+	tc_cfg.key_cfg_iova = key_cfg_iova;
+	if (rss_dist)
+		tc_cfg.enable = true;
+	else
+		tc_cfg.enable = false;
+	tc_cfg.tc = tc_id;
+	ret = dpni_set_rx_hash_dist(dpni, CMD_PRI_LOW,
+			priv->token, &tc_cfg);
+	if (ret < 0) {
+		if (rss_dist) {
+			DPAA2_PMD_ERR("RSS TC[%d] set failed",
+				tc_id);
+		} else {
+			DPAA2_PMD_ERR("FS TC[%d] hash disable failed",
+				tc_id);
+		}
+
+		return ret;
+	}
+
+	if (rss_dist)
+		return 0;
+
+	tc_cfg.enable = true;
+	tc_cfg.fs_miss_flow_id = dpaa2_flow_miss_flow_id;
+	ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW,
+			priv->token, &tc_cfg);
+	if (ret < 0) {
+		DPAA2_PMD_ERR("TC[%d] FS configured failed", tc_id);
+		return ret;
+	}
+
+	ret = dpaa2_flow_rule_add_all(priv, DPAA2_FLOW_FS_TYPE,
+			entry_size, tc_id);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int
+dpaa2_configure_qos_table(struct dpaa2_dev_priv *priv,
+	int rss_dist)
+{
+	struct dpaa2_key_extract *qos_extract;
+	uint8_t *key_cfg_buf;
+	uint64_t key_cfg_iova;
+	int ret;
+	struct dpni_qos_tbl_cfg qos_cfg;
+	struct fsl_mc_io *dpni = priv->hw;
+	uint16_t entry_size;
+	uint16_t key_max_size;
+
+	if (!rss_dist && priv->num_rx_tc <= 1) {
+		/* QoS table is effecitive for FS multiple TCs or RSS.*/
+		return 0;
+	}
+
+	if (LIST_FIRST(&priv->flows)) {
+		ret = dpni_clear_qos_table(dpni, CMD_PRI_LOW,
+				priv->token);
+		if (ret < 0) {
+			DPAA2_PMD_ERR("QoS table clear failed");
+			return ret;
+		}
+	}
+
+	qos_extract = &priv->extract.qos_key_extract;
+	key_cfg_buf = priv->extract.qos_extract_param;
+	key_cfg_iova = DPAA2_VADDR_TO_IOVA(key_cfg_buf);
+
+	key_max_size = qos_extract->key_profile.key_max_size;
+	entry_size = dpaa2_flow_entry_size(key_max_size);
+
+	dpaa2_flow_qos_extracts_log(priv);
+
+	ret = dpkg_prepare_key_cfg(&qos_extract->dpkg,
+			key_cfg_buf);
+	if (ret < 0) {
+		DPAA2_PMD_ERR("QoS prepare extract failed");
+		return ret;
+	}
+	memset(&qos_cfg, 0, sizeof(struct dpni_qos_tbl_cfg));
+	qos_cfg.keep_entries = true;
+	qos_cfg.key_cfg_iova = key_cfg_iova;
+	if (rss_dist) {
+		qos_cfg.discard_on_miss = true;
+	} else {
+		qos_cfg.discard_on_miss = false;
+		qos_cfg.default_tc = 0;
+	}
+
+	ret = dpni_set_qos_table(dpni, CMD_PRI_LOW,
+			priv->token, &qos_cfg);
+	if (ret < 0) {
+		DPAA2_PMD_ERR("QoS table set failed");
+		return ret;
+	}
+
+	ret = dpaa2_flow_rule_add_all(priv, DPAA2_FLOW_QOS_TYPE,
+			entry_size, 0);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int
+dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow,
+	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)
+{
 	const struct rte_flow_action_rss *rss_conf;
 	int is_keycfg_configured = 0, end_of_list = 0;
 	int ret = 0, i = 0, j = 0;
-	struct dpni_rx_dist_cfg tc_cfg;
-	struct dpni_qos_tbl_cfg qos_cfg;
-	struct dpni_fs_action_cfg action;
 	struct dpaa2_dev_priv *priv = dev->data->dev_private;
-	struct dpaa2_queue *dest_q;
-	struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
-	size_t param;
-	struct rte_flow *curr = LIST_FIRST(&priv->flows);
-	uint16_t qos_index;
-	struct rte_eth_dev *dest_dev;
-	struct dpaa2_dev_priv *dest_priv;
+	struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows);
+	uint16_t dist_size, key_size;
+	struct dpaa2_key_extract *qos_key_extract;
+	struct dpaa2_key_extract *tc_key_extract;
 
 	ret = dpaa2_flow_verify_attr(priv, attr);
 	if (ret)
@@ -3413,7 +2688,7 @@  dpaa2_generic_flow_set(struct rte_flow *flow,
 					dev, attr, &pattern[i], actions, error,
 					&is_keycfg_configured);
 			if (ret) {
-				DPAA2_PMD_ERR("ETH flow configuration failed!");
+				DPAA2_PMD_ERR("ETH flow config failed!");
 				return ret;
 			}
 			break;
@@ -3422,17 +2697,25 @@  dpaa2_generic_flow_set(struct rte_flow *flow,
 					dev, attr, &pattern[i], actions, error,
 					&is_keycfg_configured);
 			if (ret) {
-				DPAA2_PMD_ERR("vLan flow configuration failed!");
+				DPAA2_PMD_ERR("vLan flow config failed!");
 				return ret;
 			}
 			break;
 		case RTE_FLOW_ITEM_TYPE_IPV4:
+			ret = dpaa2_configure_flow_ipv4(flow,
+					dev, attr, &pattern[i], actions, error,
+					&is_keycfg_configured);
+			if (ret) {
+				DPAA2_PMD_ERR("IPV4 flow config failed!");
+				return ret;
+			}
+			break;
 		case RTE_FLOW_ITEM_TYPE_IPV6:
-			ret = dpaa2_configure_flow_generic_ip(flow,
+			ret = dpaa2_configure_flow_ipv6(flow,
 					dev, attr, &pattern[i], actions, error,
 					&is_keycfg_configured);
 			if (ret) {
-				DPAA2_PMD_ERR("IP flow configuration failed!");
+				DPAA2_PMD_ERR("IPV6 flow config failed!");
 				return ret;
 			}
 			break;
@@ -3441,7 +2724,7 @@  dpaa2_generic_flow_set(struct rte_flow *flow,
 					dev, attr, &pattern[i], actions, error,
 					&is_keycfg_configured);
 			if (ret) {
-				DPAA2_PMD_ERR("ICMP flow configuration failed!");
+				DPAA2_PMD_ERR("ICMP flow config failed!");
 				return ret;
 			}
 			break;
@@ -3450,7 +2733,7 @@  dpaa2_generic_flow_set(struct rte_flow *flow,
 					dev, attr, &pattern[i], actions, error,
 					&is_keycfg_configured);
 			if (ret) {
-				DPAA2_PMD_ERR("UDP flow configuration failed!");
+				DPAA2_PMD_ERR("UDP flow config failed!");
 				return ret;
 			}
 			break;
@@ -3459,7 +2742,7 @@  dpaa2_generic_flow_set(struct rte_flow *flow,
 					dev, attr, &pattern[i], actions, error,
 					&is_keycfg_configured);
 			if (ret) {
-				DPAA2_PMD_ERR("TCP flow configuration failed!");
+				DPAA2_PMD_ERR("TCP flow config failed!");
 				return ret;
 			}
 			break;
@@ -3468,7 +2751,7 @@  dpaa2_generic_flow_set(struct rte_flow *flow,
 					dev, attr, &pattern[i], actions, error,
 					&is_keycfg_configured);
 			if (ret) {
-				DPAA2_PMD_ERR("SCTP flow configuration failed!");
+				DPAA2_PMD_ERR("SCTP flow config failed!");
 				return ret;
 			}
 			break;
@@ -3477,17 +2760,17 @@  dpaa2_generic_flow_set(struct rte_flow *flow,
 					dev, attr, &pattern[i], actions, error,
 					&is_keycfg_configured);
 			if (ret) {
-				DPAA2_PMD_ERR("GRE flow configuration failed!");
+				DPAA2_PMD_ERR("GRE flow config failed!");
 				return ret;
 			}
 			break;
 		case RTE_FLOW_ITEM_TYPE_RAW:
 			ret = dpaa2_configure_flow_raw(flow,
-						       dev, attr, &pattern[i],
-						       actions, error,
-						       &is_keycfg_configured);
+					dev, attr, &pattern[i],
+					actions, error,
+					&is_keycfg_configured);
 			if (ret) {
-				DPAA2_PMD_ERR("RAW flow configuration failed!");
+				DPAA2_PMD_ERR("RAW flow config failed!");
 				return ret;
 			}
 			break;
@@ -3502,6 +2785,14 @@  dpaa2_generic_flow_set(struct rte_flow *flow,
 		i++;
 	}
 
+	qos_key_extract = &priv->extract.qos_key_extract;
+	key_size = qos_key_extract->key_profile.key_max_size;
+	flow->qos_rule.key_size = dpaa2_flow_entry_size(key_size);
+
+	tc_key_extract = &priv->extract.tc_key_extract[flow->tc_id];
+	key_size = tc_key_extract->key_profile.key_max_size;
+	flow->fs_rule.key_size = dpaa2_flow_entry_size(key_size);
+
 	/* Let's parse action on matching traffic */
 	end_of_list = 0;
 	while (!end_of_list) {
@@ -3509,150 +2800,33 @@  dpaa2_generic_flow_set(struct rte_flow *flow,
 		case RTE_FLOW_ACTION_TYPE_QUEUE:
 		case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
 		case RTE_FLOW_ACTION_TYPE_PORT_ID:
-			memset(&action, 0, sizeof(struct dpni_fs_action_cfg));
-			flow->action = actions[j].type;
-
-			if (actions[j].type == RTE_FLOW_ACTION_TYPE_QUEUE) {
-				dest_queue = (const struct rte_flow_action_queue *)
-								(actions[j].conf);
-				dest_q = priv->rx_vq[dest_queue->index];
-				action.flow_id = dest_q->flow_id;
-			} else {
-				dest_dev = dpaa2_flow_redirect_dev(priv,
-								   &actions[j]);
-				if (!dest_dev) {
-					DPAA2_PMD_ERR("Invalid destination device to redirect!");
-					return -1;
-				}
-
-				dest_priv = dest_dev->data->dev_private;
-				dest_q = dest_priv->tx_vq[0];
-				action.options =
-						DPNI_FS_OPT_REDIRECT_TO_DPNI_TX;
-				action.redirect_obj_token = dest_priv->token;
-				action.flow_id = dest_q->flow_id;
-			}
+			ret = dpaa2_configure_flow_fs_action(priv, flow,
+							     &actions[j]);
+			if (ret)
+				return ret;
 
 			/* Configure FS table first*/
-			if (is_keycfg_configured & DPAA2_FS_TABLE_RECONFIGURE) {
-				dpaa2_flow_fs_table_extracts_log(priv,
-							flow->tc_id, stdout);
-				if (dpkg_prepare_key_cfg(
-				&priv->extract.tc_key_extract[flow->tc_id].dpkg,
-				(uint8_t *)(size_t)priv->extract
-				.tc_extract_param[flow->tc_id]) < 0) {
-					DPAA2_PMD_ERR(
-					"Unable to prepare extract parameters");
-					return -1;
-				}
-
-				memset(&tc_cfg, 0,
-					sizeof(struct dpni_rx_dist_cfg));
-				tc_cfg.dist_size = priv->nb_rx_queues / priv->num_rx_tc;
-				tc_cfg.key_cfg_iova =
-					(uint64_t)priv->extract.tc_extract_param[flow->tc_id];
-				tc_cfg.tc = flow->tc_id;
-				tc_cfg.enable = false;
-				ret = dpni_set_rx_hash_dist(dpni, CMD_PRI_LOW,
-						priv->token, &tc_cfg);
-				if (ret < 0) {
-					DPAA2_PMD_ERR(
-						"TC hash cannot be disabled.(%d)",
-						ret);
-					return -1;
-				}
-				tc_cfg.enable = true;
-				tc_cfg.fs_miss_flow_id = dpaa2_flow_miss_flow_id;
-				ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW,
-							 priv->token, &tc_cfg);
-				if (ret < 0) {
-					DPAA2_PMD_ERR(
-						"TC distribution cannot be configured.(%d)",
-						ret);
-					return -1;
-				}
+			dist_size = priv->nb_rx_queues / priv->num_rx_tc;
+			if (is_keycfg_configured & DPAA2_FLOW_FS_TYPE) {
+				ret = dpaa2_configure_fs_rss_table(priv,
+								   flow->tc_id,
+								   dist_size,
+								   false);
+				if (ret)
+					return ret;
 			}
 
 			/* Configure QoS table then.*/
-			if (is_keycfg_configured & DPAA2_QOS_TABLE_RECONFIGURE) {
-				dpaa2_flow_qos_table_extracts_log(priv, stdout);
-				if (dpkg_prepare_key_cfg(
-					&priv->extract.qos_key_extract.dpkg,
-					(uint8_t *)(size_t)priv->extract.qos_extract_param) < 0) {
-					DPAA2_PMD_ERR(
-						"Unable to prepare extract parameters");
-					return -1;
-				}
-
-				memset(&qos_cfg, 0, sizeof(struct dpni_qos_tbl_cfg));
-				qos_cfg.discard_on_miss = false;
-				qos_cfg.default_tc = 0;
-				qos_cfg.keep_entries = true;
-				qos_cfg.key_cfg_iova =
-					(size_t)priv->extract.qos_extract_param;
-				/* QoS table is effective for multiple TCs. */
-				if (priv->num_rx_tc > 1) {
-					ret = dpni_set_qos_table(dpni, CMD_PRI_LOW,
-						priv->token, &qos_cfg);
-					if (ret < 0) {
-						DPAA2_PMD_ERR(
-						"RSS QoS table can not be configured(%d)",
-							ret);
-						return -1;
-					}
-				}
-			}
-
-			flow->qos_real_key_size = priv->extract
-				.qos_key_extract.key_info.key_total_size;
-			if (flow->ipaddr_rule.ipaddr_type == FLOW_IPV4_ADDR) {
-				if (flow->ipaddr_rule.qos_ipdst_offset >=
-					flow->ipaddr_rule.qos_ipsrc_offset) {
-					flow->qos_real_key_size =
-						flow->ipaddr_rule.qos_ipdst_offset +
-						NH_FLD_IPV4_ADDR_SIZE;
-				} else {
-					flow->qos_real_key_size =
-						flow->ipaddr_rule.qos_ipsrc_offset +
-						NH_FLD_IPV4_ADDR_SIZE;
-				}
-			} else if (flow->ipaddr_rule.ipaddr_type ==
-				FLOW_IPV6_ADDR) {
-				if (flow->ipaddr_rule.qos_ipdst_offset >=
-					flow->ipaddr_rule.qos_ipsrc_offset) {
-					flow->qos_real_key_size =
-						flow->ipaddr_rule.qos_ipdst_offset +
-						NH_FLD_IPV6_ADDR_SIZE;
-				} else {
-					flow->qos_real_key_size =
-						flow->ipaddr_rule.qos_ipsrc_offset +
-						NH_FLD_IPV6_ADDR_SIZE;
-				}
+			if (is_keycfg_configured & DPAA2_FLOW_QOS_TYPE) {
+				ret = dpaa2_configure_qos_table(priv, false);
+				if (ret)
+					return ret;
 			}
 
-			/* QoS entry added is only effective for multiple TCs.*/
 			if (priv->num_rx_tc > 1) {
-				qos_index = flow->tc_id * priv->fs_entries +
-					flow->tc_index;
-				if (qos_index >= priv->qos_entries) {
-					DPAA2_PMD_ERR("QoS table with %d entries full",
-						priv->qos_entries);
-					return -1;
-				}
-				flow->qos_rule.key_size = FIXED_ENTRY_SIZE;
-
-				dpaa2_flow_qos_entry_log("Start add", flow,
-							qos_index, stdout);
-
-				ret = dpni_add_qos_entry(dpni, CMD_PRI_LOW,
-						priv->token, &flow->qos_rule,
-						flow->tc_id, qos_index,
-						0, 0);
-				if (ret < 0) {
-					DPAA2_PMD_ERR(
-						"Error in adding entry to QoS table(%d)", ret);
+				ret = dpaa2_flow_add_qos_rule(priv, flow);
+				if (ret)
 					return ret;
-				}
 			}
 
 			if (flow->tc_index >= priv->fs_entries) {
@@ -3661,140 +2835,47 @@  dpaa2_generic_flow_set(struct rte_flow *flow,
 				return -1;
 			}
 
-			flow->fs_real_key_size =
-				priv->extract.tc_key_extract[flow->tc_id]
-				.key_info.key_total_size;
-
-			if (flow->ipaddr_rule.ipaddr_type ==
-				FLOW_IPV4_ADDR) {
-				if (flow->ipaddr_rule.fs_ipdst_offset >=
-					flow->ipaddr_rule.fs_ipsrc_offset) {
-					flow->fs_real_key_size =
-						flow->ipaddr_rule.fs_ipdst_offset +
-						NH_FLD_IPV4_ADDR_SIZE;
-				} else {
-					flow->fs_real_key_size =
-						flow->ipaddr_rule.fs_ipsrc_offset +
-						NH_FLD_IPV4_ADDR_SIZE;
-				}
-			} else if (flow->ipaddr_rule.ipaddr_type ==
-				FLOW_IPV6_ADDR) {
-				if (flow->ipaddr_rule.fs_ipdst_offset >=
-					flow->ipaddr_rule.fs_ipsrc_offset) {
-					flow->fs_real_key_size =
-						flow->ipaddr_rule.fs_ipdst_offset +
-						NH_FLD_IPV6_ADDR_SIZE;
-				} else {
-					flow->fs_real_key_size =
-						flow->ipaddr_rule.fs_ipsrc_offset +
-						NH_FLD_IPV6_ADDR_SIZE;
-				}
-			}
-
-			flow->fs_rule.key_size = FIXED_ENTRY_SIZE;
-
-			dpaa2_flow_fs_entry_log("Start add", flow, stdout);
-
-			ret = dpni_add_fs_entry(dpni, CMD_PRI_LOW, priv->token,
-						flow->tc_id, flow->tc_index,
-						&flow->fs_rule, &action);
-			if (ret < 0) {
-				DPAA2_PMD_ERR(
-				"Error in adding entry to FS table(%d)", ret);
+			ret = dpaa2_flow_add_fs_rule(priv, flow);
+			if (ret)
 				return ret;
-			}
-			memcpy(&flow->action_cfg, &action,
-				sizeof(struct dpni_fs_action_cfg));
+
 			break;
 		case RTE_FLOW_ACTION_TYPE_RSS:
-			rss_conf = (const struct rte_flow_action_rss *)(actions[j].conf);
+			rss_conf = actions[j].conf;
+			flow->action_type = RTE_FLOW_ACTION_TYPE_RSS;
 
-			flow->action = RTE_FLOW_ACTION_TYPE_RSS;
 			ret = dpaa2_distset_to_dpkg_profile_cfg(rss_conf->types,
-					&priv->extract.tc_key_extract[flow->tc_id].dpkg);
+					&tc_key_extract->dpkg);
 			if (ret < 0) {
-				DPAA2_PMD_ERR(
-				"unable to set flow distribution.please check queue config");
+				DPAA2_PMD_ERR("TC[%d] distset RSS failed",
+					      flow->tc_id);
 				return ret;
 			}
 
-			/* Allocate DMA'ble memory to write the rules */
-			param = (size_t)rte_malloc(NULL, 256, 64);
-			if (!param) {
-				DPAA2_PMD_ERR("Memory allocation failure");
-				return -1;
-			}
-
-			if (dpkg_prepare_key_cfg(
-				&priv->extract.tc_key_extract[flow->tc_id].dpkg,
-				(uint8_t *)param) < 0) {
-				DPAA2_PMD_ERR(
-				"Unable to prepare extract parameters");
-				rte_free((void *)param);
-				return -1;
-			}
-
-			memset(&tc_cfg, 0, sizeof(struct dpni_rx_dist_cfg));
-			tc_cfg.dist_size = rss_conf->queue_num;
-			tc_cfg.key_cfg_iova = (size_t)param;
-			tc_cfg.enable = true;
-			tc_cfg.tc = flow->tc_id;
-			ret = dpni_set_rx_hash_dist(dpni, CMD_PRI_LOW,
-						 priv->token, &tc_cfg);
-			if (ret < 0) {
-				DPAA2_PMD_ERR(
-					"RSS TC table cannot be configured: %d",
-					ret);
-				rte_free((void *)param);
-				return -1;
+			dist_size = rss_conf->queue_num;
+			if (is_keycfg_configured & DPAA2_FLOW_FS_TYPE) {
+				ret = dpaa2_configure_fs_rss_table(priv,
+								   flow->tc_id,
+								   dist_size,
+								   true);
+				if (ret)
+					return ret;
 			}
 
-			rte_free((void *)param);
-			if (is_keycfg_configured & DPAA2_QOS_TABLE_RECONFIGURE) {
-				if (dpkg_prepare_key_cfg(
-					&priv->extract.qos_key_extract.dpkg,
-					(uint8_t *)(size_t)priv->extract.qos_extract_param) < 0) {
-					DPAA2_PMD_ERR(
-					"Unable to prepare extract parameters");
-					return -1;
-				}
-				memset(&qos_cfg, 0,
-					sizeof(struct dpni_qos_tbl_cfg));
-				qos_cfg.discard_on_miss = true;
-				qos_cfg.keep_entries = true;
-				qos_cfg.key_cfg_iova =
-					(size_t)priv->extract.qos_extract_param;
-				ret = dpni_set_qos_table(dpni, CMD_PRI_LOW,
-							 priv->token, &qos_cfg);
-				if (ret < 0) {
-					DPAA2_PMD_ERR(
-					"RSS QoS dist can't be configured-%d",
-					ret);
-					return -1;
-				}
+			if (is_keycfg_configured & DPAA2_FLOW_QOS_TYPE) {
+				ret = dpaa2_configure_qos_table(priv, true);
+				if (ret)
+					return ret;
 			}
 
-			/* Add Rule into QoS table */
-			qos_index = flow->tc_id * priv->fs_entries +
-				flow->tc_index;
-			if (qos_index >= priv->qos_entries) {
-				DPAA2_PMD_ERR("QoS table with %d entries full",
-					priv->qos_entries);
-				return -1;
-			}
+			ret = dpaa2_flow_add_qos_rule(priv, flow);
+			if (ret)
+				return ret;
 
-			flow->qos_real_key_size =
-			  priv->extract.qos_key_extract.key_info.key_total_size;
-			flow->qos_rule.key_size = FIXED_ENTRY_SIZE;
-			ret = dpni_add_qos_entry(dpni, CMD_PRI_LOW, priv->token,
-						&flow->qos_rule, flow->tc_id,
-						qos_index, 0, 0);
-			if (ret < 0) {
-				DPAA2_PMD_ERR(
-				"Error in entry addition in QoS table(%d)",
-				ret);
+			ret = dpaa2_flow_add_fs_rule(priv, flow);
+			if (ret)
 				return ret;
-			}
+
 			break;
 		case RTE_FLOW_ACTION_TYPE_END:
 			end_of_list = 1;
@@ -3808,16 +2889,6 @@  dpaa2_generic_flow_set(struct rte_flow *flow,
 	}
 
 	if (!ret) {
-		if (is_keycfg_configured &
-			(DPAA2_QOS_TABLE_RECONFIGURE |
-			DPAA2_FS_TABLE_RECONFIGURE)) {
-			ret = dpaa2_flow_entry_update(priv, flow->tc_id);
-			if (ret) {
-				DPAA2_PMD_ERR("Flow entry update failed.");
-
-				return -1;
-			}
-		}
 		/* New rules are inserted. */
 		if (!curr) {
 			LIST_INSERT_HEAD(&priv->flows, flow, next);
@@ -3832,7 +2903,7 @@  dpaa2_generic_flow_set(struct rte_flow *flow,
 
 static inline int
 dpaa2_dev_verify_attr(struct dpni_attr *dpni_attr,
-		      const struct rte_flow_attr *attr)
+	const struct rte_flow_attr *attr)
 {
 	int ret = 0;
 
@@ -3906,18 +2977,18 @@  dpaa2_dev_verify_actions(const struct rte_flow_action actions[])
 	}
 	for (j = 0; actions[j].type != RTE_FLOW_ACTION_TYPE_END; j++) {
 		if (actions[j].type != RTE_FLOW_ACTION_TYPE_DROP &&
-				!actions[j].conf)
+		    !actions[j].conf)
 			ret = -EINVAL;
 	}
 	return ret;
 }
 
-static
-int dpaa2_flow_validate(struct rte_eth_dev *dev,
-			const struct rte_flow_attr *flow_attr,
-			const struct rte_flow_item pattern[],
-			const struct rte_flow_action actions[],
-			struct rte_flow_error *error)
+static int
+dpaa2_flow_validate(struct rte_eth_dev *dev,
+	const struct rte_flow_attr *flow_attr,
+	const struct rte_flow_item pattern[],
+	const struct rte_flow_action actions[],
+	struct rte_flow_error *error)
 {
 	struct dpaa2_dev_priv *priv = dev->data->dev_private;
 	struct dpni_attr dpni_attr;
@@ -3971,127 +3042,128 @@  int dpaa2_flow_validate(struct rte_eth_dev *dev,
 	return ret;
 }
 
-static
-struct rte_flow *dpaa2_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 struct rte_flow *
+dpaa2_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 rte_flow *flow = NULL;
-	size_t key_iova = 0, mask_iova = 0;
+	struct dpaa2_dev_flow *flow = NULL;
+	struct dpaa2_dev_priv *priv = dev->data->dev_private;
 	int ret;
 
 	dpaa2_flow_control_log =
 		getenv("DPAA2_FLOW_CONTROL_LOG");
 
 	if (getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")) {
-		struct dpaa2_dev_priv *priv = dev->data->dev_private;
-
 		dpaa2_flow_miss_flow_id =
 			(uint16_t)atoi(getenv("DPAA2_FLOW_CONTROL_MISS_FLOW"));
 		if (dpaa2_flow_miss_flow_id >= priv->dist_queues) {
-			DPAA2_PMD_ERR(
-				"The missed flow ID %d exceeds the max flow ID %d",
-				dpaa2_flow_miss_flow_id,
-				priv->dist_queues - 1);
+			DPAA2_PMD_ERR("Missed flow ID %d >= dist size(%d)",
+				      dpaa2_flow_miss_flow_id,
+				      priv->dist_queues);
 			return NULL;
 		}
 	}
 
-	flow = rte_zmalloc(NULL, sizeof(struct rte_flow), RTE_CACHE_LINE_SIZE);
+	flow = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_flow),
+			   RTE_CACHE_LINE_SIZE);
 	if (!flow) {
 		DPAA2_PMD_ERR("Failure to allocate memory for flow");
 		goto mem_failure;
 	}
-	/* Allocate DMA'ble memory to write the rules */
-	key_iova = (size_t)rte_zmalloc(NULL, 256, 64);
-	if (!key_iova) {
-		DPAA2_PMD_ERR(
-			"Memory allocation failure for rule configuration");
+
+	/* Allocate DMA'ble memory to write the qos rules */
+	flow->qos_key_addr = rte_zmalloc(NULL, 256, 64);
+	if (!flow->qos_key_addr) {
+		DPAA2_PMD_ERR("Memory allocation failed");
 		goto mem_failure;
 	}
-	mask_iova = (size_t)rte_zmalloc(NULL, 256, 64);
-	if (!mask_iova) {
-		DPAA2_PMD_ERR(
-			"Memory allocation failure for rule configuration");
+	flow->qos_rule.key_iova = DPAA2_VADDR_TO_IOVA(flow->qos_key_addr);
+
+	flow->qos_mask_addr = rte_zmalloc(NULL, 256, 64);
+	if (!flow->qos_mask_addr) {
+		DPAA2_PMD_ERR("Memory allocation failed");
 		goto mem_failure;
 	}
+	flow->qos_rule.mask_iova = DPAA2_VADDR_TO_IOVA(flow->qos_mask_addr);
 
-	flow->qos_rule.key_iova = key_iova;
-	flow->qos_rule.mask_iova = mask_iova;
-
-	/* Allocate DMA'ble memory to write the rules */
-	key_iova = (size_t)rte_zmalloc(NULL, 256, 64);
-	if (!key_iova) {
-		DPAA2_PMD_ERR(
-			"Memory allocation failure for rule configuration");
+	/* Allocate DMA'ble memory to write the FS rules */
+	flow->fs_key_addr = rte_zmalloc(NULL, 256, 64);
+	if (!flow->fs_key_addr) {
+		DPAA2_PMD_ERR("Memory allocation failed");
 		goto mem_failure;
 	}
-	mask_iova = (size_t)rte_zmalloc(NULL, 256, 64);
-	if (!mask_iova) {
-		DPAA2_PMD_ERR(
-			"Memory allocation failure for rule configuration");
+	flow->fs_rule.key_iova = DPAA2_VADDR_TO_IOVA(flow->fs_key_addr);
+
+	flow->fs_mask_addr = rte_zmalloc(NULL, 256, 64);
+	if (!flow->fs_mask_addr) {
+		DPAA2_PMD_ERR("Memory allocation failed");
 		goto mem_failure;
 	}
+	flow->fs_rule.mask_iova = DPAA2_VADDR_TO_IOVA(flow->fs_mask_addr);
 
-	flow->fs_rule.key_iova = key_iova;
-	flow->fs_rule.mask_iova = mask_iova;
-
-	flow->ipaddr_rule.ipaddr_type = FLOW_NONE_IPADDR;
-	flow->ipaddr_rule.qos_ipsrc_offset =
-		IP_ADDRESS_OFFSET_INVALID;
-	flow->ipaddr_rule.qos_ipdst_offset =
-		IP_ADDRESS_OFFSET_INVALID;
-	flow->ipaddr_rule.fs_ipsrc_offset =
-		IP_ADDRESS_OFFSET_INVALID;
-	flow->ipaddr_rule.fs_ipdst_offset =
-		IP_ADDRESS_OFFSET_INVALID;
+	priv->curr = flow;
 
-	ret = dpaa2_generic_flow_set(flow, dev, attr, pattern,
-			actions, error);
+	ret = dpaa2_generic_flow_set(flow, dev, attr, pattern, actions, error);
 	if (ret < 0) {
 		if (error && error->type > RTE_FLOW_ERROR_TYPE_ACTION)
 			rte_flow_error_set(error, EPERM,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					attr, "unknown");
-		DPAA2_PMD_ERR("Failure to create flow, return code (%d)", ret);
+					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					   attr, "unknown");
+		DPAA2_PMD_ERR("Create flow failed (%d)", ret);
 		goto creation_error;
 	}
 
-	return flow;
+	priv->curr = NULL;
+	return (struct rte_flow *)flow;
+
 mem_failure:
-	rte_flow_error_set(error, EPERM,
-			   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			   NULL, "memory alloc");
+	rte_flow_error_set(error, EPERM, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+			   "memory alloc");
+
 creation_error:
-	rte_free((void *)flow);
-	rte_free((void *)key_iova);
-	rte_free((void *)mask_iova);
+	if (flow) {
+		if (flow->qos_key_addr)
+			rte_free(flow->qos_key_addr);
+		if (flow->qos_mask_addr)
+			rte_free(flow->qos_mask_addr);
+		if (flow->fs_key_addr)
+			rte_free(flow->fs_key_addr);
+		if (flow->fs_mask_addr)
+			rte_free(flow->fs_mask_addr);
+		rte_free(flow);
+	}
+	priv->curr = NULL;
 
 	return NULL;
 }
 
-static
-int dpaa2_flow_destroy(struct rte_eth_dev *dev,
-		       struct rte_flow *flow,
-		       struct rte_flow_error *error)
+static int
+dpaa2_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *_flow,
+		   struct rte_flow_error *error)
 {
 	int ret = 0;
+	struct dpaa2_dev_flow *flow;
 	struct dpaa2_dev_priv *priv = dev->data->dev_private;
-	struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
+	struct fsl_mc_io *dpni = priv->hw;
 
-	switch (flow->action) {
+	flow = (struct dpaa2_dev_flow *)_flow;
+
+	switch (flow->action_type) {
 	case RTE_FLOW_ACTION_TYPE_QUEUE:
 	case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
 	case RTE_FLOW_ACTION_TYPE_PORT_ID:
 		if (priv->num_rx_tc > 1) {
 			/* Remove entry from QoS table first */
-			ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, priv->token,
-					&flow->qos_rule);
+			ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW,
+						    priv->token,
+						    &flow->qos_rule);
 			if (ret < 0) {
-				DPAA2_PMD_ERR(
-					"Error in removing entry from QoS table(%d)", ret);
+				DPAA2_PMD_ERR("Remove FS QoS entry failed");
+				dpaa2_flow_qos_entry_log("Delete failed", flow,
+							 -1);
+				abort();
 				goto error;
 			}
 		}
@@ -4100,34 +3172,37 @@  int dpaa2_flow_destroy(struct rte_eth_dev *dev,
 		ret = dpni_remove_fs_entry(dpni, CMD_PRI_LOW, priv->token,
 					   flow->tc_id, &flow->fs_rule);
 		if (ret < 0) {
-			DPAA2_PMD_ERR(
-				"Error in removing entry from FS table(%d)", ret);
+			DPAA2_PMD_ERR("Remove entry from FS[%d] failed",
+				      flow->tc_id);
 			goto error;
 		}
 		break;
 	case RTE_FLOW_ACTION_TYPE_RSS:
 		if (priv->num_rx_tc > 1) {
-			ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, priv->token,
-					&flow->qos_rule);
+			ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW,
+						    priv->token,
+						    &flow->qos_rule);
 			if (ret < 0) {
-				DPAA2_PMD_ERR(
-					"Error in entry addition in QoS table(%d)", ret);
+				DPAA2_PMD_ERR("Remove RSS QoS entry failed");
 				goto error;
 			}
 		}
 		break;
 	default:
-		DPAA2_PMD_ERR(
-		"Action type (%d) is not supported", flow->action);
+		DPAA2_PMD_ERR("Action(%d) not supported", flow->action_type);
 		ret = -ENOTSUP;
 		break;
 	}
 
 	LIST_REMOVE(flow, next);
-	rte_free((void *)(size_t)flow->qos_rule.key_iova);
-	rte_free((void *)(size_t)flow->qos_rule.mask_iova);
-	rte_free((void *)(size_t)flow->fs_rule.key_iova);
-	rte_free((void *)(size_t)flow->fs_rule.mask_iova);
+	if (flow->qos_key_addr)
+		rte_free(flow->qos_key_addr);
+	if (flow->qos_mask_addr)
+		rte_free(flow->qos_mask_addr);
+	if (flow->fs_key_addr)
+		rte_free(flow->fs_key_addr);
+	if (flow->fs_mask_addr)
+		rte_free(flow->fs_mask_addr);
 	/* Now free the flow */
 	rte_free(flow);
 
@@ -4152,12 +3227,12 @@  dpaa2_flow_flush(struct rte_eth_dev *dev,
 		struct rte_flow_error *error)
 {
 	struct dpaa2_dev_priv *priv = dev->data->dev_private;
-	struct rte_flow *flow = LIST_FIRST(&priv->flows);
+	struct dpaa2_dev_flow *flow = LIST_FIRST(&priv->flows);
 
 	while (flow) {
-		struct rte_flow *next = LIST_NEXT(flow, next);
+		struct dpaa2_dev_flow *next = LIST_NEXT(flow, next);
 
-		dpaa2_flow_destroy(dev, flow, error);
+		dpaa2_flow_destroy(dev, (struct rte_flow *)flow, error);
 		flow = next;
 	}
 	return 0;
@@ -4165,10 +3240,10 @@  dpaa2_flow_flush(struct rte_eth_dev *dev,
 
 static int
 dpaa2_flow_query(struct rte_eth_dev *dev __rte_unused,
-		struct rte_flow *flow __rte_unused,
-		const struct rte_flow_action *actions __rte_unused,
-		void *data __rte_unused,
-		struct rte_flow_error *error __rte_unused)
+	struct rte_flow *_flow __rte_unused,
+	const struct rte_flow_action *actions __rte_unused,
+	void *data __rte_unused,
+	struct rte_flow_error *error __rte_unused)
 {
 	return 0;
 }
@@ -4185,11 +3260,11 @@  dpaa2_flow_query(struct rte_eth_dev *dev __rte_unused,
 void
 dpaa2_flow_clean(struct rte_eth_dev *dev)
 {
-	struct rte_flow *flow;
+	struct dpaa2_dev_flow *flow;
 	struct dpaa2_dev_priv *priv = dev->data->dev_private;
 
 	while ((flow = LIST_FIRST(&priv->flows)))
-		dpaa2_flow_destroy(dev, flow, NULL);
+		dpaa2_flow_destroy(dev, (struct rte_flow *)flow, NULL);
 }
 
 const struct rte_flow_ops dpaa2_flow_ops = {