diff --git a/app/test-flow-perf/actions_gen.c b/app/test-flow-perf/actions_gen.c
index cb9316f1df..d115cdd723 100644
--- a/app/test-flow-perf/actions_gen.c
+++ b/app/test-flow-perf/actions_gen.c
@@ -182,14 +182,14 @@ add_count(struct rte_flow_action *actions,
 }
 
 void
-fill_actions(struct rte_flow_action *actions, uint64_t flow_actions,
+fill_actions(struct rte_flow_action *actions, uint64_t *flow_actions,
 	uint32_t counter, uint16_t next_table, uint16_t hairpinq)
 {
 	struct additional_para additional_para_data;
 	uint8_t actions_counter = 0;
 	uint16_t hairpin_queues[hairpinq];
 	uint16_t queues[RXQ_NUM];
-	uint16_t i;
+	uint16_t i, j;
 
 	for (i = 0; i < RXQ_NUM; i++)
 		queues[i] = i;
@@ -217,7 +217,7 @@ fill_actions(struct rte_flow_action *actions, uint64_t flow_actions,
 			uint8_t actions_counter,
 			struct additional_para para
 			);
-	} flows_actions[] = {
+	} actions_list[] = {
 		{
 			.mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_MARK),
 			.funct = add_mark,
@@ -264,13 +264,19 @@ fill_actions(struct rte_flow_action *actions, uint64_t flow_actions,
 		},
 	};
 
-	for (i = 0; i < RTE_DIM(flows_actions); i++) {
-		if ((flow_actions & flows_actions[i].mask) == 0)
-			continue;
-		flows_actions[i].funct(
-			actions, actions_counter++,
-			additional_para_data
-		);
+	for (j = 0; j < MAX_ACTIONS_NUM; j++) {
+		if (flow_actions[j] == 0)
+			break;
+		for (i = 0; i < RTE_DIM(actions_list); i++) {
+			if ((flow_actions[j] &
+				actions_list[i].mask) == 0)
+				continue;
+			actions_list[i].funct(
+				actions, actions_counter++,
+				additional_para_data
+			);
+			break;
+		}
 	}
 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_END;
 }
diff --git a/app/test-flow-perf/actions_gen.h b/app/test-flow-perf/actions_gen.h
index 0defa7c97c..d6918a53a6 100644
--- a/app/test-flow-perf/actions_gen.h
+++ b/app/test-flow-perf/actions_gen.h
@@ -12,7 +12,7 @@
 
 #include "config.h"
 
-void fill_actions(struct rte_flow_action *actions, uint64_t actions_selector,
+void fill_actions(struct rte_flow_action *actions, uint64_t *flow_actions,
 	uint32_t counter, uint16_t next_table, uint16_t hairpinq);
 
 #endif /* FLOW_PERF_ACTION_GEN */
diff --git a/app/test-flow-perf/config.h b/app/test-flow-perf/config.h
index e47d788572..439f3264b4 100644
--- a/app/test-flow-perf/config.h
+++ b/app/test-flow-perf/config.h
@@ -29,3 +29,4 @@
 /* Flow items/acctions max size */
 #define MAX_ITEMS_NUM 32
 #define MAX_ACTIONS_NUM 32
+#define MAX_ATTRS_NUM 16
diff --git a/app/test-flow-perf/flow_gen.c b/app/test-flow-perf/flow_gen.c
index e87276bd14..b2c828c7df 100644
--- a/app/test-flow-perf/flow_gen.c
+++ b/app/test-flow-perf/flow_gen.c
@@ -18,23 +18,28 @@
 
 static void
 fill_attributes(struct rte_flow_attr *attr,
-	uint64_t flow_attrs, uint16_t group)
+	uint64_t *flow_attrs, uint16_t group)
 {
-	if (flow_attrs & INGRESS)
-		attr->ingress = 1;
-	if (flow_attrs & EGRESS)
-		attr->egress = 1;
-	if (flow_attrs & TRANSFER)
-		attr->transfer = 1;
+	uint8_t i;
+	for (i = 0; i < MAX_ATTRS_NUM; i++) {
+		if (flow_attrs[i] == 0)
+			break;
+		if (flow_attrs[i] & INGRESS)
+			attr->ingress = 1;
+		else if (flow_attrs[i] & EGRESS)
+			attr->egress = 1;
+		else if (flow_attrs[i] & TRANSFER)
+			attr->transfer = 1;
+	}
 	attr->group = group;
 }
 
 struct rte_flow *
 generate_flow(uint16_t port_id,
 	uint16_t group,
-	uint64_t flow_attrs,
-	uint64_t flow_items,
-	uint64_t flow_actions,
+	uint64_t *flow_attrs,
+	uint64_t *flow_items,
+	uint64_t *flow_actions,
 	uint16_t next_table,
 	uint32_t outer_ip_src,
 	uint16_t hairpinq,
diff --git a/app/test-flow-perf/flow_gen.h b/app/test-flow-perf/flow_gen.h
index 848331e229..53469c659f 100644
--- a/app/test-flow-perf/flow_gen.h
+++ b/app/test-flow-perf/flow_gen.h
@@ -26,9 +26,9 @@
 struct rte_flow *
 generate_flow(uint16_t port_id,
 	uint16_t group,
-	uint64_t flow_attrs,
-	uint64_t flow_items,
-	uint64_t flow_actions,
+	uint64_t *flow_attrs,
+	uint64_t *flow_items,
+	uint64_t *flow_actions,
 	uint16_t next_table,
 	uint32_t outer_ip_src,
 	uint16_t hairpinq,
diff --git a/app/test-flow-perf/items_gen.c b/app/test-flow-perf/items_gen.c
index 6a8915100c..cc031f24a5 100644
--- a/app/test-flow-perf/items_gen.c
+++ b/app/test-flow-perf/items_gen.c
@@ -312,10 +312,10 @@ add_meta_tag(struct rte_flow_item *items,
 
 void
 fill_items(struct rte_flow_item *items,
-	uint64_t flow_items, uint32_t outer_ip_src)
+	uint64_t *flow_items, uint32_t outer_ip_src)
 {
 	uint8_t items_counter = 0;
-	uint8_t i;
+	uint8_t i, j;
 	struct additional_para additional_para_data = {
 		.src_ip = outer_ip_src,
 	};
@@ -328,7 +328,7 @@ fill_items(struct rte_flow_item *items,
 			uint8_t items_counter,
 			struct additional_para para
 			);
-	} flows_items[] = {
+	} items_list[] = {
 		{
 			.mask = RTE_FLOW_ITEM_TYPE_META,
 			.funct = add_meta_data,
@@ -384,13 +384,19 @@ fill_items(struct rte_flow_item *items,
 
 	};
 
-	for (i = 0; i < RTE_DIM(flows_items); i++) {
-		if ((flow_items & FLOW_ITEM_MASK(flows_items[i].mask)) == 0)
-			continue;
-		flows_items[i].funct(
-			items, items_counter++,
-			additional_para_data
-		);
+	for (j = 0; j < MAX_ITEMS_NUM; j++) {
+		if (flow_items[j] == 0)
+			break;
+		for (i = 0; i < RTE_DIM(items_list); i++) {
+			if ((flow_items[j] &
+				FLOW_ITEM_MASK(items_list[i].mask)) == 0)
+				continue;
+			items_list[i].funct(
+				items, items_counter++,
+				additional_para_data
+			);
+			break;
+		}
 	}
 
 	items[items_counter].type = RTE_FLOW_ITEM_TYPE_END;
diff --git a/app/test-flow-perf/items_gen.h b/app/test-flow-perf/items_gen.h
index 9509d0f11c..d68958e4d3 100644
--- a/app/test-flow-perf/items_gen.h
+++ b/app/test-flow-perf/items_gen.h
@@ -12,7 +12,7 @@
 
 #include "config.h"
 
-void fill_items(struct rte_flow_item *items, uint64_t flow_items,
+void fill_items(struct rte_flow_item *items, uint64_t *flow_items,
 	uint32_t outer_ip_src);
 
 #endif /* FLOW_PERF_ITEMS_GEN */
diff --git a/app/test-flow-perf/main.c b/app/test-flow-perf/main.c
index 3589b316f9..0ff8080aa0 100644
--- a/app/test-flow-perf/main.c
+++ b/app/test-flow-perf/main.c
@@ -45,9 +45,10 @@
 struct rte_flow *flow;
 static uint8_t flow_group;
 
-static uint64_t flow_items;
-static uint64_t flow_actions;
-static uint64_t flow_attrs;
+static uint64_t flow_items[MAX_ITEMS_NUM];
+static uint64_t flow_actions[MAX_ACTIONS_NUM];
+static uint64_t flow_attrs[MAX_ATTRS_NUM];
+static uint8_t items_idx, actions_idx, attrs_idx;
 
 static volatile bool force_quit;
 static bool dump_iterations;
@@ -150,132 +151,159 @@ args_parse(int argc, char **argv)
 	static const struct option_dict {
 		const char *str;
 		const uint64_t mask;
-		uint64_t *bitmap;
+		uint64_t *map;
+		uint8_t *map_idx;
+
 	} flow_options[] = {
 		{
 			.str = "ether",
 			.mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_ETH),
-			.bitmap = &flow_items
+			.map = &flow_items[0],
+			.map_idx = &items_idx
 		},
 		{
 			.str = "ipv4",
 			.mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_IPV4),
-			.bitmap = &flow_items
+			.map = &flow_items[0],
+			.map_idx = &items_idx
 		},
 		{
 			.str = "ipv6",
 			.mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_IPV6),
-			.bitmap = &flow_items
+			.map = &flow_items[0],
+			.map_idx = &items_idx
 		},
 		{
 			.str = "vlan",
 			.mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_VLAN),
-			.bitmap = &flow_items
+			.map = &flow_items[0],
+			.map_idx = &items_idx
 		},
 		{
 			.str = "tcp",
 			.mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_TCP),
-			.bitmap = &flow_items
+			.map = &flow_items[0],
+			.map_idx = &items_idx
 		},
 		{
 			.str = "udp",
 			.mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_UDP),
-			.bitmap = &flow_items
+			.map = &flow_items[0],
+			.map_idx = &items_idx
 		},
 		{
 			.str = "vxlan",
 			.mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_VXLAN),
-			.bitmap = &flow_items
+			.map = &flow_items[0],
+			.map_idx = &items_idx
 		},
 		{
 			.str = "vxlan-gpe",
 			.mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_VXLAN_GPE),
-			.bitmap = &flow_items
+			.map = &flow_items[0],
+			.map_idx = &items_idx
 		},
 		{
 			.str = "gre",
 			.mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_GRE),
