net: add macro for VLAN header length
[dpdk.git] / drivers / net / mvpp2 / mrvl_flow.c
index 8fd4dbf..99695b9 100644 (file)
 
 #include <arpa/inet.h>
 
-#ifdef container_of
-#undef container_of
-#endif
-
-#include "mrvl_ethdev.h"
+#include "mrvl_flow.h"
 #include "mrvl_qos.h"
-#include "env/mv_common.h" /* for BIT() */
 
 /** Number of rules in the classifier table. */
 #define MRVL_CLS_MAX_NUM_RULES 20
 /** Size of the classifier key and mask strings. */
 #define MRVL_CLS_STR_SIZE_MAX 40
 
-/** Parsed fields in processed rte_flow_item. */
-enum mrvl_parsed_fields {
-       /* eth flags */
-       F_DMAC =         BIT(0),
-       F_SMAC =         BIT(1),
-       F_TYPE =         BIT(2),
-       /* vlan flags */
-       F_VLAN_ID =      BIT(3),
-       F_VLAN_PRI =     BIT(4),
-       F_VLAN_TCI =     BIT(5), /* not supported by MUSDK yet */
-       /* ip4 flags */
-       F_IP4_TOS =      BIT(6),
-       F_IP4_SIP =      BIT(7),
-       F_IP4_DIP =      BIT(8),
-       F_IP4_PROTO =    BIT(9),
-       /* ip6 flags */
-       F_IP6_TC =       BIT(10), /* not supported by MUSDK yet */
-       F_IP6_SIP =      BIT(11),
-       F_IP6_DIP =      BIT(12),
-       F_IP6_FLOW =     BIT(13),
-       F_IP6_NEXT_HDR = BIT(14),
-       /* tcp flags */
-       F_TCP_SPORT =    BIT(15),
-       F_TCP_DPORT =    BIT(16),
-       /* udp flags */
-       F_UDP_SPORT =    BIT(17),
-       F_UDP_DPORT =    BIT(18),
-};
-
-/** PMD-specific definition of a flow rule handle. */
-struct rte_flow {
-       LIST_ENTRY(rte_flow) next;
-
-       enum mrvl_parsed_fields pattern;
-
-       struct pp2_cls_tbl_rule rule;
-       struct pp2_cls_cos_desc cos;
-       struct pp2_cls_tbl_action action;
-};
-
-static const enum rte_flow_item_type pattern_eth[] = {
-       RTE_FLOW_ITEM_TYPE_ETH,
-       RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_eth_vlan[] = {
-       RTE_FLOW_ITEM_TYPE_ETH,
-       RTE_FLOW_ITEM_TYPE_VLAN,
-       RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_eth_vlan_ip[] = {
-       RTE_FLOW_ITEM_TYPE_ETH,
-       RTE_FLOW_ITEM_TYPE_VLAN,
-       RTE_FLOW_ITEM_TYPE_IPV4,
-       RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_eth_vlan_ip6[] = {
-       RTE_FLOW_ITEM_TYPE_ETH,
-       RTE_FLOW_ITEM_TYPE_VLAN,
-       RTE_FLOW_ITEM_TYPE_IPV6,
-       RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_eth_ip4[] = {
-       RTE_FLOW_ITEM_TYPE_ETH,
-       RTE_FLOW_ITEM_TYPE_IPV4,
-       RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_eth_ip4_tcp[] = {
-       RTE_FLOW_ITEM_TYPE_ETH,
-       RTE_FLOW_ITEM_TYPE_IPV4,
-       RTE_FLOW_ITEM_TYPE_TCP,
-       RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_eth_ip4_udp[] = {
-       RTE_FLOW_ITEM_TYPE_ETH,
-       RTE_FLOW_ITEM_TYPE_IPV4,
-       RTE_FLOW_ITEM_TYPE_UDP,
-       RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_eth_ip6[] = {
-       RTE_FLOW_ITEM_TYPE_ETH,
-       RTE_FLOW_ITEM_TYPE_IPV6,
-       RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_eth_ip6_tcp[] = {
-       RTE_FLOW_ITEM_TYPE_ETH,
-       RTE_FLOW_ITEM_TYPE_IPV6,
-       RTE_FLOW_ITEM_TYPE_TCP,
-       RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_eth_ip6_udp[] = {
-       RTE_FLOW_ITEM_TYPE_ETH,
-       RTE_FLOW_ITEM_TYPE_IPV6,
-       RTE_FLOW_ITEM_TYPE_UDP,
-       RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_vlan[] = {
-       RTE_FLOW_ITEM_TYPE_VLAN,
-       RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_vlan_ip[] = {
-       RTE_FLOW_ITEM_TYPE_VLAN,
-       RTE_FLOW_ITEM_TYPE_IPV4,
-       RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_vlan_ip_tcp[] = {
-       RTE_FLOW_ITEM_TYPE_VLAN,
-       RTE_FLOW_ITEM_TYPE_IPV4,
-       RTE_FLOW_ITEM_TYPE_TCP,
-       RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_vlan_ip_udp[] = {
-       RTE_FLOW_ITEM_TYPE_VLAN,
-       RTE_FLOW_ITEM_TYPE_IPV4,
-       RTE_FLOW_ITEM_TYPE_UDP,
-       RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_vlan_ip6[] = {
-       RTE_FLOW_ITEM_TYPE_VLAN,
-       RTE_FLOW_ITEM_TYPE_IPV6,
-       RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_vlan_ip6_tcp[] = {
-       RTE_FLOW_ITEM_TYPE_VLAN,
-       RTE_FLOW_ITEM_TYPE_IPV6,
-       RTE_FLOW_ITEM_TYPE_TCP,
-       RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_vlan_ip6_udp[] = {
-       RTE_FLOW_ITEM_TYPE_VLAN,
-       RTE_FLOW_ITEM_TYPE_IPV6,
-       RTE_FLOW_ITEM_TYPE_UDP,
-       RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_ip[] = {
-       RTE_FLOW_ITEM_TYPE_IPV4,
-       RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_ip6[] = {
-       RTE_FLOW_ITEM_TYPE_IPV6,
-       RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_ip_tcp[] = {
-       RTE_FLOW_ITEM_TYPE_IPV4,
-       RTE_FLOW_ITEM_TYPE_TCP,
-       RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_ip6_tcp[] = {
-       RTE_FLOW_ITEM_TYPE_IPV6,
-       RTE_FLOW_ITEM_TYPE_TCP,
-       RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_ip_udp[] = {
-       RTE_FLOW_ITEM_TYPE_IPV4,
-       RTE_FLOW_ITEM_TYPE_UDP,
-       RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_ip6_udp[] = {
-       RTE_FLOW_ITEM_TYPE_IPV6,
-       RTE_FLOW_ITEM_TYPE_UDP,
-       RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_tcp[] = {
-       RTE_FLOW_ITEM_TYPE_TCP,
-       RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_udp[] = {
-       RTE_FLOW_ITEM_TYPE_UDP,
-       RTE_FLOW_ITEM_TYPE_END
-};
-
 #define MRVL_VLAN_ID_MASK 0x0fff
 #define MRVL_VLAN_PRI_MASK 0x7000
 #define MRVL_IPV4_DSCP_MASK 0xfc
 #define MRVL_IPV4_ADDR_MASK 0xffffffff
 #define MRVL_IPV6_FLOW_MASK 0x0fffff
 
-/**
- * Given a flow item, return the next non-void one.
- *
- * @param items Pointer to the item in the table.
- * @returns Next not-void item, NULL otherwise.
- */
-static const struct rte_flow_item *
-mrvl_next_item(const struct rte_flow_item *items)
-{
-       const struct rte_flow_item *item = items;
-
-       for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
-               if (item->type != RTE_FLOW_ITEM_TYPE_VOID)
-                       return item;
-       }
-
-       return NULL;
-}
-
 /**
  * Allocate memory for classifier rule key and mask fields.
  *
@@ -394,7 +176,8 @@ mrvl_parse_init(const struct rte_flow_item *item,
  *
  * @param spec Pointer to the specific flow item.
  * @param mask Pointer to the specific flow item's mask.
- * @param mask Pointer to the flow.
+ * @param parse_dst Parse either destination or source mac address.
+ * @param flow Pointer to the flow.
  * @return 0 in case of success, negative error value otherwise.
  */
 static int
@@ -405,19 +188,18 @@ mrvl_parse_mac(const struct rte_flow_item_eth *spec,
        struct pp2_cls_rule_key_field *key_field;
        const uint8_t *k, *m;
 
-       if (flow->rule.num_fields >= PP2_CLS_TBL_MAX_NUM_FIELDS)
-               return -ENOSPC;
-
        if (parse_dst) {
                k = spec->dst.addr_bytes;
                m = mask->dst.addr_bytes;
 
-               flow->pattern |= F_DMAC;
+               flow->table_key.proto_field[flow->rule.num_fields].field.eth =
+                       MV_NET_ETH_F_DA;
        } else {
                k = spec->src.addr_bytes;
                m = mask->src.addr_bytes;
 
-               flow->pattern |= F_SMAC;
+               flow->table_key.proto_field[flow->rule.num_fields].field.eth =
+                       MV_NET_ETH_F_SA;
        }
 
        key_field = &flow->rule.fields[flow->rule.num_fields];
@@ -425,13 +207,17 @@ mrvl_parse_mac(const struct rte_flow_item_eth *spec,
        key_field->size = 6;
 
        snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX,
-                "%02x:%02x:%02x:%02x:%02x:%02x",
+                RTE_ETHER_ADDR_PRT_FMT,
                 k[0], k[1], k[2], k[3], k[4], k[5]);
 
        snprintf((char *)key_field->mask, MRVL_CLS_STR_SIZE_MAX,
-                "%02x:%02x:%02x:%02x:%02x:%02x",
+                RTE_ETHER_ADDR_PRT_FMT,
                 m[0], m[1], m[2], m[3], m[4], m[5]);
 
+       flow->table_key.proto_field[flow->rule.num_fields].proto =
+               MV_NET_PROTO_ETH;
+       flow->table_key.key_size += key_field->size;
+
        flow->rule.num_fields += 1;
 
        return 0;
@@ -485,9 +271,6 @@ mrvl_parse_type(const struct rte_flow_item_eth *spec,
        struct pp2_cls_rule_key_field *key_field;
        uint16_t k;
 
-       if (flow->rule.num_fields >= PP2_CLS_TBL_MAX_NUM_FIELDS)
-               return -ENOSPC;
-
        key_field = &flow->rule.fields[flow->rule.num_fields];
        mrvl_alloc_key_mask(key_field);
        key_field->size = 2;
@@ -495,7 +278,12 @@ mrvl_parse_type(const struct rte_flow_item_eth *spec,
        k = rte_be_to_cpu_16(spec->type);
        snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
 
-       flow->pattern |= F_TYPE;
+       flow->table_key.proto_field[flow->rule.num_fields].proto =
+               MV_NET_PROTO_ETH;
+       flow->table_key.proto_field[flow->rule.num_fields].field.eth =
+               MV_NET_ETH_F_TYPE;
+       flow->table_key.key_size += key_field->size;
+
        flow->rule.num_fields += 1;
 
        return 0;
@@ -519,9 +307,6 @@ mrvl_parse_vlan_id(const struct rte_flow_item_vlan *spec,
        struct pp2_cls_rule_key_field *key_field;
        uint16_t k;
 
-       if (flow->rule.num_fields >= PP2_CLS_TBL_MAX_NUM_FIELDS)
-               return -ENOSPC;
-
        key_field = &flow->rule.fields[flow->rule.num_fields];
        mrvl_alloc_key_mask(key_field);
        key_field->size = 2;
@@ -529,7 +314,12 @@ mrvl_parse_vlan_id(const struct rte_flow_item_vlan *spec,
        k = rte_be_to_cpu_16(spec->tci) & MRVL_VLAN_ID_MASK;
        snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
 
-       flow->pattern |= F_VLAN_ID;
+       flow->table_key.proto_field[flow->rule.num_fields].proto =
+               MV_NET_PROTO_VLAN;
+       flow->table_key.proto_field[flow->rule.num_fields].field.vlan =
+               MV_NET_VLAN_F_ID;
+       flow->table_key.key_size += key_field->size;
+
        flow->rule.num_fields += 1;
 
        return 0;
@@ -553,9 +343,6 @@ mrvl_parse_vlan_pri(const struct rte_flow_item_vlan *spec,
        struct pp2_cls_rule_key_field *key_field;
        uint16_t k;
 
-       if (flow->rule.num_fields >= PP2_CLS_TBL_MAX_NUM_FIELDS)
-               return -ENOSPC;
-
        key_field = &flow->rule.fields[flow->rule.num_fields];
        mrvl_alloc_key_mask(key_field);
        key_field->size = 1;
@@ -563,7 +350,12 @@ mrvl_parse_vlan_pri(const struct rte_flow_item_vlan *spec,
        k = (rte_be_to_cpu_16(spec->tci) & MRVL_VLAN_PRI_MASK) >> 13;
        snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
 
-       flow->pattern |= F_VLAN_PRI;
+       flow->table_key.proto_field[flow->rule.num_fields].proto =
+               MV_NET_PROTO_VLAN;
+       flow->table_key.proto_field[flow->rule.num_fields].field.vlan =
+               MV_NET_VLAN_F_PRI;
+       flow->table_key.key_size += key_field->size;
+
        flow->rule.num_fields += 1;
 
        return 0;
@@ -587,9 +379,6 @@ mrvl_parse_ip4_dscp(const struct rte_flow_item_ipv4 *spec,
        struct pp2_cls_rule_key_field *key_field;
        uint8_t k, m;
 
-       if (flow->rule.num_fields >= PP2_CLS_TBL_MAX_NUM_FIELDS)
-               return -ENOSPC;
-
        key_field = &flow->rule.fields[flow->rule.num_fields];
        mrvl_alloc_key_mask(key_field);
        key_field->size = 1;
@@ -599,7 +388,12 @@ mrvl_parse_ip4_dscp(const struct rte_flow_item_ipv4 *spec,
        snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
        snprintf((char *)key_field->mask, MRVL_CLS_STR_SIZE_MAX, "%u", m);
 
-       flow->pattern |= F_IP4_TOS;
+       flow->table_key.proto_field[flow->rule.num_fields].proto =
+               MV_NET_PROTO_IP4;
+       flow->table_key.proto_field[flow->rule.num_fields].field.ipv4 =
+               MV_NET_IP4_F_DSCP;
+       flow->table_key.key_size += key_field->size;
+
        flow->rule.num_fields += 1;
 
        return 0;
@@ -613,6 +407,7 @@ mrvl_parse_ip4_dscp(const struct rte_flow_item_ipv4 *spec,
  *
  * @param spec Pointer to the specific flow item.
  * @param mask Pointer to the specific flow item's mask.
+ * @param parse_dst Parse either destination or source ip address.
  * @param flow Pointer to the flow.
  * @return 0 in case of success, negative error value otherwise.
  */
@@ -625,20 +420,19 @@ mrvl_parse_ip4_addr(const struct rte_flow_item_ipv4 *spec,
        struct in_addr k;
        uint32_t m;
 
-       if (flow->rule.num_fields >= PP2_CLS_TBL_MAX_NUM_FIELDS)
-               return -ENOSPC;
-
        memset(&k, 0, sizeof(k));
        if (parse_dst) {
                k.s_addr = spec->hdr.dst_addr;
                m = rte_be_to_cpu_32(mask->hdr.dst_addr);
 
-               flow->pattern |= F_IP4_DIP;
+               flow->table_key.proto_field[flow->rule.num_fields].field.ipv4 =
+                       MV_NET_IP4_F_DA;
        } else {
                k.s_addr = spec->hdr.src_addr;
                m = rte_be_to_cpu_32(mask->hdr.src_addr);
 
-               flow->pattern |= F_IP4_SIP;
+               flow->table_key.proto_field[flow->rule.num_fields].field.ipv4 =
+                       MV_NET_IP4_F_SA;
        }
 
        key_field = &flow->rule.fields[flow->rule.num_fields];
@@ -648,6 +442,10 @@ mrvl_parse_ip4_addr(const struct rte_flow_item_ipv4 *spec,
        inet_ntop(AF_INET, &k, (char *)key_field->key, MRVL_CLS_STR_SIZE_MAX);
        snprintf((char *)key_field->mask, MRVL_CLS_STR_SIZE_MAX, "0x%x", m);
 
+       flow->table_key.proto_field[flow->rule.num_fields].proto =
+               MV_NET_PROTO_IP4;
+       flow->table_key.key_size += key_field->size;
+
        flow->rule.num_fields += 1;
 
        return 0;
@@ -703,16 +501,18 @@ mrvl_parse_ip4_proto(const struct rte_flow_item_ipv4 *spec,
        struct pp2_cls_rule_key_field *key_field;
        uint8_t k = spec->hdr.next_proto_id;
 
-       if (flow->rule.num_fields >= PP2_CLS_TBL_MAX_NUM_FIELDS)
-               return -ENOSPC;
-
        key_field = &flow->rule.fields[flow->rule.num_fields];
        mrvl_alloc_key_mask(key_field);
        key_field->size = 1;
 
        snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
 
-       flow->pattern |= F_IP4_PROTO;
+       flow->table_key.proto_field[flow->rule.num_fields].proto =
+               MV_NET_PROTO_IP4;
+       flow->table_key.proto_field[flow->rule.num_fields].field.ipv4 =
+               MV_NET_IP4_F_PROTO;
+       flow->table_key.key_size += key_field->size;
+
        flow->rule.num_fields += 1;
 
        return 0;
@@ -726,6 +526,7 @@ mrvl_parse_ip4_proto(const struct rte_flow_item_ipv4 *spec,
  *
  * @param spec Pointer to the specific flow item.
  * @param mask Pointer to the specific flow item's mask.
+ * @param parse_dst Parse either destination or source ipv6 address.
  * @param flow Pointer to the flow.
  * @return 0 in case of success, negative error value otherwise.
  */
@@ -738,20 +539,19 @@ mrvl_parse_ip6_addr(const struct rte_flow_item_ipv6 *spec,
        int size = sizeof(spec->hdr.dst_addr);
        struct in6_addr k, m;
 
-       if (flow->rule.num_fields >= PP2_CLS_TBL_MAX_NUM_FIELDS)
-               return -ENOSPC;
-
        memset(&k, 0, sizeof(k));
        if (parse_dst) {
                memcpy(k.s6_addr, spec->hdr.dst_addr, size);
                memcpy(m.s6_addr, mask->hdr.dst_addr, size);
 
-               flow->pattern |= F_IP6_DIP;
+               flow->table_key.proto_field[flow->rule.num_fields].field.ipv6 =
+                       MV_NET_IP6_F_DA;
        } else {
                memcpy(k.s6_addr, spec->hdr.src_addr, size);
                memcpy(m.s6_addr, mask->hdr.src_addr, size);
 
-               flow->pattern |= F_IP6_SIP;
+               flow->table_key.proto_field[flow->rule.num_fields].field.ipv6 =
+                       MV_NET_IP6_F_SA;
        }
 
        key_field = &flow->rule.fields[flow->rule.num_fields];
@@ -761,6 +561,10 @@ mrvl_parse_ip6_addr(const struct rte_flow_item_ipv6 *spec,
        inet_ntop(AF_INET6, &k, (char *)key_field->key, MRVL_CLS_STR_SIZE_MAX);
        inet_ntop(AF_INET6, &m, (char *)key_field->mask, MRVL_CLS_STR_SIZE_MAX);
 
+       flow->table_key.proto_field[flow->rule.num_fields].proto =
+               MV_NET_PROTO_IP6;
+       flow->table_key.key_size += key_field->size;
+
        flow->rule.num_fields += 1;
 
        return 0;
@@ -817,9 +621,6 @@ mrvl_parse_ip6_flow(const struct rte_flow_item_ipv6 *spec,
        uint32_t k = rte_be_to_cpu_32(spec->hdr.vtc_flow) & MRVL_IPV6_FLOW_MASK,
                 m = rte_be_to_cpu_32(mask->hdr.vtc_flow) & MRVL_IPV6_FLOW_MASK;
 
-       if (flow->rule.num_fields >= PP2_CLS_TBL_MAX_NUM_FIELDS)
-               return -ENOSPC;
-
        key_field = &flow->rule.fields[flow->rule.num_fields];
        mrvl_alloc_key_mask(key_field);
        key_field->size = 3;
@@ -827,7 +628,12 @@ mrvl_parse_ip6_flow(const struct rte_flow_item_ipv6 *spec,
        snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
        snprintf((char *)key_field->mask, MRVL_CLS_STR_SIZE_MAX, "%u", m);
 
-       flow->pattern |= F_IP6_FLOW;
+       flow->table_key.proto_field[flow->rule.num_fields].proto =
+               MV_NET_PROTO_IP6;
+       flow->table_key.proto_field[flow->rule.num_fields].field.ipv6 =
+               MV_NET_IP6_F_FLOW;
+       flow->table_key.key_size += key_field->size;
+
        flow->rule.num_fields += 1;
 
        return 0;
@@ -851,16 +657,18 @@ mrvl_parse_ip6_next_hdr(const struct rte_flow_item_ipv6 *spec,
        struct pp2_cls_rule_key_field *key_field;
        uint8_t k = spec->hdr.proto;
 
-       if (flow->rule.num_fields >= PP2_CLS_TBL_MAX_NUM_FIELDS)
-               return -ENOSPC;
-
        key_field = &flow->rule.fields[flow->rule.num_fields];
        mrvl_alloc_key_mask(key_field);
        key_field->size = 1;
 
        snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
 
-       flow->pattern |= F_IP6_NEXT_HDR;
+       flow->table_key.proto_field[flow->rule.num_fields].proto =
+               MV_NET_PROTO_IP6;
+       flow->table_key.proto_field[flow->rule.num_fields].field.ipv6 =
+               MV_NET_IP6_F_NEXT_HDR;
+       flow->table_key.key_size += key_field->size;
+
        flow->rule.num_fields += 1;
 
        return 0;
@@ -874,6 +682,7 @@ mrvl_parse_ip6_next_hdr(const struct rte_flow_item_ipv6 *spec,
  *
  * @param spec Pointer to the specific flow item.
  * @param mask Pointer to the specific flow item's mask.
+ * @param parse_dst Parse either destination or source port.
  * @param flow Pointer to the flow.
  * @return 0 in case of success, negative error value otherwise.
  */
@@ -885,9 +694,6 @@ mrvl_parse_tcp_port(const struct rte_flow_item_tcp *spec,
        struct pp2_cls_rule_key_field *key_field;
        uint16_t k;
 
-       if (flow->rule.num_fields >= PP2_CLS_TBL_MAX_NUM_FIELDS)
-               return -ENOSPC;
-
        key_field = &flow->rule.fields[flow->rule.num_fields];
        mrvl_alloc_key_mask(key_field);
        key_field->size = 2;
@@ -895,15 +701,21 @@ mrvl_parse_tcp_port(const struct rte_flow_item_tcp *spec,
        if (parse_dst) {
                k = rte_be_to_cpu_16(spec->hdr.dst_port);
 
-               flow->pattern |= F_TCP_DPORT;
+               flow->table_key.proto_field[flow->rule.num_fields].field.tcp =
+                       MV_NET_TCP_F_DP;
        } else {
                k = rte_be_to_cpu_16(spec->hdr.src_port);
 
-               flow->pattern |= F_TCP_SPORT;
+               flow->table_key.proto_field[flow->rule.num_fields].field.tcp =
+                       MV_NET_TCP_F_SP;
        }
 
        snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
 
+       flow->table_key.proto_field[flow->rule.num_fields].proto =
+               MV_NET_PROTO_TCP;
+       flow->table_key.key_size += key_field->size;
+
        flow->rule.num_fields += 1;
 
        return 0;
@@ -949,6 +761,7 @@ mrvl_parse_tcp_dport(const struct rte_flow_item_tcp *spec,
  *
  * @param spec Pointer to the specific flow item.
  * @param mask Pointer to the specific flow item's mask.
+ * @param parse_dst Parse either destination or source port.
  * @param flow Pointer to the flow.
  * @return 0 in case of success, negative error value otherwise.
  */
@@ -960,9 +773,6 @@ mrvl_parse_udp_port(const struct rte_flow_item_udp *spec,
        struct pp2_cls_rule_key_field *key_field;
        uint16_t k;
 
-       if (flow->rule.num_fields >= PP2_CLS_TBL_MAX_NUM_FIELDS)
-               return -ENOSPC;
-
        key_field = &flow->rule.fields[flow->rule.num_fields];
        mrvl_alloc_key_mask(key_field);
        key_field->size = 2;
@@ -970,15 +780,21 @@ mrvl_parse_udp_port(const struct rte_flow_item_udp *spec,
        if (parse_dst) {
                k = rte_be_to_cpu_16(spec->hdr.dst_port);
 
-               flow->pattern |= F_UDP_DPORT;
+               flow->table_key.proto_field[flow->rule.num_fields].field.udp =
+                       MV_NET_UDP_F_DP;
        } else {
                k = rte_be_to_cpu_16(spec->hdr.src_port);
 
-               flow->pattern |= F_UDP_SPORT;
+               flow->table_key.proto_field[flow->rule.num_fields].field.udp =
+                       MV_NET_UDP_F_SP;
        }
 
        snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
 
+       flow->table_key.proto_field[flow->rule.num_fields].proto =
+               MV_NET_PROTO_UDP;
+       flow->table_key.key_size += key_field->size;
+
        flow->rule.num_fields += 1;
 
        return 0;
@@ -1022,7 +838,6 @@ mrvl_parse_udp_dport(const struct rte_flow_item_udp *spec,
  * @param item Pointer to the flow item.
  * @param flow Pointer to the flow.
  * @param error Pointer to the flow error.
- * @param fields Pointer to the parsed parsed fields enum.
  * @returns 0 on success, negative value otherwise.
  */
 static int
@@ -1030,7 +845,7 @@ mrvl_parse_eth(const struct rte_flow_item *item, struct rte_flow *flow,
               struct rte_flow_error *error)
 {
        const struct rte_flow_item_eth *spec = NULL, *mask = NULL;
-       struct ether_addr zero;
+       struct rte_ether_addr zero;
        int ret;
 
        ret = mrvl_parse_init(item, (const void **)&spec, (const void **)&mask,
@@ -1054,7 +869,7 @@ mrvl_parse_eth(const struct rte_flow_item *item, struct rte_flow *flow,
        }
 
        if (mask->type) {
-               RTE_LOG(WARNING, PMD, "eth type mask is ignored\n");
+               MRVL_LOG(WARNING, "eth type mask is ignored");
                ret = mrvl_parse_type(spec, mask, flow);
                if (ret)
                        goto out;
@@ -1073,7 +888,6 @@ out:
  * @param item Pointer to the flow item.
  * @param flow Pointer to the flow.
  * @param error Pointer to the flow error.
- * @param fields Pointer to the parsed parsed fields enum.
  * @returns 0 on success, negative value otherwise.
  */
 static int
@@ -1083,7 +897,7 @@ mrvl_parse_vlan(const struct rte_flow_item *item,
 {
        const struct rte_flow_item_vlan *spec = NULL, *mask = NULL;
        uint16_t m;
-       int ret;
+       int ret, i;
 
        ret = mrvl_parse_init(item, (const void **)&spec, (const void **)&mask,
                              &rte_flow_item_vlan_mask,
@@ -1091,27 +905,50 @@ mrvl_parse_vlan(const struct rte_flow_item *item,
        if (ret)
                return ret;
 
-       if (mask->tpid) {
-               rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
-                                  NULL, "Not supported by classifier\n");
-               return -rte_errno;
-       }
-
        m = rte_be_to_cpu_16(mask->tci);
        if (m & MRVL_VLAN_ID_MASK) {
-               RTE_LOG(WARNING, PMD, "vlan id mask is ignored\n");
+               MRVL_LOG(WARNING, "vlan id mask is ignored");
                ret = mrvl_parse_vlan_id(spec, mask, flow);
                if (ret)
                        goto out;
        }
 
        if (m & MRVL_VLAN_PRI_MASK) {
-               RTE_LOG(WARNING, PMD, "vlan pri mask is ignored\n");
+               MRVL_LOG(WARNING, "vlan pri mask is ignored");
                ret = mrvl_parse_vlan_pri(spec, mask, flow);
                if (ret)
                        goto out;
        }
 
+       if (mask->inner_type) {
+               struct rte_flow_item_eth spec_eth = {
+                       .type = spec->inner_type,
+               };
+               struct rte_flow_item_eth mask_eth = {
+                       .type = mask->inner_type,
+               };
+
+               /* TPID is not supported so if ETH_TYPE was selected,
+                * error is return. else, classify eth-type with the tpid value
+                */
+               for (i = 0; i < flow->rule.num_fields; i++)
+                       if (flow->table_key.proto_field[i].proto ==
+                           MV_NET_PROTO_ETH &&
+                           flow->table_key.proto_field[i].field.eth ==
+                           MV_NET_ETH_F_TYPE) {
+                               rte_flow_error_set(error, ENOTSUP,
+                                                  RTE_FLOW_ERROR_TYPE_ITEM,
+                                                  item,
+                                                  "VLAN TPID matching is not supported");
+                               return -rte_errno;
+                       }
+
+               MRVL_LOG(WARNING, "inner eth type mask is ignored");
+               ret = mrvl_parse_type(&spec_eth, &mask_eth, flow);
+               if (ret)
+                       goto out;
+       }
+
        return 0;
 out:
        rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
@@ -1125,7 +962,6 @@ out:
  * @param item Pointer to the flow item.
  * @param flow Pointer to the flow.
  * @param error Pointer to the flow error.
- * @param fields Pointer to the parsed parsed fields enum.
  * @returns 0 on success, negative value otherwise.
  */
 static int
@@ -1172,7 +1008,7 @@ mrvl_parse_ip4(const struct rte_flow_item *item,
        }
 
        if (mask->hdr.next_proto_id) {
-               RTE_LOG(WARNING, PMD, "next proto id mask is ignored\n");
+               MRVL_LOG(WARNING, "next proto id mask is ignored");
                ret = mrvl_parse_ip4_proto(spec, mask, flow);
                if (ret)
                        goto out;
@@ -1191,7 +1027,6 @@ out:
  * @param item Pointer to the flow item.
  * @param flow Pointer to the flow.
  * @param error Pointer to the flow error.
- * @param fields Pointer to the parsed parsed fields enum.
  * @returns 0 on success, negative value otherwise.
  */
 static int
@@ -1200,7 +1035,7 @@ mrvl_parse_ip6(const struct rte_flow_item *item,
               struct rte_flow_error *error)
 {
        const struct rte_flow_item_ipv6 *spec = NULL, *mask = NULL;
-       struct ipv6_hdr zero;
+       struct rte_ipv6_hdr zero;
        uint32_t flow_mask;
        int ret;
 
@@ -1243,7 +1078,7 @@ mrvl_parse_ip6(const struct rte_flow_item *item,
        }
 
        if (mask->hdr.proto) {
-               RTE_LOG(WARNING, PMD, "next header mask is ignored\n");
+               MRVL_LOG(WARNING, "next header mask is ignored");
                ret = mrvl_parse_ip6_next_hdr(spec, mask, flow);
                if (ret)
                        goto out;
@@ -1262,7 +1097,6 @@ out:
  * @param item Pointer to the flow item.
  * @param flow Pointer to the flow.
  * @param error Pointer to the flow error.
- * @param fields Pointer to the parsed parsed fields enum.
  * @returns 0 on success, negative value otherwise.
  */
 static int
@@ -1274,8 +1108,8 @@ mrvl_parse_tcp(const struct rte_flow_item *item,
        int ret;
 
        ret = mrvl_parse_init(item, (const void **)&spec, (const void **)&mask,
-                             &rte_flow_item_ipv4_mask,
-                             sizeof(struct rte_flow_item_ipv4), error);
+                             &rte_flow_item_tcp_mask,
+                             sizeof(struct rte_flow_item_tcp), error);
        if (ret)
                return ret;
 
@@ -1292,14 +1126,14 @@ mrvl_parse_tcp(const struct rte_flow_item *item,
        }
 
        if (mask->hdr.src_port) {
-               RTE_LOG(WARNING, PMD, "tcp sport mask is ignored\n");
+               MRVL_LOG(WARNING, "tcp sport mask is ignored");
                ret = mrvl_parse_tcp_sport(spec, mask, flow);
                if (ret)
                        goto out;
        }
 
        if (mask->hdr.dst_port) {
-               RTE_LOG(WARNING, PMD, "tcp dport mask is ignored\n");
+               MRVL_LOG(WARNING, "tcp dport mask is ignored");
                ret = mrvl_parse_tcp_dport(spec, mask, flow);
                if (ret)
                        goto out;
@@ -1318,7 +1152,6 @@ out:
  * @param item Pointer to the flow item.
  * @param flow Pointer to the flow.
  * @param error Pointer to the flow error.
- * @param fields Pointer to the parsed parsed fields enum.
  * @returns 0 on success, negative value otherwise.
  */
 static int
@@ -1330,8 +1163,8 @@ mrvl_parse_udp(const struct rte_flow_item *item,
        int ret;
 
        ret = mrvl_parse_init(item, (const void **)&spec, (const void **)&mask,
-                             &rte_flow_item_ipv4_mask,
-                             sizeof(struct rte_flow_item_ipv4), error);
+                             &rte_flow_item_udp_mask,
+                             sizeof(struct rte_flow_item_udp), error);
        if (ret)
                return ret;
 
@@ -1343,14 +1176,14 @@ mrvl_parse_udp(const struct rte_flow_item *item,
        }
 
        if (mask->hdr.src_port) {
-               RTE_LOG(WARNING, PMD, "udp sport mask is ignored\n");
+               MRVL_LOG(WARNING, "udp sport mask is ignored");
                ret = mrvl_parse_udp_sport(spec, mask, flow);
                if (ret)
                        goto out;
        }
 
        if (mask->hdr.dst_port) {
-               RTE_LOG(WARNING, PMD, "udp dport mask is ignored\n");
+               MRVL_LOG(WARNING, "udp dport mask is ignored");
                ret = mrvl_parse_udp_dport(spec, mask, flow);
                if (ret)
                        goto out;
@@ -1363,857 +1196,280 @@ out:
        return -rte_errno;
 }
 
-/**
- * Parse flow pattern composed of the the eth item.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
 static int
-mrvl_parse_pattern_eth(const struct rte_flow_item pattern[],
-                      struct rte_flow *flow,
-                      struct rte_flow_error *error)
+mrvl_string_to_hex_values(const uint8_t *input_string,
+                         uint8_t *hex_key,
+                         uint8_t *length)
 {
-       return mrvl_parse_eth(pattern, flow, error);
-}
+       char tmp_arr[3], tmp_string[MRVL_CLS_STR_SIZE_MAX], *string_iter;
+       int i;
 
-/**
- * Parse flow pattern composed of the eth and vlan items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static int
-mrvl_parse_pattern_eth_vlan(const struct rte_flow_item pattern[],
-                           struct rte_flow *flow,
-                           struct rte_flow_error *error)
-{
-       const struct rte_flow_item *item = mrvl_next_item(pattern);
-       int ret;
+       strcpy(tmp_string, (const char *)input_string);
+       string_iter = tmp_string;
 
-       ret = mrvl_parse_eth(item, flow, error);
-       if (ret)
-               return ret;
+       string_iter += 2; /* skip the '0x' */
+       *length = ((*length - 2) + 1) / 2;
 
-       item = mrvl_next_item(item + 1);
+       for (i = 0; i < *length; i++) {
+               strncpy(tmp_arr, string_iter, 2);
+               tmp_arr[2] = '\0';
+               if (get_val_securely8(tmp_arr, 16,
+                                     &hex_key[*length - 1 - i]) < 0)
+                       return -1;
+               string_iter += 2;
+       }
 
-       return mrvl_parse_vlan(item, flow, error);
+       return 0;
 }
 
 /**
- * Parse flow pattern composed of the eth, vlan and ip4/ip6 items.
+ * Parse raw flow item.
  *
- * @param pattern Pointer to the flow pattern table.
+ * @param item Pointer to the flow item.
  * @param flow Pointer to the flow.
  * @param error Pointer to the flow error.
- * @param ip6 1 to parse ip6 item, 0 to parse ip4 item.
- * @returns 0 in case of success, negative value otherwise.
+ * @returns 0 on success, negative value otherwise.
  */
 static int
-mrvl_parse_pattern_eth_vlan_ip4_ip6(const struct rte_flow_item pattern[],
-                                   struct rte_flow *flow,
-                                   struct rte_flow_error *error, int ip6)
+mrvl_parse_raw(const struct rte_flow_item *item,
+              struct rte_flow *flow,
+              struct rte_flow_error *error)
 {
-       const struct rte_flow_item *item = mrvl_next_item(pattern);
+       const struct rte_flow_item_raw *spec = NULL, *mask = NULL;
+       struct pp2_cls_rule_key_field *key_field;
+       struct mv_net_udf *udf_params;
+       uint8_t length;
        int ret;
 
-       ret = mrvl_parse_eth(item, flow, error);
+       ret = mrvl_parse_init(item, (const void **)&spec, (const void **)&mask,
+                             &rte_flow_item_raw_mask,
+                             sizeof(struct rte_flow_item_raw), error);
        if (ret)
                return ret;
 
-       item = mrvl_next_item(item + 1);
-       ret = mrvl_parse_vlan(item, flow, error);
-       if (ret)
-               return ret;
+       if (!spec->pattern) {
+               rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
+                                  NULL, "pattern pointer MUST be given\n");
+               return -rte_errno;
+       }
+
+       /* Only hex string is supported; so, it must start with '0x' */
+       if (strncmp((const char *)spec->pattern, "0x", 2) != 0)  {
+               rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
+                                  NULL, "'pattern' string must start with '0x'\n");
+               return -rte_errno;
+       }
+
+       if (mask->pattern &&
+           strncmp((const char *)mask->pattern, "0x", 2) != 0)  {
+               rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
+                                  NULL, "'mask-pattern' string must start with '0x'\n");
+               return -rte_errno;
+       }
+
+       if (mask->search && spec->search) {
+               rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
+                                  NULL, "'search' option must be '0'\n");
+               return -rte_errno;
+       }
+
+       if (mask->offset && spec->offset != 0) {
+               rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
+                                  NULL, "'offset' option must be '0'\n");
+               return -rte_errno;
+       }
+
+       if (!mask->relative || !spec->relative) {
+               rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
+                                  NULL, "'relative' option must be given and enabled\n");
+               return -rte_errno;
+       }
+
+       length = spec->length & mask->length;
+       if (!length) {
+               rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
+                                  NULL, "'length' option must be given bigger than '0'\n");
+               return -rte_errno;
+       }
+
+       key_field = &flow->rule.fields[flow->rule.num_fields];
+       mrvl_alloc_key_mask(key_field);
+
+       /* pattern and length refer to string bytes. we need to convert it to
+        * values.
+        */
+       key_field->size = length;
+       ret = mrvl_string_to_hex_values(spec->pattern, key_field->key,
+                                       &key_field->size);
+       if (ret) {
+               rte_flow_error_set(error, EINVAL,
+                                  RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
+                                  NULL,
+                                  "can't convert pattern from string to hex\n");
+               return -rte_errno;
+       }
+       if (mask->pattern) {
+               ret = mrvl_string_to_hex_values(mask->pattern, key_field->mask,
+                                               &length);
+               if (ret) {
+                       rte_flow_error_set(error, EINVAL,
+                                          RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
+                                          NULL,
+                                          "can't convert mask-pattern from string to hex\n");
+                       return -rte_errno;
+               }
+       } else {
+               rte_free(key_field->mask);
+               key_field->mask = NULL;
+       }
+
+       flow->table_key.proto_field[flow->rule.num_fields].proto =
+               MV_NET_UDF;
+       udf_params =
+               &flow->table_key.proto_field[flow->rule.num_fields].field.udf;
+       udf_params->id = flow->next_udf_id++;
+       udf_params->size = key_field->size;
+       flow->table_key.key_size += key_field->size;
 
-       item = mrvl_next_item(item + 1);
+       flow->rule.num_fields += 1;
 
-       return ip6 ? mrvl_parse_ip6(item, flow, error) :
-                    mrvl_parse_ip4(item, flow, error);
+       return 0;
 }
 
 /**
- * Parse flow pattern composed of the eth, vlan and ipv4 items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
+ * Structure used to map specific flow pattern to the pattern parse callback
+ * which will iterate over each pattern item and extract relevant data.
  */
-static int
-mrvl_parse_pattern_eth_vlan_ip4(const struct rte_flow_item pattern[],
-                               struct rte_flow *flow,
-                               struct rte_flow_error *error)
-{
-       return mrvl_parse_pattern_eth_vlan_ip4_ip6(pattern, flow, error, 0);
-}
+static const struct {
+       const enum rte_flow_item_type pattern_type;
+       int (*parse)(const struct rte_flow_item *pattern,
+               struct rte_flow *flow,
+               struct rte_flow_error *error);
+} mrvl_patterns[] = {
+       { RTE_FLOW_ITEM_TYPE_ETH, mrvl_parse_eth },
+       { RTE_FLOW_ITEM_TYPE_VLAN, mrvl_parse_vlan },
+       { RTE_FLOW_ITEM_TYPE_IPV4, mrvl_parse_ip4 },
+       { RTE_FLOW_ITEM_TYPE_IPV6, mrvl_parse_ip6 },
+       { RTE_FLOW_ITEM_TYPE_TCP, mrvl_parse_tcp },
+       { RTE_FLOW_ITEM_TYPE_UDP, mrvl_parse_udp },
+       { RTE_FLOW_ITEM_TYPE_RAW, mrvl_parse_raw },
+       { RTE_FLOW_ITEM_TYPE_END, NULL }
+};
 
 /**
- * Parse flow pattern composed of the eth, vlan and ipv6 items.
+ * Parse flow attribute.
  *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
+ * This will check whether the provided attribute's flags are supported.
+ *
+ * @param priv Unused
+ * @param attr Pointer to the flow attribute.
+ * @param flow Unused
  * @param error Pointer to the flow error.
  * @returns 0 in case of success, negative value otherwise.
  */
 static int
-mrvl_parse_pattern_eth_vlan_ip6(const struct rte_flow_item pattern[],
-                               struct rte_flow *flow,
-                               struct rte_flow_error *error)
+mrvl_flow_parse_attr(struct mrvl_priv *priv __rte_unused,
+                    const struct rte_flow_attr *attr,
+                    struct rte_flow *flow __rte_unused,
+                    struct rte_flow_error *error)
 {
-       return mrvl_parse_pattern_eth_vlan_ip4_ip6(pattern, flow, error, 1);
+       if (!attr) {
+               rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR,
+                                  NULL, "NULL attribute");
+               return -rte_errno;
+       }
+
+       if (attr->group) {
+               rte_flow_error_set(error, ENOTSUP,
+                                  RTE_FLOW_ERROR_TYPE_ATTR_GROUP, NULL,
+                                  "Groups are not supported");
+               return -rte_errno;
+       }
+       if (attr->priority) {
+               rte_flow_error_set(error, ENOTSUP,
+                                  RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, NULL,
+                                  "Priorities are not supported");
+               return -rte_errno;
+       }
+       if (!attr->ingress) {
+               rte_flow_error_set(error, ENOTSUP,
+                                  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, NULL,
+                                  "Only ingress is supported");
+               return -rte_errno;
+       }
+       if (attr->egress) {
+               rte_flow_error_set(error, ENOTSUP,
+                                  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
+                                  "Egress is not supported");
+               return -rte_errno;
+       }
+       if (attr->transfer) {
+               rte_flow_error_set(error, ENOTSUP,
+                                  RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER, NULL,
+                                  "Transfer is not supported");
+               return -rte_errno;
+       }
+
+       return 0;
 }
 
 /**
- * Parse flow pattern composed of the eth and ip4/ip6 items.
+ * Parse flow pattern.
+ *
+ * Specific classifier rule will be created as well.
  *
- * @param pattern Pointer to the flow pattern table.
+ * @param priv Unused
+ * @param pattern Pointer to the flow pattern.
  * @param flow Pointer to the flow.
  * @param error Pointer to the flow error.
- * @param ip6 1 to parse ip6 item, 0 to parse ip4 item.
  * @returns 0 in case of success, negative value otherwise.
  */
 static int
-mrvl_parse_pattern_eth_ip4_ip6(const struct rte_flow_item pattern[],
-                              struct rte_flow *flow,
-                              struct rte_flow_error *error, int ip6)
+mrvl_flow_parse_pattern(struct mrvl_priv *priv __rte_unused,
+                       const struct rte_flow_item pattern[],
+                       struct rte_flow *flow,
+                       struct rte_flow_error *error)
 {
-       const struct rte_flow_item *item = mrvl_next_item(pattern);
+       unsigned int i, j;
        int ret;
 
-       ret = mrvl_parse_eth(item, flow, error);
-       if (ret)
-               return ret;
-
-       item = mrvl_next_item(item + 1);
-
-       return ip6 ? mrvl_parse_ip6(item, flow, error) :
-                    mrvl_parse_ip4(item, flow, error);
-}
+       for (i = 0; pattern[i].type != RTE_FLOW_ITEM_TYPE_END; i++) {
+               if (pattern[i].type == RTE_FLOW_ITEM_TYPE_VOID)
+                       continue;
+               for (j = 0; mrvl_patterns[j].pattern_type !=
+                       RTE_FLOW_ITEM_TYPE_END; j++) {
+                       if (mrvl_patterns[j].pattern_type != pattern[i].type)
+                               continue;
+
+                       if (flow->rule.num_fields >=
+                           PP2_CLS_TBL_MAX_NUM_FIELDS) {
+                               rte_flow_error_set(error, ENOSPC,
+                                                  RTE_FLOW_ERROR_TYPE_ITEM_NUM,
+                                                  NULL,
+                                                  "too many pattern (max %d)");
+                               return -rte_errno;
+                       }
 
-/**
- * Parse flow pattern composed of the eth and ipv4 items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_eth_ip4(const struct rte_flow_item pattern[],
-                          struct rte_flow *flow,
-                          struct rte_flow_error *error)
-{
-       return mrvl_parse_pattern_eth_ip4_ip6(pattern, flow, error, 0);
-}
-
-/**
- * Parse flow pattern composed of the eth and ipv6 items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_eth_ip6(const struct rte_flow_item pattern[],
-                          struct rte_flow *flow,
-                          struct rte_flow_error *error)
-{
-       return mrvl_parse_pattern_eth_ip4_ip6(pattern, flow, error, 1);
-}
-
-/**
- * Parse flow pattern composed of the eth, ip4 and tcp/udp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @param tcp 1 to parse tcp item, 0 to parse udp item.
- * @returns 0 in case of success, negative value otherwise.
- */
-static int
-mrvl_parse_pattern_eth_ip4_tcp_udp(const struct rte_flow_item pattern[],
-                                  struct rte_flow *flow,
-                                  struct rte_flow_error *error, int tcp)
-{
-       const struct rte_flow_item *item = mrvl_next_item(pattern);
-       int ret;
-
-       ret = mrvl_parse_pattern_eth_ip4_ip6(pattern, flow, error, 0);
-       if (ret)
-               return ret;
-
-       item = mrvl_next_item(item + 1);
-       item = mrvl_next_item(item + 1);
-
-       if (tcp)
-               return mrvl_parse_tcp(item, flow, error);
-
-       return mrvl_parse_udp(item, flow, error);
-}
-
-/**
- * Parse flow pattern composed of the eth, ipv4 and tcp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_eth_ip4_tcp(const struct rte_flow_item pattern[],
-                              struct rte_flow *flow,
-                              struct rte_flow_error *error)
-{
-       return mrvl_parse_pattern_eth_ip4_tcp_udp(pattern, flow, error, 1);
-}
-
-/**
- * Parse flow pattern composed of the eth, ipv4 and udp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_eth_ip4_udp(const struct rte_flow_item pattern[],
-                              struct rte_flow *flow,
-                              struct rte_flow_error *error)
-{
-       return mrvl_parse_pattern_eth_ip4_tcp_udp(pattern, flow, error, 0);
-}
-
-/**
- * Parse flow pattern composed of the eth, ipv6 and tcp/udp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @param tcp 1 to parse tcp item, 0 to parse udp item.
- * @returns 0 in case of success, negative value otherwise.
- */
-static int
-mrvl_parse_pattern_eth_ip6_tcp_udp(const struct rte_flow_item pattern[],
-                                  struct rte_flow *flow,
-                                  struct rte_flow_error *error, int tcp)
-{
-       const struct rte_flow_item *item = mrvl_next_item(pattern);
-       int ret;
-
-       ret = mrvl_parse_pattern_eth_ip4_ip6(pattern, flow, error, 1);
-       if (ret)
-               return ret;
-
-       item = mrvl_next_item(item + 1);
-       item = mrvl_next_item(item + 1);
-
-       if (tcp)
-               return mrvl_parse_tcp(item, flow, error);
-
-       return mrvl_parse_udp(item, flow, error);
-}
-
-/**
- * Parse flow pattern composed of the eth, ipv6 and tcp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_eth_ip6_tcp(const struct rte_flow_item pattern[],
-                              struct rte_flow *flow,
-                              struct rte_flow_error *error)
-{
-       return mrvl_parse_pattern_eth_ip6_tcp_udp(pattern, flow, error, 1);
-}
-
-/**
- * Parse flow pattern composed of the eth, ipv6 and udp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_eth_ip6_udp(const struct rte_flow_item pattern[],
-                              struct rte_flow *flow,
-                              struct rte_flow_error *error)
-{
-       return mrvl_parse_pattern_eth_ip6_tcp_udp(pattern, flow, error, 0);
-}
-
-/**
- * Parse flow pattern composed of the vlan item.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static int
-mrvl_parse_pattern_vlan(const struct rte_flow_item pattern[],
-                           struct rte_flow *flow,
-                           struct rte_flow_error *error)
-{
-       const struct rte_flow_item *item = mrvl_next_item(pattern);
-
-       return mrvl_parse_vlan(item, flow, error);
-}
-
-/**
- * Parse flow pattern composed of the vlan and ip4/ip6 items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @param ip6 1 to parse ip6 item, 0 to parse ip4 item.
- * @returns 0 in case of success, negative value otherwise.
- */
-static int
-mrvl_parse_pattern_vlan_ip4_ip6(const struct rte_flow_item pattern[],
-                               struct rte_flow *flow,
-                               struct rte_flow_error *error, int ip6)
-{
-       const struct rte_flow_item *item = mrvl_next_item(pattern);
-       int ret;
-
-       ret = mrvl_parse_vlan(item, flow, error);
-       if (ret)
-               return ret;
-
-       item = mrvl_next_item(item + 1);
-
-       return ip6 ? mrvl_parse_ip6(item, flow, error) :
-                    mrvl_parse_ip4(item, flow, error);
-}
-
-/**
- * Parse flow pattern composed of the vlan and ipv4 items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_vlan_ip4(const struct rte_flow_item pattern[],
-                           struct rte_flow *flow,
-                           struct rte_flow_error *error)
-{
-       return mrvl_parse_pattern_vlan_ip4_ip6(pattern, flow, error, 0);
-}
-
-/**
- * Parse flow pattern composed of the vlan, ipv4 and tcp/udp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static int
-mrvl_parse_pattern_vlan_ip_tcp_udp(const struct rte_flow_item pattern[],
-                                  struct rte_flow *flow,
-                                  struct rte_flow_error *error, int tcp)
-{
-       const struct rte_flow_item *item = mrvl_next_item(pattern);
-       int ret;
-
-       ret = mrvl_parse_pattern_vlan_ip4_ip6(pattern, flow, error, 0);
-       if (ret)
-               return ret;
-
-       item = mrvl_next_item(item + 1);
-       item = mrvl_next_item(item + 1);
-
-       if (tcp)
-               return mrvl_parse_tcp(item, flow, error);
-
-       return mrvl_parse_udp(item, flow, error);
-}
-
-/**
- * Parse flow pattern composed of the vlan, ipv4 and tcp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_vlan_ip_tcp(const struct rte_flow_item pattern[],
-                              struct rte_flow *flow,
-                              struct rte_flow_error *error)
-{
-       return mrvl_parse_pattern_vlan_ip_tcp_udp(pattern, flow, error, 1);
-}
-
-/**
- * Parse flow pattern composed of the vlan, ipv4 and udp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_vlan_ip_udp(const struct rte_flow_item pattern[],
-                              struct rte_flow *flow,
-                              struct rte_flow_error *error)
-{
-       return mrvl_parse_pattern_vlan_ip_tcp_udp(pattern, flow, error, 0);
-}
-
-/**
- * Parse flow pattern composed of the vlan and ipv6 items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_vlan_ip6(const struct rte_flow_item pattern[],
-                           struct rte_flow *flow,
-                           struct rte_flow_error *error)
-{
-       return mrvl_parse_pattern_vlan_ip4_ip6(pattern, flow, error, 1);
-}
-
-/**
- * Parse flow pattern composed of the vlan, ipv6 and tcp/udp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static int
-mrvl_parse_pattern_vlan_ip6_tcp_udp(const struct rte_flow_item pattern[],
-                                   struct rte_flow *flow,
-                                   struct rte_flow_error *error, int tcp)
-{
-       const struct rte_flow_item *item = mrvl_next_item(pattern);
-       int ret;
-
-       ret = mrvl_parse_pattern_vlan_ip4_ip6(pattern, flow, error, 1);
-       if (ret)
-               return ret;
-
-       item = mrvl_next_item(item + 1);
-       item = mrvl_next_item(item + 1);
-
-       if (tcp)
-               return mrvl_parse_tcp(item, flow, error);
-
-       return mrvl_parse_udp(item, flow, error);
-}
-
-/**
- * Parse flow pattern composed of the vlan, ipv6 and tcp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_vlan_ip6_tcp(const struct rte_flow_item pattern[],
-                               struct rte_flow *flow,
-                               struct rte_flow_error *error)
-{
-       return mrvl_parse_pattern_vlan_ip6_tcp_udp(pattern, flow, error, 1);
-}
-
-/**
- * Parse flow pattern composed of the vlan, ipv6 and udp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_vlan_ip6_udp(const struct rte_flow_item pattern[],
-                               struct rte_flow *flow,
-                               struct rte_flow_error *error)
-{
-       return mrvl_parse_pattern_vlan_ip6_tcp_udp(pattern, flow, error, 0);
-}
-
-/**
- * Parse flow pattern composed of the ip4/ip6 item.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @param ip6 1 to parse ip6 item, 0 to parse ip4 item.
- * @returns 0 in case of success, negative value otherwise.
- */
-static int
-mrvl_parse_pattern_ip4_ip6(const struct rte_flow_item pattern[],
-                      struct rte_flow *flow,
-                      struct rte_flow_error *error, int ip6)
-{
-       const struct rte_flow_item *item = mrvl_next_item(pattern);
-
-       return ip6 ? mrvl_parse_ip6(item, flow, error) :
-                    mrvl_parse_ip4(item, flow, error);
-}
-
-/**
- * Parse flow pattern composed of the ipv4 item.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_ip4(const struct rte_flow_item pattern[],
-                      struct rte_flow *flow,
-                      struct rte_flow_error *error)
-{
-       return mrvl_parse_pattern_ip4_ip6(pattern, flow, error, 0);
-}
-
-/**
- * Parse flow pattern composed of the ipv6 item.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_ip6(const struct rte_flow_item pattern[],
-                      struct rte_flow *flow,
-                      struct rte_flow_error *error)
-{
-       return mrvl_parse_pattern_ip4_ip6(pattern, flow, error, 1);
-}
-
-/**
- * Parse flow pattern composed of the ip4/ip6 and tcp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @param ip6 1 to parse ip6 item, 0 to parse ip4 item.
- * @returns 0 in case of success, negative value otherwise.
- */
-static int
-mrvl_parse_pattern_ip4_ip6_tcp(const struct rte_flow_item pattern[],
-                          struct rte_flow *flow,
-                          struct rte_flow_error *error, int ip6)
-{
-       const struct rte_flow_item *item = mrvl_next_item(pattern);
-       int ret;
-
-       ret = ip6 ? mrvl_parse_ip6(item, flow, error) :
-                   mrvl_parse_ip4(item, flow, error);
-       if (ret)
-               return ret;
-
-       item = mrvl_next_item(item + 1);
-
-       return mrvl_parse_tcp(item, flow, error);
-}
-
-/**
- * Parse flow pattern composed of the ipv4 and tcp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_ip4_tcp(const struct rte_flow_item pattern[],
-                          struct rte_flow *flow,
-                          struct rte_flow_error *error)
-{
-       return mrvl_parse_pattern_ip4_ip6_tcp(pattern, flow, error, 0);
-}
-
-/**
- * Parse flow pattern composed of the ipv6 and tcp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_ip6_tcp(const struct rte_flow_item pattern[],
-                          struct rte_flow *flow,
-                          struct rte_flow_error *error)
-{
-       return mrvl_parse_pattern_ip4_ip6_tcp(pattern, flow, error, 1);
-}
-
-/**
- * Parse flow pattern composed of the ipv4/ipv6 and udp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static int
-mrvl_parse_pattern_ip4_ip6_udp(const struct rte_flow_item pattern[],
-                          struct rte_flow *flow,
-                          struct rte_flow_error *error, int ip6)
-{
-       const struct rte_flow_item *item = mrvl_next_item(pattern);
-       int ret;
-
-       ret = ip6 ? mrvl_parse_ip6(item, flow, error) :
-                   mrvl_parse_ip4(item, flow, error);
-       if (ret)
-               return ret;
-
-       item = mrvl_next_item(item + 1);
-
-       return mrvl_parse_udp(item, flow, error);
-}
-
-/**
- * Parse flow pattern composed of the ipv4 and udp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_ip4_udp(const struct rte_flow_item pattern[],
-                          struct rte_flow *flow,
-                          struct rte_flow_error *error)
-{
-       return mrvl_parse_pattern_ip4_ip6_udp(pattern, flow, error, 0);
-}
-
-/**
- * Parse flow pattern composed of the ipv6 and udp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_ip6_udp(const struct rte_flow_item pattern[],
-                          struct rte_flow *flow,
-                          struct rte_flow_error *error)
-{
-       return mrvl_parse_pattern_ip4_ip6_udp(pattern, flow, error, 1);
-}
-
-/**
- * Parse flow pattern composed of the tcp item.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static int
-mrvl_parse_pattern_tcp(const struct rte_flow_item pattern[],
-                      struct rte_flow *flow,
-                      struct rte_flow_error *error)
-{
-       const struct rte_flow_item *item = mrvl_next_item(pattern);
-
-       return mrvl_parse_tcp(item, flow, error);
-}
-
-/**
- * Parse flow pattern composed of the udp item.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static int
-mrvl_parse_pattern_udp(const struct rte_flow_item pattern[],
-                      struct rte_flow *flow,
-                      struct rte_flow_error *error)
-{
-       const struct rte_flow_item *item = mrvl_next_item(pattern);
-
-       return mrvl_parse_udp(item, flow, error);
-}
-
-/**
- * Structure used to map specific flow pattern to the pattern parse callback
- * which will iterate over each pattern item and extract relevant data.
- */
-static const struct {
-       const enum rte_flow_item_type *pattern;
-       int (*parse)(const struct rte_flow_item pattern[],
-               struct rte_flow *flow,
-               struct rte_flow_error *error);
-} mrvl_patterns[] = {
-       { pattern_eth, mrvl_parse_pattern_eth },
-       { pattern_eth_vlan, mrvl_parse_pattern_eth_vlan },
-       { pattern_eth_vlan_ip, mrvl_parse_pattern_eth_vlan_ip4 },
-       { pattern_eth_vlan_ip6, mrvl_parse_pattern_eth_vlan_ip6 },
-       { pattern_eth_ip4, mrvl_parse_pattern_eth_ip4 },
-       { pattern_eth_ip4_tcp, mrvl_parse_pattern_eth_ip4_tcp },
-       { pattern_eth_ip4_udp, mrvl_parse_pattern_eth_ip4_udp },
-       { pattern_eth_ip6, mrvl_parse_pattern_eth_ip6 },
-       { pattern_eth_ip6_tcp, mrvl_parse_pattern_eth_ip6_tcp },
-       { pattern_eth_ip6_udp, mrvl_parse_pattern_eth_ip6_udp },
-       { pattern_vlan, mrvl_parse_pattern_vlan },
-       { pattern_vlan_ip, mrvl_parse_pattern_vlan_ip4 },
-       { pattern_vlan_ip_tcp, mrvl_parse_pattern_vlan_ip_tcp },
-       { pattern_vlan_ip_udp, mrvl_parse_pattern_vlan_ip_udp },
-       { pattern_vlan_ip6, mrvl_parse_pattern_vlan_ip6 },
-       { pattern_vlan_ip6_tcp, mrvl_parse_pattern_vlan_ip6_tcp },
-       { pattern_vlan_ip6_udp, mrvl_parse_pattern_vlan_ip6_udp },
-       { pattern_ip, mrvl_parse_pattern_ip4 },
-       { pattern_ip_tcp, mrvl_parse_pattern_ip4_tcp },
-       { pattern_ip_udp, mrvl_parse_pattern_ip4_udp },
-       { pattern_ip6, mrvl_parse_pattern_ip6 },
-       { pattern_ip6_tcp, mrvl_parse_pattern_ip6_tcp },
-       { pattern_ip6_udp, mrvl_parse_pattern_ip6_udp },
-       { pattern_tcp, mrvl_parse_pattern_tcp },
-       { pattern_udp, mrvl_parse_pattern_udp }
-};
-
-/**
- * Check whether provided pattern matches any of the supported ones.
- *
- * @param type_pattern Pointer to the pattern type.
- * @param item_pattern Pointer to the flow pattern.
- * @returns 1 in case of success, 0 value otherwise.
- */
-static int
-mrvl_patterns_match(const enum rte_flow_item_type *type_pattern,
-                   const struct rte_flow_item *item_pattern)
-{
-       const enum rte_flow_item_type *type = type_pattern;
-       const struct rte_flow_item *item = item_pattern;
-
-       for (;;) {
-               if (item->type == RTE_FLOW_ITEM_TYPE_VOID) {
-                       item++;
-                       continue;
-               }
-
-               if (*type == RTE_FLOW_ITEM_TYPE_END ||
-                   item->type == RTE_FLOW_ITEM_TYPE_END)
-                       break;
-
-               if (*type != item->type)
+                       ret = mrvl_patterns[j].parse(&pattern[i], flow, error);
+                       if (ret) {
+                               mrvl_free_all_key_mask(&flow->rule);
+                               return ret;
+                       }
                        break;
-
-               item++;
-               type++;
-       }
-
-       return *type == item->type;
-}
-
-/**
- * Parse flow attribute.
- *
- * This will check whether the provided attribute's flags are supported.
- *
- * @param priv Unused
- * @param attr Pointer to the flow attribute.
- * @param flow Unused
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static int
-mrvl_flow_parse_attr(struct mrvl_priv *priv __rte_unused,
-                    const struct rte_flow_attr *attr,
-                    struct rte_flow *flow __rte_unused,
-                    struct rte_flow_error *error)
-{
-       if (!attr) {
-               rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR,
-                                  NULL, "NULL attribute");
-               return -rte_errno;
+               }
+               if (mrvl_patterns[j].pattern_type == RTE_FLOW_ITEM_TYPE_END) {
+                       rte_flow_error_set(error, ENOTSUP,
+                                          RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+                                          "Unsupported pattern");
+                       return -rte_errno;
+               }
        }
 
-       if (attr->group) {
-               rte_flow_error_set(error, ENOTSUP,
-                                  RTE_FLOW_ERROR_TYPE_ATTR_GROUP, NULL,
-                                  "Groups are not supported");
-               return -rte_errno;
-       }
-       if (attr->priority) {
-               rte_flow_error_set(error, ENOTSUP,
-                                  RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, NULL,
-                                  "Priorities are not supported");
-               return -rte_errno;
-       }
-       if (!attr->ingress) {
-               rte_flow_error_set(error, ENOTSUP,
-                                  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, NULL,
-                                  "Only ingress is supported");
-               return -rte_errno;
-       }
-       if (attr->egress) {
-               rte_flow_error_set(error, ENOTSUP,
-                                  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
-                                  "Egress is not supported");
-               return -rte_errno;
-       }
+       flow->table_key.num_fields = flow->rule.num_fields;
 
        return 0;
 }
 
-/**
- * Parse flow pattern.
- *
- * Specific classifier rule will be created as well.
- *
- * @param priv Unused
- * @param pattern Pointer to the flow pattern.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static int
-mrvl_flow_parse_pattern(struct mrvl_priv *priv __rte_unused,
-                       const struct rte_flow_item pattern[],
-                       struct rte_flow *flow,
-                       struct rte_flow_error *error)
-{
-       unsigned int i;
-       int ret;
-
-       for (i = 0; i < RTE_DIM(mrvl_patterns); i++) {
-               if (!mrvl_patterns_match(mrvl_patterns[i].pattern, pattern))
-                       continue;
-
-               ret = mrvl_patterns[i].parse(pattern, flow, error);
-               if (ret)
-                       mrvl_free_all_key_mask(&flow->rule);
-
-               return ret;
-       }
-
-       rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
-                          "Unsupported pattern");
-
-       return -rte_errno;
-}
-
 /**
  * Parse flow actions.
  *
@@ -2260,8 +1516,8 @@ mrvl_flow_parse_actions(struct mrvl_priv *priv,
                                 * Unknown TC mapping, mapping will not have
                                 * a correct queue.
                                 */
-                               RTE_LOG(ERR, PMD,
-                                       "Unknown TC mapping for queue %hu eth%hhu\n",
+                               MRVL_LOG(ERR,
+                                       "Unknown TC mapping for queue %hu eth%hhu",
                                        q->index, priv->ppio_id);
 
                                rte_flow_error_set(error, EFAULT,
@@ -2270,8 +1526,8 @@ mrvl_flow_parse_actions(struct mrvl_priv *priv,
                                return -rte_errno;
                        }
 
-                       RTE_LOG(DEBUG, PMD,
-                               "Action: Assign packets to queue %d, tc:%d, q:%d\n",
+                       MRVL_LOG(DEBUG,
+                               "Action: Assign packets to queue %d, tc:%d, q:%d",
                                q->index, priv->rxq_map[q->index].tc,
                                priv->rxq_map[q->index].inq);
 
@@ -2280,19 +1536,59 @@ mrvl_flow_parse_actions(struct mrvl_priv *priv,
                        flow->action.type = PP2_CLS_TBL_ACT_DONE;
                        flow->action.cos = &flow->cos;
                        specified++;
+               } else if (action->type == RTE_FLOW_ACTION_TYPE_METER) {
+                       const struct rte_flow_action_meter *meter;
+                       struct mrvl_mtr *mtr;
+
+                       meter = action->conf;
+                       if (!meter)
+                               return -rte_flow_error_set(error, EINVAL,
+                                               RTE_FLOW_ERROR_TYPE_ACTION,
+                                               NULL, "Invalid meter\n");
+
+                       LIST_FOREACH(mtr, &priv->mtrs, next)
+                               if (mtr->mtr_id == meter->mtr_id)
+                                       break;
+
+                       if (!mtr)
+                               return -rte_flow_error_set(error, EINVAL,
+                                               RTE_FLOW_ERROR_TYPE_ACTION,
+                                               NULL,
+                                               "Meter id does not exist\n");
+
+                       if (!mtr->shared && mtr->refcnt)
+                               return -rte_flow_error_set(error, EPERM,
+                                               RTE_FLOW_ERROR_TYPE_ACTION,
+                                               NULL,
+                                               "Meter cannot be shared\n");
+
+                       /*
+                        * In case cos has already been set
+                        * do not modify it.
+                        */
+                       if (!flow->cos.ppio) {
+                               flow->cos.ppio = priv->ppio;
+                               flow->cos.tc = 0;
+                       }
+
+                       flow->action.type = PP2_CLS_TBL_ACT_DONE;
+                       flow->action.cos = &flow->cos;
+                       flow->action.plcr = mtr->enabled ? mtr->plcr : NULL;
+                       flow->mtr = mtr;
+                       mtr->refcnt++;
+                       specified++;
                } else {
                        rte_flow_error_set(error, ENOTSUP,
                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
                                           "Action not supported");
                        return -rte_errno;
                }
-
        }
 
        if (!specified) {
                rte_flow_error_set(error, EINVAL,
-                                  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-                                  NULL, "Action not specified");
+                                  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+                                  "Action not specified");
                return -rte_errno;
        }
 
@@ -2330,6 +1626,12 @@ mrvl_flow_parse(struct mrvl_priv *priv, const struct rte_flow_attr *attr,
        return mrvl_flow_parse_actions(priv, actions, flow, error);
 }
 
+/**
+ * Get engine type for the given flow.
+ *
+ * @param field Pointer to the flow.
+ * @returns The type of the engine.
+ */
 static inline enum pp2_cls_tbl_type
 mrvl_engine_type(const struct rte_flow *flow)
 {
@@ -2349,6 +1651,13 @@ mrvl_engine_type(const struct rte_flow *flow)
        return PP2_CLS_TBL_MASKABLE;
 }
 
+/**
+ * Create classifier table.
+ *
+ * @param dev Pointer to the device.
+ * @param flow Pointer to the very first flow.
+ * @returns 0 in case of success, negative value otherwise.
+ */
 static int
 mrvl_create_cls_table(struct rte_eth_dev *dev, struct rte_flow *first_flow)
 {
@@ -2364,139 +1673,15 @@ mrvl_create_cls_table(struct rte_eth_dev *dev, struct rte_flow *first_flow)
        memset(&priv->cls_tbl_params, 0, sizeof(priv->cls_tbl_params));
 
        priv->cls_tbl_params.type = mrvl_engine_type(first_flow);
-       RTE_LOG(INFO, PMD, "Setting cls search engine type to %s\n",
+       MRVL_LOG(INFO, "Setting cls search engine type to %s",
                        priv->cls_tbl_params.type == PP2_CLS_TBL_EXACT_MATCH ?
                        "exact" : "maskable");
        priv->cls_tbl_params.max_num_rules = MRVL_CLS_MAX_NUM_RULES;
        priv->cls_tbl_params.default_act.type = PP2_CLS_TBL_ACT_DONE;
        priv->cls_tbl_params.default_act.cos = &first_flow->cos;
-
-       if (first_flow->pattern & F_DMAC) {
-               key->proto_field[key->num_fields].proto = MV_NET_PROTO_ETH;
-               key->proto_field[key->num_fields].field.eth = MV_NET_ETH_F_DA;
-               key->key_size += 6;
-               key->num_fields += 1;
-       }
-
-       if (first_flow->pattern & F_SMAC) {
-               key->proto_field[key->num_fields].proto = MV_NET_PROTO_ETH;
-               key->proto_field[key->num_fields].field.eth = MV_NET_ETH_F_SA;
-               key->key_size += 6;
-               key->num_fields += 1;
-       }
-
-       if (first_flow->pattern & F_TYPE) {
-               key->proto_field[key->num_fields].proto = MV_NET_PROTO_ETH;
-               key->proto_field[key->num_fields].field.eth = MV_NET_ETH_F_TYPE;
-               key->key_size += 2;
-               key->num_fields += 1;
-       }
-
-       if (first_flow->pattern & F_VLAN_ID) {
-               key->proto_field[key->num_fields].proto = MV_NET_PROTO_VLAN;
-               key->proto_field[key->num_fields].field.vlan = MV_NET_VLAN_F_ID;
-               key->key_size += 2;
-               key->num_fields += 1;
-       }
-
-       if (first_flow->pattern & F_VLAN_PRI) {
-               key->proto_field[key->num_fields].proto = MV_NET_PROTO_VLAN;
-               key->proto_field[key->num_fields].field.vlan =
-                       MV_NET_VLAN_F_PRI;
-               key->key_size += 1;
-               key->num_fields += 1;
-       }
-
-       if (first_flow->pattern & F_IP4_TOS) {
-               key->proto_field[key->num_fields].proto = MV_NET_PROTO_IP4;
-               key->proto_field[key->num_fields].field.ipv4 = MV_NET_IP4_F_TOS;
-               key->key_size += 1;
-               key->num_fields += 1;
-       }
-
-       if (first_flow->pattern & F_IP4_SIP) {
-               key->proto_field[key->num_fields].proto = MV_NET_PROTO_IP4;
-               key->proto_field[key->num_fields].field.ipv4 = MV_NET_IP4_F_SA;
-               key->key_size += 4;
-               key->num_fields += 1;
-       }
-
-       if (first_flow->pattern & F_IP4_DIP) {
-               key->proto_field[key->num_fields].proto = MV_NET_PROTO_IP4;
-               key->proto_field[key->num_fields].field.ipv4 = MV_NET_IP4_F_DA;
-               key->key_size += 4;
-               key->num_fields += 1;
-       }
-
-       if (first_flow->pattern & F_IP4_PROTO) {
-               key->proto_field[key->num_fields].proto = MV_NET_PROTO_IP4;
-               key->proto_field[key->num_fields].field.ipv4 =
-                       MV_NET_IP4_F_PROTO;
-               key->key_size += 1;
-               key->num_fields += 1;
-       }
-
-       if (first_flow->pattern & F_IP6_SIP) {
-               key->proto_field[key->num_fields].proto = MV_NET_PROTO_IP6;
-               key->proto_field[key->num_fields].field.ipv6 = MV_NET_IP6_F_SA;
-               key->key_size += 16;
-               key->num_fields += 1;
-       }
-
-       if (first_flow->pattern & F_IP6_DIP) {
-               key->proto_field[key->num_fields].proto = MV_NET_PROTO_IP6;
-               key->proto_field[key->num_fields].field.ipv6 = MV_NET_IP6_F_DA;
-               key->key_size += 16;
-               key->num_fields += 1;
-       }
-
-       if (first_flow->pattern & F_IP6_FLOW) {
-               key->proto_field[key->num_fields].proto = MV_NET_PROTO_IP6;
-               key->proto_field[key->num_fields].field.ipv6 =
-                       MV_NET_IP6_F_FLOW;
-               key->key_size += 3;
-               key->num_fields += 1;
-       }
-
-       if (first_flow->pattern & F_IP6_NEXT_HDR) {
-               key->proto_field[key->num_fields].proto = MV_NET_PROTO_IP6;
-               key->proto_field[key->num_fields].field.ipv6 =
-                       MV_NET_IP6_F_NEXT_HDR;
-               key->key_size += 1;
-               key->num_fields += 1;
-       }
-
-       if (first_flow->pattern & F_TCP_SPORT) {
-               key->proto_field[key->num_fields].proto = MV_NET_PROTO_TCP;
-               key->proto_field[key->num_fields].field.tcp = MV_NET_TCP_F_SP;
-               key->key_size += 2;
-               key->num_fields += 1;
-       }
-
-       if (first_flow->pattern & F_TCP_DPORT) {
-               key->proto_field[key->num_fields].proto = MV_NET_PROTO_TCP;
-               key->proto_field[key->num_fields].field.tcp = MV_NET_TCP_F_DP;
-               key->key_size += 2;
-               key->num_fields += 1;
-       }
-
-       if (first_flow->pattern & F_UDP_SPORT) {
-               key->proto_field[key->num_fields].proto = MV_NET_PROTO_UDP;
-               key->proto_field[key->num_fields].field.tcp = MV_NET_TCP_F_SP;
-               key->key_size += 2;
-               key->num_fields += 1;
-       }
-
-       if (first_flow->pattern & F_UDP_DPORT) {
-               key->proto_field[key->num_fields].proto = MV_NET_PROTO_UDP;
-               key->proto_field[key->num_fields].field.udp = MV_NET_TCP_F_DP;
-               key->key_size += 2;
-               key->num_fields += 1;
-       }
+       memcpy(key, &first_flow->table_key, sizeof(struct pp2_cls_tbl_key));
 
        ret = pp2_cls_tbl_init(&priv->cls_tbl_params, &priv->cls_tbl);
-       if (!ret)
-               priv->cls_tbl_pattern = first_flow->pattern;
 
        return ret;
 }
@@ -2511,8 +1696,10 @@ mrvl_create_cls_table(struct rte_eth_dev *dev, struct rte_flow *first_flow)
 static inline int
 mrvl_flow_can_be_added(struct mrvl_priv *priv, const struct rte_flow *flow)
 {
-       return flow->pattern == priv->cls_tbl_pattern &&
-              mrvl_engine_type(flow) == priv->cls_tbl_params.type;
+       int same = memcmp(&flow->table_key, &priv->cls_tbl_params.key,
+                         sizeof(struct pp2_cls_tbl_key)) == 0;
+
+       return same && mrvl_engine_type(flow) == priv->cls_tbl_params.type;
 }
 
 /**
@@ -2629,13 +1816,18 @@ mrvl_flow_remove(struct mrvl_priv *priv, struct rte_flow *flow,
 
        mrvl_free_all_key_mask(&flow->rule);
 
+       if (flow->mtr) {
+               flow->mtr->refcnt--;
+               flow->mtr = NULL;
+       }
+
        return 0;
 }
 
 /**
  * DPDK flow destroy callback called when flow is to be removed.
  *
- * @param priv Pointer to the port's private data.
+ * @param dev Pointer to the device.
  * @param flow Pointer to the flow.
  * @param error Pointer to the flow error.
  * @returns 0 in case of success, negative value otherwise.
@@ -2721,6 +1913,11 @@ mrvl_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
                rte_free(flow);
        }
 
+       if (priv->cls_tbl) {
+               pp2_cls_tbl_deinit(priv->cls_tbl);
+               priv->cls_tbl = NULL;
+       }
+
        return 0;
 }
 
@@ -2757,3 +1954,27 @@ const struct rte_flow_ops mrvl_flow_ops = {
        .flush = mrvl_flow_flush,
        .isolate = mrvl_flow_isolate
 };
+
+/**
+ * Initialize flow resources.
+ *
+ * @param dev Pointer to the device.
+ */
+void
+mrvl_flow_init(struct rte_eth_dev *dev)
+{
+       struct mrvl_priv *priv = dev->data->dev_private;
+
+       LIST_INIT(&priv->flows);
+}
+
+/**
+ * Cleanup flow resources.
+ *
+ * @param dev Pointer to the device.
+ */
+void
+mrvl_flow_deinit(struct rte_eth_dev *dev)
+{
+       mrvl_flow_flush(dev, NULL);
+}