get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/73397/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 73397,
    "url": "https://patches.dpdk.org/api/patches/73397/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20200707092244.12791-17-hemant.agrawal@nxp.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20200707092244.12791-17-hemant.agrawal@nxp.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20200707092244.12791-17-hemant.agrawal@nxp.com",
    "date": "2020-07-07T09:22:31",
    "name": "[v2,16/29] net/dpaa2: support key extracts of flow API",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "53bb48df439cb882192d54ebe3df199a831f91cb",
    "submitter": {
        "id": 477,
        "url": "https://patches.dpdk.org/api/people/477/?format=api",
        "name": "Hemant Agrawal",
        "email": "hemant.agrawal@nxp.com"
    },
    "delegate": {
        "id": 319,
        "url": "https://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20200707092244.12791-17-hemant.agrawal@nxp.com/mbox/",
    "series": [
        {
            "id": 10842,
            "url": "https://patches.dpdk.org/api/series/10842/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=10842",
            "date": "2020-07-07T09:22:15",
            "name": "NXP DPAAx enhancements",
            "version": 2,
            "mbox": "https://patches.dpdk.org/series/10842/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/73397/comments/",
    "check": "warning",
    "checks": "https://patches.dpdk.org/api/patches/73397/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 7C22FA00BE;\n\tTue,  7 Jul 2020 11:30:34 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id F20601DDDA;\n\tTue,  7 Jul 2020 11:27:26 +0200 (CEST)",
            "from inva021.nxp.com (inva021.nxp.com [92.121.34.21])\n by dpdk.org (Postfix) with ESMTP id 1846D1DC74\n for <dev@dpdk.org>; Tue,  7 Jul 2020 11:27:11 +0200 (CEST)",
            "from inva021.nxp.com (localhost [127.0.0.1])\n by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id DA3D22008DD;\n Tue,  7 Jul 2020 11:27:10 +0200 (CEST)",
            "from invc005.ap-rdc01.nxp.com (invc005.ap-rdc01.nxp.com\n [165.114.16.14])\n by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id ECB7F2008CE;\n Tue,  7 Jul 2020 11:27:07 +0200 (CEST)",
            "from bf-netperf1.ap.freescale.net (bf-netperf1.ap.freescale.net\n [10.232.133.63])\n by invc005.ap-rdc01.nxp.com (Postfix) with ESMTP id EA107402F7;\n Tue,  7 Jul 2020 17:27:04 +0800 (SGT)"
        ],
        "From": "Hemant Agrawal <hemant.agrawal@nxp.com>",
        "To": "dev@dpdk.org",
        "Cc": "ferruh.yigit@intel.com,\n\tJun Yang <jun.yang@nxp.com>",
        "Date": "Tue,  7 Jul 2020 14:52:31 +0530",
        "Message-Id": "<20200707092244.12791-17-hemant.agrawal@nxp.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20200707092244.12791-1-hemant.agrawal@nxp.com>",
        "References": "<20200527132326.1382-1-hemant.agrawal@nxp.com>\n <20200707092244.12791-1-hemant.agrawal@nxp.com>",
        "X-Virus-Scanned": "ClamAV using ClamSMTP",
        "Subject": "[dpdk-dev] [PATCH v2 16/29] net/dpaa2: support key extracts of flow\n\tAPI",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "From: Jun Yang <jun.yang@nxp.com>\n\n1) Support QoS extracts and TC extracts for multiple TCs.\n\n2) Protocol type of L2 extract is used to parse L3.\n   Next protocol of L3 extract is used to parse L4.\n\n3) generic IP key extracts instead of IPv4 and IPv6 respectively.\n\n4) Special for IP address extracts:\n   Put IP(v4/v6) address extract(s)/rule(s) at the end of extracts array\n   to make rest fields at fixed poisition.\n\nSigned-off-by: Jun Yang <jun.yang@nxp.com>\n---\n drivers/net/dpaa2/dpaa2_ethdev.c |   35 +-\n drivers/net/dpaa2/dpaa2_ethdev.h |   43 +-\n drivers/net/dpaa2/dpaa2_flow.c   | 3628 +++++++++++++++++++++---------\n 3 files changed, 2665 insertions(+), 1041 deletions(-)",
    "diff": "diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c\nindex 8edd4b3cd..492b65840 100644\n--- a/drivers/net/dpaa2/dpaa2_ethdev.c\n+++ b/drivers/net/dpaa2/dpaa2_ethdev.c\n@@ -1,7 +1,7 @@\n /* * SPDX-License-Identifier: BSD-3-Clause\n  *\n  *   Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved.\n- *   Copyright 2016 NXP\n+ *   Copyright 2016-2020 NXP\n  *\n  */\n \n@@ -2501,23 +2501,41 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev)\n \teth_dev->tx_pkt_burst = dpaa2_dev_tx;\n \n \t/*Init fields w.r.t. classficaition*/\n-\tmemset(&priv->extract.qos_key_cfg, 0, sizeof(struct dpkg_profile_cfg));\n+\tmemset(&priv->extract.qos_key_extract, 0,\n+\t\tsizeof(struct dpaa2_key_extract));\n \tpriv->extract.qos_extract_param = (size_t)rte_malloc(NULL, 256, 64);\n \tif (!priv->extract.qos_extract_param) {\n \t\tDPAA2_PMD_ERR(\" Error(%d) in allocation resources for flow \"\n \t\t\t    \" classificaiton \", ret);\n \t\tgoto init_err;\n \t}\n+\tpriv->extract.qos_key_extract.key_info.ipv4_src_offset =\n+\t\tIP_ADDRESS_OFFSET_INVALID;\n+\tpriv->extract.qos_key_extract.key_info.ipv4_dst_offset =\n+\t\tIP_ADDRESS_OFFSET_INVALID;\n+\tpriv->extract.qos_key_extract.key_info.ipv6_src_offset =\n+\t\tIP_ADDRESS_OFFSET_INVALID;\n+\tpriv->extract.qos_key_extract.key_info.ipv6_dst_offset =\n+\t\tIP_ADDRESS_OFFSET_INVALID;\n+\n \tfor (i = 0; i < MAX_TCS; i++) {\n-\t\tmemset(&priv->extract.fs_key_cfg[i], 0,\n-\t\t\tsizeof(struct dpkg_profile_cfg));\n-\t\tpriv->extract.fs_extract_param[i] =\n+\t\tmemset(&priv->extract.tc_key_extract[i], 0,\n+\t\t\tsizeof(struct dpaa2_key_extract));\n+\t\tpriv->extract.tc_extract_param[i] =\n \t\t\t(size_t)rte_malloc(NULL, 256, 64);\n-\t\tif (!priv->extract.fs_extract_param[i]) {\n+\t\tif (!priv->extract.tc_extract_param[i]) {\n \t\t\tDPAA2_PMD_ERR(\" Error(%d) in allocation resources for flow classificaiton\",\n \t\t\t\t     ret);\n \t\t\tgoto init_err;\n \t\t}\n+\t\tpriv->extract.tc_key_extract[i].key_info.ipv4_src_offset =\n+\t\t\tIP_ADDRESS_OFFSET_INVALID;\n+\t\tpriv->extract.tc_key_extract[i].key_info.ipv4_dst_offset =\n+\t\t\tIP_ADDRESS_OFFSET_INVALID;\n+\t\tpriv->extract.tc_key_extract[i].key_info.ipv6_src_offset =\n+\t\t\tIP_ADDRESS_OFFSET_INVALID;\n+\t\tpriv->extract.tc_key_extract[i].key_info.ipv6_dst_offset =\n+\t\t\tIP_ADDRESS_OFFSET_INVALID;\n \t}\n \n \tret = dpni_set_max_frame_length(dpni_dev, CMD_PRI_LOW, priv->token,\n@@ -2593,8 +2611,9 @@ dpaa2_dev_uninit(struct rte_eth_dev *eth_dev)\n \trte_free(dpni);\n \n \tfor (i = 0; i < MAX_TCS; i++) {\n-\t\tif (priv->extract.fs_extract_param[i])\n-\t\t\trte_free((void *)(size_t)priv->extract.fs_extract_param[i]);\n+\t\tif (priv->extract.tc_extract_param[i])\n+\t\t\trte_free((void *)\n+\t\t\t\t(size_t)priv->extract.tc_extract_param[i]);\n \t}\n \n \tif (priv->extract.qos_extract_param)\ndiff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h\nindex c7fb6539f..030c625e3 100644\n--- a/drivers/net/dpaa2/dpaa2_ethdev.h\n+++ b/drivers/net/dpaa2/dpaa2_ethdev.h\n@@ -96,10 +96,39 @@ extern enum pmd_dpaa2_ts dpaa2_enable_ts;\n #define DPAA2_QOS_TABLE_RECONFIGURE\t1\n #define DPAA2_FS_TABLE_RECONFIGURE\t2\n \n+#define DPAA2_QOS_TABLE_IPADDR_EXTRACT 4\n+#define DPAA2_FS_TABLE_IPADDR_EXTRACT 8\n+\n+\n /*Externaly defined*/\n extern const struct rte_flow_ops dpaa2_flow_ops;\n extern enum rte_filter_type dpaa2_filter_type;\n \n+#define IP_ADDRESS_OFFSET_INVALID (-1)\n+\n+struct dpaa2_key_info {\n+\tuint8_t key_offset[DPKG_MAX_NUM_OF_EXTRACTS];\n+\tuint8_t key_size[DPKG_MAX_NUM_OF_EXTRACTS];\n+\t/* Special for IP address. */\n+\tint ipv4_src_offset;\n+\tint ipv4_dst_offset;\n+\tint ipv6_src_offset;\n+\tint ipv6_dst_offset;\n+\tuint8_t key_total_size;\n+};\n+\n+struct dpaa2_key_extract {\n+\tstruct dpkg_profile_cfg dpkg;\n+\tstruct dpaa2_key_info key_info;\n+};\n+\n+struct extract_s {\n+\tstruct dpaa2_key_extract qos_key_extract;\n+\tstruct dpaa2_key_extract tc_key_extract[MAX_TCS];\n+\tuint64_t qos_extract_param;\n+\tuint64_t tc_extract_param[MAX_TCS];\n+};\n+\n struct dpaa2_dev_priv {\n \tvoid *hw;\n \tint32_t hw_id;\n@@ -122,17 +151,9 @@ struct dpaa2_dev_priv {\n \tuint8_t max_cgs;\n \tuint8_t cgid_in_use[MAX_RX_QUEUES];\n \n-\tstruct pattern_s {\n-\t\tuint8_t item_count;\n-\t\tuint8_t pattern_type[DPKG_MAX_NUM_OF_EXTRACTS];\n-\t} pattern[MAX_TCS + 1];\n-\n-\tstruct extract_s {\n-\t\tstruct dpkg_profile_cfg qos_key_cfg;\n-\t\tstruct dpkg_profile_cfg fs_key_cfg[MAX_TCS];\n-\t\tuint64_t qos_extract_param;\n-\t\tuint64_t fs_extract_param[MAX_TCS];\n-\t} extract;\n+\tstruct extract_s extract;\n+\tuint8_t *qos_index;\n+\tuint8_t *fs_index;\n \n \tuint16_t ss_offset;\n \tuint64_t ss_iova;\ndiff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c\nindex 05d115c78..779cb64ab 100644\n--- a/drivers/net/dpaa2/dpaa2_flow.c\n+++ b/drivers/net/dpaa2/dpaa2_flow.c\n@@ -1,5 +1,5 @@\n-/* * SPDX-License-Identifier: BSD-3-Clause\n- *   Copyright 2018 NXP\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright 2018-2020 NXP\n  */\n \n #include <sys/queue.h>\n@@ -22,15 +22,44 @@\n #include <dpaa2_ethdev.h>\n #include <dpaa2_pmd_logs.h>\n \n+/* Workaround to discriminate the UDP/TCP/SCTP\n+ * with next protocol of l3.\n+ * MC/WRIOP are not able to identify\n+ * the l4 protocol with l4 ports.\n+ */\n+int mc_l4_port_identification;\n+\n+enum flow_rule_ipaddr_type {\n+\tFLOW_NONE_IPADDR,\n+\tFLOW_IPV4_ADDR,\n+\tFLOW_IPV6_ADDR\n+};\n+\n+struct flow_rule_ipaddr {\n+\tenum flow_rule_ipaddr_type ipaddr_type;\n+\tint qos_ipsrc_offset;\n+\tint qos_ipdst_offset;\n+\tint fs_ipsrc_offset;\n+\tint fs_ipdst_offset;\n+};\n+\n struct rte_flow {\n \tLIST_ENTRY(rte_flow) next; /**< Pointer to the next flow structure. */\n-\tstruct dpni_rule_cfg rule;\n+\tstruct dpni_rule_cfg qos_rule;\n+\tstruct dpni_rule_cfg fs_rule;\n+\tuint16_t qos_index;\n+\tuint16_t fs_index;\n \tuint8_t key_size;\n-\tuint8_t tc_id;\n+\tuint8_t tc_id; /** Traffic Class ID. */\n \tuint8_t flow_type;\n-\tuint8_t index;\n+\tuint8_t tc_index; /** index within this Traffic Class. */\n \tenum rte_flow_action_type action;\n \tuint16_t flow_id;\n+\t/* Special for IP address to specify the offset\n+\t * in key/mask.\n+\t */\n+\tstruct flow_rule_ipaddr ipaddr_rule;\n+\tstruct dpni_fs_action_cfg action_cfg;\n };\n \n static const\n@@ -54,166 +83,717 @@ enum rte_flow_action_type dpaa2_supported_action_type[] = {\n \tRTE_FLOW_ACTION_TYPE_RSS\n };\n \n+/* Max of enum rte_flow_item_type + 1, for both IPv4 and IPv6*/\n+#define DPAA2_FLOW_ITEM_TYPE_GENERIC_IP (RTE_FLOW_ITEM_TYPE_META + 1)\n+\n enum rte_filter_type dpaa2_filter_type = RTE_ETH_FILTER_NONE;\n static const void *default_mask;\n \n+static inline void dpaa2_flow_extract_key_set(\n+\tstruct dpaa2_key_info *key_info, int index, uint8_t size)\n+{\n+\tkey_info->key_size[index] = size;\n+\tif (index > 0) {\n+\t\tkey_info->key_offset[index] =\n+\t\t\tkey_info->key_offset[index - 1] +\n+\t\t\tkey_info->key_size[index - 1];\n+\t} else {\n+\t\tkey_info->key_offset[index] = 0;\n+\t}\n+\tkey_info->key_total_size += size;\n+}\n+\n+static int dpaa2_flow_extract_add(\n+\tstruct dpaa2_key_extract *key_extract,\n+\tenum net_prot prot,\n+\tuint32_t field, uint8_t field_size)\n+{\n+\tint index, ip_src = -1, ip_dst = -1;\n+\tstruct dpkg_profile_cfg *dpkg = &key_extract->dpkg;\n+\tstruct dpaa2_key_info *key_info = &key_extract->key_info;\n+\n+\tif (dpkg->num_extracts >=\n+\t\tDPKG_MAX_NUM_OF_EXTRACTS) {\n+\t\tDPAA2_PMD_WARN(\"Number of extracts overflows\");\n+\t\treturn -1;\n+\t}\n+\t/* Before reorder, the IP SRC and IP DST are already last\n+\t * extract(s).\n+\t */\n+\tfor (index = 0; index < dpkg->num_extracts; index++) {\n+\t\tif (dpkg->extracts[index].extract.from_hdr.prot ==\n+\t\t\tNET_PROT_IP) {\n+\t\t\tif (dpkg->extracts[index].extract.from_hdr.field ==\n+\t\t\t\tNH_FLD_IP_SRC) {\n+\t\t\t\tip_src = index;\n+\t\t\t}\n+\t\t\tif (dpkg->extracts[index].extract.from_hdr.field ==\n+\t\t\t\tNH_FLD_IP_DST) {\n+\t\t\t\tip_dst = index;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tif (ip_src >= 0)\n+\t\tRTE_ASSERT((ip_src + 2) >= dpkg->num_extracts);\n+\n+\tif (ip_dst >= 0)\n+\t\tRTE_ASSERT((ip_dst + 2) >= dpkg->num_extracts);\n+\n+\tif (prot == NET_PROT_IP &&\n+\t\t(field == NH_FLD_IP_SRC ||\n+\t\tfield == NH_FLD_IP_DST)) {\n+\t\tindex = dpkg->num_extracts;\n+\t} else {\n+\t\tif (ip_src >= 0 && ip_dst >= 0)\n+\t\t\tindex = dpkg->num_extracts - 2;\n+\t\telse if (ip_src >= 0 || ip_dst >= 0)\n+\t\t\tindex = dpkg->num_extracts - 1;\n+\t\telse\n+\t\t\tindex = dpkg->num_extracts;\n+\t}\n+\n+\tdpkg->extracts[index].type =\tDPKG_EXTRACT_FROM_HDR;\n+\tdpkg->extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n+\tdpkg->extracts[index].extract.from_hdr.prot = prot;\n+\tdpkg->extracts[index].extract.from_hdr.field = field;\n+\tif (prot == NET_PROT_IP &&\n+\t\t(field == NH_FLD_IP_SRC ||\n+\t\tfield == NH_FLD_IP_DST)) {\n+\t\tdpaa2_flow_extract_key_set(key_info, index, 0);\n+\t} else {\n+\t\tdpaa2_flow_extract_key_set(key_info, index, field_size);\n+\t}\n+\n+\tif (prot == NET_PROT_IP) {\n+\t\tif (field == NH_FLD_IP_SRC) {\n+\t\t\tif (key_info->ipv4_dst_offset >= 0) {\n+\t\t\t\tkey_info->ipv4_src_offset =\n+\t\t\t\t\tkey_info->ipv4_dst_offset +\n+\t\t\t\t\tNH_FLD_IPV4_ADDR_SIZE;\n+\t\t\t} else {\n+\t\t\t\tkey_info->ipv4_src_offset =\n+\t\t\t\t\tkey_info->key_offset[index - 1] +\n+\t\t\t\t\t\tkey_info->key_size[index - 1];\n+\t\t\t}\n+\t\t\tif (key_info->ipv6_dst_offset >= 0) {\n+\t\t\t\tkey_info->ipv6_src_offset =\n+\t\t\t\t\tkey_info->ipv6_dst_offset +\n+\t\t\t\t\tNH_FLD_IPV6_ADDR_SIZE;\n+\t\t\t} else {\n+\t\t\t\tkey_info->ipv6_src_offset =\n+\t\t\t\t\tkey_info->key_offset[index - 1] +\n+\t\t\t\t\t\tkey_info->key_size[index - 1];\n+\t\t\t}\n+\t\t} else if (field == NH_FLD_IP_DST) {\n+\t\t\tif (key_info->ipv4_src_offset >= 0) {\n+\t\t\t\tkey_info->ipv4_dst_offset =\n+\t\t\t\t\tkey_info->ipv4_src_offset +\n+\t\t\t\t\tNH_FLD_IPV4_ADDR_SIZE;\n+\t\t\t} else {\n+\t\t\t\tkey_info->ipv4_dst_offset =\n+\t\t\t\t\tkey_info->key_offset[index - 1] +\n+\t\t\t\t\t\tkey_info->key_size[index - 1];\n+\t\t\t}\n+\t\t\tif (key_info->ipv6_src_offset >= 0) {\n+\t\t\t\tkey_info->ipv6_dst_offset =\n+\t\t\t\t\tkey_info->ipv6_src_offset +\n+\t\t\t\t\tNH_FLD_IPV6_ADDR_SIZE;\n+\t\t\t} else {\n+\t\t\t\tkey_info->ipv6_dst_offset =\n+\t\t\t\t\tkey_info->key_offset[index - 1] +\n+\t\t\t\t\t\tkey_info->key_size[index - 1];\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tif (index == dpkg->num_extracts) {\n+\t\tdpkg->num_extracts++;\n+\t\treturn 0;\n+\t}\n+\n+\tif (ip_src >= 0) {\n+\t\tip_src++;\n+\t\tdpkg->extracts[ip_src].type =\n+\t\t\tDPKG_EXTRACT_FROM_HDR;\n+\t\tdpkg->extracts[ip_src].extract.from_hdr.type =\n+\t\t\tDPKG_FULL_FIELD;\n+\t\tdpkg->extracts[ip_src].extract.from_hdr.prot =\n+\t\t\tNET_PROT_IP;\n+\t\tdpkg->extracts[ip_src].extract.from_hdr.field =\n+\t\t\tNH_FLD_IP_SRC;\n+\t\tdpaa2_flow_extract_key_set(key_info, ip_src, 0);\n+\t\tkey_info->ipv4_src_offset += field_size;\n+\t\tkey_info->ipv6_src_offset += field_size;\n+\t}\n+\tif (ip_dst >= 0) {\n+\t\tip_dst++;\n+\t\tdpkg->extracts[ip_dst].type =\n+\t\t\tDPKG_EXTRACT_FROM_HDR;\n+\t\tdpkg->extracts[ip_dst].extract.from_hdr.type =\n+\t\t\tDPKG_FULL_FIELD;\n+\t\tdpkg->extracts[ip_dst].extract.from_hdr.prot =\n+\t\t\tNET_PROT_IP;\n+\t\tdpkg->extracts[ip_dst].extract.from_hdr.field =\n+\t\t\tNH_FLD_IP_DST;\n+\t\tdpaa2_flow_extract_key_set(key_info, ip_dst, 0);\n+\t\tkey_info->ipv4_dst_offset += field_size;\n+\t\tkey_info->ipv6_dst_offset += field_size;\n+\t}\n+\n+\tdpkg->num_extracts++;\n+\n+\treturn 0;\n+}\n+\n+/* Protocol discrimination.\n+ * Discriminate IPv4/IPv6/vLan by Eth type.\n+ * Discriminate UDP/TCP/ICMP by next proto of IP.\n+ */\n+static inline int\n+dpaa2_flow_proto_discrimination_extract(\n+\tstruct dpaa2_key_extract *key_extract,\n+\tenum rte_flow_item_type type)\n+{\n+\tif (type == RTE_FLOW_ITEM_TYPE_ETH) {\n+\t\treturn dpaa2_flow_extract_add(\n+\t\t\t\tkey_extract, NET_PROT_ETH,\n+\t\t\t\tNH_FLD_ETH_TYPE,\n+\t\t\t\tsizeof(rte_be16_t));\n+\t} else if (type == (enum rte_flow_item_type)\n+\t\tDPAA2_FLOW_ITEM_TYPE_GENERIC_IP) {\n+\t\treturn dpaa2_flow_extract_add(\n+\t\t\t\tkey_extract, NET_PROT_IP,\n+\t\t\t\tNH_FLD_IP_PROTO,\n+\t\t\t\tNH_FLD_IP_PROTO_SIZE);\n+\t}\n+\n+\treturn -1;\n+}\n+\n+static inline int dpaa2_flow_extract_search(\n+\tstruct dpkg_profile_cfg *dpkg,\n+\tenum net_prot prot, uint32_t field)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < dpkg->num_extracts; i++) {\n+\t\tif (dpkg->extracts[i].extract.from_hdr.prot == prot &&\n+\t\t\tdpkg->extracts[i].extract.from_hdr.field == field) {\n+\t\t\treturn i;\n+\t\t}\n+\t}\n+\n+\treturn -1;\n+}\n+\n+static inline int dpaa2_flow_extract_key_offset(\n+\tstruct dpaa2_key_extract *key_extract,\n+\tenum net_prot prot, uint32_t field)\n+{\n+\tint i;\n+\tstruct dpkg_profile_cfg *dpkg = &key_extract->dpkg;\n+\tstruct dpaa2_key_info *key_info = &key_extract->key_info;\n+\n+\tif (prot == NET_PROT_IPV4 ||\n+\t\tprot == NET_PROT_IPV6)\n+\t\ti = dpaa2_flow_extract_search(dpkg, NET_PROT_IP, field);\n+\telse\n+\t\ti = dpaa2_flow_extract_search(dpkg, prot, field);\n+\n+\tif (i >= 0) {\n+\t\tif (prot == NET_PROT_IPV4 && field == NH_FLD_IP_SRC)\n+\t\t\treturn key_info->ipv4_src_offset;\n+\t\telse if (prot == NET_PROT_IPV4 && field == NH_FLD_IP_DST)\n+\t\t\treturn key_info->ipv4_dst_offset;\n+\t\telse if (prot == NET_PROT_IPV6 && field == NH_FLD_IP_SRC)\n+\t\t\treturn key_info->ipv6_src_offset;\n+\t\telse if (prot == NET_PROT_IPV6 && field == NH_FLD_IP_DST)\n+\t\t\treturn key_info->ipv6_dst_offset;\n+\t\telse\n+\t\t\treturn key_info->key_offset[i];\n+\t} else {\n+\t\treturn -1;\n+\t}\n+}\n+\n+struct proto_discrimination {\n+\tenum rte_flow_item_type type;\n+\tunion {\n+\t\trte_be16_t eth_type;\n+\t\tuint8_t ip_proto;\n+\t};\n+};\n+\n+static int\n+dpaa2_flow_proto_discrimination_rule(\n+\tstruct dpaa2_dev_priv *priv, struct rte_flow *flow,\n+\tstruct proto_discrimination proto, int group)\n+{\n+\tenum net_prot prot;\n+\tuint32_t field;\n+\tint offset;\n+\tsize_t key_iova;\n+\tsize_t mask_iova;\n+\trte_be16_t eth_type;\n+\tuint8_t ip_proto;\n+\n+\tif (proto.type == RTE_FLOW_ITEM_TYPE_ETH) {\n+\t\tprot = NET_PROT_ETH;\n+\t\tfield = NH_FLD_ETH_TYPE;\n+\t} else if (proto.type == DPAA2_FLOW_ITEM_TYPE_GENERIC_IP) {\n+\t\tprot = NET_PROT_IP;\n+\t\tfield = NH_FLD_IP_PROTO;\n+\t} else {\n+\t\tDPAA2_PMD_ERR(\n+\t\t\t\"Only Eth and IP support to discriminate next proto.\");\n+\t\treturn -1;\n+\t}\n+\n+\toffset = dpaa2_flow_extract_key_offset(&priv->extract.qos_key_extract,\n+\t\t\tprot, field);\n+\tif (offset < 0) {\n+\t\tDPAA2_PMD_ERR(\"QoS prot %d field %d extract failed\",\n+\t\t\t\tprot, field);\n+\t\treturn -1;\n+\t}\n+\tkey_iova = flow->qos_rule.key_iova + offset;\n+\tmask_iova = flow->qos_rule.mask_iova + offset;\n+\tif (proto.type == RTE_FLOW_ITEM_TYPE_ETH) {\n+\t\teth_type = proto.eth_type;\n+\t\tmemcpy((void *)key_iova, (const void *)(&eth_type),\n+\t\t\tsizeof(rte_be16_t));\n+\t\teth_type = 0xffff;\n+\t\tmemcpy((void *)mask_iova, (const void *)(&eth_type),\n+\t\t\tsizeof(rte_be16_t));\n+\t} else {\n+\t\tip_proto = proto.ip_proto;\n+\t\tmemcpy((void *)key_iova, (const void *)(&ip_proto),\n+\t\t\tsizeof(uint8_t));\n+\t\tip_proto = 0xff;\n+\t\tmemcpy((void *)mask_iova, (const void *)(&ip_proto),\n+\t\t\tsizeof(uint8_t));\n+\t}\n+\n+\toffset = dpaa2_flow_extract_key_offset(\n+\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\tprot, field);\n+\tif (offset < 0) {\n+\t\tDPAA2_PMD_ERR(\"FS prot %d field %d extract failed\",\n+\t\t\t\tprot, field);\n+\t\treturn -1;\n+\t}\n+\tkey_iova = flow->fs_rule.key_iova + offset;\n+\tmask_iova = flow->fs_rule.mask_iova + offset;\n+\n+\tif (proto.type == RTE_FLOW_ITEM_TYPE_ETH) {\n+\t\teth_type = proto.eth_type;\n+\t\tmemcpy((void *)key_iova, (const void *)(&eth_type),\n+\t\t\tsizeof(rte_be16_t));\n+\t\teth_type = 0xffff;\n+\t\tmemcpy((void *)mask_iova, (const void *)(&eth_type),\n+\t\t\tsizeof(rte_be16_t));\n+\t} else {\n+\t\tip_proto = proto.ip_proto;\n+\t\tmemcpy((void *)key_iova, (const void *)(&ip_proto),\n+\t\t\tsizeof(uint8_t));\n+\t\tip_proto = 0xff;\n+\t\tmemcpy((void *)mask_iova, (const void *)(&ip_proto),\n+\t\t\tsizeof(uint8_t));\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static inline int\n+dpaa2_flow_rule_data_set(\n+\tstruct dpaa2_key_extract *key_extract,\n+\tstruct dpni_rule_cfg *rule,\n+\tenum net_prot prot, uint32_t field,\n+\tconst void *key, const void *mask, int size)\n+{\n+\tint offset = dpaa2_flow_extract_key_offset(key_extract,\n+\t\t\t\tprot, field);\n+\n+\tif (offset < 0) {\n+\t\tDPAA2_PMD_ERR(\"prot %d, field %d extract failed\",\n+\t\t\tprot, field);\n+\t\treturn -1;\n+\t}\n+\tmemcpy((void *)(size_t)(rule->key_iova + offset), key, size);\n+\tmemcpy((void *)(size_t)(rule->mask_iova + offset), mask, size);\n+\n+\treturn 0;\n+}\n+\n+static inline int\n+_dpaa2_flow_rule_move_ipaddr_tail(\n+\tstruct dpaa2_key_extract *key_extract,\n+\tstruct dpni_rule_cfg *rule, int src_offset,\n+\tuint32_t field, bool ipv4)\n+{\n+\tsize_t key_src;\n+\tsize_t mask_src;\n+\tsize_t key_dst;\n+\tsize_t mask_dst;\n+\tint dst_offset, len;\n+\tenum net_prot prot;\n+\tchar tmp[NH_FLD_IPV6_ADDR_SIZE];\n+\n+\tif (field != NH_FLD_IP_SRC &&\n+\t\tfield != NH_FLD_IP_DST) {\n+\t\tDPAA2_PMD_ERR(\"Field of IP addr reorder must be IP SRC/DST\");\n+\t\treturn -1;\n+\t}\n+\tif (ipv4)\n+\t\tprot = NET_PROT_IPV4;\n+\telse\n+\t\tprot = NET_PROT_IPV6;\n+\tdst_offset = dpaa2_flow_extract_key_offset(key_extract,\n+\t\t\t\tprot, field);\n+\tif (dst_offset < 0) {\n+\t\tDPAA2_PMD_ERR(\"Field %d reorder extract failed\", field);\n+\t\treturn -1;\n+\t}\n+\tkey_src = rule->key_iova + src_offset;\n+\tmask_src = rule->mask_iova + src_offset;\n+\tkey_dst = rule->key_iova + dst_offset;\n+\tmask_dst = rule->mask_iova + dst_offset;\n+\tif (ipv4)\n+\t\tlen = sizeof(rte_be32_t);\n+\telse\n+\t\tlen = NH_FLD_IPV6_ADDR_SIZE;\n+\n+\tmemcpy(tmp, (char *)key_src, len);\n+\tmemcpy((char *)key_dst, tmp, len);\n+\n+\tmemcpy(tmp, (char *)mask_src, len);\n+\tmemcpy((char *)mask_dst, tmp, len);\n+\n+\treturn 0;\n+}\n+\n+static inline int\n+dpaa2_flow_rule_move_ipaddr_tail(\n+\tstruct rte_flow *flow, struct dpaa2_dev_priv *priv,\n+\tint fs_group)\n+{\n+\tint ret;\n+\tenum net_prot prot;\n+\n+\tif (flow->ipaddr_rule.ipaddr_type == FLOW_NONE_IPADDR)\n+\t\treturn 0;\n+\n+\tif (flow->ipaddr_rule.ipaddr_type == FLOW_IPV4_ADDR)\n+\t\tprot = NET_PROT_IPV4;\n+\telse\n+\t\tprot = NET_PROT_IPV6;\n+\n+\tif (flow->ipaddr_rule.qos_ipsrc_offset >= 0) {\n+\t\tret = _dpaa2_flow_rule_move_ipaddr_tail(\n+\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t&flow->qos_rule,\n+\t\t\t\tflow->ipaddr_rule.qos_ipsrc_offset,\n+\t\t\t\tNH_FLD_IP_SRC, prot == NET_PROT_IPV4);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"QoS src address reorder failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\t\tflow->ipaddr_rule.qos_ipsrc_offset =\n+\t\t\tdpaa2_flow_extract_key_offset(\n+\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\tprot, NH_FLD_IP_SRC);\n+\t}\n+\n+\tif (flow->ipaddr_rule.qos_ipdst_offset >= 0) {\n+\t\tret = _dpaa2_flow_rule_move_ipaddr_tail(\n+\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t&flow->qos_rule,\n+\t\t\t\tflow->ipaddr_rule.qos_ipdst_offset,\n+\t\t\t\tNH_FLD_IP_DST, prot == NET_PROT_IPV4);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"QoS dst address reorder failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\t\tflow->ipaddr_rule.qos_ipdst_offset =\n+\t\t\tdpaa2_flow_extract_key_offset(\n+\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\tprot, NH_FLD_IP_DST);\n+\t}\n+\n+\tif (flow->ipaddr_rule.fs_ipsrc_offset >= 0) {\n+\t\tret = _dpaa2_flow_rule_move_ipaddr_tail(\n+\t\t\t\t&priv->extract.tc_key_extract[fs_group],\n+\t\t\t\t&flow->fs_rule,\n+\t\t\t\tflow->ipaddr_rule.fs_ipsrc_offset,\n+\t\t\t\tNH_FLD_IP_SRC, prot == NET_PROT_IPV4);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"FS src address reorder failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\t\tflow->ipaddr_rule.fs_ipsrc_offset =\n+\t\t\tdpaa2_flow_extract_key_offset(\n+\t\t\t\t&priv->extract.tc_key_extract[fs_group],\n+\t\t\t\tprot, NH_FLD_IP_SRC);\n+\t}\n+\tif (flow->ipaddr_rule.fs_ipdst_offset >= 0) {\n+\t\tret = _dpaa2_flow_rule_move_ipaddr_tail(\n+\t\t\t\t&priv->extract.tc_key_extract[fs_group],\n+\t\t\t\t&flow->fs_rule,\n+\t\t\t\tflow->ipaddr_rule.fs_ipdst_offset,\n+\t\t\t\tNH_FLD_IP_DST, prot == NET_PROT_IPV4);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"FS dst address reorder failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\t\tflow->ipaddr_rule.fs_ipdst_offset =\n+\t\t\tdpaa2_flow_extract_key_offset(\n+\t\t\t\t&priv->extract.tc_key_extract[fs_group],\n+\t\t\t\tprot, NH_FLD_IP_DST);\n+\t}\n+\n+\treturn 0;\n+}\n+\n static int\n dpaa2_configure_flow_eth(struct rte_flow *flow,\n \t\t\t struct rte_eth_dev *dev,\n \t\t\t const struct rte_flow_attr *attr,\n \t\t\t const struct rte_flow_item *pattern,\n \t\t\t const struct rte_flow_action actions[] __rte_unused,\n-\t\t\t struct rte_flow_error *error __rte_unused)\n+\t\t\t struct rte_flow_error *error __rte_unused,\n+\t\t\t int *device_configured)\n {\n-\tint index, j = 0;\n-\tsize_t key_iova;\n-\tsize_t mask_iova;\n-\tint device_configured = 0, entry_found = 0;\n+\tint index, ret;\n+\tint local_cfg = 0;\n \tuint32_t group;\n \tconst struct rte_flow_item_eth *spec, *mask;\n \n \t/* TODO: Currently upper bound of range parameter is not implemented */\n \tconst struct rte_flow_item_eth *last __rte_unused;\n \tstruct dpaa2_dev_priv *priv = dev->data->dev_private;\n+\tconst char zero_cmp[RTE_ETHER_ADDR_LEN] = {0};\n \n \tgroup = attr->group;\n \n-\t/* DPAA2 platform has a limitation that extract parameter can not be */\n-\t/* more than DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too.*/\n-\t/* TODO: pattern is an array of 9 elements where 9th pattern element */\n-\t/* is for QoS table and 1-8th pattern element is for FS tables. */\n-\t/* It can be changed to macro. */\n-\tif (priv->pattern[8].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {\n-\t\tDPAA2_PMD_ERR(\"Maximum limit for different pattern type = %d\\n\",\n-\t\t\t\t\t\tDPKG_MAX_NUM_OF_EXTRACTS);\n-\t\treturn -ENOTSUP;\n+\t/* Parse pattern list to get the matching parameters */\n+\tspec    = (const struct rte_flow_item_eth *)pattern->spec;\n+\tlast    = (const struct rte_flow_item_eth *)pattern->last;\n+\tmask    = (const struct rte_flow_item_eth *)\n+\t\t(pattern->mask ? pattern->mask : default_mask);\n+\tif (!spec) {\n+\t\t/* Don't care any field of eth header,\n+\t\t * only care eth protocol.\n+\t\t */\n+\t\tDPAA2_PMD_WARN(\"No pattern spec for Eth flow, just skip\");\n+\t\treturn 0;\n \t}\n \n-\tif (priv->pattern[group].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {\n-\t\tDPAA2_PMD_ERR(\"Maximum limit for different pattern type = %d\\n\",\n-\t\t\t\t\t\tDPKG_MAX_NUM_OF_EXTRACTS);\n-\t\treturn -ENOTSUP;\n-\t}\n+\t/* Get traffic class index and flow id to be configured */\n+\tflow->tc_id = group;\n+\tflow->tc_index = attr->priority;\n+\n+\tif (memcmp((const char *)&mask->src, zero_cmp, RTE_ETHER_ADDR_LEN)) {\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.qos_key_extract.dpkg,\n+\t\t\t\tNET_PROT_ETH, NH_FLD_ETH_SA);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t\tNET_PROT_ETH, NH_FLD_ETH_SA,\n+\t\t\t\t\tRTE_ETHER_ADDR_LEN);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"QoS Extract add ETH_SA failed.\");\n \n-\tfor (j = 0; j < priv->pattern[8].item_count; j++) {\n-\t\tif (priv->pattern[8].pattern_type[j] != pattern->type) {\n-\t\t\tcontinue;\n-\t\t} else {\n-\t\t\tentry_found = 1;\n-\t\t\tbreak;\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;\n+\t\t}\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.tc_key_extract[group].dpkg,\n+\t\t\t\tNET_PROT_ETH, NH_FLD_ETH_SA);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t\tNET_PROT_ETH, NH_FLD_ETH_SA,\n+\t\t\t\t\tRTE_ETHER_ADDR_LEN);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"FS Extract add ETH_SA failed.\");\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_FS_TABLE_RECONFIGURE;\n \t\t}\n-\t}\n \n-\tif (!entry_found) {\n-\t\tpriv->pattern[8].pattern_type[j] = pattern->type;\n-\t\tpriv->pattern[8].item_count++;\n-\t\tdevice_configured |= DPAA2_QOS_TABLE_RECONFIGURE;\n-\t}\n+\t\tret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"Move ipaddr before ETH_SA rule set failed\");\n+\t\t\treturn -1;\n+\t\t}\n \n-\tentry_found = 0;\n-\tfor (j = 0; j < priv->pattern[group].item_count; j++) {\n-\t\tif (priv->pattern[group].pattern_type[j] != pattern->type) {\n-\t\t\tcontinue;\n-\t\t} else {\n-\t\t\tentry_found = 1;\n-\t\t\tbreak;\n+\t\tret = dpaa2_flow_rule_data_set(\n+\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t&flow->qos_rule,\n+\t\t\t\tNET_PROT_ETH,\n+\t\t\t\tNH_FLD_ETH_SA,\n+\t\t\t\t&spec->src.addr_bytes,\n+\t\t\t\t&mask->src.addr_bytes,\n+\t\t\t\tsizeof(struct rte_ether_addr));\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"QoS NH_FLD_ETH_SA rule data set failed\");\n+\t\t\treturn -1;\n \t\t}\n-\t}\n \n-\tif (!entry_found) {\n-\t\tpriv->pattern[group].pattern_type[j] = pattern->type;\n-\t\tpriv->pattern[group].item_count++;\n-\t\tdevice_configured |= DPAA2_FS_TABLE_RECONFIGURE;\n+\t\tret = dpaa2_flow_rule_data_set(\n+\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t&flow->fs_rule,\n+\t\t\t\tNET_PROT_ETH,\n+\t\t\t\tNH_FLD_ETH_SA,\n+\t\t\t\t&spec->src.addr_bytes,\n+\t\t\t\t&mask->src.addr_bytes,\n+\t\t\t\tsizeof(struct rte_ether_addr));\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"FS NH_FLD_ETH_SA rule data set failed\");\n+\t\t\treturn -1;\n+\t\t}\n \t}\n \n-\t/* Get traffic class index and flow id to be configured */\n-\tflow->tc_id = group;\n-\tflow->index = attr->priority;\n-\n-\tif (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) {\n-\t\tindex = priv->extract.qos_key_cfg.num_extracts;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_ETH;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_ETH_SA;\n-\t\tindex++;\n-\n-\t\tpriv->extract.qos_key_cfg.extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_ETH;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_ETH_DA;\n-\t\tindex++;\n-\n-\t\tpriv->extract.qos_key_cfg.extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_ETH;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_ETH_TYPE;\n-\t\tindex++;\n-\n-\t\tpriv->extract.qos_key_cfg.num_extracts = index;\n-\t}\n-\n-\tif (device_configured & DPAA2_FS_TABLE_RECONFIGURE) {\n-\t\tindex = priv->extract.fs_key_cfg[group].num_extracts;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_ETH;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_ETH_SA;\n-\t\tindex++;\n-\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_ETH;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_ETH_DA;\n-\t\tindex++;\n-\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_ETH;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_ETH_TYPE;\n-\t\tindex++;\n-\n-\t\tpriv->extract.fs_key_cfg[group].num_extracts = index;\n+\tif (memcmp((const char *)&mask->dst, zero_cmp, RTE_ETHER_ADDR_LEN)) {\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.qos_key_extract.dpkg,\n+\t\t\t\tNET_PROT_ETH, NH_FLD_ETH_DA);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t\tNET_PROT_ETH, NH_FLD_ETH_DA,\n+\t\t\t\t\tRTE_ETHER_ADDR_LEN);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"QoS Extract add ETH_DA failed.\");\n+\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;\n+\t\t}\n+\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.tc_key_extract[group].dpkg,\n+\t\t\t\tNET_PROT_ETH, NH_FLD_ETH_DA);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t\tNET_PROT_ETH, NH_FLD_ETH_DA,\n+\t\t\t\t\tRTE_ETHER_ADDR_LEN);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"FS Extract add ETH_DA failed.\");\n+\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_FS_TABLE_RECONFIGURE;\n+\t\t}\n+\n+\t\tret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"Move ipaddr before ETH DA rule set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tret = dpaa2_flow_rule_data_set(\n+\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t&flow->qos_rule,\n+\t\t\t\tNET_PROT_ETH,\n+\t\t\t\tNH_FLD_ETH_DA,\n+\t\t\t\t&spec->dst.addr_bytes,\n+\t\t\t\t&mask->dst.addr_bytes,\n+\t\t\t\tsizeof(struct rte_ether_addr));\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"QoS NH_FLD_ETH_DA rule data set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tret = dpaa2_flow_rule_data_set(\n+\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t&flow->fs_rule,\n+\t\t\t\tNET_PROT_ETH,\n+\t\t\t\tNH_FLD_ETH_DA,\n+\t\t\t\t&spec->dst.addr_bytes,\n+\t\t\t\t&mask->dst.addr_bytes,\n+\t\t\t\tsizeof(struct rte_ether_addr));\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"FS NH_FLD_ETH_DA rule data set failed\");\n+\t\t\treturn -1;\n+\t\t}\n \t}\n \n-\t/* Parse pattern list to get the matching parameters */\n-\tspec\t= (const struct rte_flow_item_eth *)pattern->spec;\n-\tlast\t= (const struct rte_flow_item_eth *)pattern->last;\n-\tmask\t= (const struct rte_flow_item_eth *)\n-\t\t\t(pattern->mask ? pattern->mask : default_mask);\n+\tif (memcmp((const char *)&mask->type, zero_cmp, sizeof(rte_be16_t))) {\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.qos_key_extract.dpkg,\n+\t\t\t\tNET_PROT_ETH, NH_FLD_ETH_TYPE);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t\tNET_PROT_ETH, NH_FLD_ETH_TYPE,\n+\t\t\t\t\tRTE_ETHER_TYPE_LEN);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"QoS Extract add ETH_TYPE failed.\");\n \n-\t/* Key rule */\n-\tkey_iova = flow->rule.key_iova + flow->key_size;\n-\tmemcpy((void *)key_iova, (const void *)(spec->src.addr_bytes),\n-\t\t\t\t\t\tsizeof(struct rte_ether_addr));\n-\tkey_iova += sizeof(struct rte_ether_addr);\n-\tmemcpy((void *)key_iova, (const void *)(spec->dst.addr_bytes),\n-\t\t\t\t\t\tsizeof(struct rte_ether_addr));\n-\tkey_iova += sizeof(struct rte_ether_addr);\n-\tmemcpy((void *)key_iova, (const void *)(&spec->type),\n-\t\t\t\t\t\tsizeof(rte_be16_t));\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;\n+\t\t}\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.tc_key_extract[group].dpkg,\n+\t\t\t\tNET_PROT_ETH, NH_FLD_ETH_TYPE);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t\tNET_PROT_ETH, NH_FLD_ETH_TYPE,\n+\t\t\t\t\tRTE_ETHER_TYPE_LEN);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"FS Extract add ETH_TYPE failed.\");\n \n-\t/* Key mask */\n-\tmask_iova = flow->rule.mask_iova + flow->key_size;\n-\tmemcpy((void *)mask_iova, (const void *)(mask->src.addr_bytes),\n-\t\t\t\t\t\tsizeof(struct rte_ether_addr));\n-\tmask_iova += sizeof(struct rte_ether_addr);\n-\tmemcpy((void *)mask_iova, (const void *)(mask->dst.addr_bytes),\n-\t\t\t\t\t\tsizeof(struct rte_ether_addr));\n-\tmask_iova += sizeof(struct rte_ether_addr);\n-\tmemcpy((void *)mask_iova, (const void *)(&mask->type),\n-\t\t\t\t\t\tsizeof(rte_be16_t));\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_FS_TABLE_RECONFIGURE;\n+\t\t}\n+\n+\t\tret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"Move ipaddr before ETH TYPE rule set failed\");\n+\t\t\t\treturn -1;\n+\t\t}\n \n-\tflow->key_size += ((2  * sizeof(struct rte_ether_addr)) +\n-\t\t\t\t\tsizeof(rte_be16_t));\n+\t\tret = dpaa2_flow_rule_data_set(\n+\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t&flow->qos_rule,\n+\t\t\t\tNET_PROT_ETH,\n+\t\t\t\tNH_FLD_ETH_TYPE,\n+\t\t\t\t&spec->type,\n+\t\t\t\t&mask->type,\n+\t\t\t\tsizeof(rte_be16_t));\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"QoS NH_FLD_ETH_TYPE rule data set failed\");\n+\t\t\treturn -1;\n+\t\t}\n \n-\treturn device_configured;\n+\t\tret = dpaa2_flow_rule_data_set(\n+\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t&flow->fs_rule,\n+\t\t\t\tNET_PROT_ETH,\n+\t\t\t\tNH_FLD_ETH_TYPE,\n+\t\t\t\t&spec->type,\n+\t\t\t\t&mask->type,\n+\t\t\t\tsizeof(rte_be16_t));\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"FS NH_FLD_ETH_TYPE rule data set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\t(*device_configured) |= local_cfg;\n+\n+\treturn 0;\n }\n \n static int\n@@ -222,12 +802,11 @@ dpaa2_configure_flow_vlan(struct rte_flow *flow,\n \t\t\t  const struct rte_flow_attr *attr,\n \t\t\t  const struct rte_flow_item *pattern,\n \t\t\t  const struct rte_flow_action actions[] __rte_unused,\n-\t\t\t  struct rte_flow_error *error __rte_unused)\n+\t\t\t  struct rte_flow_error *error __rte_unused,\n+\t\t\t  int *device_configured)\n {\n-\tint index, j = 0;\n-\tsize_t key_iova;\n-\tsize_t mask_iova;\n-\tint device_configured = 0, entry_found = 0;\n+\tint index, ret;\n+\tint local_cfg = 0;\n \tuint32_t group;\n \tconst struct rte_flow_item_vlan *spec, *mask;\n \n@@ -236,375 +815,524 @@ dpaa2_configure_flow_vlan(struct rte_flow *flow,\n \n \tgroup = attr->group;\n \n-\t/* DPAA2 platform has a limitation that extract parameter can not be */\n-\t/*  more than DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too.*/\n-\tif (priv->pattern[8].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {\n-\t\tDPAA2_PMD_ERR(\"Maximum limit for different pattern type = %d\\n\",\n-\t\t\t\t\t\tDPKG_MAX_NUM_OF_EXTRACTS);\n-\t\treturn -ENOTSUP;\n-\t}\n+\t/* Parse pattern list to get the matching parameters */\n+\tspec    = (const struct rte_flow_item_vlan *)pattern->spec;\n+\tlast    = (const struct rte_flow_item_vlan *)pattern->last;\n+\tmask    = (const struct rte_flow_item_vlan *)\n+\t\t(pattern->mask ? pattern->mask : default_mask);\n \n-\tif (priv->pattern[group].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {\n-\t\tDPAA2_PMD_ERR(\"Maximum limit for different pattern type = %d\\n\",\n-\t\t\t\t\t\tDPKG_MAX_NUM_OF_EXTRACTS);\n-\t\treturn -ENOTSUP;\n-\t}\n+\t/* Get traffic class index and flow id to be configured */\n+\tflow->tc_id = group;\n+\tflow->tc_index = attr->priority;\n+\n+\tif (!spec) {\n+\t\t/* Don't care any field of vlan header,\n+\t\t * only care vlan protocol.\n+\t\t */\n+\t\t/* Eth type is actually used for vLan classification.\n+\t\t */\n+\t\tstruct proto_discrimination proto;\n+\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.qos_key_extract.dpkg,\n+\t\t\t\tNET_PROT_ETH, NH_FLD_ETH_TYPE);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_proto_discrimination_extract(\n+\t\t\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t\t\tRTE_FLOW_ITEM_TYPE_ETH);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"QoS Ext ETH_TYPE to discriminate vLan failed\");\n \n-\tfor (j = 0; j < priv->pattern[8].item_count; j++) {\n-\t\tif (priv->pattern[8].pattern_type[j] != pattern->type) {\n-\t\t\tcontinue;\n-\t\t} else {\n-\t\t\tentry_found = 1;\n-\t\t\tbreak;\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;\n \t\t}\n-\t}\n \n-\tif (!entry_found) {\n-\t\tpriv->pattern[8].pattern_type[j] = pattern->type;\n-\t\tpriv->pattern[8].item_count++;\n-\t\tdevice_configured |= DPAA2_QOS_TABLE_RECONFIGURE;\n-\t}\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.tc_key_extract[group].dpkg,\n+\t\t\t\tNET_PROT_ETH, NH_FLD_ETH_TYPE);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_proto_discrimination_extract(\n+\t\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t\tRTE_FLOW_ITEM_TYPE_ETH);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"FS Ext ETH_TYPE to discriminate vLan failed.\");\n \n-\tentry_found = 0;\n-\tfor (j = 0; j < priv->pattern[group].item_count; j++) {\n-\t\tif (priv->pattern[group].pattern_type[j] != pattern->type) {\n-\t\t\tcontinue;\n-\t\t} else {\n-\t\t\tentry_found = 1;\n-\t\t\tbreak;\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_FS_TABLE_RECONFIGURE;\n+\t\t}\n+\n+\t\tret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\"Move ipaddr before vLan discrimination set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tproto.type = RTE_FLOW_ITEM_TYPE_ETH;\n+\t\tproto.eth_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);\n+\t\tret = dpaa2_flow_proto_discrimination_rule(priv, flow,\n+\t\t\t\t\t\t\tproto, group);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"vLan discrimination rule set failed\");\n+\t\t\treturn -1;\n \t\t}\n-\t}\n \n-\tif (!entry_found) {\n-\t\tpriv->pattern[group].pattern_type[j] = pattern->type;\n-\t\tpriv->pattern[group].item_count++;\n-\t\tdevice_configured |= DPAA2_FS_TABLE_RECONFIGURE;\n+\t\t(*device_configured) |= local_cfg;\n+\n+\t\treturn 0;\n \t}\n \n+\tif (!mask->tci)\n+\t\treturn 0;\n \n-\t/* Get traffic class index and flow id to be configured */\n-\tflow->tc_id = group;\n-\tflow->index = attr->priority;\n+\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.qos_key_extract.dpkg,\n+\t\t\t\tNET_PROT_VLAN, NH_FLD_VLAN_TCI);\n+\tif (index < 0) {\n+\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t\t\tNET_PROT_VLAN,\n+\t\t\t\t\t\tNH_FLD_VLAN_TCI,\n+\t\t\t\t\t\tsizeof(rte_be16_t));\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"QoS Extract add VLAN_TCI failed.\");\n \n-\tif (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) {\n-\t\tindex = priv->extract.qos_key_cfg.num_extracts;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_VLAN;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_VLAN_TCI;\n-\t\tpriv->extract.qos_key_cfg.num_extracts++;\n+\t\t\treturn -1;\n+\t\t}\n+\t\tlocal_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;\n+\t}\n+\n+\tindex = dpaa2_flow_extract_search(\n+\t\t\t&priv->extract.tc_key_extract[group].dpkg,\n+\t\t\tNET_PROT_VLAN, NH_FLD_VLAN_TCI);\n+\tif (index < 0) {\n+\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\tNET_PROT_VLAN,\n+\t\t\t\tNH_FLD_VLAN_TCI,\n+\t\t\t\tsizeof(rte_be16_t));\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"FS Extract add VLAN_TCI failed.\");\n+\n+\t\t\treturn -1;\n+\t\t}\n+\t\tlocal_cfg |= DPAA2_FS_TABLE_RECONFIGURE;\n \t}\n \n-\tif (device_configured & DPAA2_FS_TABLE_RECONFIGURE) {\n-\t\tindex = priv->extract.fs_key_cfg[group].num_extracts;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_VLAN;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_VLAN_TCI;\n-\t\tpriv->extract.fs_key_cfg[group].num_extracts++;\n+\tret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);\n+\tif (ret) {\n+\t\tDPAA2_PMD_ERR(\n+\t\t\t\"Move ipaddr before VLAN TCI rule set failed\");\n+\t\treturn -1;\n \t}\n \n-\t/* Parse pattern list to get the matching parameters */\n-\tspec\t= (const struct rte_flow_item_vlan *)pattern->spec;\n-\tlast\t= (const struct rte_flow_item_vlan *)pattern->last;\n-\tmask\t= (const struct rte_flow_item_vlan *)\n-\t\t\t(pattern->mask ? pattern->mask : default_mask);\n+\tret = dpaa2_flow_rule_data_set(&priv->extract.qos_key_extract,\n+\t\t\t\t&flow->qos_rule,\n+\t\t\t\tNET_PROT_VLAN,\n+\t\t\t\tNH_FLD_VLAN_TCI,\n+\t\t\t\t&spec->tci,\n+\t\t\t\t&mask->tci,\n+\t\t\t\tsizeof(rte_be16_t));\n+\tif (ret) {\n+\t\tDPAA2_PMD_ERR(\"QoS NH_FLD_VLAN_TCI rule data set failed\");\n+\t\treturn -1;\n+\t}\n \n-\tkey_iova = flow->rule.key_iova + flow->key_size;\n-\tmemcpy((void *)key_iova, (const void *)(&spec->tci),\n-\t\t\t\t\t\t\tsizeof(rte_be16_t));\n+\tret = dpaa2_flow_rule_data_set(\n+\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t&flow->fs_rule,\n+\t\t\tNET_PROT_VLAN,\n+\t\t\tNH_FLD_VLAN_TCI,\n+\t\t\t&spec->tci,\n+\t\t\t&mask->tci,\n+\t\t\tsizeof(rte_be16_t));\n+\tif (ret) {\n+\t\tDPAA2_PMD_ERR(\"FS NH_FLD_VLAN_TCI rule data set failed\");\n+\t\treturn -1;\n+\t}\n \n-\tmask_iova = flow->rule.mask_iova + flow->key_size;\n-\tmemcpy((void *)mask_iova, (const void *)(&mask->tci),\n-\t\t\t\t\t\t\tsizeof(rte_be16_t));\n+\t(*device_configured) |= local_cfg;\n \n-\tflow->key_size += sizeof(rte_be16_t);\n-\treturn device_configured;\n+\treturn 0;\n }\n \n static int\n-dpaa2_configure_flow_ipv4(struct rte_flow *flow,\n-\t\t\t  struct rte_eth_dev *dev,\n-\t\t\t  const struct rte_flow_attr *attr,\n-\t\t\t  const struct rte_flow_item *pattern,\n-\t\t\t  const struct rte_flow_action actions[] __rte_unused,\n-\t\t\t  struct rte_flow_error *error __rte_unused)\n+dpaa2_configure_flow_generic_ip(\n+\tstruct rte_flow *flow,\n+\tstruct rte_eth_dev *dev,\n+\tconst struct rte_flow_attr *attr,\n+\tconst struct rte_flow_item *pattern,\n+\tconst struct rte_flow_action actions[] __rte_unused,\n+\tstruct rte_flow_error *error __rte_unused,\n+\tint *device_configured)\n {\n-\tint index, j = 0;\n-\tsize_t key_iova;\n-\tsize_t mask_iova;\n-\tint device_configured = 0, entry_found = 0;\n+\tint index, ret;\n+\tint local_cfg = 0;\n \tuint32_t group;\n-\tconst struct rte_flow_item_ipv4 *spec, *mask;\n+\tconst struct rte_flow_item_ipv4 *spec_ipv4 = 0,\n+\t\t*mask_ipv4 = 0;\n+\tconst struct rte_flow_item_ipv6 *spec_ipv6 = 0,\n+\t\t*mask_ipv6 = 0;\n+\tconst void *key, *mask;\n+\tenum net_prot prot;\n \n-\tconst struct rte_flow_item_ipv4 *last __rte_unused;\n \tstruct dpaa2_dev_priv *priv = dev->data->dev_private;\n+\tconst char zero_cmp[NH_FLD_IPV6_ADDR_SIZE] = {0};\n+\tint size;\n \n \tgroup = attr->group;\n \n-\t/* DPAA2 platform has a limitation that extract parameter can not be */\n-\t/* more than DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too.*/\n-\tif (priv->pattern[8].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {\n-\t\tDPAA2_PMD_ERR(\"Maximum limit for different pattern type = %d\\n\",\n-\t\t\t\t\t\tDPKG_MAX_NUM_OF_EXTRACTS);\n-\t\treturn -ENOTSUP;\n+\t/* Parse pattern list to get the matching parameters */\n+\tif (pattern->type == RTE_FLOW_ITEM_TYPE_IPV4) {\n+\t\tspec_ipv4 = (const struct rte_flow_item_ipv4 *)pattern->spec;\n+\t\tmask_ipv4 = (const struct rte_flow_item_ipv4 *)\n+\t\t\t(pattern->mask ? pattern->mask : default_mask);\n+\t} else {\n+\t\tspec_ipv6 = (const struct rte_flow_item_ipv6 *)pattern->spec;\n+\t\tmask_ipv6 = (const struct rte_flow_item_ipv6 *)\n+\t\t\t(pattern->mask ? pattern->mask : default_mask);\n \t}\n \n-\tif (priv->pattern[group].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {\n-\t\tDPAA2_PMD_ERR(\"Maximum limit for different pattern type = %d\\n\",\n-\t\t\t\t\t\tDPKG_MAX_NUM_OF_EXTRACTS);\n-\t\treturn -ENOTSUP;\n-\t}\n+\t/* Get traffic class index and flow id to be configured */\n+\tflow->tc_id = group;\n+\tflow->tc_index = attr->priority;\n+\n+\tif (!spec_ipv4 && !spec_ipv6) {\n+\t\t/* Don't care any field of IP header,\n+\t\t * only care IP protocol.\n+\t\t * Example: flow create 0 ingress pattern ipv6 /\n+\t\t */\n+\t\t/* Eth type is actually used for IP identification.\n+\t\t */\n+\t\t/* TODO: Current design only supports Eth + IP,\n+\t\t *  Eth + vLan + IP needs to add.\n+\t\t */\n+\t\tstruct proto_discrimination proto;\n+\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.qos_key_extract.dpkg,\n+\t\t\t\tNET_PROT_ETH, NH_FLD_ETH_TYPE);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_proto_discrimination_extract(\n+\t\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t\tRTE_FLOW_ITEM_TYPE_ETH);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"QoS Ext ETH_TYPE to discriminate IP failed.\");\n \n-\tfor (j = 0; j < priv->pattern[8].item_count; j++) {\n-\t\tif (priv->pattern[8].pattern_type[j] != pattern->type) {\n-\t\t\tcontinue;\n-\t\t} else {\n-\t\t\tentry_found = 1;\n-\t\t\tbreak;\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;\n \t\t}\n-\t}\n \n-\tif (!entry_found) {\n-\t\tpriv->pattern[8].pattern_type[j] = pattern->type;\n-\t\tpriv->pattern[8].item_count++;\n-\t\tdevice_configured |= DPAA2_QOS_TABLE_RECONFIGURE;\n-\t}\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.tc_key_extract[group].dpkg,\n+\t\t\t\tNET_PROT_ETH, NH_FLD_ETH_TYPE);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_proto_discrimination_extract(\n+\t\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t\tRTE_FLOW_ITEM_TYPE_ETH);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"FS Ext ETH_TYPE to discriminate IP failed\");\n \n-\tentry_found = 0;\n-\tfor (j = 0; j < priv->pattern[group].item_count; j++) {\n-\t\tif (priv->pattern[group].pattern_type[j] != pattern->type) {\n-\t\t\tcontinue;\n-\t\t} else {\n-\t\t\tentry_found = 1;\n-\t\t\tbreak;\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_FS_TABLE_RECONFIGURE;\n \t\t}\n-\t}\n \n-\tif (!entry_found) {\n-\t\tpriv->pattern[group].pattern_type[j] = pattern->type;\n-\t\tpriv->pattern[group].item_count++;\n-\t\tdevice_configured |= DPAA2_FS_TABLE_RECONFIGURE;\n-\t}\n+\t\tret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\"Move ipaddr before IP discrimination set failed\");\n+\t\t\treturn -1;\n+\t\t}\n \n-\t/* Get traffic class index and flow id to be configured */\n-\tflow->tc_id = group;\n-\tflow->index = attr->priority;\n-\n-\tif (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) {\n-\t\tindex = priv->extract.qos_key_cfg.num_extracts;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_IP;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_IP_SRC;\n-\t\tindex++;\n-\n-\t\tpriv->extract.qos_key_cfg.extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_IP;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_IP_DST;\n-\t\tindex++;\n-\n-\t\tpriv->extract.qos_key_cfg.extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_IP;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_IP_PROTO;\n-\t\tindex++;\n-\n-\t\tpriv->extract.qos_key_cfg.num_extracts = index;\n-\t}\n-\n-\tif (device_configured & DPAA2_FS_TABLE_RECONFIGURE) {\n-\t\tindex = priv->extract.fs_key_cfg[group].num_extracts;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_IP;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_IP_SRC;\n-\t\tindex++;\n-\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_IP;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_IP_DST;\n-\t\tindex++;\n-\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_IP;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_IP_PROTO;\n-\t\tindex++;\n-\n-\t\tpriv->extract.fs_key_cfg[group].num_extracts = index;\n-\t}\n+\t\tproto.type = RTE_FLOW_ITEM_TYPE_ETH;\n+\t\tif (pattern->type == RTE_FLOW_ITEM_TYPE_IPV4)\n+\t\t\tproto.eth_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);\n+\t\telse\n+\t\t\tproto.eth_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);\n+\t\tret = dpaa2_flow_proto_discrimination_rule(priv, flow,\n+\t\t\t\t\t\t\tproto, group);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"IP discrimination rule set failed\");\n+\t\t\treturn -1;\n+\t\t}\n \n-\t/* Parse pattern list to get the matching parameters */\n-\tspec\t= (const struct rte_flow_item_ipv4 *)pattern->spec;\n-\tlast\t= (const struct rte_flow_item_ipv4 *)pattern->last;\n-\tmask\t= (const struct rte_flow_item_ipv4 *)\n-\t\t\t(pattern->mask ? pattern->mask : default_mask);\n+\t\t(*device_configured) |= local_cfg;\n+\n+\t\treturn 0;\n+\t}\n+\n+\tif (mask_ipv4 && (mask_ipv4->hdr.src_addr ||\n+\t\tmask_ipv4->hdr.dst_addr)) {\n+\t\tflow->ipaddr_rule.ipaddr_type = FLOW_IPV4_ADDR;\n+\t} else if (mask_ipv6 &&\n+\t\t(memcmp((const char *)mask_ipv6->hdr.src_addr,\n+\t\t\t\tzero_cmp, NH_FLD_IPV6_ADDR_SIZE) ||\n+\t\tmemcmp((const char *)mask_ipv6->hdr.dst_addr,\n+\t\t\t\tzero_cmp, NH_FLD_IPV6_ADDR_SIZE))) {\n+\t\tflow->ipaddr_rule.ipaddr_type = FLOW_IPV6_ADDR;\n+\t}\n+\n+\tif ((mask_ipv4 && mask_ipv4->hdr.src_addr) ||\n+\t\t(mask_ipv6 &&\n+\t\t\tmemcmp((const char *)mask_ipv6->hdr.src_addr,\n+\t\t\t\tzero_cmp, NH_FLD_IPV6_ADDR_SIZE))) {\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.qos_key_extract.dpkg,\n+\t\t\t\tNET_PROT_IP, NH_FLD_IP_SRC);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t\t\tNET_PROT_IP,\n+\t\t\t\t\t\tNH_FLD_IP_SRC,\n+\t\t\t\t\t\t0);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"QoS Extract add IP_SRC failed.\");\n \n-\tkey_iova = flow->rule.key_iova + flow->key_size;\n-\tmemcpy((void *)key_iova, (const void *)&spec->hdr.src_addr,\n-\t\t\t\t\t\t\tsizeof(uint32_t));\n-\tkey_iova += sizeof(uint32_t);\n-\tmemcpy((void *)key_iova, (const void *)&spec->hdr.dst_addr,\n-\t\t\t\t\t\t\tsizeof(uint32_t));\n-\tkey_iova += sizeof(uint32_t);\n-\tmemcpy((void *)key_iova, (const void *)&spec->hdr.next_proto_id,\n-\t\t\t\t\t\t\tsizeof(uint8_t));\n-\n-\tmask_iova = flow->rule.mask_iova + flow->key_size;\n-\tmemcpy((void *)mask_iova, (const void *)&mask->hdr.src_addr,\n-\t\t\t\t\t\t\tsizeof(uint32_t));\n-\tmask_iova += sizeof(uint32_t);\n-\tmemcpy((void *)mask_iova, (const void *)&mask->hdr.dst_addr,\n-\t\t\t\t\t\t\tsizeof(uint32_t));\n-\tmask_iova += sizeof(uint32_t);\n-\tmemcpy((void *)mask_iova, (const void *)&mask->hdr.next_proto_id,\n-\t\t\t\t\t\t\tsizeof(uint8_t));\n-\n-\tflow->key_size += (2 * sizeof(uint32_t)) + sizeof(uint8_t);\n-\treturn device_configured;\n-}\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= (DPAA2_QOS_TABLE_RECONFIGURE |\n+\t\t\t\tDPAA2_QOS_TABLE_IPADDR_EXTRACT);\n+\t\t}\n \n-static int\n-dpaa2_configure_flow_ipv6(struct rte_flow *flow,\n-\t\t\t  struct rte_eth_dev *dev,\n-\t\t\t  const struct rte_flow_attr *attr,\n-\t\t\t  const struct rte_flow_item *pattern,\n-\t\t\t  const struct rte_flow_action actions[] __rte_unused,\n-\t\t\t  struct rte_flow_error *error __rte_unused)\n-{\n-\tint index, j = 0;\n-\tsize_t key_iova;\n-\tsize_t mask_iova;\n-\tint device_configured = 0, entry_found = 0;\n-\tuint32_t group;\n-\tconst struct rte_flow_item_ipv6 *spec, *mask;\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.tc_key_extract[group].dpkg,\n+\t\t\t\tNET_PROT_IP, NH_FLD_IP_SRC);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t\tNET_PROT_IP,\n+\t\t\t\t\tNH_FLD_IP_SRC,\n+\t\t\t\t\t0);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"FS Extract add IP_SRC failed.\");\n \n-\tconst struct rte_flow_item_ipv6 *last __rte_unused;\n-\tstruct dpaa2_dev_priv *priv = dev->data->dev_private;\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= (DPAA2_FS_TABLE_RECONFIGURE |\n+\t\t\t\tDPAA2_FS_TABLE_IPADDR_EXTRACT);\n+\t\t}\n \n-\tgroup = attr->group;\n+\t\tif (spec_ipv4)\n+\t\t\tkey = &spec_ipv4->hdr.src_addr;\n+\t\telse\n+\t\t\tkey = &spec_ipv6->hdr.src_addr[0];\n+\t\tif (mask_ipv4) {\n+\t\t\tmask = &mask_ipv4->hdr.src_addr;\n+\t\t\tsize = NH_FLD_IPV4_ADDR_SIZE;\n+\t\t\tprot = NET_PROT_IPV4;\n+\t\t} else {\n+\t\t\tmask = &mask_ipv6->hdr.src_addr[0];\n+\t\t\tsize = NH_FLD_IPV6_ADDR_SIZE;\n+\t\t\tprot = NET_PROT_IPV6;\n+\t\t}\n \n-\t/* DPAA2 platform has a limitation that extract parameter can not be */\n-\t/* more\tthan DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too.*/\n-\tif (priv->pattern[8].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {\n-\t\tDPAA2_PMD_ERR(\"Maximum limit for different pattern type = %d\\n\",\n-\t\t\t\t\t\tDPKG_MAX_NUM_OF_EXTRACTS);\n-\t\treturn -ENOTSUP;\n-\t}\n+\t\tret = dpaa2_flow_rule_data_set(\n+\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t&flow->qos_rule,\n+\t\t\t\tprot, NH_FLD_IP_SRC,\n+\t\t\t\tkey,\tmask, size);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"QoS NH_FLD_IP_SRC rule data set failed\");\n+\t\t\treturn -1;\n+\t\t}\n \n-\tif (priv->pattern[group].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {\n-\t\tDPAA2_PMD_ERR(\"Maximum limit for different pattern type = %d\\n\",\n-\t\t\t\t\t\tDPKG_MAX_NUM_OF_EXTRACTS);\n-\t\treturn -ENOTSUP;\n-\t}\n+\t\tret = dpaa2_flow_rule_data_set(\n+\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t&flow->fs_rule,\n+\t\t\t\tprot, NH_FLD_IP_SRC,\n+\t\t\t\tkey,\tmask, size);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"FS NH_FLD_IP_SRC rule data set failed\");\n+\t\t\treturn -1;\n+\t\t}\n \n-\tfor (j = 0; j < priv->pattern[8].item_count; j++) {\n-\t\tif (priv->pattern[8].pattern_type[j] != pattern->type) {\n-\t\t\tcontinue;\n-\t\t} else {\n-\t\t\tentry_found = 1;\n-\t\t\tbreak;\n+\t\tflow->ipaddr_rule.qos_ipsrc_offset =\n+\t\t\tdpaa2_flow_extract_key_offset(\n+\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\tprot, NH_FLD_IP_SRC);\n+\t\tflow->ipaddr_rule.fs_ipsrc_offset =\n+\t\t\tdpaa2_flow_extract_key_offset(\n+\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\tprot, NH_FLD_IP_SRC);\n+\t}\n+\n+\tif ((mask_ipv4 && mask_ipv4->hdr.dst_addr) ||\n+\t\t(mask_ipv6 &&\n+\t\t\tmemcmp((const char *)mask_ipv6->hdr.dst_addr,\n+\t\t\t\tzero_cmp, NH_FLD_IPV6_ADDR_SIZE))) {\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.qos_key_extract.dpkg,\n+\t\t\t\tNET_PROT_IP, NH_FLD_IP_DST);\n+\t\tif (index < 0) {\n+\t\t\tif (mask_ipv4)\n+\t\t\t\tsize = NH_FLD_IPV4_ADDR_SIZE;\n+\t\t\telse\n+\t\t\t\tsize = NH_FLD_IPV6_ADDR_SIZE;\n+\t\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t\t\tNET_PROT_IP,\n+\t\t\t\t\t\tNH_FLD_IP_DST,\n+\t\t\t\t\t\tsize);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"QoS Extract add IP_DST failed.\");\n+\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= (DPAA2_QOS_TABLE_RECONFIGURE |\n+\t\t\t\tDPAA2_QOS_TABLE_IPADDR_EXTRACT);\n \t\t}\n-\t}\n \n-\tif (!entry_found) {\n-\t\tpriv->pattern[8].pattern_type[j] = pattern->type;\n-\t\tpriv->pattern[8].item_count++;\n-\t\tdevice_configured |= DPAA2_QOS_TABLE_RECONFIGURE;\n-\t}\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.tc_key_extract[group].dpkg,\n+\t\t\t\tNET_PROT_IP, NH_FLD_IP_DST);\n+\t\tif (index < 0) {\n+\t\t\tif (mask_ipv4)\n+\t\t\t\tsize = NH_FLD_IPV4_ADDR_SIZE;\n+\t\t\telse\n+\t\t\t\tsize = NH_FLD_IPV6_ADDR_SIZE;\n+\t\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t\tNET_PROT_IP,\n+\t\t\t\t\tNH_FLD_IP_DST,\n+\t\t\t\t\tsize);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"FS Extract add IP_DST failed.\");\n \n-\tentry_found = 0;\n-\tfor (j = 0; j < priv->pattern[group].item_count; j++) {\n-\t\tif (priv->pattern[group].pattern_type[j] != pattern->type) {\n-\t\t\tcontinue;\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= (DPAA2_FS_TABLE_RECONFIGURE |\n+\t\t\t\tDPAA2_FS_TABLE_IPADDR_EXTRACT);\n+\t\t}\n+\n+\t\tif (spec_ipv4)\n+\t\t\tkey = &spec_ipv4->hdr.dst_addr;\n+\t\telse\n+\t\t\tkey = spec_ipv6->hdr.dst_addr;\n+\t\tif (mask_ipv4) {\n+\t\t\tmask = &mask_ipv4->hdr.dst_addr;\n+\t\t\tsize = NH_FLD_IPV4_ADDR_SIZE;\n+\t\t\tprot = NET_PROT_IPV4;\n \t\t} else {\n-\t\t\tentry_found = 1;\n-\t\t\tbreak;\n+\t\t\tmask = &mask_ipv6->hdr.dst_addr[0];\n+\t\t\tsize = NH_FLD_IPV6_ADDR_SIZE;\n+\t\t\tprot = NET_PROT_IPV6;\n \t\t}\n-\t}\n \n-\tif (!entry_found) {\n-\t\tpriv->pattern[group].pattern_type[j] = pattern->type;\n-\t\tpriv->pattern[group].item_count++;\n-\t\tdevice_configured |= DPAA2_FS_TABLE_RECONFIGURE;\n-\t}\n+\t\tret = dpaa2_flow_rule_data_set(\n+\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t&flow->qos_rule,\n+\t\t\t\tprot, NH_FLD_IP_DST,\n+\t\t\t\tkey,\tmask, size);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"QoS NH_FLD_IP_DST rule data set failed\");\n+\t\t\treturn -1;\n+\t\t}\n \n-\t/* Get traffic class index and flow id to be configured */\n-\tflow->tc_id = group;\n-\tflow->index = attr->priority;\n-\n-\tif (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) {\n-\t\tindex = priv->extract.qos_key_cfg.num_extracts;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_IP;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_IP_SRC;\n-\t\tindex++;\n-\n-\t\tpriv->extract.qos_key_cfg.extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_IP;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_IP_DST;\n-\t\tindex++;\n-\n-\t\tpriv->extract.qos_key_cfg.num_extracts = index;\n-\t}\n-\n-\tif (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) {\n-\t\tindex = priv->extract.fs_key_cfg[group].num_extracts;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_IP;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_IP_SRC;\n-\t\tindex++;\n-\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_IP;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_IP_DST;\n-\t\tindex++;\n-\n-\t\tpriv->extract.fs_key_cfg[group].num_extracts = index;\n+\t\tret = dpaa2_flow_rule_data_set(\n+\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t&flow->fs_rule,\n+\t\t\t\tprot, NH_FLD_IP_DST,\n+\t\t\t\tkey,\tmask, size);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"FS NH_FLD_IP_DST rule data set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\t\tflow->ipaddr_rule.qos_ipdst_offset =\n+\t\t\tdpaa2_flow_extract_key_offset(\n+\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\tprot, NH_FLD_IP_DST);\n+\t\tflow->ipaddr_rule.fs_ipdst_offset =\n+\t\t\tdpaa2_flow_extract_key_offset(\n+\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\tprot, NH_FLD_IP_DST);\n+\t}\n+\n+\tif ((mask_ipv4 && mask_ipv4->hdr.next_proto_id) ||\n+\t\t(mask_ipv6 && mask_ipv6->hdr.proto)) {\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.qos_key_extract.dpkg,\n+\t\t\t\tNET_PROT_IP, NH_FLD_IP_PROTO);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\tNET_PROT_IP,\n+\t\t\t\tNH_FLD_IP_PROTO,\n+\t\t\t\tNH_FLD_IP_PROTO_SIZE);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"QoS Extract add IP_DST failed.\");\n+\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;\n+\t\t}\n+\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.tc_key_extract[group].dpkg,\n+\t\t\t\tNET_PROT_IP, NH_FLD_IP_PROTO);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t\tNET_PROT_IP,\n+\t\t\t\t\tNH_FLD_IP_PROTO,\n+\t\t\t\t\tNH_FLD_IP_PROTO_SIZE);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"FS Extract add IP_DST failed.\");\n+\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_FS_TABLE_RECONFIGURE;\n+\t\t}\n+\n+\t\tret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"Move ipaddr after NH_FLD_IP_PROTO rule set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tif (spec_ipv4)\n+\t\t\tkey = &spec_ipv4->hdr.next_proto_id;\n+\t\telse\n+\t\t\tkey = &spec_ipv6->hdr.proto;\n+\t\tif (mask_ipv4)\n+\t\t\tmask = &mask_ipv4->hdr.next_proto_id;\n+\t\telse\n+\t\t\tmask = &mask_ipv6->hdr.proto;\n+\n+\t\tret = dpaa2_flow_rule_data_set(\n+\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t&flow->qos_rule,\n+\t\t\t\tNET_PROT_IP,\n+\t\t\t\tNH_FLD_IP_PROTO,\n+\t\t\t\tkey,\tmask, NH_FLD_IP_PROTO_SIZE);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"QoS NH_FLD_IP_PROTO rule data set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tret = dpaa2_flow_rule_data_set(\n+\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t&flow->fs_rule,\n+\t\t\t\tNET_PROT_IP,\n+\t\t\t\tNH_FLD_IP_PROTO,\n+\t\t\t\tkey,\tmask, NH_FLD_IP_PROTO_SIZE);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"FS NH_FLD_IP_PROTO rule data set failed\");\n+\t\t\treturn -1;\n+\t\t}\n \t}\n \n-\t/* Parse pattern list to get the matching parameters */\n-\tspec\t= (const struct rte_flow_item_ipv6 *)pattern->spec;\n-\tlast\t= (const struct rte_flow_item_ipv6 *)pattern->last;\n-\tmask\t= (const struct rte_flow_item_ipv6 *)\n-\t\t\t(pattern->mask ? pattern->mask : default_mask);\n+\t(*device_configured) |= local_cfg;\n \n-\tkey_iova = flow->rule.key_iova + flow->key_size;\n-\tmemcpy((void *)key_iova, (const void *)(spec->hdr.src_addr),\n-\t\t\t\t\t\tsizeof(spec->hdr.src_addr));\n-\tkey_iova += sizeof(spec->hdr.src_addr);\n-\tmemcpy((void *)key_iova, (const void *)(spec->hdr.dst_addr),\n-\t\t\t\t\t\tsizeof(spec->hdr.dst_addr));\n-\n-\tmask_iova = flow->rule.mask_iova + flow->key_size;\n-\tmemcpy((void *)mask_iova, (const void *)(mask->hdr.src_addr),\n-\t\t\t\t\t\tsizeof(mask->hdr.src_addr));\n-\tmask_iova += sizeof(mask->hdr.src_addr);\n-\tmemcpy((void *)mask_iova, (const void *)(mask->hdr.dst_addr),\n-\t\t\t\t\t\tsizeof(mask->hdr.dst_addr));\n-\n-\tflow->key_size += sizeof(spec->hdr.src_addr) +\n-\t\t\t\t\tsizeof(mask->hdr.dst_addr);\n-\treturn device_configured;\n+\treturn 0;\n }\n \n static int\n@@ -613,12 +1341,11 @@ dpaa2_configure_flow_icmp(struct rte_flow *flow,\n \t\t\t  const struct rte_flow_attr *attr,\n \t\t\t  const struct rte_flow_item *pattern,\n \t\t\t  const struct rte_flow_action actions[] __rte_unused,\n-\t\t\t  struct rte_flow_error *error __rte_unused)\n+\t\t\t  struct rte_flow_error *error __rte_unused,\n+\t\t\t  int *device_configured)\n {\n-\tint index, j = 0;\n-\tsize_t key_iova;\n-\tsize_t mask_iova;\n-\tint device_configured = 0, entry_found = 0;\n+\tint index, ret;\n+\tint local_cfg = 0;\n \tuint32_t group;\n \tconst struct rte_flow_item_icmp *spec, *mask;\n \n@@ -627,116 +1354,220 @@ dpaa2_configure_flow_icmp(struct rte_flow *flow,\n \n \tgroup = attr->group;\n \n-\t/* DPAA2 platform has a limitation that extract parameter can not be */\n-\t/* more than DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too.*/\n-\tif (priv->pattern[8].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {\n-\t\tDPAA2_PMD_ERR(\"Maximum limit for different pattern type = %d\\n\",\n-\t\t\t\t\t\tDPKG_MAX_NUM_OF_EXTRACTS);\n-\t\treturn -ENOTSUP;\n-\t}\n+\t/* Parse pattern list to get the matching parameters */\n+\tspec    = (const struct rte_flow_item_icmp *)pattern->spec;\n+\tlast    = (const struct rte_flow_item_icmp *)pattern->last;\n+\tmask    = (const struct rte_flow_item_icmp *)\n+\t\t(pattern->mask ? pattern->mask : default_mask);\n \n-\tif (priv->pattern[group].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {\n-\t\tDPAA2_PMD_ERR(\"Maximum limit for different pattern type = %d\\n\",\n-\t\t\t\t\t\tDPKG_MAX_NUM_OF_EXTRACTS);\n-\t\treturn -ENOTSUP;\n-\t}\n+\t/* Get traffic class index and flow id to be configured */\n+\tflow->tc_id = group;\n+\tflow->tc_index = attr->priority;\n+\n+\tif (!spec) {\n+\t\t/* Don't care any field of ICMP header,\n+\t\t * only care ICMP protocol.\n+\t\t * Example: flow create 0 ingress pattern icmp /\n+\t\t */\n+\t\t/* Next proto of Generical IP is actually used\n+\t\t * for ICMP identification.\n+\t\t */\n+\t\tstruct proto_discrimination proto;\n+\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.qos_key_extract.dpkg,\n+\t\t\t\tNET_PROT_IP, NH_FLD_IP_PROTO);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_proto_discrimination_extract(\n+\t\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t\tDPAA2_FLOW_ITEM_TYPE_GENERIC_IP);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\t\"QoS Extract IP protocol to discriminate ICMP failed.\");\n \n-\tfor (j = 0; j < priv->pattern[8].item_count; j++) {\n-\t\tif (priv->pattern[8].pattern_type[j] != pattern->type) {\n-\t\t\tcontinue;\n-\t\t} else {\n-\t\t\tentry_found = 1;\n-\t\t\tbreak;\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;\n \t\t}\n-\t}\n \n-\tif (!entry_found) {\n-\t\tpriv->pattern[8].pattern_type[j] = pattern->type;\n-\t\tpriv->pattern[8].item_count++;\n-\t\tdevice_configured |= DPAA2_QOS_TABLE_RECONFIGURE;\n-\t}\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.tc_key_extract[group].dpkg,\n+\t\t\t\tNET_PROT_IP, NH_FLD_IP_PROTO);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_proto_discrimination_extract(\n+\t\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t\tDPAA2_FLOW_ITEM_TYPE_GENERIC_IP);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\t\"FS Extract IP protocol to discriminate ICMP failed.\");\n \n-\tentry_found = 0;\n-\tfor (j = 0; j < priv->pattern[group].item_count; j++) {\n-\t\tif (priv->pattern[group].pattern_type[j] != pattern->type) {\n-\t\t\tcontinue;\n-\t\t} else {\n-\t\t\tentry_found = 1;\n-\t\t\tbreak;\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_FS_TABLE_RECONFIGURE;\n \t\t}\n-\t}\n \n-\tif (!entry_found) {\n-\t\tpriv->pattern[group].pattern_type[j] = pattern->type;\n-\t\tpriv->pattern[group].item_count++;\n-\t\tdevice_configured |= DPAA2_FS_TABLE_RECONFIGURE;\n+\t\tret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"Move IP addr before ICMP discrimination set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tproto.type = DPAA2_FLOW_ITEM_TYPE_GENERIC_IP;\n+\t\tproto.ip_proto = IPPROTO_ICMP;\n+\t\tret = dpaa2_flow_proto_discrimination_rule(priv, flow,\n+\t\t\t\t\t\t\tproto, group);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"ICMP discrimination rule set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\t(*device_configured) |= local_cfg;\n+\n+\t\treturn 0;\n \t}\n \n-\t/* Get traffic class index and flow id to be configured */\n-\tflow->tc_id = group;\n-\tflow->index = attr->priority;\n-\n-\tif (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) {\n-\t\tindex = priv->extract.qos_key_cfg.num_extracts;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_ICMP;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_ICMP_TYPE;\n-\t\tindex++;\n-\n-\t\tpriv->extract.qos_key_cfg.extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_ICMP;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_ICMP_CODE;\n-\t\tindex++;\n-\n-\t\tpriv->extract.qos_key_cfg.num_extracts = index;\n-\t}\n-\n-\tif (device_configured & DPAA2_FS_TABLE_RECONFIGURE) {\n-\t\tindex = priv->extract.fs_key_cfg[group].num_extracts;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_ICMP;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_ICMP_TYPE;\n-\t\tindex++;\n-\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_ICMP;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_ICMP_CODE;\n-\t\tindex++;\n-\n-\t\tpriv->extract.fs_key_cfg[group].num_extracts = index;\n+\tif (mask->hdr.icmp_type) {\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.qos_key_extract.dpkg,\n+\t\t\t\tNET_PROT_ICMP, NH_FLD_ICMP_TYPE);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t\tNET_PROT_ICMP,\n+\t\t\t\t\tNH_FLD_ICMP_TYPE,\n+\t\t\t\t\tNH_FLD_ICMP_TYPE_SIZE);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"QoS Extract add ICMP_TYPE failed.\");\n+\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;\n+\t\t}\n+\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.tc_key_extract[group].dpkg,\n+\t\t\t\tNET_PROT_ICMP, NH_FLD_ICMP_TYPE);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t\tNET_PROT_ICMP,\n+\t\t\t\t\tNH_FLD_ICMP_TYPE,\n+\t\t\t\t\tNH_FLD_ICMP_TYPE_SIZE);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"FS Extract add ICMP_TYPE failed.\");\n+\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_FS_TABLE_RECONFIGURE;\n+\t\t}\n+\n+\t\tret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"Move ipaddr before ICMP TYPE set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tret = dpaa2_flow_rule_data_set(\n+\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t&flow->qos_rule,\n+\t\t\t\tNET_PROT_ICMP,\n+\t\t\t\tNH_FLD_ICMP_TYPE,\n+\t\t\t\t&spec->hdr.icmp_type,\n+\t\t\t\t&mask->hdr.icmp_type,\n+\t\t\t\tNH_FLD_ICMP_TYPE_SIZE);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"QoS NH_FLD_ICMP_TYPE rule data set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tret = dpaa2_flow_rule_data_set(\n+\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t&flow->fs_rule,\n+\t\t\t\tNET_PROT_ICMP,\n+\t\t\t\tNH_FLD_ICMP_TYPE,\n+\t\t\t\t&spec->hdr.icmp_type,\n+\t\t\t\t&mask->hdr.icmp_type,\n+\t\t\t\tNH_FLD_ICMP_TYPE_SIZE);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"FS NH_FLD_ICMP_TYPE rule data set failed\");\n+\t\t\treturn -1;\n+\t\t}\n \t}\n \n-\t/* Parse pattern list to get the matching parameters */\n-\tspec\t= (const struct rte_flow_item_icmp *)pattern->spec;\n-\tlast\t= (const struct rte_flow_item_icmp *)pattern->last;\n-\tmask\t= (const struct rte_flow_item_icmp *)\n-\t\t\t(pattern->mask ? pattern->mask : default_mask);\n+\tif (mask->hdr.icmp_code) {\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.qos_key_extract.dpkg,\n+\t\t\t\tNET_PROT_ICMP, NH_FLD_ICMP_CODE);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t\tNET_PROT_ICMP,\n+\t\t\t\t\tNH_FLD_ICMP_CODE,\n+\t\t\t\t\tNH_FLD_ICMP_CODE_SIZE);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"QoS Extract add ICMP_CODE failed.\");\n+\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;\n+\t\t}\n \n-\tkey_iova = flow->rule.key_iova + flow->key_size;\n-\tmemcpy((void *)key_iova, (const void *)&spec->hdr.icmp_type,\n-\t\t\t\t\t\t\tsizeof(uint8_t));\n-\tkey_iova += sizeof(uint8_t);\n-\tmemcpy((void *)key_iova, (const void *)&spec->hdr.icmp_code,\n-\t\t\t\t\t\t\tsizeof(uint8_t));\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.tc_key_extract[group].dpkg,\n+\t\t\t\tNET_PROT_ICMP, NH_FLD_ICMP_CODE);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t\tNET_PROT_ICMP,\n+\t\t\t\t\tNH_FLD_ICMP_CODE,\n+\t\t\t\t\tNH_FLD_ICMP_CODE_SIZE);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"FS Extract add ICMP_CODE failed.\");\n \n-\tmask_iova = flow->rule.mask_iova + flow->key_size;\n-\tmemcpy((void *)mask_iova, (const void *)&mask->hdr.icmp_type,\n-\t\t\t\t\t\t\tsizeof(uint8_t));\n-\tkey_iova += sizeof(uint8_t);\n-\tmemcpy((void *)mask_iova, (const void *)&mask->hdr.icmp_code,\n-\t\t\t\t\t\t\tsizeof(uint8_t));\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_FS_TABLE_RECONFIGURE;\n+\t\t}\n \n-\tflow->key_size += 2 * sizeof(uint8_t);\n+\t\tret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"Move ipaddr after ICMP CODE set failed\");\n+\t\t\treturn -1;\n+\t\t}\n \n-\treturn device_configured;\n+\t\tret = dpaa2_flow_rule_data_set(\n+\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t&flow->qos_rule,\n+\t\t\t\tNET_PROT_ICMP,\n+\t\t\t\tNH_FLD_ICMP_CODE,\n+\t\t\t\t&spec->hdr.icmp_code,\n+\t\t\t\t&mask->hdr.icmp_code,\n+\t\t\t\tNH_FLD_ICMP_CODE_SIZE);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"QoS NH_FLD_ICMP_CODE rule data set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tret = dpaa2_flow_rule_data_set(\n+\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t&flow->fs_rule,\n+\t\t\t\tNET_PROT_ICMP,\n+\t\t\t\tNH_FLD_ICMP_CODE,\n+\t\t\t\t&spec->hdr.icmp_code,\n+\t\t\t\t&mask->hdr.icmp_code,\n+\t\t\t\tNH_FLD_ICMP_CODE_SIZE);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"FS NH_FLD_ICMP_CODE rule data set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\t(*device_configured) |= local_cfg;\n+\n+\treturn 0;\n }\n \n static int\n@@ -745,12 +1576,11 @@ dpaa2_configure_flow_udp(struct rte_flow *flow,\n \t\t\t  const struct rte_flow_attr *attr,\n \t\t\t  const struct rte_flow_item *pattern,\n \t\t\t  const struct rte_flow_action actions[] __rte_unused,\n-\t\t\t  struct rte_flow_error *error __rte_unused)\n+\t\t\t  struct rte_flow_error *error __rte_unused,\n+\t\t\t  int *device_configured)\n {\n-\tint index, j = 0;\n-\tsize_t key_iova;\n-\tsize_t mask_iova;\n-\tint device_configured = 0, entry_found = 0;\n+\tint index, ret;\n+\tint local_cfg = 0;\n \tuint32_t group;\n \tconst struct rte_flow_item_udp *spec, *mask;\n \n@@ -759,115 +1589,217 @@ dpaa2_configure_flow_udp(struct rte_flow *flow,\n \n \tgroup = attr->group;\n \n-\t/* DPAA2 platform has a limitation that extract parameter can not be */\n-\t/* more than DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too.*/\n-\tif (priv->pattern[8].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {\n-\t\tDPAA2_PMD_ERR(\"Maximum limit for different pattern type = %d\\n\",\n-\t\t\t\t\t\tDPKG_MAX_NUM_OF_EXTRACTS);\n-\t\treturn -ENOTSUP;\n-\t}\n+\t/* Parse pattern list to get the matching parameters */\n+\tspec    = (const struct rte_flow_item_udp *)pattern->spec;\n+\tlast    = (const struct rte_flow_item_udp *)pattern->last;\n+\tmask    = (const struct rte_flow_item_udp *)\n+\t\t(pattern->mask ? pattern->mask : default_mask);\n \n-\tif (priv->pattern[group].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {\n-\t\tDPAA2_PMD_ERR(\"Maximum limit for different pattern type = %d\\n\",\n-\t\t\t\t\t\tDPKG_MAX_NUM_OF_EXTRACTS);\n-\t\treturn -ENOTSUP;\n-\t}\n+\t/* Get traffic class index and flow id to be configured */\n+\tflow->tc_id = group;\n+\tflow->tc_index = attr->priority;\n+\n+\tif (!spec || !mc_l4_port_identification) {\n+\t\tstruct proto_discrimination proto;\n+\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.qos_key_extract.dpkg,\n+\t\t\t\tNET_PROT_IP, NH_FLD_IP_PROTO);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_proto_discrimination_extract(\n+\t\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t\tDPAA2_FLOW_ITEM_TYPE_GENERIC_IP);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\t\"QoS Extract IP protocol to discriminate UDP failed.\");\n \n-\tfor (j = 0; j < priv->pattern[8].item_count; j++) {\n-\t\tif (priv->pattern[8].pattern_type[j] != pattern->type) {\n-\t\t\tcontinue;\n-\t\t} else {\n-\t\t\t entry_found = 1;\n-\t\t\tbreak;\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;\n \t\t}\n-\t}\n \n-\tif (!entry_found) {\n-\t\tpriv->pattern[8].pattern_type[j] = pattern->type;\n-\t\tpriv->pattern[8].item_count++;\n-\t\tdevice_configured |= DPAA2_QOS_TABLE_RECONFIGURE;\n-\t}\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.tc_key_extract[group].dpkg,\n+\t\t\t\tNET_PROT_IP, NH_FLD_IP_PROTO);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_proto_discrimination_extract(\n+\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\tDPAA2_FLOW_ITEM_TYPE_GENERIC_IP);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\t\"FS Extract IP protocol to discriminate UDP failed.\");\n \n-\tentry_found = 0;\n-\tfor (j = 0; j < priv->pattern[group].item_count; j++) {\n-\t\tif (priv->pattern[group].pattern_type[j] != pattern->type) {\n-\t\t\tcontinue;\n-\t\t} else {\n-\t\t\tentry_found = 1;\n-\t\t\tbreak;\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_FS_TABLE_RECONFIGURE;\n \t\t}\n-\t}\n \n-\tif (!entry_found) {\n-\t\tpriv->pattern[group].pattern_type[j] = pattern->type;\n-\t\tpriv->pattern[group].item_count++;\n-\t\tdevice_configured |= DPAA2_FS_TABLE_RECONFIGURE;\n+\t\tret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"Move IP addr before UDP discrimination set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tproto.type = DPAA2_FLOW_ITEM_TYPE_GENERIC_IP;\n+\t\tproto.ip_proto = IPPROTO_UDP;\n+\t\tret = dpaa2_flow_proto_discrimination_rule(priv, flow,\n+\t\t\t\t\t\t\tproto, group);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"UDP discrimination rule set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\t(*device_configured) |= local_cfg;\n+\n+\t\tif (!spec)\n+\t\t\treturn 0;\n \t}\n \n-\t/* Get traffic class index and flow id to be configured */\n-\tflow->tc_id = group;\n-\tflow->index = attr->priority;\n+\tif (mask->hdr.src_port) {\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.qos_key_extract.dpkg,\n+\t\t\t\tNET_PROT_UDP, NH_FLD_UDP_PORT_SRC);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\tNET_PROT_UDP,\n+\t\t\t\tNH_FLD_UDP_PORT_SRC,\n+\t\t\t\tNH_FLD_UDP_PORT_SIZE);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"QoS Extract add UDP_SRC failed.\");\n \n-\tif (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) {\n-\t\tindex = priv->extract.qos_key_cfg.num_extracts;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_UDP;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_UDP_PORT_SRC;\n-\t\tindex++;\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;\n+\t\t}\n \n-\t\tpriv->extract.qos_key_cfg.extracts[index].type = DPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_UDP;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_UDP_PORT_DST;\n-\t\tindex++;\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.tc_key_extract[group].dpkg,\n+\t\t\t\tNET_PROT_UDP, NH_FLD_UDP_PORT_SRC);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t\tNET_PROT_UDP,\n+\t\t\t\t\tNH_FLD_UDP_PORT_SRC,\n+\t\t\t\t\tNH_FLD_UDP_PORT_SIZE);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"FS Extract add UDP_SRC failed.\");\n \n-\t\tpriv->extract.qos_key_cfg.num_extracts = index;\n-\t}\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_FS_TABLE_RECONFIGURE;\n+\t\t}\n \n-\tif (device_configured & DPAA2_FS_TABLE_RECONFIGURE) {\n-\t\tindex = priv->extract.fs_key_cfg[group].num_extracts;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_UDP;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_UDP_PORT_SRC;\n-\t\tindex++;\n+\t\tret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"Move ipaddr before UDP_PORT_SRC set failed\");\n+\t\t\treturn -1;\n+\t\t}\n \n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_UDP;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_UDP_PORT_DST;\n-\t\tindex++;\n+\t\tret = dpaa2_flow_rule_data_set(&priv->extract.qos_key_extract,\n+\t\t\t\t&flow->qos_rule,\n+\t\t\t\tNET_PROT_UDP,\n+\t\t\t\tNH_FLD_UDP_PORT_SRC,\n+\t\t\t\t&spec->hdr.src_port,\n+\t\t\t\t&mask->hdr.src_port,\n+\t\t\t\tNH_FLD_UDP_PORT_SIZE);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"QoS NH_FLD_UDP_PORT_SRC rule data set failed\");\n+\t\t\treturn -1;\n+\t\t}\n \n-\t\tpriv->extract.fs_key_cfg[group].num_extracts = index;\n+\t\tret = dpaa2_flow_rule_data_set(\n+\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t&flow->fs_rule,\n+\t\t\t\tNET_PROT_UDP,\n+\t\t\t\tNH_FLD_UDP_PORT_SRC,\n+\t\t\t\t&spec->hdr.src_port,\n+\t\t\t\t&mask->hdr.src_port,\n+\t\t\t\tNH_FLD_UDP_PORT_SIZE);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"FS NH_FLD_UDP_PORT_SRC rule data set failed\");\n+\t\t\treturn -1;\n+\t\t}\n \t}\n \n-\t/* Parse pattern list to get the matching parameters */\n-\tspec\t= (const struct rte_flow_item_udp *)pattern->spec;\n-\tlast\t= (const struct rte_flow_item_udp *)pattern->last;\n-\tmask\t= (const struct rte_flow_item_udp *)\n-\t\t\t(pattern->mask ? pattern->mask : default_mask);\n+\tif (mask->hdr.dst_port) {\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.qos_key_extract.dpkg,\n+\t\t\t\tNET_PROT_UDP, NH_FLD_UDP_PORT_DST);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t\tNET_PROT_UDP,\n+\t\t\t\t\tNH_FLD_UDP_PORT_DST,\n+\t\t\t\t\tNH_FLD_UDP_PORT_SIZE);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"QoS Extract add UDP_DST failed.\");\n \n-\tkey_iova = flow->rule.key_iova + flow->key_size;\n-\tmemcpy((void *)key_iova, (const void *)(&spec->hdr.src_port),\n-\t\t\t\t\t\t\tsizeof(uint16_t));\n-\tkey_iova +=  sizeof(uint16_t);\n-\tmemcpy((void *)key_iova, (const void *)(&spec->hdr.dst_port),\n-\t\t\t\t\t\t\tsizeof(uint16_t));\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;\n+\t\t}\n \n-\tmask_iova = flow->rule.mask_iova + flow->key_size;\n-\tmemcpy((void *)mask_iova, (const void *)(&mask->hdr.src_port),\n-\t\t\t\t\t\t\tsizeof(uint16_t));\n-\tmask_iova +=  sizeof(uint16_t);\n-\tmemcpy((void *)mask_iova, (const void *)(&mask->hdr.dst_port),\n-\t\t\t\t\t\t\tsizeof(uint16_t));\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.tc_key_extract[group].dpkg,\n+\t\t\t\tNET_PROT_UDP, NH_FLD_UDP_PORT_DST);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t\tNET_PROT_UDP,\n+\t\t\t\t\tNH_FLD_UDP_PORT_DST,\n+\t\t\t\t\tNH_FLD_UDP_PORT_SIZE);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"FS Extract add UDP_DST failed.\");\n+\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_FS_TABLE_RECONFIGURE;\n+\t\t}\n+\n+\t\tret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"Move ipaddr before UDP_PORT_DST set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tret = dpaa2_flow_rule_data_set(\n+\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t&flow->qos_rule,\n+\t\t\t\tNET_PROT_UDP,\n+\t\t\t\tNH_FLD_UDP_PORT_DST,\n+\t\t\t\t&spec->hdr.dst_port,\n+\t\t\t\t&mask->hdr.dst_port,\n+\t\t\t\tNH_FLD_UDP_PORT_SIZE);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"QoS NH_FLD_UDP_PORT_DST rule data set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tret = dpaa2_flow_rule_data_set(\n+\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t&flow->fs_rule,\n+\t\t\t\tNET_PROT_UDP,\n+\t\t\t\tNH_FLD_UDP_PORT_DST,\n+\t\t\t\t&spec->hdr.dst_port,\n+\t\t\t\t&mask->hdr.dst_port,\n+\t\t\t\tNH_FLD_UDP_PORT_SIZE);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"FS NH_FLD_UDP_PORT_DST rule data set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n \n-\tflow->key_size += (2 * sizeof(uint16_t));\n+\t(*device_configured) |= local_cfg;\n \n-\treturn device_configured;\n+\treturn 0;\n }\n \n static int\n@@ -876,130 +1808,231 @@ dpaa2_configure_flow_tcp(struct rte_flow *flow,\n \t\t\t const struct rte_flow_attr *attr,\n \t\t\t const struct rte_flow_item *pattern,\n \t\t\t const struct rte_flow_action actions[] __rte_unused,\n-\t\t\t struct rte_flow_error *error __rte_unused)\n+\t\t\t struct rte_flow_error *error __rte_unused,\n+\t\t\t int *device_configured)\n {\n-\tint index, j = 0;\n-\tsize_t key_iova;\n-\tsize_t mask_iova;\n-\tint device_configured = 0, entry_found = 0;\n+\tint index, ret;\n+\tint local_cfg = 0;\n \tuint32_t group;\n \tconst struct rte_flow_item_tcp *spec, *mask;\n \n-\tconst struct rte_flow_item_tcp *last __rte_unused;\n-\tstruct dpaa2_dev_priv *priv = dev->data->dev_private;\n+\tconst struct rte_flow_item_tcp *last __rte_unused;\n+\tstruct dpaa2_dev_priv *priv = dev->data->dev_private;\n+\n+\tgroup = attr->group;\n+\n+\t/* Parse pattern list to get the matching parameters */\n+\tspec    = (const struct rte_flow_item_tcp *)pattern->spec;\n+\tlast    = (const struct rte_flow_item_tcp *)pattern->last;\n+\tmask    = (const struct rte_flow_item_tcp *)\n+\t\t(pattern->mask ? pattern->mask : default_mask);\n+\n+\t/* Get traffic class index and flow id to be configured */\n+\tflow->tc_id = group;\n+\tflow->tc_index = attr->priority;\n+\n+\tif (!spec || !mc_l4_port_identification) {\n+\t\tstruct proto_discrimination proto;\n+\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.qos_key_extract.dpkg,\n+\t\t\t\tNET_PROT_IP, NH_FLD_IP_PROTO);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_proto_discrimination_extract(\n+\t\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t\tDPAA2_FLOW_ITEM_TYPE_GENERIC_IP);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\t\"QoS Extract IP protocol to discriminate TCP failed.\");\n+\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;\n+\t\t}\n+\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.tc_key_extract[group].dpkg,\n+\t\t\t\tNET_PROT_IP, NH_FLD_IP_PROTO);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_proto_discrimination_extract(\n+\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\tDPAA2_FLOW_ITEM_TYPE_GENERIC_IP);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\t\"FS Extract IP protocol to discriminate TCP failed.\");\n+\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_FS_TABLE_RECONFIGURE;\n+\t\t}\n+\n+\t\tret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"Move IP addr before TCP discrimination set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tproto.type = DPAA2_FLOW_ITEM_TYPE_GENERIC_IP;\n+\t\tproto.ip_proto = IPPROTO_TCP;\n+\t\tret = dpaa2_flow_proto_discrimination_rule(priv, flow,\n+\t\t\t\t\t\t\tproto, group);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"TCP discrimination rule set failed\");\n+\t\t\treturn -1;\n+\t\t}\n \n-\tgroup = attr->group;\n+\t\t(*device_configured) |= local_cfg;\n \n-\t/* DPAA2 platform has a limitation that extract parameter can not be */\n-\t/* more than DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too.*/\n-\tif (priv->pattern[8].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {\n-\t\tDPAA2_PMD_ERR(\"Maximum limit for different pattern type = %d\\n\",\n-\t\t\t\t\t\tDPKG_MAX_NUM_OF_EXTRACTS);\n-\t\treturn -ENOTSUP;\n+\t\tif (!spec)\n+\t\t\treturn 0;\n \t}\n \n-\tif (priv->pattern[group].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {\n-\t\tDPAA2_PMD_ERR(\"Maximum limit for different pattern type = %d\\n\",\n-\t\t\t\t\t\tDPKG_MAX_NUM_OF_EXTRACTS);\n-\t\treturn -ENOTSUP;\n-\t}\n+\tif (mask->hdr.src_port) {\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.qos_key_extract.dpkg,\n+\t\t\t\tNET_PROT_TCP, NH_FLD_TCP_PORT_SRC);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t\tNET_PROT_TCP,\n+\t\t\t\t\tNH_FLD_TCP_PORT_SRC,\n+\t\t\t\t\tNH_FLD_TCP_PORT_SIZE);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"QoS Extract add TCP_SRC failed.\");\n \n-\tfor (j = 0; j < priv->pattern[8].item_count; j++) {\n-\t\tif (priv->pattern[8].pattern_type[j] != pattern->type) {\n-\t\t\tcontinue;\n-\t\t} else {\n-\t\t\tentry_found = 1;\n-\t\t\tbreak;\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;\n \t\t}\n-\t}\n \n-\tif (!entry_found) {\n-\t\tpriv->pattern[8].pattern_type[j] = pattern->type;\n-\t\tpriv->pattern[8].item_count++;\n-\t\tdevice_configured |= DPAA2_QOS_TABLE_RECONFIGURE;\n-\t}\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.tc_key_extract[group].dpkg,\n+\t\t\t\tNET_PROT_TCP, NH_FLD_TCP_PORT_SRC);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t\tNET_PROT_TCP,\n+\t\t\t\t\tNH_FLD_TCP_PORT_SRC,\n+\t\t\t\t\tNH_FLD_TCP_PORT_SIZE);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"FS Extract add TCP_SRC failed.\");\n \n-\tentry_found = 0;\n-\tfor (j = 0; j < priv->pattern[group].item_count; j++) {\n-\t\tif (priv->pattern[group].pattern_type[j] != pattern->type) {\n-\t\t\tcontinue;\n-\t\t} else {\n-\t\t\tentry_found = 1;\n-\t\t\tbreak;\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_FS_TABLE_RECONFIGURE;\n \t\t}\n-\t}\n \n-\tif (!entry_found) {\n-\t\tpriv->pattern[group].pattern_type[j] = pattern->type;\n-\t\tpriv->pattern[group].item_count++;\n-\t\tdevice_configured |= DPAA2_FS_TABLE_RECONFIGURE;\n-\t}\n+\t\tret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"Move ipaddr before TCP_PORT_SRC set failed\");\n+\t\t\treturn -1;\n+\t\t}\n \n-\t/* Get traffic class index and flow id to be configured */\n-\tflow->tc_id = group;\n-\tflow->index = attr->priority;\n-\n-\tif (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) {\n-\t\tindex = priv->extract.qos_key_cfg.num_extracts;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_TCP;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_TCP_PORT_SRC;\n-\t\tindex++;\n-\n-\t\tpriv->extract.qos_key_cfg.extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_TCP;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_TCP_PORT_DST;\n-\t\tindex++;\n-\n-\t\tpriv->extract.qos_key_cfg.num_extracts = index;\n-\t}\n-\n-\tif (device_configured & DPAA2_FS_TABLE_RECONFIGURE) {\n-\t\tindex = priv->extract.fs_key_cfg[group].num_extracts;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_TCP;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_TCP_PORT_SRC;\n-\t\tindex++;\n-\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_TCP;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_TCP_PORT_DST;\n-\t\tindex++;\n-\n-\t\tpriv->extract.fs_key_cfg[group].num_extracts = index;\n+\t\tret = dpaa2_flow_rule_data_set(\n+\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t&flow->qos_rule,\n+\t\t\t\tNET_PROT_TCP,\n+\t\t\t\tNH_FLD_TCP_PORT_SRC,\n+\t\t\t\t&spec->hdr.src_port,\n+\t\t\t\t&mask->hdr.src_port,\n+\t\t\t\tNH_FLD_TCP_PORT_SIZE);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"QoS NH_FLD_TCP_PORT_SRC rule data set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tret = dpaa2_flow_rule_data_set(\n+\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t&flow->fs_rule,\n+\t\t\t\tNET_PROT_TCP,\n+\t\t\t\tNH_FLD_TCP_PORT_SRC,\n+\t\t\t\t&spec->hdr.src_port,\n+\t\t\t\t&mask->hdr.src_port,\n+\t\t\t\tNH_FLD_TCP_PORT_SIZE);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"FS NH_FLD_TCP_PORT_SRC rule data set failed\");\n+\t\t\treturn -1;\n+\t\t}\n \t}\n \n-\t/* Parse pattern list to get the matching parameters */\n-\tspec\t= (const struct rte_flow_item_tcp *)pattern->spec;\n-\tlast\t= (const struct rte_flow_item_tcp *)pattern->last;\n-\tmask\t= (const struct rte_flow_item_tcp *)\n-\t\t\t(pattern->mask ? pattern->mask : default_mask);\n+\tif (mask->hdr.dst_port) {\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.qos_key_extract.dpkg,\n+\t\t\t\tNET_PROT_TCP, NH_FLD_TCP_PORT_DST);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t\tNET_PROT_TCP,\n+\t\t\t\t\tNH_FLD_TCP_PORT_DST,\n+\t\t\t\t\tNH_FLD_TCP_PORT_SIZE);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"QoS Extract add TCP_DST failed.\");\n+\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;\n+\t\t}\n+\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.tc_key_extract[group].dpkg,\n+\t\t\t\tNET_PROT_TCP, NH_FLD_TCP_PORT_DST);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t\tNET_PROT_TCP,\n+\t\t\t\t\tNH_FLD_TCP_PORT_DST,\n+\t\t\t\t\tNH_FLD_TCP_PORT_SIZE);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"FS Extract add TCP_DST failed.\");\n+\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_FS_TABLE_RECONFIGURE;\n+\t\t}\n \n-\tkey_iova = flow->rule.key_iova + flow->key_size;\n-\tmemcpy((void *)key_iova, (const void *)(&spec->hdr.src_port),\n-\t\t\t\t\t\t\tsizeof(uint16_t));\n-\tkey_iova += sizeof(uint16_t);\n-\tmemcpy((void *)key_iova, (const void *)(&spec->hdr.dst_port),\n-\t\t\t\t\t\t\tsizeof(uint16_t));\n+\t\tret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"Move ipaddr before TCP_PORT_DST set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tret = dpaa2_flow_rule_data_set(\n+\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t&flow->qos_rule,\n+\t\t\t\tNET_PROT_TCP,\n+\t\t\t\tNH_FLD_TCP_PORT_DST,\n+\t\t\t\t&spec->hdr.dst_port,\n+\t\t\t\t&mask->hdr.dst_port,\n+\t\t\t\tNH_FLD_TCP_PORT_SIZE);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"QoS NH_FLD_TCP_PORT_DST rule data set failed\");\n+\t\t\treturn -1;\n+\t\t}\n \n-\tmask_iova = flow->rule.mask_iova + flow->key_size;\n-\tmemcpy((void *)mask_iova, (const void *)(&mask->hdr.src_port),\n-\t\t\t\t\t\t\tsizeof(uint16_t));\n-\tmask_iova += sizeof(uint16_t);\n-\tmemcpy((void *)mask_iova, (const void *)(&mask->hdr.dst_port),\n-\t\t\t\t\t\t\tsizeof(uint16_t));\n+\t\tret = dpaa2_flow_rule_data_set(\n+\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t&flow->fs_rule,\n+\t\t\t\tNET_PROT_TCP,\n+\t\t\t\tNH_FLD_TCP_PORT_DST,\n+\t\t\t\t&spec->hdr.dst_port,\n+\t\t\t\t&mask->hdr.dst_port,\n+\t\t\t\tNH_FLD_TCP_PORT_SIZE);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"FS NH_FLD_TCP_PORT_DST rule data set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n \n-\tflow->key_size += 2 * sizeof(uint16_t);\n+\t(*device_configured) |= local_cfg;\n \n-\treturn device_configured;\n+\treturn 0;\n }\n \n static int\n@@ -1008,12 +2041,11 @@ dpaa2_configure_flow_sctp(struct rte_flow *flow,\n \t\t\t  const struct rte_flow_attr *attr,\n \t\t\t  const struct rte_flow_item *pattern,\n \t\t\t  const struct rte_flow_action actions[] __rte_unused,\n-\t\t\t  struct rte_flow_error *error __rte_unused)\n+\t\t\t  struct rte_flow_error *error __rte_unused,\n+\t\t\t  int *device_configured)\n {\n-\tint index, j = 0;\n-\tsize_t key_iova;\n-\tsize_t mask_iova;\n-\tint device_configured = 0, entry_found = 0;\n+\tint index, ret;\n+\tint local_cfg = 0;\n \tuint32_t group;\n \tconst struct rte_flow_item_sctp *spec, *mask;\n \n@@ -1022,116 +2054,218 @@ dpaa2_configure_flow_sctp(struct rte_flow *flow,\n \n \tgroup = attr->group;\n \n-\t/* DPAA2 platform has a limitation that extract parameter can not be */\n-\t/* more than DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too. */\n-\tif (priv->pattern[8].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {\n-\t\tDPAA2_PMD_ERR(\"Maximum limit for different pattern type = %d\\n\",\n-\t\t\t\t\t\tDPKG_MAX_NUM_OF_EXTRACTS);\n-\t\treturn -ENOTSUP;\n-\t}\n+\t/* Parse pattern list to get the matching parameters */\n+\tspec    = (const struct rte_flow_item_sctp *)pattern->spec;\n+\tlast    = (const struct rte_flow_item_sctp *)pattern->last;\n+\tmask    = (const struct rte_flow_item_sctp *)\n+\t\t\t(pattern->mask ? pattern->mask : default_mask);\n \n-\tif (priv->pattern[group].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {\n-\t\tDPAA2_PMD_ERR(\"Maximum limit for different pattern type = %d\\n\",\n-\t\t\t\t\t\tDPKG_MAX_NUM_OF_EXTRACTS);\n-\t\treturn -ENOTSUP;\n-\t}\n+\t/* Get traffic class index and flow id to be configured */\n+\tflow->tc_id = group;\n+\tflow->tc_index = attr->priority;\n+\n+\tif (!spec || !mc_l4_port_identification) {\n+\t\tstruct proto_discrimination proto;\n+\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.qos_key_extract.dpkg,\n+\t\t\t\tNET_PROT_IP, NH_FLD_IP_PROTO);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_proto_discrimination_extract(\n+\t\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t\tDPAA2_FLOW_ITEM_TYPE_GENERIC_IP);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\t\"QoS Extract IP protocol to discriminate SCTP failed.\");\n \n-\tfor (j = 0; j < priv->pattern[8].item_count; j++) {\n-\t\tif (priv->pattern[8].pattern_type[j] != pattern->type) {\n-\t\t\tcontinue;\n-\t\t} else {\n-\t\t\tentry_found = 1;\n-\t\t\tbreak;\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;\n \t\t}\n-\t}\n \n-\tif (!entry_found) {\n-\t\tpriv->pattern[8].pattern_type[j] = pattern->type;\n-\t\tpriv->pattern[8].item_count++;\n-\t\tdevice_configured |= DPAA2_QOS_TABLE_RECONFIGURE;\n-\t}\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.tc_key_extract[group].dpkg,\n+\t\t\t\tNET_PROT_IP, NH_FLD_IP_PROTO);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_proto_discrimination_extract(\n+\t\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t\tDPAA2_FLOW_ITEM_TYPE_GENERIC_IP);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\t\"FS Extract IP protocol to discriminate SCTP failed.\");\n \n-\tentry_found = 0;\n-\tfor (j = 0; j < priv->pattern[group].item_count; j++) {\n-\t\tif (priv->pattern[group].pattern_type[j] != pattern->type) {\n-\t\t\tcontinue;\n-\t\t} else {\n-\t\t\tentry_found = 1;\n-\t\t\tbreak;\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_FS_TABLE_RECONFIGURE;\n \t\t}\n-\t}\n \n-\tif (!entry_found) {\n-\t\tpriv->pattern[group].pattern_type[j] = pattern->type;\n-\t\tpriv->pattern[group].item_count++;\n-\t\tdevice_configured |= DPAA2_FS_TABLE_RECONFIGURE;\n+\t\tret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"Move ipaddr before SCTP discrimination set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tproto.type = DPAA2_FLOW_ITEM_TYPE_GENERIC_IP;\n+\t\tproto.ip_proto = IPPROTO_SCTP;\n+\t\tret = dpaa2_flow_proto_discrimination_rule(priv, flow,\n+\t\t\t\t\t\t\tproto, group);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"SCTP discrimination rule set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\t(*device_configured) |= local_cfg;\n+\n+\t\tif (!spec)\n+\t\t\treturn 0;\n \t}\n \n-\t/* Get traffic class index and flow id to be configured */\n-\tflow->tc_id = group;\n-\tflow->index = attr->priority;\n-\n-\tif (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) {\n-\t\tindex = priv->extract.qos_key_cfg.num_extracts;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_SCTP;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_SCTP_PORT_SRC;\n-\t\tindex++;\n-\n-\t\tpriv->extract.qos_key_cfg.extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_SCTP;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_SCTP_PORT_DST;\n-\t\tindex++;\n-\n-\t\tpriv->extract.qos_key_cfg.num_extracts = index;\n-\t}\n-\n-\tif (device_configured & DPAA2_FS_TABLE_RECONFIGURE) {\n-\t\tindex = priv->extract.fs_key_cfg[group].num_extracts;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_SCTP;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_SCTP_PORT_SRC;\n-\t\tindex++;\n-\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_SCTP;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_SCTP_PORT_DST;\n-\t\tindex++;\n-\n-\t\tpriv->extract.fs_key_cfg[group].num_extracts = index;\n+\tif (mask->hdr.src_port) {\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.qos_key_extract.dpkg,\n+\t\t\t\tNET_PROT_SCTP, NH_FLD_SCTP_PORT_SRC);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t\tNET_PROT_SCTP,\n+\t\t\t\t\tNH_FLD_SCTP_PORT_SRC,\n+\t\t\t\t\tNH_FLD_SCTP_PORT_SIZE);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"QoS Extract add SCTP_SRC failed.\");\n+\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;\n+\t\t}\n+\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.tc_key_extract[group].dpkg,\n+\t\t\t\tNET_PROT_SCTP, NH_FLD_SCTP_PORT_SRC);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t\tNET_PROT_SCTP,\n+\t\t\t\t\tNH_FLD_SCTP_PORT_SRC,\n+\t\t\t\t\tNH_FLD_SCTP_PORT_SIZE);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"FS Extract add SCTP_SRC failed.\");\n+\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_FS_TABLE_RECONFIGURE;\n+\t\t}\n+\n+\t\tret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"Move ipaddr before SCTP_PORT_SRC set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tret = dpaa2_flow_rule_data_set(\n+\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t&flow->qos_rule,\n+\t\t\t\tNET_PROT_SCTP,\n+\t\t\t\tNH_FLD_SCTP_PORT_SRC,\n+\t\t\t\t&spec->hdr.src_port,\n+\t\t\t\t&mask->hdr.src_port,\n+\t\t\t\tNH_FLD_SCTP_PORT_SIZE);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"QoS NH_FLD_SCTP_PORT_SRC rule data set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tret = dpaa2_flow_rule_data_set(\n+\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t&flow->fs_rule,\n+\t\t\t\tNET_PROT_SCTP,\n+\t\t\t\tNH_FLD_SCTP_PORT_SRC,\n+\t\t\t\t&spec->hdr.src_port,\n+\t\t\t\t&mask->hdr.src_port,\n+\t\t\t\tNH_FLD_SCTP_PORT_SIZE);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"FS NH_FLD_SCTP_PORT_SRC rule data set failed\");\n+\t\t\treturn -1;\n+\t\t}\n \t}\n \n-\t/* Parse pattern list to get the matching parameters */\n-\tspec\t= (const struct rte_flow_item_sctp *)pattern->spec;\n-\tlast\t= (const struct rte_flow_item_sctp *)pattern->last;\n-\tmask\t= (const struct rte_flow_item_sctp *)\n-\t\t\t(pattern->mask ? pattern->mask : default_mask);\n+\tif (mask->hdr.dst_port) {\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.qos_key_extract.dpkg,\n+\t\t\t\tNET_PROT_SCTP, NH_FLD_SCTP_PORT_DST);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t\tNET_PROT_SCTP,\n+\t\t\t\t\tNH_FLD_SCTP_PORT_DST,\n+\t\t\t\t\tNH_FLD_SCTP_PORT_SIZE);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"QoS Extract add SCTP_DST failed.\");\n+\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;\n+\t\t}\n+\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.tc_key_extract[group].dpkg,\n+\t\t\t\tNET_PROT_SCTP, NH_FLD_SCTP_PORT_DST);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t\tNET_PROT_SCTP,\n+\t\t\t\t\tNH_FLD_SCTP_PORT_DST,\n+\t\t\t\t\tNH_FLD_SCTP_PORT_SIZE);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"FS Extract add SCTP_DST failed.\");\n+\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_FS_TABLE_RECONFIGURE;\n+\t\t}\n+\n+\t\tret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"Move ipaddr before SCTP_PORT_DST set failed\");\n+\t\t\treturn -1;\n+\t\t}\n \n-\tkey_iova = flow->rule.key_iova + flow->key_size;\n-\tmemcpy((void *)key_iova, (const void *)(&spec->hdr.src_port),\n-\t\t\t\t\t\t\tsizeof(uint16_t));\n-\tkey_iova += sizeof(uint16_t);\n-\tmemcpy((void *)key_iova, (const void *)(&spec->hdr.dst_port),\n-\t\t\t\t\t\t\tsizeof(uint16_t));\n+\t\tret = dpaa2_flow_rule_data_set(\n+\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t&flow->qos_rule,\n+\t\t\t\tNET_PROT_SCTP,\n+\t\t\t\tNH_FLD_SCTP_PORT_DST,\n+\t\t\t\t&spec->hdr.dst_port,\n+\t\t\t\t&mask->hdr.dst_port,\n+\t\t\t\tNH_FLD_SCTP_PORT_SIZE);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"QoS NH_FLD_SCTP_PORT_DST rule data set failed\");\n+\t\t\treturn -1;\n+\t\t}\n \n-\tmask_iova = flow->rule.mask_iova + flow->key_size;\n-\tmemcpy((void *)mask_iova, (const void *)(&mask->hdr.src_port),\n-\t\t\t\t\t\t\tsizeof(uint16_t));\n-\tmask_iova += sizeof(uint16_t);\n-\tmemcpy((void *)mask_iova, (const void *)(&mask->hdr.dst_port),\n-\t\t\t\t\t\t\tsizeof(uint16_t));\n+\t\tret = dpaa2_flow_rule_data_set(\n+\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t&flow->fs_rule,\n+\t\t\t\tNET_PROT_SCTP,\n+\t\t\t\tNH_FLD_SCTP_PORT_DST,\n+\t\t\t\t&spec->hdr.dst_port,\n+\t\t\t\t&mask->hdr.dst_port,\n+\t\t\t\tNH_FLD_SCTP_PORT_SIZE);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"FS NH_FLD_SCTP_PORT_DST rule data set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n \n-\tflow->key_size += 2 * sizeof(uint16_t);\n+\t(*device_configured) |= local_cfg;\n \n-\treturn device_configured;\n+\treturn 0;\n }\n \n static int\n@@ -1140,12 +2274,11 @@ dpaa2_configure_flow_gre(struct rte_flow *flow,\n \t\t\t const struct rte_flow_attr *attr,\n \t\t\t const struct rte_flow_item *pattern,\n \t\t\t const struct rte_flow_action actions[] __rte_unused,\n-\t\t\t struct rte_flow_error *error __rte_unused)\n+\t\t\t struct rte_flow_error *error __rte_unused,\n+\t\t\t int *device_configured)\n {\n-\tint index, j = 0;\n-\tsize_t key_iova;\n-\tsize_t mask_iova;\n-\tint device_configured = 0, entry_found = 0;\n+\tint index, ret;\n+\tint local_cfg = 0;\n \tuint32_t group;\n \tconst struct rte_flow_item_gre *spec, *mask;\n \n@@ -1154,96 +2287,413 @@ dpaa2_configure_flow_gre(struct rte_flow *flow,\n \n \tgroup = attr->group;\n \n-\t/* DPAA2 platform has a limitation that extract parameter can not be */\n-\t/* more than DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too. */\n-\tif (priv->pattern[8].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {\n-\t\tDPAA2_PMD_ERR(\"Maximum limit for different pattern type = %d\\n\",\n-\t\t\t\t\t\tDPKG_MAX_NUM_OF_EXTRACTS);\n-\t\treturn -ENOTSUP;\n-\t}\n+\t/* Parse pattern list to get the matching parameters */\n+\tspec    = (const struct rte_flow_item_gre *)pattern->spec;\n+\tlast    = (const struct rte_flow_item_gre *)pattern->last;\n+\tmask    = (const struct rte_flow_item_gre *)\n+\t\t(pattern->mask ? pattern->mask : default_mask);\n+\n+\t/* Get traffic class index and flow id to be configured */\n+\tflow->tc_id = group;\n+\tflow->tc_index = attr->priority;\n+\n+\tif (!spec) {\n+\t\tstruct proto_discrimination proto;\n+\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.qos_key_extract.dpkg,\n+\t\t\t\tNET_PROT_IP, NH_FLD_IP_PROTO);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_proto_discrimination_extract(\n+\t\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t\tDPAA2_FLOW_ITEM_TYPE_GENERIC_IP);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\t\"QoS Extract IP protocol to discriminate GRE failed.\");\n+\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;\n+\t\t}\n+\n+\t\tindex = dpaa2_flow_extract_search(\n+\t\t\t\t&priv->extract.tc_key_extract[group].dpkg,\n+\t\t\t\tNET_PROT_IP, NH_FLD_IP_PROTO);\n+\t\tif (index < 0) {\n+\t\t\tret = dpaa2_flow_proto_discrimination_extract(\n+\t\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\t\tDPAA2_FLOW_ITEM_TYPE_GENERIC_IP);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\t\"FS Extract IP protocol to discriminate GRE failed.\");\n+\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tlocal_cfg |= DPAA2_FS_TABLE_RECONFIGURE;\n+\t\t}\n \n-\tif (priv->pattern[group].item_count >= DPKG_MAX_NUM_OF_EXTRACTS) {\n-\t\tDPAA2_PMD_ERR(\"Maximum limit for different pattern type = %d\\n\",\n-\t\t\t\t\t\tDPKG_MAX_NUM_OF_EXTRACTS);\n-\t\treturn -ENOTSUP;\n+\t\tret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\n+\t\t\t\t\"Move IP addr before GRE discrimination set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tproto.type = DPAA2_FLOW_ITEM_TYPE_GENERIC_IP;\n+\t\tproto.ip_proto = IPPROTO_GRE;\n+\t\tret = dpaa2_flow_proto_discrimination_rule(priv, flow,\n+\t\t\t\t\t\t\tproto, group);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"GRE discrimination rule set failed\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\t(*device_configured) |= local_cfg;\n+\n+\t\treturn 0;\n \t}\n \n-\tfor (j = 0; j < priv->pattern[8].item_count; j++) {\n-\t\tif (priv->pattern[8].pattern_type[j] != pattern->type) {\n-\t\t\tcontinue;\n-\t\t} else {\n-\t\t\tentry_found = 1;\n-\t\t\tbreak;\n+\tif (!mask->protocol)\n+\t\treturn 0;\n+\n+\tindex = dpaa2_flow_extract_search(\n+\t\t\t&priv->extract.qos_key_extract.dpkg,\n+\t\t\tNET_PROT_GRE, NH_FLD_GRE_TYPE);\n+\tif (index < 0) {\n+\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\tNET_PROT_GRE,\n+\t\t\t\tNH_FLD_GRE_TYPE,\n+\t\t\t\tsizeof(rte_be16_t));\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"QoS Extract add GRE_TYPE failed.\");\n+\n+\t\t\treturn -1;\n+\t\t}\n+\t\tlocal_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;\n+\t}\n+\n+\tindex = dpaa2_flow_extract_search(\n+\t\t\t&priv->extract.tc_key_extract[group].dpkg,\n+\t\t\tNET_PROT_GRE, NH_FLD_GRE_TYPE);\n+\tif (index < 0) {\n+\t\tret = dpaa2_flow_extract_add(\n+\t\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t\tNET_PROT_GRE,\n+\t\t\t\tNH_FLD_GRE_TYPE,\n+\t\t\t\tsizeof(rte_be16_t));\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"FS Extract add GRE_TYPE failed.\");\n+\n+\t\t\treturn -1;\n \t\t}\n+\t\tlocal_cfg |= DPAA2_FS_TABLE_RECONFIGURE;\n \t}\n \n-\tif (!entry_found) {\n-\t\tpriv->pattern[8].pattern_type[j] = pattern->type;\n-\t\tpriv->pattern[8].item_count++;\n-\t\tdevice_configured |= DPAA2_QOS_TABLE_RECONFIGURE;\n+\tret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);\n+\tif (ret) {\n+\t\tDPAA2_PMD_ERR(\n+\t\t\t\"Move ipaddr before GRE_TYPE set failed\");\n+\t\treturn -1;\n+\t}\n+\n+\tret = dpaa2_flow_rule_data_set(\n+\t\t\t\t&priv->extract.qos_key_extract,\n+\t\t\t\t&flow->qos_rule,\n+\t\t\t\tNET_PROT_GRE,\n+\t\t\t\tNH_FLD_GRE_TYPE,\n+\t\t\t\t&spec->protocol,\n+\t\t\t\t&mask->protocol,\n+\t\t\t\tsizeof(rte_be16_t));\n+\tif (ret) {\n+\t\tDPAA2_PMD_ERR(\n+\t\t\t\"QoS NH_FLD_GRE_TYPE rule data set failed\");\n+\t\treturn -1;\n+\t}\n+\n+\tret = dpaa2_flow_rule_data_set(\n+\t\t\t&priv->extract.tc_key_extract[group],\n+\t\t\t&flow->fs_rule,\n+\t\t\tNET_PROT_GRE,\n+\t\t\tNH_FLD_GRE_TYPE,\n+\t\t\t&spec->protocol,\n+\t\t\t&mask->protocol,\n+\t\t\tsizeof(rte_be16_t));\n+\tif (ret) {\n+\t\tDPAA2_PMD_ERR(\n+\t\t\t\"FS NH_FLD_GRE_TYPE rule data set failed\");\n+\t\treturn -1;\n \t}\n \n-\tentry_found = 0;\n-\tfor (j = 0; j < priv->pattern[group].item_count; j++) {\n-\t\tif (priv->pattern[group].pattern_type[j] != pattern->type) {\n+\t(*device_configured) |= local_cfg;\n+\n+\treturn 0;\n+}\n+\n+/* The existing QoS/FS entry with IP address(es)\n+ * needs update after\n+ * new extract(s) are inserted before IP\n+ * address(es) extract(s).\n+ */\n+static int\n+dpaa2_flow_entry_update(\n+\tstruct dpaa2_dev_priv *priv, uint8_t tc_id)\n+{\n+\tstruct rte_flow *curr = LIST_FIRST(&priv->flows);\n+\tstruct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;\n+\tint ret;\n+\tint qos_ipsrc_offset = -1, qos_ipdst_offset = -1;\n+\tint fs_ipsrc_offset = -1, fs_ipdst_offset = -1;\n+\tstruct dpaa2_key_extract *qos_key_extract =\n+\t\t&priv->extract.qos_key_extract;\n+\tstruct dpaa2_key_extract *tc_key_extract =\n+\t\t&priv->extract.tc_key_extract[tc_id];\n+\tchar ipsrc_key[NH_FLD_IPV6_ADDR_SIZE];\n+\tchar ipdst_key[NH_FLD_IPV6_ADDR_SIZE];\n+\tchar ipsrc_mask[NH_FLD_IPV6_ADDR_SIZE];\n+\tchar ipdst_mask[NH_FLD_IPV6_ADDR_SIZE];\n+\tint extend = -1, extend1, size;\n+\n+\twhile (curr) {\n+\t\tif (curr->ipaddr_rule.ipaddr_type ==\n+\t\t\tFLOW_NONE_IPADDR) {\n+\t\t\tcurr = LIST_NEXT(curr, next);\n \t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (curr->ipaddr_rule.ipaddr_type ==\n+\t\t\tFLOW_IPV4_ADDR) {\n+\t\t\tqos_ipsrc_offset =\n+\t\t\t\tqos_key_extract->key_info.ipv4_src_offset;\n+\t\t\tqos_ipdst_offset =\n+\t\t\t\tqos_key_extract->key_info.ipv4_dst_offset;\n+\t\t\tfs_ipsrc_offset =\n+\t\t\t\ttc_key_extract->key_info.ipv4_src_offset;\n+\t\t\tfs_ipdst_offset =\n+\t\t\t\ttc_key_extract->key_info.ipv4_dst_offset;\n+\t\t\tsize = NH_FLD_IPV4_ADDR_SIZE;\n \t\t} else {\n-\t\t\tentry_found = 1;\n-\t\t\tbreak;\n+\t\t\tqos_ipsrc_offset =\n+\t\t\t\tqos_key_extract->key_info.ipv6_src_offset;\n+\t\t\tqos_ipdst_offset =\n+\t\t\t\tqos_key_extract->key_info.ipv6_dst_offset;\n+\t\t\tfs_ipsrc_offset =\n+\t\t\t\ttc_key_extract->key_info.ipv6_src_offset;\n+\t\t\tfs_ipdst_offset =\n+\t\t\t\ttc_key_extract->key_info.ipv6_dst_offset;\n+\t\t\tsize = NH_FLD_IPV6_ADDR_SIZE;\n \t\t}\n-\t}\n \n-\tif (!entry_found) {\n-\t\tpriv->pattern[group].pattern_type[j] = pattern->type;\n-\t\tpriv->pattern[group].item_count++;\n-\t\tdevice_configured |= DPAA2_FS_TABLE_RECONFIGURE;\n-\t}\n+\t\tret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW,\n+\t\t\t\tpriv->token, &curr->qos_rule);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"Qos entry remove failed.\");\n+\t\t\treturn -1;\n+\t\t}\n \n-\t/* Get traffic class index and flow id to be configured */\n-\tflow->tc_id = group;\n-\tflow->index = attr->priority;\n+\t\textend = -1;\n+\n+\t\tif (curr->ipaddr_rule.qos_ipsrc_offset >= 0) {\n+\t\t\tRTE_ASSERT(qos_ipsrc_offset >=\n+\t\t\t\tcurr->ipaddr_rule.qos_ipsrc_offset);\n+\t\t\textend1 = qos_ipsrc_offset -\n+\t\t\t\tcurr->ipaddr_rule.qos_ipsrc_offset;\n+\t\t\tif (extend >= 0)\n+\t\t\t\tRTE_ASSERT(extend == extend1);\n+\t\t\telse\n+\t\t\t\textend = extend1;\n+\n+\t\t\tmemcpy(ipsrc_key,\n+\t\t\t\t(char *)(size_t)curr->qos_rule.key_iova +\n+\t\t\t\tcurr->ipaddr_rule.qos_ipsrc_offset,\n+\t\t\t\tsize);\n+\t\t\tmemset((char *)(size_t)curr->qos_rule.key_iova +\n+\t\t\t\tcurr->ipaddr_rule.qos_ipsrc_offset,\n+\t\t\t\t0, size);\n+\n+\t\t\tmemcpy(ipsrc_mask,\n+\t\t\t\t(char *)(size_t)curr->qos_rule.mask_iova +\n+\t\t\t\tcurr->ipaddr_rule.qos_ipsrc_offset,\n+\t\t\t\tsize);\n+\t\t\tmemset((char *)(size_t)curr->qos_rule.mask_iova +\n+\t\t\t\tcurr->ipaddr_rule.qos_ipsrc_offset,\n+\t\t\t\t0, size);\n+\n+\t\t\tcurr->ipaddr_rule.qos_ipsrc_offset = qos_ipsrc_offset;\n+\t\t}\n \n-\tif (device_configured & DPAA2_QOS_TABLE_RECONFIGURE) {\n-\t\tindex = priv->extract.qos_key_cfg.num_extracts;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.prot = NET_PROT_GRE;\n-\t\tpriv->extract.qos_key_cfg.extracts[index].extract.from_hdr.field = NH_FLD_GRE_TYPE;\n-\t\tindex++;\n+\t\tif (curr->ipaddr_rule.qos_ipdst_offset >= 0) {\n+\t\t\tRTE_ASSERT(qos_ipdst_offset >=\n+\t\t\t\tcurr->ipaddr_rule.qos_ipdst_offset);\n+\t\t\textend1 = qos_ipdst_offset -\n+\t\t\t\tcurr->ipaddr_rule.qos_ipdst_offset;\n+\t\t\tif (extend >= 0)\n+\t\t\t\tRTE_ASSERT(extend == extend1);\n+\t\t\telse\n+\t\t\t\textend = extend1;\n+\n+\t\t\tmemcpy(ipdst_key,\n+\t\t\t\t(char *)(size_t)curr->qos_rule.key_iova +\n+\t\t\t\tcurr->ipaddr_rule.qos_ipdst_offset,\n+\t\t\t\tsize);\n+\t\t\tmemset((char *)(size_t)curr->qos_rule.key_iova +\n+\t\t\t\tcurr->ipaddr_rule.qos_ipdst_offset,\n+\t\t\t\t0, size);\n+\n+\t\t\tmemcpy(ipdst_mask,\n+\t\t\t\t(char *)(size_t)curr->qos_rule.mask_iova +\n+\t\t\t\tcurr->ipaddr_rule.qos_ipdst_offset,\n+\t\t\t\tsize);\n+\t\t\tmemset((char *)(size_t)curr->qos_rule.mask_iova +\n+\t\t\t\tcurr->ipaddr_rule.qos_ipdst_offset,\n+\t\t\t\t0, size);\n+\n+\t\t\tcurr->ipaddr_rule.qos_ipdst_offset = qos_ipdst_offset;\n+\t\t}\n \n-\t\tpriv->extract.qos_key_cfg.num_extracts = index;\n-\t}\n+\t\tif (curr->ipaddr_rule.qos_ipsrc_offset >= 0) {\n+\t\t\tmemcpy((char *)(size_t)curr->qos_rule.key_iova +\n+\t\t\t\tcurr->ipaddr_rule.qos_ipsrc_offset,\n+\t\t\t\tipsrc_key,\n+\t\t\t\tsize);\n+\t\t\tmemcpy((char *)(size_t)curr->qos_rule.mask_iova +\n+\t\t\t\tcurr->ipaddr_rule.qos_ipsrc_offset,\n+\t\t\t\tipsrc_mask,\n+\t\t\t\tsize);\n+\t\t}\n+\t\tif (curr->ipaddr_rule.qos_ipdst_offset >= 0) {\n+\t\t\tmemcpy((char *)(size_t)curr->qos_rule.key_iova +\n+\t\t\t\tcurr->ipaddr_rule.qos_ipdst_offset,\n+\t\t\t\tipdst_key,\n+\t\t\t\tsize);\n+\t\t\tmemcpy((char *)(size_t)curr->qos_rule.mask_iova +\n+\t\t\t\tcurr->ipaddr_rule.qos_ipdst_offset,\n+\t\t\t\tipdst_mask,\n+\t\t\t\tsize);\n+\t\t}\n \n-\tif (device_configured & DPAA2_FS_TABLE_RECONFIGURE) {\n-\t\tindex = priv->extract.fs_key_cfg[group].num_extracts;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].type =\n-\t\t\t\t\t\t\tDPKG_EXTRACT_FROM_HDR;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.prot = NET_PROT_GRE;\n-\t\tpriv->extract.fs_key_cfg[group].extracts[index].extract.from_hdr.field = NH_FLD_GRE_TYPE;\n-\t\tindex++;\n+\t\tif (extend >= 0)\n+\t\t\tcurr->qos_rule.key_size += extend;\n \n-\t\tpriv->extract.fs_key_cfg[group].num_extracts = index;\n-\t}\n+\t\tret = dpni_add_qos_entry(dpni, CMD_PRI_LOW,\n+\t\t\t\tpriv->token, &curr->qos_rule,\n+\t\t\t\tcurr->tc_id, curr->qos_index,\n+\t\t\t\t0, 0);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"Qos entry update failed.\");\n+\t\t\treturn -1;\n+\t\t}\n \n-\t/* Parse pattern list to get the matching parameters */\n-\tspec\t= (const struct rte_flow_item_gre *)pattern->spec;\n-\tlast\t= (const struct rte_flow_item_gre *)pattern->last;\n-\tmask\t= (const struct rte_flow_item_gre *)\n-\t\t\t(pattern->mask ? pattern->mask : default_mask);\n+\t\tif (curr->action != RTE_FLOW_ACTION_TYPE_QUEUE) {\n+\t\t\tcurr = LIST_NEXT(curr, next);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\textend = -1;\n+\n+\t\tret = dpni_remove_fs_entry(dpni, CMD_PRI_LOW,\n+\t\t\t\tpriv->token, curr->tc_id, &curr->fs_rule);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"FS entry remove failed.\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tif (curr->ipaddr_rule.fs_ipsrc_offset >= 0 &&\n+\t\t\ttc_id == curr->tc_id) {\n+\t\t\tRTE_ASSERT(fs_ipsrc_offset >=\n+\t\t\t\tcurr->ipaddr_rule.fs_ipsrc_offset);\n+\t\t\textend1 = fs_ipsrc_offset -\n+\t\t\t\tcurr->ipaddr_rule.fs_ipsrc_offset;\n+\t\t\tif (extend >= 0)\n+\t\t\t\tRTE_ASSERT(extend == extend1);\n+\t\t\telse\n+\t\t\t\textend = extend1;\n+\n+\t\t\tmemcpy(ipsrc_key,\n+\t\t\t\t(char *)(size_t)curr->fs_rule.key_iova +\n+\t\t\t\tcurr->ipaddr_rule.fs_ipsrc_offset,\n+\t\t\t\tsize);\n+\t\t\tmemset((char *)(size_t)curr->fs_rule.key_iova +\n+\t\t\t\tcurr->ipaddr_rule.fs_ipsrc_offset,\n+\t\t\t\t0, size);\n+\n+\t\t\tmemcpy(ipsrc_mask,\n+\t\t\t\t(char *)(size_t)curr->fs_rule.mask_iova +\n+\t\t\t\tcurr->ipaddr_rule.fs_ipsrc_offset,\n+\t\t\t\tsize);\n+\t\t\tmemset((char *)(size_t)curr->fs_rule.mask_iova +\n+\t\t\t\tcurr->ipaddr_rule.fs_ipsrc_offset,\n+\t\t\t\t0, size);\n+\n+\t\t\tcurr->ipaddr_rule.fs_ipsrc_offset = fs_ipsrc_offset;\n+\t\t}\n+\n+\t\tif (curr->ipaddr_rule.fs_ipdst_offset >= 0 &&\n+\t\t\ttc_id == curr->tc_id) {\n+\t\t\tRTE_ASSERT(fs_ipdst_offset >=\n+\t\t\t\tcurr->ipaddr_rule.fs_ipdst_offset);\n+\t\t\textend1 = fs_ipdst_offset -\n+\t\t\t\tcurr->ipaddr_rule.fs_ipdst_offset;\n+\t\t\tif (extend >= 0)\n+\t\t\t\tRTE_ASSERT(extend == extend1);\n+\t\t\telse\n+\t\t\t\textend = extend1;\n+\n+\t\t\tmemcpy(ipdst_key,\n+\t\t\t\t(char *)(size_t)curr->fs_rule.key_iova +\n+\t\t\t\tcurr->ipaddr_rule.fs_ipdst_offset,\n+\t\t\t\tsize);\n+\t\t\tmemset((char *)(size_t)curr->fs_rule.key_iova +\n+\t\t\t\tcurr->ipaddr_rule.fs_ipdst_offset,\n+\t\t\t\t0, size);\n+\n+\t\t\tmemcpy(ipdst_mask,\n+\t\t\t\t(char *)(size_t)curr->fs_rule.mask_iova +\n+\t\t\t\tcurr->ipaddr_rule.fs_ipdst_offset,\n+\t\t\t\tsize);\n+\t\t\tmemset((char *)(size_t)curr->fs_rule.mask_iova +\n+\t\t\t\tcurr->ipaddr_rule.fs_ipdst_offset,\n+\t\t\t\t0, size);\n+\n+\t\t\tcurr->ipaddr_rule.fs_ipdst_offset = fs_ipdst_offset;\n+\t\t}\n+\n+\t\tif (curr->ipaddr_rule.fs_ipsrc_offset >= 0) {\n+\t\t\tmemcpy((char *)(size_t)curr->fs_rule.key_iova +\n+\t\t\t\tcurr->ipaddr_rule.fs_ipsrc_offset,\n+\t\t\t\tipsrc_key,\n+\t\t\t\tsize);\n+\t\t\tmemcpy((char *)(size_t)curr->fs_rule.mask_iova +\n+\t\t\t\tcurr->ipaddr_rule.fs_ipsrc_offset,\n+\t\t\t\tipsrc_mask,\n+\t\t\t\tsize);\n+\t\t}\n+\t\tif (curr->ipaddr_rule.fs_ipdst_offset >= 0) {\n+\t\t\tmemcpy((char *)(size_t)curr->fs_rule.key_iova +\n+\t\t\t\tcurr->ipaddr_rule.fs_ipdst_offset,\n+\t\t\t\tipdst_key,\n+\t\t\t\tsize);\n+\t\t\tmemcpy((char *)(size_t)curr->fs_rule.mask_iova +\n+\t\t\t\tcurr->ipaddr_rule.fs_ipdst_offset,\n+\t\t\t\tipdst_mask,\n+\t\t\t\tsize);\n+\t\t}\n \n-\tkey_iova = flow->rule.key_iova + flow->key_size;\n-\tmemcpy((void *)key_iova, (const void *)(&spec->protocol),\n-\t\t\t\t\t\t\tsizeof(rte_be16_t));\n+\t\tif (extend >= 0)\n+\t\t\tcurr->fs_rule.key_size += extend;\n \n-\tmask_iova = flow->rule.mask_iova + flow->key_size;\n-\tmemcpy((void *)mask_iova, (const void *)(&mask->protocol),\n-\t\t\t\t\t\t\tsizeof(rte_be16_t));\n+\t\tret = dpni_add_fs_entry(dpni, CMD_PRI_LOW,\n+\t\t\t\tpriv->token, curr->tc_id, curr->fs_index,\n+\t\t\t\t&curr->fs_rule, &curr->action_cfg);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"FS entry update failed.\");\n+\t\t\treturn -1;\n+\t\t}\n \n-\tflow->key_size += sizeof(rte_be16_t);\n+\t\tcurr = LIST_NEXT(curr, next);\n+\t}\n \n-\treturn device_configured;\n+\treturn 0;\n }\n \n static int\n@@ -1262,7 +2712,6 @@ dpaa2_generic_flow_set(struct rte_flow *flow,\n \tstruct dpni_attr nic_attr;\n \tstruct dpni_rx_tc_dist_cfg tc_cfg;\n \tstruct dpni_qos_tbl_cfg qos_cfg;\n-\tstruct dpkg_profile_cfg key_cfg;\n \tstruct dpni_fs_action_cfg action;\n \tstruct dpaa2_dev_priv *priv = dev->data->dev_private;\n \tstruct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;\n@@ -1273,75 +2722,77 @@ dpaa2_generic_flow_set(struct rte_flow *flow,\n \twhile (!end_of_list) {\n \t\tswitch (pattern[i].type) {\n \t\tcase RTE_FLOW_ITEM_TYPE_ETH:\n-\t\t\tis_keycfg_configured = dpaa2_configure_flow_eth(flow,\n-\t\t\t\t\t\t\t\t\tdev,\n-\t\t\t\t\t\t\t\t\tattr,\n-\t\t\t\t\t\t\t\t\t&pattern[i],\n-\t\t\t\t\t\t\t\t\tactions,\n-\t\t\t\t\t\t\t\t\terror);\n+\t\t\tret = dpaa2_configure_flow_eth(flow,\n+\t\t\t\t\tdev, attr, &pattern[i], actions, error,\n+\t\t\t\t\t&is_keycfg_configured);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"ETH flow configuration failed!\");\n+\t\t\t\treturn ret;\n+\t\t\t}\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ITEM_TYPE_VLAN:\n-\t\t\tis_keycfg_configured = dpaa2_configure_flow_vlan(flow,\n-\t\t\t\t\t\t\t\t\tdev,\n-\t\t\t\t\t\t\t\t\tattr,\n-\t\t\t\t\t\t\t\t\t&pattern[i],\n-\t\t\t\t\t\t\t\t\tactions,\n-\t\t\t\t\t\t\t\t\terror);\n+\t\t\tret = dpaa2_configure_flow_vlan(flow,\n+\t\t\t\t\tdev, attr, &pattern[i], actions, error,\n+\t\t\t\t\t&is_keycfg_configured);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"vLan flow configuration failed!\");\n+\t\t\t\treturn ret;\n+\t\t\t}\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ITEM_TYPE_IPV4:\n-\t\t\tis_keycfg_configured = dpaa2_configure_flow_ipv4(flow,\n-\t\t\t\t\t\t\t\t\tdev,\n-\t\t\t\t\t\t\t\t\tattr,\n-\t\t\t\t\t\t\t\t\t&pattern[i],\n-\t\t\t\t\t\t\t\t\tactions,\n-\t\t\t\t\t\t\t\t\terror);\n-\t\t\tbreak;\n \t\tcase RTE_FLOW_ITEM_TYPE_IPV6:\n-\t\t\tis_keycfg_configured = dpaa2_configure_flow_ipv6(flow,\n-\t\t\t\t\t\t\t\t\tdev,\n-\t\t\t\t\t\t\t\t\tattr,\n-\t\t\t\t\t\t\t\t\t&pattern[i],\n-\t\t\t\t\t\t\t\t\tactions,\n-\t\t\t\t\t\t\t\t\terror);\n+\t\t\tret = dpaa2_configure_flow_generic_ip(flow,\n+\t\t\t\t\tdev, attr, &pattern[i], actions, error,\n+\t\t\t\t\t&is_keycfg_configured);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"IP flow configuration failed!\");\n+\t\t\t\treturn ret;\n+\t\t\t}\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ITEM_TYPE_ICMP:\n-\t\t\tis_keycfg_configured = dpaa2_configure_flow_icmp(flow,\n-\t\t\t\t\t\t\t\t\tdev,\n-\t\t\t\t\t\t\t\t\tattr,\n-\t\t\t\t\t\t\t\t\t&pattern[i],\n-\t\t\t\t\t\t\t\t\tactions,\n-\t\t\t\t\t\t\t\t\terror);\n+\t\t\tret = dpaa2_configure_flow_icmp(flow,\n+\t\t\t\t\tdev, attr, &pattern[i], actions, error,\n+\t\t\t\t\t&is_keycfg_configured);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"ICMP flow configuration failed!\");\n+\t\t\t\treturn ret;\n+\t\t\t}\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ITEM_TYPE_UDP:\n-\t\t\tis_keycfg_configured = dpaa2_configure_flow_udp(flow,\n-\t\t\t\t\t\t\t\t\tdev,\n-\t\t\t\t\t\t\t\t\tattr,\n-\t\t\t\t\t\t\t\t\t&pattern[i],\n-\t\t\t\t\t\t\t\t\tactions,\n-\t\t\t\t\t\t\t\t\terror);\n+\t\t\tret = dpaa2_configure_flow_udp(flow,\n+\t\t\t\t\tdev, attr, &pattern[i], actions, error,\n+\t\t\t\t\t&is_keycfg_configured);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"UDP flow configuration failed!\");\n+\t\t\t\treturn ret;\n+\t\t\t}\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ITEM_TYPE_TCP:\n-\t\t\tis_keycfg_configured = dpaa2_configure_flow_tcp(flow,\n-\t\t\t\t\t\t\t\t\tdev,\n-\t\t\t\t\t\t\t\t\tattr,\n-\t\t\t\t\t\t\t\t\t&pattern[i],\n-\t\t\t\t\t\t\t\t\tactions,\n-\t\t\t\t\t\t\t\t\terror);\n+\t\t\tret = dpaa2_configure_flow_tcp(flow,\n+\t\t\t\t\tdev, attr, &pattern[i], actions, error,\n+\t\t\t\t\t&is_keycfg_configured);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"TCP flow configuration failed!\");\n+\t\t\t\treturn ret;\n+\t\t\t}\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ITEM_TYPE_SCTP:\n-\t\t\tis_keycfg_configured = dpaa2_configure_flow_sctp(flow,\n-\t\t\t\t\t\t\t\t\tdev, attr,\n-\t\t\t\t\t\t\t\t\t&pattern[i],\n-\t\t\t\t\t\t\t\t\tactions,\n-\t\t\t\t\t\t\t\t\terror);\n+\t\t\tret = dpaa2_configure_flow_sctp(flow,\n+\t\t\t\t\tdev, attr, &pattern[i], actions, error,\n+\t\t\t\t\t&is_keycfg_configured);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"SCTP flow configuration failed!\");\n+\t\t\t\treturn ret;\n+\t\t\t}\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ITEM_TYPE_GRE:\n-\t\t\tis_keycfg_configured = dpaa2_configure_flow_gre(flow,\n-\t\t\t\t\t\t\t\t\tdev,\n-\t\t\t\t\t\t\t\t\tattr,\n-\t\t\t\t\t\t\t\t\t&pattern[i],\n-\t\t\t\t\t\t\t\t\tactions,\n-\t\t\t\t\t\t\t\t\terror);\n+\t\t\tret = dpaa2_configure_flow_gre(flow,\n+\t\t\t\t\tdev, attr, &pattern[i], actions, error,\n+\t\t\t\t\t&is_keycfg_configured);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_ERR(\"GRE flow configuration failed!\");\n+\t\t\t\treturn ret;\n+\t\t\t}\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ITEM_TYPE_END:\n \t\t\tend_of_list = 1;\n@@ -1365,8 +2816,8 @@ dpaa2_generic_flow_set(struct rte_flow *flow,\n \t\t\tmemset(&action, 0, sizeof(struct dpni_fs_action_cfg));\n \t\t\taction.flow_id = flow->flow_id;\n \t\t\tif (is_keycfg_configured & DPAA2_QOS_TABLE_RECONFIGURE) {\n-\t\t\t\tif (dpkg_prepare_key_cfg(&priv->extract.qos_key_cfg,\n-\t\t\t\t\t\t\t (uint8_t *)(size_t)priv->extract.qos_extract_param) < 0) {\n+\t\t\t\tif (dpkg_prepare_key_cfg(&priv->extract.qos_key_extract.dpkg,\n+\t\t\t\t\t(uint8_t *)(size_t)priv->extract.qos_extract_param) < 0) {\n \t\t\t\t\tDPAA2_PMD_ERR(\n \t\t\t\t\t\"Unable to prepare extract parameters\");\n \t\t\t\t\treturn -1;\n@@ -1377,7 +2828,7 @@ dpaa2_generic_flow_set(struct rte_flow *flow,\n \t\t\t\tqos_cfg.keep_entries = true;\n \t\t\t\tqos_cfg.key_cfg_iova = (size_t)priv->extract.qos_extract_param;\n \t\t\t\tret = dpni_set_qos_table(dpni, CMD_PRI_LOW,\n-\t\t\t\t\t\t\t priv->token, &qos_cfg);\n+\t\t\t\t\t\tpriv->token, &qos_cfg);\n \t\t\t\tif (ret < 0) {\n \t\t\t\t\tDPAA2_PMD_ERR(\n \t\t\t\t\t\"Distribution cannot be configured.(%d)\"\n@@ -1386,8 +2837,10 @@ dpaa2_generic_flow_set(struct rte_flow *flow,\n \t\t\t\t}\n \t\t\t}\n \t\t\tif (is_keycfg_configured & DPAA2_FS_TABLE_RECONFIGURE) {\n-\t\t\t\tif (dpkg_prepare_key_cfg(&priv->extract.fs_key_cfg[flow->tc_id],\n-\t\t\t\t\t\t(uint8_t *)(size_t)priv->extract.fs_extract_param[flow->tc_id]) < 0) {\n+\t\t\t\tif (dpkg_prepare_key_cfg(\n+\t\t\t\t&priv->extract.tc_key_extract[flow->tc_id].dpkg,\n+\t\t\t\t(uint8_t *)(size_t)priv->extract\n+\t\t\t\t.tc_extract_param[flow->tc_id]) < 0) {\n \t\t\t\t\tDPAA2_PMD_ERR(\n \t\t\t\t\t\"Unable to prepare extract parameters\");\n \t\t\t\t\treturn -1;\n@@ -1397,7 +2850,7 @@ dpaa2_generic_flow_set(struct rte_flow *flow,\n \t\t\t\ttc_cfg.dist_size = priv->nb_rx_queues / priv->num_rx_tc;\n \t\t\t\ttc_cfg.dist_mode = DPNI_DIST_MODE_FS;\n \t\t\t\ttc_cfg.key_cfg_iova =\n-\t\t\t\t\t(uint64_t)priv->extract.fs_extract_param[flow->tc_id];\n+\t\t\t\t\t(uint64_t)priv->extract.tc_extract_param[flow->tc_id];\n \t\t\t\ttc_cfg.fs_cfg.miss_action = DPNI_FS_MISS_DROP;\n \t\t\t\ttc_cfg.fs_cfg.keep_entries = true;\n \t\t\t\tret = dpni_set_rx_tc_dist(dpni, CMD_PRI_LOW,\n@@ -1422,27 +2875,114 @@ dpaa2_generic_flow_set(struct rte_flow *flow,\n \t\t\t}\n \n \t\t\taction.flow_id = action.flow_id % nic_attr.num_rx_tcs;\n-\t\t\tindex = flow->index + (flow->tc_id * nic_attr.fs_entries);\n-\t\t\tflow->rule.key_size = flow->key_size;\n+\n+\t\t\tif (!priv->qos_index) {\n+\t\t\t\tpriv->qos_index = rte_zmalloc(0,\n+\t\t\t\t\t\tnic_attr.qos_entries, 64);\n+\t\t\t}\n+\t\t\tfor (index = 0; index < nic_attr.qos_entries; index++) {\n+\t\t\t\tif (!priv->qos_index[index]) {\n+\t\t\t\t\tpriv->qos_index[index] = 1;\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tif (index >= nic_attr.qos_entries) {\n+\t\t\t\tDPAA2_PMD_ERR(\"QoS table with %d entries full\",\n+\t\t\t\t\tnic_attr.qos_entries);\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tflow->qos_rule.key_size = priv->extract\n+\t\t\t\t.qos_key_extract.key_info.key_total_size;\n+\t\t\tif (flow->ipaddr_rule.ipaddr_type == FLOW_IPV4_ADDR) {\n+\t\t\t\tif (flow->ipaddr_rule.qos_ipdst_offset >=\n+\t\t\t\t\tflow->ipaddr_rule.qos_ipsrc_offset) {\n+\t\t\t\t\tflow->qos_rule.key_size =\n+\t\t\t\t\t\tflow->ipaddr_rule.qos_ipdst_offset +\n+\t\t\t\t\t\tNH_FLD_IPV4_ADDR_SIZE;\n+\t\t\t\t} else {\n+\t\t\t\t\tflow->qos_rule.key_size =\n+\t\t\t\t\t\tflow->ipaddr_rule.qos_ipsrc_offset +\n+\t\t\t\t\t\tNH_FLD_IPV4_ADDR_SIZE;\n+\t\t\t\t}\n+\t\t\t} else if (flow->ipaddr_rule.ipaddr_type == FLOW_IPV6_ADDR) {\n+\t\t\t\tif (flow->ipaddr_rule.qos_ipdst_offset >=\n+\t\t\t\t\tflow->ipaddr_rule.qos_ipsrc_offset) {\n+\t\t\t\t\tflow->qos_rule.key_size =\n+\t\t\t\t\t\tflow->ipaddr_rule.qos_ipdst_offset +\n+\t\t\t\t\t\tNH_FLD_IPV6_ADDR_SIZE;\n+\t\t\t\t} else {\n+\t\t\t\t\tflow->qos_rule.key_size =\n+\t\t\t\t\t\tflow->ipaddr_rule.qos_ipsrc_offset +\n+\t\t\t\t\t\tNH_FLD_IPV6_ADDR_SIZE;\n+\t\t\t\t}\n+\t\t\t}\n \t\t\tret = dpni_add_qos_entry(dpni, CMD_PRI_LOW,\n-\t\t\t\t\t\tpriv->token, &flow->rule,\n+\t\t\t\t\t\tpriv->token, &flow->qos_rule,\n \t\t\t\t\t\tflow->tc_id, index,\n \t\t\t\t\t\t0, 0);\n \t\t\tif (ret < 0) {\n \t\t\t\tDPAA2_PMD_ERR(\n \t\t\t\t\"Error in addnig entry to QoS table(%d)\", ret);\n+\t\t\t\tpriv->qos_index[index] = 0;\n \t\t\t\treturn ret;\n \t\t\t}\n+\t\t\tflow->qos_index = index;\n \n \t\t\t/* Then Configure FS table */\n+\t\t\tif (!priv->fs_index) {\n+\t\t\t\tpriv->fs_index = rte_zmalloc(0,\n+\t\t\t\t\t\t\t\tnic_attr.fs_entries, 64);\n+\t\t\t}\n+\t\t\tfor (index = 0; index < nic_attr.fs_entries; index++) {\n+\t\t\t\tif (!priv->fs_index[index]) {\n+\t\t\t\t\tpriv->fs_index[index] = 1;\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tif (index >= nic_attr.fs_entries) {\n+\t\t\t\tDPAA2_PMD_ERR(\"FS table with %d entries full\",\n+\t\t\t\t\tnic_attr.fs_entries);\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tflow->fs_rule.key_size = priv->extract\n+\t\t\t\t\t.tc_key_extract[attr->group].key_info.key_total_size;\n+\t\t\tif (flow->ipaddr_rule.ipaddr_type ==\n+\t\t\t\tFLOW_IPV4_ADDR) {\n+\t\t\t\tif (flow->ipaddr_rule.fs_ipdst_offset >=\n+\t\t\t\t\tflow->ipaddr_rule.fs_ipsrc_offset) {\n+\t\t\t\t\tflow->fs_rule.key_size =\n+\t\t\t\t\t\tflow->ipaddr_rule.fs_ipdst_offset +\n+\t\t\t\t\t\tNH_FLD_IPV4_ADDR_SIZE;\n+\t\t\t\t} else {\n+\t\t\t\t\tflow->fs_rule.key_size =\n+\t\t\t\t\t\tflow->ipaddr_rule.fs_ipsrc_offset +\n+\t\t\t\t\t\tNH_FLD_IPV4_ADDR_SIZE;\n+\t\t\t\t}\n+\t\t\t} else if (flow->ipaddr_rule.ipaddr_type ==\n+\t\t\t\tFLOW_IPV6_ADDR) {\n+\t\t\t\tif (flow->ipaddr_rule.fs_ipdst_offset >=\n+\t\t\t\t\tflow->ipaddr_rule.fs_ipsrc_offset) {\n+\t\t\t\t\tflow->fs_rule.key_size =\n+\t\t\t\t\t\tflow->ipaddr_rule.fs_ipdst_offset +\n+\t\t\t\t\t\tNH_FLD_IPV6_ADDR_SIZE;\n+\t\t\t\t} else {\n+\t\t\t\t\tflow->fs_rule.key_size =\n+\t\t\t\t\t\tflow->ipaddr_rule.fs_ipsrc_offset +\n+\t\t\t\t\t\tNH_FLD_IPV6_ADDR_SIZE;\n+\t\t\t\t}\n+\t\t\t}\n \t\t\tret = dpni_add_fs_entry(dpni, CMD_PRI_LOW, priv->token,\n-\t\t\t\t\t\tflow->tc_id, flow->index,\n-\t\t\t\t\t\t&flow->rule, &action);\n+\t\t\t\t\t\tflow->tc_id, index,\n+\t\t\t\t\t\t&flow->fs_rule, &action);\n \t\t\tif (ret < 0) {\n \t\t\t\tDPAA2_PMD_ERR(\n \t\t\t\t\"Error in adding entry to FS table(%d)\", ret);\n+\t\t\t\tpriv->fs_index[index] = 0;\n \t\t\t\treturn ret;\n \t\t\t}\n+\t\t\tflow->fs_index = index;\n+\t\t\tmemcpy(&flow->action_cfg, &action,\n+\t\t\t\tsizeof(struct dpni_fs_action_cfg));\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_RSS:\n \t\t\tret = dpni_get_attributes(dpni, CMD_PRI_LOW,\n@@ -1465,7 +3005,7 @@ dpaa2_generic_flow_set(struct rte_flow *flow,\n \n \t\t\tflow->action = RTE_FLOW_ACTION_TYPE_RSS;\n \t\t\tret = dpaa2_distset_to_dpkg_profile_cfg(rss_conf->types,\n-\t\t\t\t\t\t\t\t&key_cfg);\n+\t\t\t\t\t&priv->extract.tc_key_extract[flow->tc_id].dpkg);\n \t\t\tif (ret < 0) {\n \t\t\t\tDPAA2_PMD_ERR(\n \t\t\t\t\"unable to set flow distribution.please check queue config\\n\");\n@@ -1479,7 +3019,9 @@ dpaa2_generic_flow_set(struct rte_flow *flow,\n \t\t\t\treturn -1;\n \t\t\t}\n \n-\t\t\tif (dpkg_prepare_key_cfg(&key_cfg, (uint8_t *)param) < 0) {\n+\t\t\tif (dpkg_prepare_key_cfg(\n+\t\t\t\t&priv->extract.tc_key_extract[flow->tc_id].dpkg,\n+\t\t\t\t(uint8_t *)param) < 0) {\n \t\t\t\tDPAA2_PMD_ERR(\n \t\t\t\t\"Unable to prepare extract parameters\");\n \t\t\t\trte_free((void *)param);\n@@ -1503,8 +3045,9 @@ dpaa2_generic_flow_set(struct rte_flow *flow,\n \t\t\t}\n \n \t\t\trte_free((void *)param);\n-\t\t\tif (is_keycfg_configured & DPAA2_FS_TABLE_RECONFIGURE) {\n-\t\t\t\tif (dpkg_prepare_key_cfg(&priv->extract.qos_key_cfg,\n+\t\t\tif (is_keycfg_configured & DPAA2_QOS_TABLE_RECONFIGURE) {\n+\t\t\t\tif (dpkg_prepare_key_cfg(\n+\t\t\t\t\t&priv->extract.qos_key_extract.dpkg,\n \t\t\t\t\t(uint8_t *)(size_t)priv->extract.qos_extract_param) < 0) {\n \t\t\t\t\tDPAA2_PMD_ERR(\n \t\t\t\t\t\"Unable to prepare extract parameters\");\n@@ -1514,29 +3057,47 @@ dpaa2_generic_flow_set(struct rte_flow *flow,\n \t\t\t\t\tsizeof(struct dpni_qos_tbl_cfg));\n \t\t\t\tqos_cfg.discard_on_miss = true;\n \t\t\t\tqos_cfg.keep_entries = true;\n-\t\t\t\tqos_cfg.key_cfg_iova = (size_t)priv->extract.qos_extract_param;\n+\t\t\t\tqos_cfg.key_cfg_iova =\n+\t\t\t\t\t(size_t)priv->extract.qos_extract_param;\n \t\t\t\tret = dpni_set_qos_table(dpni, CMD_PRI_LOW,\n \t\t\t\t\t\t\t priv->token, &qos_cfg);\n \t\t\t\tif (ret < 0) {\n \t\t\t\t\tDPAA2_PMD_ERR(\n-\t\t\t\t\t\"Distribution can not be configured(%d)\\n\",\n+\t\t\t\t\t\"Distribution can't be configured %d\\n\",\n \t\t\t\t\tret);\n \t\t\t\t\treturn -1;\n \t\t\t\t}\n \t\t\t}\n \n \t\t\t/* Add Rule into QoS table */\n-\t\t\tindex = flow->index + (flow->tc_id * nic_attr.fs_entries);\n-\t\t\tflow->rule.key_size = flow->key_size;\n+\t\t\tif (!priv->qos_index) {\n+\t\t\t\tpriv->qos_index = rte_zmalloc(0,\n+\t\t\t\t\t\tnic_attr.qos_entries, 64);\n+\t\t\t}\n+\t\t\tfor (index = 0; index < nic_attr.qos_entries; index++) {\n+\t\t\t\tif (!priv->qos_index[index]) {\n+\t\t\t\t\tpriv->qos_index[index] = 1;\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tif (index >= nic_attr.qos_entries) {\n+\t\t\t\tDPAA2_PMD_ERR(\"QoS table with %d entries full\",\n+\t\t\t\t\tnic_attr.qos_entries);\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tflow->qos_rule.key_size =\n+\t\t\t  priv->extract.qos_key_extract.key_info.key_total_size;\n \t\t\tret = dpni_add_qos_entry(dpni, CMD_PRI_LOW, priv->token,\n-\t\t\t\t\t\t&flow->rule, flow->tc_id,\n+\t\t\t\t\t\t&flow->qos_rule, flow->tc_id,\n \t\t\t\t\t\tindex, 0, 0);\n \t\t\tif (ret < 0) {\n \t\t\t\tDPAA2_PMD_ERR(\n \t\t\t\t\"Error in entry addition in QoS table(%d)\",\n \t\t\t\tret);\n+\t\t\t\tpriv->qos_index[index] = 0;\n \t\t\t\treturn ret;\n \t\t\t}\n+\t\t\tflow->qos_index = index;\n \t\t\tbreak;\n \t\tcase RTE_FLOW_ACTION_TYPE_END:\n \t\t\tend_of_list = 1;\n@@ -1550,6 +3111,12 @@ dpaa2_generic_flow_set(struct rte_flow *flow,\n \t}\n \n \tif (!ret) {\n+\t\tret = dpaa2_flow_entry_update(priv, flow->tc_id);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"Flow entry update failed.\");\n+\n+\t\t\treturn -1;\n+\t\t}\n \t\t/* New rules are inserted. */\n \t\tif (!curr) {\n \t\t\tLIST_INSERT_HEAD(&priv->flows, flow, next);\n@@ -1625,15 +3192,15 @@ dpaa2_dev_update_default_mask(const struct rte_flow_item *pattern)\n }\n \n static inline int\n-dpaa2_dev_verify_patterns(struct dpaa2_dev_priv *dev_priv,\n-\t\t\t  const struct rte_flow_item pattern[])\n+dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[])\n {\n-\tunsigned int i, j, k, is_found = 0;\n+\tunsigned int i, j, is_found = 0;\n \tint ret = 0;\n \n \tfor (j = 0; pattern[j].type != RTE_FLOW_ITEM_TYPE_END; j++) {\n \t\tfor (i = 0; i < RTE_DIM(dpaa2_supported_pattern_type); i++) {\n-\t\t\tif (dpaa2_supported_pattern_type[i] == pattern[j].type) {\n+\t\t\tif (dpaa2_supported_pattern_type[i]\n+\t\t\t\t\t== pattern[j].type) {\n \t\t\t\tis_found = 1;\n \t\t\t\tbreak;\n \t\t\t}\n@@ -1653,18 +3220,6 @@ dpaa2_dev_verify_patterns(struct dpaa2_dev_priv *dev_priv,\n \t\t\tdpaa2_dev_update_default_mask(&pattern[j]);\n \t}\n \n-\t/* DPAA2 platform has a limitation that extract parameter can not be */\n-\t/* more\tthan DPKG_MAX_NUM_OF_EXTRACTS. Verify this limitation too. */\n-\tfor (i = 0; pattern[i].type != RTE_FLOW_ITEM_TYPE_END; i++) {\n-\t\tfor (j = 0; j < MAX_TCS + 1; j++) {\n-\t\t\t\tfor (k = 0; k < DPKG_MAX_NUM_OF_EXTRACTS; k++) {\n-\t\t\t\t\tif (dev_priv->pattern[j].pattern_type[k] == pattern[i].type)\n-\t\t\t\t\t\tbreak;\n-\t\t\t\t}\n-\t\t\tif (dev_priv->pattern[j].item_count >= DPKG_MAX_NUM_OF_EXTRACTS)\n-\t\t\t\tret = -ENOTSUP;\n-\t\t}\n-\t}\n \treturn ret;\n }\n \n@@ -1687,7 +3242,8 @@ dpaa2_dev_verify_actions(const struct rte_flow_action actions[])\n \t\t}\n \t}\n \tfor (j = 0; actions[j].type != RTE_FLOW_ACTION_TYPE_END; j++) {\n-\t\tif ((actions[j].type != RTE_FLOW_ACTION_TYPE_DROP) && (!actions[j].conf))\n+\t\tif ((actions[j].type\n+\t\t\t!= RTE_FLOW_ACTION_TYPE_DROP) && (!actions[j].conf))\n \t\t\tret = -EINVAL;\n \t}\n \treturn ret;\n@@ -1729,7 +3285,7 @@ int dpaa2_flow_validate(struct rte_eth_dev *dev,\n \t\tgoto not_valid_params;\n \t}\n \t/* Verify input pattern list */\n-\tret = dpaa2_dev_verify_patterns(priv, pattern);\n+\tret = dpaa2_dev_verify_patterns(pattern);\n \tif (ret < 0) {\n \t\tDPAA2_PMD_ERR(\n \t\t\t\"Invalid pattern list is given\\n\");\n@@ -1763,28 +3319,54 @@ struct rte_flow *dpaa2_flow_create(struct rte_eth_dev *dev,\n \tsize_t key_iova = 0, mask_iova = 0;\n \tint ret;\n \n-\tflow = rte_malloc(NULL, sizeof(struct rte_flow), RTE_CACHE_LINE_SIZE);\n+\tflow = rte_zmalloc(NULL, sizeof(struct rte_flow), RTE_CACHE_LINE_SIZE);\n \tif (!flow) {\n \t\tDPAA2_PMD_ERR(\"Failure to allocate memory for flow\");\n \t\tgoto mem_failure;\n \t}\n \t/* Allocate DMA'ble memory to write the rules */\n-\tkey_iova = (size_t)rte_malloc(NULL, 256, 64);\n+\tkey_iova = (size_t)rte_zmalloc(NULL, 256, 64);\n+\tif (!key_iova) {\n+\t\tDPAA2_PMD_ERR(\n+\t\t\t\"Memory allocation failure for rule configration\\n\");\n+\t\tgoto mem_failure;\n+\t}\n+\tmask_iova = (size_t)rte_zmalloc(NULL, 256, 64);\n+\tif (!mask_iova) {\n+\t\tDPAA2_PMD_ERR(\n+\t\t\t\"Memory allocation failure for rule configration\\n\");\n+\t\tgoto mem_failure;\n+\t}\n+\n+\tflow->qos_rule.key_iova = key_iova;\n+\tflow->qos_rule.mask_iova = mask_iova;\n+\n+\t/* Allocate DMA'ble memory to write the rules */\n+\tkey_iova = (size_t)rte_zmalloc(NULL, 256, 64);\n \tif (!key_iova) {\n \t\tDPAA2_PMD_ERR(\n-\t\t\t\"Memory allocation failure for rule configuration\\n\");\n+\t\t\t\"Memory allocation failure for rule configration\\n\");\n \t\tgoto mem_failure;\n \t}\n-\tmask_iova = (size_t)rte_malloc(NULL, 256, 64);\n+\tmask_iova = (size_t)rte_zmalloc(NULL, 256, 64);\n \tif (!mask_iova) {\n \t\tDPAA2_PMD_ERR(\n-\t\t\t\"Memory allocation failure for rule configuration\\n\");\n+\t\t\t\"Memory allocation failure for rule configration\\n\");\n \t\tgoto mem_failure;\n \t}\n \n-\tflow->rule.key_iova = key_iova;\n-\tflow->rule.mask_iova = mask_iova;\n-\tflow->key_size = 0;\n+\tflow->fs_rule.key_iova = key_iova;\n+\tflow->fs_rule.mask_iova = mask_iova;\n+\n+\tflow->ipaddr_rule.ipaddr_type = FLOW_NONE_IPADDR;\n+\tflow->ipaddr_rule.qos_ipsrc_offset =\n+\t\tIP_ADDRESS_OFFSET_INVALID;\n+\tflow->ipaddr_rule.qos_ipdst_offset =\n+\t\tIP_ADDRESS_OFFSET_INVALID;\n+\tflow->ipaddr_rule.fs_ipsrc_offset =\n+\t\tIP_ADDRESS_OFFSET_INVALID;\n+\tflow->ipaddr_rule.fs_ipdst_offset =\n+\t\tIP_ADDRESS_OFFSET_INVALID;\n \n \tswitch (dpaa2_filter_type) {\n \tcase RTE_ETH_FILTER_GENERIC:\n@@ -1832,25 +3414,27 @@ int dpaa2_flow_destroy(struct rte_eth_dev *dev,\n \tcase RTE_FLOW_ACTION_TYPE_QUEUE:\n \t\t/* Remove entry from QoS table first */\n \t\tret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, priv->token,\n-\t\t\t\t\t   &flow->rule);\n+\t\t\t\t\t   &flow->qos_rule);\n \t\tif (ret < 0) {\n \t\t\tDPAA2_PMD_ERR(\n \t\t\t\t\"Error in adding entry to QoS table(%d)\", ret);\n \t\t\tgoto error;\n \t\t}\n+\t\tpriv->qos_index[flow->qos_index] = 0;\n \n \t\t/* Then remove entry from FS table */\n \t\tret = dpni_remove_fs_entry(dpni, CMD_PRI_LOW, priv->token,\n-\t\t\t\t\t   flow->tc_id, &flow->rule);\n+\t\t\t\t\t   flow->tc_id, &flow->fs_rule);\n \t\tif (ret < 0) {\n \t\t\tDPAA2_PMD_ERR(\n \t\t\t\t\"Error in entry addition in FS table(%d)\", ret);\n \t\t\tgoto error;\n \t\t}\n+\t\tpriv->fs_index[flow->fs_index] = 0;\n \t\tbreak;\n \tcase RTE_FLOW_ACTION_TYPE_RSS:\n \t\tret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, priv->token,\n-\t\t\t\t\t   &flow->rule);\n+\t\t\t\t\t   &flow->qos_rule);\n \t\tif (ret < 0) {\n \t\t\tDPAA2_PMD_ERR(\n \t\t\t\"Error in entry addition in QoS table(%d)\", ret);\n",
    "prefixes": [
        "v2",
        "16/29"
    ]
}