-			.bitmap = &flow_items
+			.map = &flow_items[0],
+			.map_idx = &items_idx
 		},
 		{
 			.str = "geneve",
 			.mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_GENEVE),
-			.bitmap = &flow_items
+			.map = &flow_items[0],
+			.map_idx = &items_idx
 		},
 		{
 			.str = "gtp",
 			.mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_GTP),
-			.bitmap = &flow_items
+			.map = &flow_items[0],
+			.map_idx = &items_idx
 		},
 		{
 			.str = "meta",
 			.mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_META),
-			.bitmap = &flow_items
+			.map = &flow_items[0],
+			.map_idx = &items_idx
 		},
 		{
 			.str = "tag",
 			.mask = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_TAG),
-			.bitmap = &flow_items
+			.map = &flow_items[0],
+			.map_idx = &items_idx
 		},
 		{
 			.str = "ingress",
 			.mask = INGRESS,
-			.bitmap = &flow_attrs
+			.map = &flow_attrs[0],
+			.map_idx = &attrs_idx
 		},
 		{
 			.str = "egress",
 			.mask = EGRESS,
-			.bitmap = &flow_attrs
+			.map = &flow_attrs[0],
+			.map_idx = &attrs_idx
 		},
 		{
 			.str = "transfer",
 			.mask = TRANSFER,
-			.bitmap = &flow_attrs
+			.map = &flow_attrs[0],
+			.map_idx = &attrs_idx
 		},
 		{
 			.str = "port-id",
 			.mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_PORT_ID),
-			.bitmap = &flow_actions
+			.map = &flow_actions[0],
+			.map_idx = &actions_idx
 		},
 		{
 			.str = "rss",
 			.mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_RSS),
-			.bitmap = &flow_actions
+			.map = &flow_actions[0],
+			.map_idx = &actions_idx
 		},
 		{
 			.str = "queue",
 			.mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_QUEUE),
-			.bitmap = &flow_actions
+			.map = &flow_actions[0],
+			.map_idx = &actions_idx
 		},
 		{
 			.str = "jump",
 			.mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_JUMP),
-			.bitmap = &flow_actions
+			.map = &flow_actions[0],
+			.map_idx = &actions_idx
 		},
 		{
 			.str = "mark",
 			.mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_MARK),
-			.bitmap = &flow_actions
+			.map = &flow_actions[0],
+			.map_idx = &actions_idx
 		},
 		{
 			.str = "count",
 			.mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_COUNT),
-			.bitmap = &flow_actions
+			.map = &flow_actions[0],
+			.map_idx = &actions_idx
 		},
 		{
 			.str = "set-meta",
 			.mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_SET_META),
-			.bitmap = &flow_actions
+			.map = &flow_actions[0],
+			.map_idx = &actions_idx
 		},
 		{
 			.str = "set-tag",
 			.mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_SET_TAG),
-			.bitmap = &flow_actions
+			.map = &flow_actions[0],
+			.map_idx = &actions_idx
 		},
 		{
 			.str = "drop",
 			.mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_DROP),
-			.bitmap = &flow_actions
+			.map = &flow_actions[0],
+			.map_idx = &actions_idx
 		}
 	};
 
@@ -320,9 +348,6 @@ args_parse(int argc, char **argv)
 		{ "hairpin-rss",                1, 0, 0 },
 	};
 
-	flow_items = 0;
-	flow_actions = 0;
-	flow_attrs = 0;
 	hairpin_queues_num = 0;
 	argvopt = argv;
 
@@ -349,7 +374,8 @@ args_parse(int argc, char **argv)
 			for (i = 0; i < RTE_DIM(flow_options); i++)
 				if (strcmp(lgopts[opt_idx].name,
 						flow_options[i].str) == 0) {
-					*flow_options[i].bitmap |=
+					flow_options[i].map[
+					(*flow_options[i].map_idx)++] =
 						flow_options[i].mask;
 					printf("%s / ", flow_options[i].str);
 				}
@@ -363,7 +389,8 @@ args_parse(int argc, char **argv)
 					rte_exit(EXIT_SUCCESS,
 						"Hairpin queues should be > 0\n");
 
-				flow_actions |= HAIRPIN_RSS_ACTION;
+				flow_actions[actions_idx++] =
+					HAIRPIN_RSS_ACTION;
 				printf("hairpin-rss / ");
 			}
 			if (strcmp(lgopts[opt_idx].name,
@@ -375,7 +402,8 @@ args_parse(int argc, char **argv)
 					rte_exit(EXIT_SUCCESS,
 						"Hairpin queues should be > 0\n");
 
-				flow_actions |= HAIRPIN_QUEUE_ACTION;
+				flow_actions[actions_idx++] =
+					HAIRPIN_QUEUE_ACTION;
 				printf("hairpin-queue / ");
 			}
 
@@ -558,6 +586,11 @@ flows_handler(void)
 	int port_id;
 	int iter_id;
 	uint32_t flow_index;
+	uint64_t global_items[MAX_ITEMS_NUM] = { 0 };
+	uint64_t global_actions[MAX_ACTIONS_NUM] = { 0 };
+
+	global_items[0] = FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_ETH);
+	global_actions[0] = FLOW_ITEM_MASK(RTE_FLOW_ACTION_TYPE_JUMP);
 
 	nr_ports = rte_eth_dev_count_avail();
 
@@ -587,8 +620,7 @@ flows_handler(void)
 			 *
 			 */
 			flow = generate_flow(port_id, 0, flow_attrs,
-				FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_ETH),
-				FLOW_ITEM_MASK(RTE_FLOW_ACTION_TYPE_JUMP),
+				global_items, global_actions,
 				flow_group, 0, 0, &error);
 
 			if (flow == NULL) {
diff --git a/doc/guides/rel_notes/release_20_08.rst b/doc/guides/rel_notes/release_20_08.rst
index a19ec6db2b..d3ba4cd1d0 100644
--- a/doc/guides/rel_notes/release_20_08.rst
+++ b/doc/guides/rel_notes/release_20_08.rst
@@ -272,6 +272,14 @@ New Features
   of ingress packets to specific NIC queues.
   See the :doc:`../sample_app_ug/ipsec_secgw` for more details.
 
+* **Add more support for flow-perf application.**
+
+  * Start supporting user order instead of bit mask:
+    Now the user can create any structure of rte_flow
+    using flow performance application with any order,
+    moreover the app also now starts to support inner
+    items matching as well.
+
 
 Removed Items
 -------------
diff --git a/doc/guides/tools/flow-perf.rst b/doc/guides/tools/flow-perf.rst
index ca551aee6e..6941155fee 100644
--- a/doc/guides/tools/flow-perf.rst
+++ b/doc/guides/tools/flow-perf.rst
@@ -16,20 +16,18 @@ After that the application will start producing rules with same pattern
 but increasing the outer IP source address by 1 each time, thus it will
 give different flow each time, and all other items will have open masks.
 
+The application also provide the ability to measure rte flow deletion rate,
+in addition to memory consumption before and after the flows creation.
+
+The app supports single and multi core performance measurements.
+
 
 Known Limitations
 -----------------
 
 The current version has limitations which can be removed in future:
 
-* Support outer items up to tunnel layer only.
 * Single core insertion only.
-* Only one instance of same action can be added in one rule.
-
-The application also provide the ability to measure rte flow deletion rate,
-in addition to memory consumption before and after the flows creation.
-
-The app supports single and multi core performance measurements.
 
 
 Compiling the Application
