get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 131467,
    "url": "http://patchwork.dpdk.org/api/patches/131467/?format=api",
    "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/20230915100047.90153-2-yuying.zhang@intel.com/",
    "project": {
        "id": 1,
        "url": "http://patchwork.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": "<20230915100047.90153-2-yuying.zhang@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20230915100047.90153-2-yuying.zhang@intel.com",
    "date": "2023-09-15T10:00:39",
    "name": "[v5,1/9] net/cpfl: add json parser for rte flow pattern rules",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "eb887a432e2af42d2f4aa402fb6f755158e6dc35",
    "submitter": {
        "id": 1844,
        "url": "http://patchwork.dpdk.org/api/people/1844/?format=api",
        "name": "Zhang, Yuying",
        "email": "yuying.zhang@intel.com"
    },
    "delegate": {
        "id": 1540,
        "url": "http://patchwork.dpdk.org/api/users/1540/?format=api",
        "username": "qzhan15",
        "first_name": "Qi",
        "last_name": "Zhang",
        "email": "qi.z.zhang@intel.com"
    },
    "mbox": "http://patchwork.dpdk.org/project/dpdk/patch/20230915100047.90153-2-yuying.zhang@intel.com/mbox/",
    "series": [
        {
            "id": 29519,
            "url": "http://patchwork.dpdk.org/api/series/29519/?format=api",
            "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=29519",
            "date": "2023-09-15T10:00:38",
            "name": "add rte flow support for cpfl",
            "version": 5,
            "mbox": "http://patchwork.dpdk.org/series/29519/mbox/"
        }
    ],
    "comments": "http://patchwork.dpdk.org/api/patches/131467/comments/",
    "check": "warning",
    "checks": "http://patchwork.dpdk.org/api/patches/131467/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 mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id C0934425A3;\n\tFri, 15 Sep 2023 11:01:57 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id AA6A14069F;\n\tFri, 15 Sep 2023 11:01:57 +0200 (CEST)",
            "from mgamail.intel.com (mgamail.intel.com [192.55.52.120])\n by mails.dpdk.org (Postfix) with ESMTP id ABAA14068E\n for <dev@dpdk.org>; Fri, 15 Sep 2023 11:01:54 +0200 (CEST)",
            "from orsmga004.jf.intel.com ([10.7.209.38])\n by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 15 Sep 2023 02:01:54 -0700",
            "from dpdk-pengyuan-mev.sh.intel.com ([10.67.119.128])\n by orsmga004.jf.intel.com with ESMTP; 15 Sep 2023 02:01:49 -0700"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple;\n d=intel.com; i=@intel.com; q=dns/txt; s=Intel;\n t=1694768514; x=1726304514;\n h=from:to:cc:subject:date:message-id:in-reply-to:\n references:mime-version:content-transfer-encoding;\n bh=1QwCy6PV79G9Zm/O+jBCY/Rin42OczZo85azITZV/ew=;\n b=F2k9BKKNX/ZXvdjWfv8Eh1lkeiu4L4rwcsbpa3lwa7A5dzfu7bkX3LIr\n tkY0xR272uPxavIN2MAj1EoP2GnEnKoE5Pj7JLP792aI8XO9WH5GVAOrY\n nIBZtU9cJdJb7VXUdo+y8lSLhJuG9vuX6jz34dHQwYVNm3njXfWcHguop\n OSBo3CnKHnAJSRHgwz7NCTWC32P0+7IUoF6mwCPXeFpRJpPmOvpoZMC4n\n v7ckIuzTVtJXUNw5aXUFj5beQKqbopgUJCMXVfoRqF66Mnx0Wr0pFxIEf\n sU2SOa+YsFZ74uEziJTJve1fP7j0LeBFpp0b88IYyEEwtip1/BaLwYmgC A==;",
        "X-IronPort-AV": [
            "E=McAfee;i=\"6600,9927,10833\"; a=\"378117426\"",
            "E=Sophos;i=\"6.02,148,1688454000\"; d=\"scan'208\";a=\"378117426\"",
            "E=McAfee;i=\"6600,9927,10833\"; a=\"868630677\"",
            "E=Sophos;i=\"6.02,148,1688454000\"; d=\"scan'208\";a=\"868630677\""
        ],
        "X-ExtLoop1": "1",
        "From": "\"Zhang, Yuying\" <yuying.zhang@intel.com>",
        "To": "yuying.zhang@intel.com, dev@dpdk.org, qi.z.zhang@intel.com,\n beilei.xing@intel.com, jingjing.wu@intel.com",
        "Cc": "mingxia.liu@intel.com,\n\tWenjing Qiao <wenjing.qiao@intel.com>",
        "Subject": "[PATCH v5 1/9] net/cpfl: add json parser for rte flow pattern rules",
        "Date": "Fri, 15 Sep 2023 10:00:39 +0000",
        "Message-Id": "<20230915100047.90153-2-yuying.zhang@intel.com>",
        "X-Mailer": "git-send-email 2.25.1",
        "In-Reply-To": "<20230915100047.90153-1-yuying.zhang@intel.com>",
        "References": "<20230906093407.3635038-1-wenjing.qiao@intel.com>\n <20230915100047.90153-1-yuying.zhang@intel.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "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"
    },
    "content": "From: Wenjing Qiao <wenjing.qiao@intel.com>\n\nAdd devargs \"flow_parser\" for rte flow json parser which\ndepends on json-c library.\n\nExample:\n    -a ca:00.0,flow_parser=\"refpkg.json\"\n\nAdd json parser for rte flow pattern rules.The cpfl\nPMD supports utilizing a JSON config file to translate\nrte flow tokens into low level hardware resources.\n\nSigned-off-by: Wenjing Qiao <wenjing.qiao@intel.com>\n---\n doc/guides/nics/cpfl.rst            |   30 +\n drivers/net/cpfl/cpfl_ethdev.c      |   38 +-\n drivers/net/cpfl/cpfl_ethdev.h      |   76 ++\n drivers/net/cpfl/cpfl_flow_parser.c | 1302 +++++++++++++++++++++++++++\n drivers/net/cpfl/cpfl_flow_parser.h |  167 ++++\n drivers/net/cpfl/meson.build        |   13 +\n 6 files changed, 1625 insertions(+), 1 deletion(-)\n create mode 100644 drivers/net/cpfl/cpfl_flow_parser.c\n create mode 100644 drivers/net/cpfl/cpfl_flow_parser.h",
    "diff": "diff --git a/doc/guides/nics/cpfl.rst b/doc/guides/nics/cpfl.rst\nindex 83a18c3f2e..aae157f0df 100644\n--- a/doc/guides/nics/cpfl.rst\n+++ b/doc/guides/nics/cpfl.rst\n@@ -128,12 +128,24 @@ Runtime Configuration\n \n     -a BDF,representor=vf[0-3],representor=c1pf1\n \n+- ``flow_parser`` (default ``not enabled``)\n+\n+  The cpfl PMD supports utilizing a JSON config file to translate rte_flow tokens into\n+  low-level hardware resources.\n+  Using the ``devargs`` option ``flow_parser`` the user can specify the path\n+  of a json file, for example::\n+\n+    -a ca:00.0,flow_parser=\"refpkg.json\"\n+\n+  Then the PMD will load json file for device ``ca:00.0``.\n+  The parameter is optional.\n \n Driver compilation and testing\n ------------------------------\n \n Refer to the document :doc:`build_and_test` for details.\n \n+The json-c library must be installed to use rte_flow.\n \n Features\n --------\n@@ -164,3 +176,21 @@ Hairpin queue\n E2100 Series can loopback packets from RX port to TX port.\n This feature is called port-to-port or hairpin.\n Currently, the PMD only supports single port hairpin.\n+\n+Rte_flow\n+~~~~~~~~~~~~~\n+\n+PMD uses a json file to direct CPF PMD to parse rte_flow tokens into\n+low level hardware resources.\n+\n+- Required Libraries\n+\n+  * json-c (version 0.14+)\n+\n+    * For Ubuntu, it can be installed using `apt install libjson-c-dev`\n+\n+- run testpmd with the json file\n+\n+   .. code-block:: console\n+\n+   dpdk-testpmd -c 0x3 -n 4 -a 0000:af:00.6,vport=[0],flow_parser=\"refpkg.json\" -- -i\ndiff --git a/drivers/net/cpfl/cpfl_ethdev.c b/drivers/net/cpfl/cpfl_ethdev.c\nindex 189072ab33..54ae127cc3 100644\n--- a/drivers/net/cpfl/cpfl_ethdev.c\n+++ b/drivers/net/cpfl/cpfl_ethdev.c\n@@ -21,6 +21,10 @@\n #define CPFL_RX_SINGLE_Q\t\"rx_single\"\n #define CPFL_VPORT\t\t\"vport\"\n \n+#ifdef CPFL_FLOW_JSON_SUPPORT\n+#define CPFL_FLOW_PARSER\t\"flow_parser\"\n+#endif\n+\n rte_spinlock_t cpfl_adapter_lock;\n /* A list for all adapters, one adapter matches one PCI device */\n struct cpfl_adapter_list cpfl_adapter_list;\n@@ -31,6 +35,9 @@ static const char * const cpfl_valid_args_first[] = {\n \tCPFL_TX_SINGLE_Q,\n \tCPFL_RX_SINGLE_Q,\n \tCPFL_VPORT,\n+#ifdef CPFL_FLOW_JSON_SUPPORT\n+\tCPFL_FLOW_PARSER,\n+#endif\n \tNULL\n };\n \n@@ -1537,6 +1544,24 @@ parse_repr(const char *key __rte_unused, const char *value, void *args)\n \treturn 0;\n }\n \n+#ifdef CPFL_FLOW_JSON_SUPPORT\n+static int\n+parse_file(const char *key, const char *value, void *args)\n+{\n+\tchar *name = args;\n+\n+\tif (strlen(value) > CPFL_FLOW_FILE_LEN - 1) {\n+\t\tPMD_DRV_LOG(ERR, \"file path(%s) is too long.\", value);\n+\t\treturn -1;\n+\t}\n+\n+\tPMD_DRV_LOG(DEBUG, \"value:\\\"%s\\\" for key:\\\"%s\\\"\", value, key);\n+\tstrlcpy(name, value, CPFL_FLOW_FILE_LEN);\n+\n+\treturn 0;\n+}\n+#endif\n+\n static int\n cpfl_parse_devargs(struct rte_pci_device *pci_dev, struct cpfl_adapter_ext *adapter, bool first)\n {\n@@ -1585,7 +1610,18 @@ cpfl_parse_devargs(struct rte_pci_device *pci_dev, struct cpfl_adapter_ext *adap\n \t\t\t\t &adapter->base.is_rx_singleq);\n \tif (ret != 0)\n \t\tgoto fail;\n-\n+#ifdef CPFL_FLOW_JSON_SUPPORT\n+\tif (rte_kvargs_get(kvlist, CPFL_FLOW_PARSER)) {\n+\t\tret = rte_kvargs_process(kvlist, CPFL_FLOW_PARSER,\n+\t\t\t\t\t &parse_file, cpfl_args->flow_parser);\n+\t\tif (ret) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Failed to parser flow_parser, ret: %d\", ret);\n+\t\t\tgoto fail;\n+\t\t}\n+\t} else {\n+\t\tcpfl_args->flow_parser[0] = '\\0';\n+\t}\n+#endif\n fail:\n \trte_kvargs_free(kvlist);\n \treturn ret;\ndiff --git a/drivers/net/cpfl/cpfl_ethdev.h b/drivers/net/cpfl/cpfl_ethdev.h\nindex d0dcc0cc05..383dbd14c6 100644\n--- a/drivers/net/cpfl/cpfl_ethdev.h\n+++ b/drivers/net/cpfl/cpfl_ethdev.h\n@@ -77,6 +77,11 @@\n #define CPFL_VPORT_LAN_PF\t0\n #define CPFL_VPORT_LAN_VF\t1\n \n+#define CPFL_FLOW_FILE_LEN 100\n+#define CPFL_INVALID_HW_ID\tUINT16_MAX\n+#define CPFL_META_CHUNK_LENGTH\t1024\n+#define CPFL_META_LENGTH\t32\n+\n /* bit[15:14] type\n  * bit[13] host/accelerator core\n  * bit[12] apf/cpf\n@@ -99,6 +104,7 @@ struct cpfl_devargs {\n \tuint16_t req_vport_nb;\n \tuint8_t repr_args_num;\n \tstruct rte_eth_devargs repr_args[CPFL_REPR_ARG_NUM_MAX];\n+\tchar flow_parser[CPFL_FLOW_FILE_LEN];\n };\n \n struct p2p_queue_chunks_info {\n@@ -165,6 +171,20 @@ struct cpfl_repr {\n \tbool func_up; /* If the represented function is up */\n };\n \n+struct cpfl_metadata_chunk {\n+\tint type;\n+\tuint8_t data[CPFL_META_CHUNK_LENGTH];\n+};\n+\n+/**\n+ * It is driver's responsibility to simlulate a metadata buffer which\n+ * can be used as data source to fill the key of a flow rule.\n+ */\n+struct cpfl_metadata {\n+\tint length;\n+\tstruct cpfl_metadata_chunk chunks[CPFL_META_LENGTH];\n+};\n+\n struct cpfl_adapter_ext {\n \tTAILQ_ENTRY(cpfl_adapter_ext) next;\n \tstruct idpf_adapter base;\n@@ -185,6 +205,8 @@ struct cpfl_adapter_ext {\n \n \trte_spinlock_t repr_lock;\n \tstruct rte_hash *repr_allowlist_hash;\n+\n+\tstruct cpfl_metadata meta;\n };\n \n TAILQ_HEAD(cpfl_adapter_list, cpfl_adapter_ext);\n@@ -211,4 +233,58 @@ int cpfl_cc_vport_info_get(struct cpfl_adapter_ext *adapter,\n #define CPFL_DEV_TO_ITF(dev)\t\t\t\t\\\n \t((struct cpfl_itf *)((dev)->data->dev_private))\n \n+static inline uint16_t\n+cpfl_get_port_id(struct cpfl_itf *itf)\n+{\n+\tif (!itf)\n+\t\treturn CPFL_INVALID_HW_ID;\n+\n+\tif (itf->type == CPFL_ITF_TYPE_VPORT) {\n+\t\tstruct cpfl_vport *vport = (void *)itf;\n+\n+\t\treturn vport->base.devarg_id;\n+\t}\n+\n+\treturn CPFL_INVALID_HW_ID;\n+}\n+\n+static inline uint16_t\n+cpfl_get_vsi_id(struct cpfl_itf *itf)\n+{\n+\tstruct cpfl_adapter_ext *adapter = itf->adapter;\n+\tstruct cpfl_vport_info *info;\n+\tuint32_t vport_id;\n+\tint ret;\n+\tstruct cpfl_vport_id vport_identity;\n+\n+\tif (!itf)\n+\t\treturn CPFL_INVALID_HW_ID;\n+\n+\tif (itf->type == CPFL_ITF_TYPE_REPRESENTOR) {\n+\t\tstruct cpfl_repr *repr = (void *)itf;\n+\n+\t\treturn repr->vport_info->vport.info.vsi_id;\n+\t} else if (itf->type == CPFL_ITF_TYPE_VPORT) {\n+\t\tvport_id = ((struct cpfl_vport *)itf)->base.vport_id;\n+\n+\t\tvport_identity.func_type = CPCHNL2_FUNC_TYPE_PF;\n+\t\t/* host: CPFL_HOST0_CPF_ID, acc: CPFL_ACC_CPF_ID */\n+\t\tvport_identity.pf_id = CPFL_ACC_CPF_ID;\n+\t\tvport_identity.vf_id = 0;\n+\t\tvport_identity.vport_id = vport_id;\n+\t\tret = rte_hash_lookup_data(adapter->vport_map_hash,\n+\t\t\t\t\t   &vport_identity,\n+\t\t\t\t\t   (void **)&info);\n+\t\tif (ret < 0) {\n+\t\t\tPMD_DRV_LOG(ERR, \"vport id not exist\");\n+\t\t\tgoto err;\n+\t\t}\n+\n+\t\treturn info->vport.info.vsi_id;\n+\t}\n+\n+err:\n+\treturn CPFL_INVALID_HW_ID;\n+}\n+\n #endif /* _CPFL_ETHDEV_H_ */\ndiff --git a/drivers/net/cpfl/cpfl_flow_parser.c b/drivers/net/cpfl/cpfl_flow_parser.c\nnew file mode 100644\nindex 0000000000..630ce8a227\n--- /dev/null\n+++ b/drivers/net/cpfl/cpfl_flow_parser.c\n@@ -0,0 +1,1302 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Intel Corporation\n+ */\n+\n+#include <arpa/inet.h>\n+#include <asm-generic/errno-base.h>\n+#include <stdint.h>\n+\n+#include \"cpfl_flow_parser.h\"\n+#include \"cpfl_ethdev.h\"\n+#include \"rte_malloc.h\"\n+\n+static enum rte_flow_item_type\n+cpfl_get_item_type_by_str(const char *type)\n+{\n+\tif (strcmp(type, \"eth\") == 0)\n+\t\treturn RTE_FLOW_ITEM_TYPE_ETH;\n+\telse if (strcmp(type, \"ipv4\") == 0)\n+\t\treturn RTE_FLOW_ITEM_TYPE_IPV4;\n+\telse if (strcmp(type, \"tcp\") == 0)\n+\t\treturn RTE_FLOW_ITEM_TYPE_TCP;\n+\telse if (strcmp(type, \"udp\") == 0)\n+\t\treturn RTE_FLOW_ITEM_TYPE_UDP;\n+\telse if (strcmp(type, \"vxlan\") == 0)\n+\t\treturn RTE_FLOW_ITEM_TYPE_VXLAN;\n+\telse if (strcmp(type, \"icmp\") == 0)\n+\t\treturn RTE_FLOW_ITEM_TYPE_ICMP;\n+\telse if (strcmp(type, \"vlan\") == 0)\n+\t\treturn RTE_FLOW_ITEM_TYPE_VLAN;\n+\n+\tPMD_DRV_LOG(ERR, \"Not support this type: %s.\", type);\n+\treturn RTE_FLOW_ITEM_TYPE_VOID;\n+}\n+\n+static const char *\n+cpfl_json_object_to_string(json_object *object, const char *name)\n+{\n+\tjson_object *subobject;\n+\n+\tif (!object) {\n+\t\tPMD_DRV_LOG(ERR, \"object doesn't exist.\");\n+\t\treturn NULL;\n+\t}\n+\tsubobject = json_object_object_get(object, name);\n+\tif (!subobject) {\n+\t\tPMD_DRV_LOG(ERR, \"%s doesn't exist.\", name);\n+\t\treturn NULL;\n+\t}\n+\n+\treturn json_object_get_string(subobject);\n+}\n+\n+static int\n+cpfl_json_object_to_uint16(json_object *object, const char *name, uint16_t *value)\n+{\n+\tjson_object *subobject;\n+\n+\tif (!object) {\n+\t\tPMD_DRV_LOG(ERR, \"object doesn't exist.\");\n+\t\treturn -EINVAL;\n+\t}\n+\tsubobject = json_object_object_get(object, name);\n+\tif (!subobject) {\n+\t\tPMD_DRV_LOG(ERR, \"%s doesn't exist.\", name);\n+\t\treturn -EINVAL;\n+\t}\n+\t*value = json_object_get_int(subobject);\n+\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_json_object_to_uint32(json_object *object, const char *name, uint32_t *value)\n+{\n+\tjson_object *subobject;\n+\n+\tif (!object) {\n+\t\tPMD_DRV_LOG(ERR, \"object doesn't exist.\");\n+\t\treturn -EINVAL;\n+\t}\n+\tsubobject = json_object_object_get(object, name);\n+\tif (!subobject) {\n+\t\tPMD_DRV_LOG(ERR, \"%s doesn't exist.\", name);\n+\t\treturn -EINVAL;\n+\t}\n+\t*value = json_object_get_int64(subobject);\n+\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_flow_js_pattern_key_attr(json_object *ob_pr_key_attrs, struct cpfl_flow_js_pr *js_pr)\n+{\n+\tint i, len;\n+\tstruct cpfl_flow_js_pr_key_attr *attr;\n+\n+\tlen = json_object_array_length(ob_pr_key_attrs);\n+\tjs_pr->key.attributes = rte_malloc(NULL, sizeof(struct cpfl_flow_js_pr_key_attr), 0);\n+\tif (!js_pr->key.attributes) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to alloc memory.\");\n+\t\treturn -ENOMEM;\n+\t}\n+\tjs_pr->key.attr_size = len;\n+\tattr = js_pr->key.attributes;\n+\tfor (i = 0; i < len; i++) {\n+\t\tjson_object *object;\n+\t\tconst char *name;\n+\t\tuint16_t value = 0;\n+\t\tint ret;\n+\n+\t\tobject = json_object_array_get_idx(ob_pr_key_attrs, i);\n+\t\tname = cpfl_json_object_to_string(object, \"Name\");\n+\t\tif (!name) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse string 'Name'.\");\n+\t\t\tgoto err;\n+\t\t}\n+\t\tret = cpfl_json_object_to_uint16(object, \"Value\", &value);\n+\t\tif (ret < 0) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse 'value'.\");\n+\t\t\tgoto err;\n+\t\t}\n+\t\tif (strcmp(name, \"ingress\") == 0) {\n+\t\t\tattr->ingress = value;\n+\t\t} else if (strcmp(name, \"egress\") == 0) {\n+\t\t\tattr->egress = value;\n+\t\t} else {\n+\t\t\t/* TODO: more... */\n+\t\t\tPMD_DRV_LOG(ERR, \"Not support attr name: %s.\", name);\n+\t\t\tgoto err;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+err:\n+\trte_free(js_pr->key.attributes);\n+\treturn -EINVAL;\n+}\n+\n+static int\n+cpfl_flow_js_pattern_key_proto_field(json_object *ob_fields,\n+\t\t\t\t     struct cpfl_flow_js_pr_key_proto *js_field)\n+{\n+\tint len, i;\n+\n+\tif (!ob_fields)\n+\t\treturn 0;\n+\tlen = json_object_array_length(ob_fields);\n+\tif (len == 0)\n+\t\treturn 0;\n+\tjs_field->fields_size = len;\n+\tjs_field->fields =\n+\t    rte_malloc(NULL, sizeof(struct cpfl_flow_js_pr_key_proto_field) * len, 0);\n+\tif (!js_field->fields) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to alloc memory.\");\n+\t\treturn -ENOMEM;\n+\t}\n+\tfor (i = 0; i < len; i++) {\n+\t\tjson_object *object;\n+\t\tconst char *name, *mask;\n+\n+\t\tobject = json_object_array_get_idx(ob_fields, i);\n+\t\tname = cpfl_json_object_to_string(object, \"name\");\n+\t\tif (!name) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse string 'name'.\");\n+\t\t\tgoto err;\n+\t\t}\n+\t\tif (strlen(name) > CPFL_FLOW_JSON_STR_SIZE_MAX) {\n+\t\t\tPMD_DRV_LOG(ERR, \"The 'name' is too long.\");\n+\t\t\tgoto err;\n+\t\t}\n+\t\tmemcpy(js_field->fields[i].name, name, strlen(name));\n+\n+\t\tif (js_field->type == RTE_FLOW_ITEM_TYPE_ETH ||\n+\t\t    js_field->type == RTE_FLOW_ITEM_TYPE_IPV4) {\n+\t\t\tmask = cpfl_json_object_to_string(object, \"mask\");\n+\t\t\tif (!mask) {\n+\t\t\t\tPMD_DRV_LOG(ERR, \"Can not parse string 'mask'.\");\n+\t\t\t\tgoto err;\n+\t\t\t}\n+\t\t\tif (strlen(mask) > CPFL_FLOW_JSON_STR_SIZE_MAX) {\n+\t\t\t\tPMD_DRV_LOG(ERR, \"The 'mask' is too long.\");\n+\t\t\t\tgoto err;\n+\t\t\t}\n+\t\t\tmemcpy(js_field->fields[i].mask, mask, strlen(mask));\n+\t\t} else {\n+\t\t\tuint32_t mask_32b;\n+\t\t\tint ret;\n+\n+\t\t\tret = cpfl_json_object_to_uint32(object, \"mask\", &mask_32b);\n+\t\t\tif (ret < 0) {\n+\t\t\t\tPMD_DRV_LOG(ERR, \"Can not parse uint32 'mask'.\");\n+\t\t\t\tgoto err;\n+\t\t\t}\n+\t\t\tjs_field->fields[i].mask_32b = mask_32b;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+\n+err:\n+\trte_free(js_field->fields);\n+\treturn -EINVAL;\n+}\n+\n+static int\n+cpfl_flow_js_pattern_key_proto(json_object *ob_pr_key_protos, struct cpfl_flow_js_pr *js_pr)\n+{\n+\tint len, i, ret;\n+\n+\tlen = json_object_array_length(ob_pr_key_protos);\n+\tif (len == 0)\n+\t\treturn 0;\n+\tjs_pr->key.proto_size = len;\n+\tjs_pr->key.protocols = rte_malloc(NULL, sizeof(struct cpfl_flow_js_pr_key_proto) * len, 0);\n+\tif (!js_pr->key.protocols) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to alloc memory.\");\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\tfor (i = 0; i < len; i++) {\n+\t\tjson_object *object, *ob_fields;\n+\t\tconst char *type;\n+\t\tenum rte_flow_item_type item_type;\n+\n+\t\tobject = json_object_array_get_idx(ob_pr_key_protos, i);\n+\t\t/* pr->key->proto->type */\n+\t\ttype = cpfl_json_object_to_string(object, \"type\");\n+\t\tif (!type) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse string 'type'.\");\n+\t\t\tgoto err;\n+\t\t}\n+\t\titem_type = cpfl_get_item_type_by_str(type);\n+\t\tif (item_type == RTE_FLOW_ITEM_TYPE_VOID)\n+\t\t\tgoto err;\n+\t\tjs_pr->key.protocols[i].type = item_type;\n+\t\t/* pr->key->proto->fields */\n+\t\tob_fields = json_object_object_get(object, \"fields\");\n+\t\tret = cpfl_flow_js_pattern_key_proto_field(ob_fields,\n+\t\t\t\t\t\t\t   &js_pr->key.protocols[i]);\n+\t\tif (ret < 0)\n+\t\t\tgoto err;\n+\t}\n+\n+\treturn 0;\n+\n+err:\n+\trte_free(js_pr->key.protocols);\n+\treturn -EINVAL;\n+}\n+\n+static int\n+cpfl_flow_js_pattern_act_fv_proto(json_object *ob_value, struct cpfl_flow_js_fv *js_fv)\n+{\n+\tuint16_t layer = 0, offset = 0, mask = 0;\n+\tconst char *header;\n+\tenum rte_flow_item_type type;\n+\tint ret;\n+\n+\tret = cpfl_json_object_to_uint16(ob_value, \"layer\", &layer);\n+\tif (ret < 0) {\n+\t\tPMD_DRV_LOG(ERR, \"Can not parse 'value'.\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\theader = cpfl_json_object_to_string(ob_value, \"header\");\n+\tif (!header) {\n+\t\tPMD_DRV_LOG(ERR, \"Can not parse string 'header'.\");\n+\t\treturn -EINVAL;\n+\t}\n+\tret = cpfl_json_object_to_uint16(ob_value, \"offset\", &offset);\n+\tif (ret < 0) {\n+\t\tPMD_DRV_LOG(ERR, \"Can not parse 'offset'.\");\n+\t\treturn -EINVAL;\n+\t}\n+\tret = cpfl_json_object_to_uint16(ob_value, \"mask\", &mask);\n+\tif (ret < 0) {\n+\t\tPMD_DRV_LOG(ERR, \"Can not parse 'mask'.\");\n+\t\treturn -EINVAL;\n+\t}\n+\ttype = cpfl_get_item_type_by_str(header);\n+\tif (type == RTE_FLOW_ITEM_TYPE_VOID)\n+\t\treturn -EINVAL;\n+\tjs_fv->proto.layer = layer;\n+\tjs_fv->proto.offset = offset;\n+\tjs_fv->proto.mask = mask;\n+\tjs_fv->proto.header = type;\n+\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_flow_js_pattern_act_fv_metadata(json_object *ob_value, struct cpfl_flow_js_fv *js_fv)\n+{\n+\tint ret;\n+\n+\tret = cpfl_json_object_to_uint16(ob_value, \"type\", &js_fv->meta.type);\n+\tif (ret < 0) {\n+\t\tPMD_DRV_LOG(ERR, \"Can not parse 'size'.\");\n+\t\treturn ret;\n+\t}\n+\tret = cpfl_json_object_to_uint16(ob_value, \"offset\", &js_fv->meta.offset);\n+\tif (ret < 0) {\n+\t\tPMD_DRV_LOG(ERR, \"Can not parse 'size'.\");\n+\t\treturn ret;\n+\t}\n+\tret = cpfl_json_object_to_uint16(ob_value, \"mask\", &js_fv->meta.mask);\n+\tif (ret < 0) {\n+\t\tPMD_DRV_LOG(ERR, \"Can not parse 'size'.\");\n+\t\treturn ret;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_flow_js_pattern_act_fv(json_object *ob_fvs, struct cpfl_flow_js_pr_action *js_act)\n+{\n+\tint len, i;\n+\n+\tlen = json_object_array_length(ob_fvs);\n+\tif (len == 0)\n+\t\treturn 0;\n+\tjs_act->sem.fv = rte_malloc(NULL, sizeof(struct cpfl_flow_js_fv) * len, 0);\n+\tif (!js_act->sem.fv) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to alloc memory.\");\n+\t\treturn -ENOMEM;\n+\t}\n+\tjs_act->sem.fv_size = len;\n+\tfor (i = 0; i < len; i++) {\n+\t\tstruct cpfl_flow_js_fv *js_fv;\n+\t\tjson_object *object, *ob_value;\n+\t\tuint16_t offset = 0;\n+\t\tconst char *type;\n+\t\tint ret;\n+\n+\t\tjs_fv = &js_act->sem.fv[i];\n+\t\tobject = json_object_array_get_idx(ob_fvs, i);\n+\t\tret = cpfl_json_object_to_uint16(object, \"offset\", &offset);\n+\t\tif (ret < 0) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse 'offset'.\");\n+\t\t\tgoto err;\n+\t\t}\n+\t\tjs_fv->offset = offset;\n+\n+\t\ttype = cpfl_json_object_to_string(object, \"type\");\n+\t\tif (!type) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse string 'type'.\");\n+\t\t\tgoto err;\n+\t\t}\n+\t\tob_value = json_object_object_get(object, \"value\");\n+\t\tif (strcmp(type, \"immediate\") == 0) {\n+\t\t\tjs_fv->type = CPFL_FV_TYPE_IMMEDIATE;\n+\t\t\tjs_fv->immediate = json_object_get_int(ob_value);\n+\t\t} else if (strcmp(type, \"metadata\") == 0) {\n+\t\t\tjs_fv->type = CPFL_FV_TYPE_METADATA;\n+\t\t\tcpfl_flow_js_pattern_act_fv_metadata(ob_value, js_fv);\n+\t\t} else if (strcmp(type, \"protocol\") == 0) {\n+\t\t\tjs_fv->type = CPFL_FV_TYPE_PROTOCOL;\n+\t\t\tcpfl_flow_js_pattern_act_fv_proto(ob_value, js_fv);\n+\t\t} else {\n+\t\t\tPMD_DRV_LOG(ERR, \"Not support this type: %s.\", type);\n+\t\t\tgoto err;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+\n+err:\n+\trte_free(js_act->sem.fv);\n+\treturn -EINVAL;\n+}\n+\n+static int\n+cpfl_flow_js_pattern_per_act(json_object *ob_per_act, struct cpfl_flow_js_pr_action *js_act)\n+{\n+\tconst char *type;\n+\tint ret;\n+\n+\t/* pr->actions->type */\n+\ttype = cpfl_json_object_to_string(ob_per_act, \"type\");\n+\tif (!type) {\n+\t\tPMD_DRV_LOG(ERR, \"Can not parse string 'type'.\");\n+\t\treturn -EINVAL;\n+\t}\n+\t/* pr->actions->data */\n+\tif (strcmp(type, \"sem\") == 0) {\n+\t\tjson_object *ob_fvs, *ob_sem;\n+\n+\t\tjs_act->type = CPFL_JS_PR_ACTION_TYPE_SEM;\n+\t\tob_sem = json_object_object_get(ob_per_act, \"data\");\n+\t\tret = cpfl_json_object_to_uint16(ob_sem, \"profile\",\n+\t\t\t\t\t\t &js_act->sem.prof);\n+\t\tif (ret < 0) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse 'profile'.\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tret = cpfl_json_object_to_uint16(ob_sem, \"subprofile\",\n+\t\t\t\t\t\t &js_act->sem.subprof);\n+\t\tif (ret < 0) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse 'subprofile'.\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tret = cpfl_json_object_to_uint16(ob_sem, \"keysize\",\n+\t\t\t\t\t\t &js_act->sem.keysize);\n+\t\tif (ret < 0) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse 'keysize'.\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tob_fvs = json_object_object_get(ob_sem, \"fieldvectors\");\n+\t\tret = cpfl_flow_js_pattern_act_fv(ob_fvs, js_act);\n+\t\tif (ret < 0)\n+\t\t\treturn ret;\n+\t} else {\n+\t\tPMD_DRV_LOG(ERR, \"Not support this type: %s.\", type);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_flow_js_pattern_act(json_object *ob_pr_acts, struct cpfl_flow_js_pr *js_pr)\n+{\n+\tint i, len, ret;\n+\n+\tlen = json_object_array_length(ob_pr_acts);\n+\tif (len == 0)\n+\t\treturn 0;\n+\tjs_pr->actions = rte_malloc(NULL, sizeof(struct cpfl_flow_js_pr_action) * len, 0);\n+\tif (!js_pr->actions) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to alloc memory.\");\n+\t\treturn -ENOMEM;\n+\t}\n+\tjs_pr->actions_size = len;\n+\tfor (i = 0; i < len; i++) {\n+\t\tstruct cpfl_flow_js_pr_action *js_act;\n+\t\tjson_object *object;\n+\n+\t\tobject = json_object_array_get_idx(ob_pr_acts, i);\n+\t\tjs_act = &js_pr->actions[i];\n+\t\tret = cpfl_flow_js_pattern_per_act(object, js_act);\n+\t\tif (ret < 0) {\n+\t\t\trte_free(js_pr->actions);\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse pattern action.\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * The patterns object array defines a set of rules directing the PMD to match sequences of\n+ * rte_flow protocol headers and translate them into profile/field vectors for each pipeline\n+ * stage. This object is mandatory.\n+ */\n+static int\n+cpfl_flow_js_pattern_rule(json_object *ob_root, struct cpfl_flow_js_parser *parser)\n+{\n+\tjson_object *ob_prs;\n+\tint i, len;\n+\n+\t/* Pattern Rules */\n+\tob_prs = json_object_object_get(ob_root, \"patterns\");\n+\tif (!ob_prs) {\n+\t\tPMD_DRV_LOG(ERR, \"The patterns is mandatory.\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tlen = json_object_array_length(ob_prs);\n+\tif (len == 0)\n+\t\treturn 0;\n+\tparser->patterns = rte_malloc(NULL, sizeof(struct cpfl_flow_js_pr) * len, 0);\n+\tif (!parser->patterns) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to alloc memory.\");\n+\t\treturn -ENOMEM;\n+\t}\n+\tparser->pr_size = len;\n+\tfor (i = 0; i < len; i++) {\n+\t\tjson_object *object;\n+\t\tjson_object *ob_pr_actions;\n+\t\tjson_object *ob_pr_key;\n+\t\tjson_object *ob_pr_key_protos;\n+\t\tjson_object *ob_pr_key_attrs;\n+\t\tint ret;\n+\n+\t\tobject = json_object_array_get_idx(ob_prs, i);\n+\t\t/* pr->key */\n+\t\tob_pr_key = json_object_object_get(object, \"key\");\n+\t\t/* pr->key->protocols */\n+\t\tob_pr_key_protos = json_object_object_get(ob_pr_key, \"protocols\");\n+\t\tret = cpfl_flow_js_pattern_key_proto(ob_pr_key_protos, &parser->patterns[i]);\n+\t\tif (ret < 0) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse key->protocols.\");\n+\t\t\tgoto err;\n+\t\t}\n+\t\t/* pr->key->attributes */\n+\t\tob_pr_key_attrs = json_object_object_get(ob_pr_key, \"attributes\");\n+\t\tret = cpfl_flow_js_pattern_key_attr(ob_pr_key_attrs, &parser->patterns[i]);\n+\t\tif (ret < 0) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse key->attributes.\");\n+\t\t\tgoto err;\n+\t\t}\n+\t\t/* pr->actions */\n+\t\tob_pr_actions = json_object_object_get(object, \"actions\");\n+\t\tret = cpfl_flow_js_pattern_act(ob_pr_actions, &parser->patterns[i]);\n+\t\tif (ret < 0) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse pattern action.\");\n+\t\t\tgoto err;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+\n+err:\n+\trte_free(parser->patterns);\n+\treturn -EINVAL;\n+}\n+\n+static int\n+cpfl_parser_init(json_object *ob_root, struct cpfl_flow_js_parser *parser)\n+{\n+\tint ret = 0;\n+\n+\tret = cpfl_flow_js_pattern_rule(ob_root, parser);\n+\tif (ret < 0) {\n+\t\tPMD_DRV_LOG(ERR, \"parse pattern_rule failed.\");\n+\t\treturn ret;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int\n+cpfl_parser_create(struct cpfl_flow_js_parser **flow_parser, const char *filename)\n+{\n+\tstruct cpfl_flow_js_parser *parser;\n+\tjson_object *root;\n+\tint ret;\n+\n+\tparser = rte_zmalloc(\"flow_parser\", sizeof(struct cpfl_flow_js_parser), 0);\n+\tif (!parser) {\n+\t\tPMD_DRV_LOG(ERR, \"Not enough memory to create flow parser.\");\n+\t\treturn -ENOMEM;\n+\t}\n+\troot = json_object_from_file(filename);\n+\tif (!root) {\n+\t\tPMD_DRV_LOG(ERR, \"Can not load JSON file: %s.\", filename);\n+\t\trte_free(parser);\n+\t\treturn -EINVAL;\n+\t}\n+\tret = cpfl_parser_init(root, parser);\n+\tif (ret < 0) {\n+\t\tPMD_DRV_LOG(ERR, \"parser init failed.\");\n+\t\tgoto free_parser;\n+\t}\n+\t*flow_parser = parser;\n+\tret = json_object_put(root);\n+\tif (ret != 1) {\n+\t\tPMD_DRV_LOG(ERR, \"Free json_object failed.\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treturn 0;\n+free_parser:\n+\trte_free(parser);\n+\treturn -EINVAL;\n+}\n+\n+static void\n+cpfl_parser_free_pr_action(struct cpfl_flow_js_pr_action *pr_act)\n+{\n+\tif (pr_act->type == CPFL_JS_PR_ACTION_TYPE_SEM)\n+\t\trte_free(pr_act->sem.fv);\n+}\n+\n+int\n+cpfl_parser_destroy(struct cpfl_flow_js_parser *parser)\n+{\n+\tint i, j;\n+\n+\tif (!parser)\n+\t\treturn 0;\n+\n+\tfor (i = 0; i < parser->pr_size; i++) {\n+\t\tstruct cpfl_flow_js_pr *pattern = &parser->patterns[i];\n+\n+\t\tif (!pattern)\n+\t\t\tcontinue;\n+\t\tfor (j = 0; j < pattern->key.proto_size; j++)\n+\t\t\trte_free(pattern->key.protocols[j].fields);\n+\t\trte_free(pattern->key.protocols);\n+\t\trte_free(pattern->key.attributes);\n+\n+\t\tfor (j = 0; j < pattern->actions_size; j++) {\n+\t\t\tstruct cpfl_flow_js_pr_action *pr_act;\n+\n+\t\t\tpr_act = &pattern->actions[j];\n+\t\t\tcpfl_parser_free_pr_action(pr_act);\n+\t\t}\n+\t\trte_free(pattern->actions);\n+\t}\n+\trte_free(parser->patterns);\n+\trte_free(parser);\n+\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_get_items_length(const struct rte_flow_item *items)\n+{\n+\tint length = 0;\n+\tconst struct rte_flow_item *item = items;\n+\n+\twhile ((item + length++)->type != RTE_FLOW_ITEM_TYPE_END)\n+\t\tcontinue;\n+\treturn length;\n+}\n+\n+static int\n+cpfl_parse_fv_protocol(struct cpfl_flow_js_fv *js_fv, const struct rte_flow_item *items,\n+\t\t       uint16_t offset, uint8_t *fv)\n+{\n+\tuint16_t v_layer, v_offset, v_mask;\n+\tenum rte_flow_item_type v_header;\n+\tint j, layer, length;\n+\tuint16_t temp_fv;\n+\n+\tlength = cpfl_get_items_length(items);\n+\tv_layer = js_fv->proto.layer;\n+\tv_header = js_fv->proto.header;\n+\tv_offset = js_fv->proto.offset;\n+\tv_mask = js_fv->proto.mask;\n+\tlayer = 0;\n+\tfor (j = 0; j < length - 1; j++) {\n+\t\tif (items[j].type == v_header) {\n+\t\t\tif (layer == v_layer) {\n+\t\t\t\t/* copy out 16 bits from offset */\n+\t\t\t\tconst uint8_t *pointer;\n+\n+\t\t\t\tpointer = &(((const uint8_t *)(items[j].spec))[v_offset]);\n+\t\t\t\ttemp_fv = ntohs((*((const uint16_t *)pointer)) & v_mask);\n+\t\t\t\tfv[2 * offset] = (uint8_t)(temp_fv >> 8);\n+\t\t\t\tfv[2 * offset + 1] = (uint8_t)(temp_fv & 0x00ff);\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\tlayer++;\n+\t\t} /* TODO: more type... */\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_parse_fieldvectors(struct cpfl_itf *itf, struct cpfl_flow_js_fv *js_fvs, int size,\n+\t\t\tuint8_t *fv, const struct rte_flow_item *items)\n+{\n+\tint i, ret;\n+\n+\tfor (i = 0; i < size; i++) {\n+\t\tuint16_t offset, temp_fv, value_int;\n+\t\tenum cpfl_flow_js_fv_type type;\n+\t\tstruct cpfl_flow_js_fv *js_fv;\n+\n+\t\tjs_fv = &js_fvs[i];\n+\t\toffset = js_fv->offset;\n+\t\ttype = js_fv->type;\n+\t\tif (type == CPFL_FV_TYPE_IMMEDIATE) {\n+\t\t\tvalue_int = js_fv->immediate;\n+\t\t\ttemp_fv = (value_int << 8) & 0xff00;\n+\t\t\tfv[2 * offset] = (uint8_t)(temp_fv >> 8);\n+\t\t\tfv[2 * offset + 1] = (uint8_t)(temp_fv & 0x00ff);\n+\t\t} else if (type == CPFL_FV_TYPE_METADATA) {\n+\t\t\tuint16_t type, v_offset, mask;\n+\n+\t\t\ttype = js_fv->meta.type;\n+\t\t\tv_offset = js_fv->meta.offset;\n+\t\t\tmask = js_fv->meta.mask;\n+\t\t\ttemp_fv = cpfl_metadata_read16(&itf->adapter->meta, type, v_offset) & mask;\n+\t\t\tfv[2 * offset] = (uint8_t)(temp_fv & 0x00ff);\n+\t\t\tfv[2 * offset + 1] = (uint8_t)(temp_fv >> 8);\n+\t\t} else if (type == CPFL_FV_TYPE_PROTOCOL) {\n+\t\t\tret = cpfl_parse_fv_protocol(js_fv, items, offset, fv);\n+\t\t\tif (ret)\n+\t\t\t\treturn ret;\n+\t\t} else {\n+\t\t\tPMD_DRV_LOG(DEBUG, \"not support this type: %d.\", type);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_parse_pr_actions(struct cpfl_itf *itf,\n+\t\t      struct cpfl_flow_js_pr_action *actions,\n+\t\t      int size,\n+\t\t      const struct rte_flow_item *items,\n+\t\t      const struct rte_flow_attr *attr,\n+\t\t      struct cpfl_flow_pr_action *pr_action)\n+{\n+\tint i, ret;\n+\n+\tfor (i = 0; i < size; i++) {\n+\t\tstruct cpfl_flow_js_pr_action *pr_act;\n+\t\tenum cpfl_flow_pr_action_type type;\n+\n+\t\tpr_act = &actions[i];\n+\t\t/* pr->actions->type */\n+\t\ttype = pr_act->type;\n+\t\t/* pr->actions->data */\n+\t\tif (attr->group == 1  && type == CPFL_JS_PR_ACTION_TYPE_SEM) {\n+\t\t\tstruct cpfl_flow_js_pr_action_sem *sem = &pr_act->sem;\n+\n+\t\t\tpr_action->type = CPFL_JS_PR_ACTION_TYPE_SEM;\n+\t\t\tpr_action->sem.prof = sem->prof;\n+\t\t\tpr_action->sem.subprof = sem->subprof;\n+\t\t\tpr_action->sem.keysize = sem->keysize;\n+\t\t\tmemset(pr_action->sem.cpfl_flow_pr_fv, 0,\n+\t\t\t       sizeof(pr_action->sem.cpfl_flow_pr_fv));\n+\t\t\tret = cpfl_parse_fieldvectors(itf, sem->fv, sem->fv_size,\n+\t\t\t\t\t\t      pr_action->sem.cpfl_flow_pr_fv, items);\n+\t\t\treturn ret;\n+\t\t} else if (attr->group > 4 || attr->group == 0) {\n+\t\t\treturn -EPERM;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_check_eth_mask(const char *mask, struct rte_ether_addr addr)\n+{\n+\tint i, ret;\n+\tstruct rte_ether_addr mask_bytes;\n+\n+\tret = rte_ether_unformat_addr(mask, &mask_bytes);\n+\tif (ret < 0) {\n+\t\tPMD_DRV_LOG(ERR, \"translate mac address from string to rte_ether_addr failed.\");\n+\t\treturn -EINVAL;\n+\t}\n+\t/* validate eth mask addr if match */\n+\tfor (i = 0; i < RTE_ETHER_ADDR_LEN; i++) {\n+\t\tif (mask_bytes.addr_bytes[i] != addr.addr_bytes[i])\n+\t\t\treturn -EINVAL;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_check_ipv4_mask(const char *mask, rte_be32_t addr)\n+{\n+\tuint32_t out_addr;\n+\n+\t/* 0: success; -EINVAL: invalid; -ENOTSUP: fail */\n+\tint ret = inet_pton(AF_INET, mask, &out_addr);\n+\n+\tif (ret < 0)\n+\t\treturn -EINVAL;\n+\t/* validate ipv4 mask addr if match */\n+\tif (out_addr != addr)\n+\t\treturn -EINVAL;\n+\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_check_eth(struct cpfl_flow_js_pr_key_proto *proto, const struct rte_flow_item_eth *eth_mask)\n+{\n+\tint field_size, j;\n+\tint flag_dst_addr, flag_src_addr, flag_ether_type;\n+\tstruct cpfl_flow_js_pr_key_proto_field *field;\n+\n+\tif (!proto)\n+\t\treturn 0;\n+\tfield_size = proto->fields_size;\n+\tif (field_size != 0 && !eth_mask)\n+\t\treturn -EINVAL;\n+\n+\tif (field_size == 0 && eth_mask)\n+\t\treturn -EINVAL;\n+\n+\tif (field_size == 0 && !eth_mask)\n+\t\treturn 0;\n+\n+\tflag_dst_addr = false;\n+\tflag_src_addr = false;\n+\tflag_ether_type = false;\n+\tfor (j = 0; j < field_size; j++) {\n+\t\tconst char *name, *s_mask;\n+\n+\t\tfield = &proto->fields[j];\n+\t\t/* match: rte_flow_item_eth.dst, more see Field Mapping\n+\t\t */\n+\t\tname = field->name;\n+\t\t/* match: rte_flow_item->mask */\n+\t\tif (strcmp(name, \"src_addr\") == 0) {\n+\t\t\ts_mask = field->mask;\n+\t\t\tif (cpfl_check_eth_mask(s_mask, eth_mask->src) < 0)\n+\t\t\t\treturn -EINVAL;\n+\t\t\tflag_src_addr = true;\n+\t\t} else if (strcmp(name, \"dst_addr\") == 0) {\n+\t\t\ts_mask = field->mask;\n+\t\t\tif (cpfl_check_eth_mask(s_mask, eth_mask->dst) < 0)\n+\t\t\t\treturn -EINVAL;\n+\t\t\tflag_dst_addr = true;\n+\t\t} else if (strcmp(name, \"ether_type\") == 0) {\n+\t\t\tuint16_t mask = (uint16_t)field->mask_32b;\n+\n+\t\t\tif (mask != eth_mask->type)\n+\t\t\t\treturn -EINVAL;\n+\t\t\tflag_ether_type = true;\n+\t\t} else {\n+\t\t\t/* TODO: more type... */\n+\t\t\tPMD_DRV_LOG(ERR, \"not support this name.\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\tif (!flag_src_addr) {\n+\t\tif (strcmp((const char *)eth_mask->src.addr_bytes, \"\\x00\\x00\\x00\\x00\\x00\\x00\") != 0)\n+\t\t\treturn -EINVAL;\n+\t}\n+\tif (!flag_dst_addr) {\n+\t\tif (strcmp((const char *)eth_mask->dst.addr_bytes, \"\\x00\\x00\\x00\\x00\\x00\\x00\") != 0)\n+\t\t\treturn -EINVAL;\n+\t}\n+\tif (!flag_ether_type) {\n+\t\tif (eth_mask->hdr.ether_type != (rte_be16_t)0)\n+\t\t\treturn -EINVAL;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_check_ipv4(struct cpfl_flow_js_pr_key_proto *proto, const struct rte_flow_item_ipv4 *ipv4_mask)\n+{\n+\tint field_size, j;\n+\tint flag_next_proto_id, flag_src_addr, flag_dst_addr;\n+\tstruct cpfl_flow_js_pr_key_proto_field *field;\n+\n+\tif (!proto)\n+\t\treturn 0;\n+\n+\tfield_size = proto->fields_size;\n+\tif (field_size != 0 && !ipv4_mask)\n+\t\treturn -EINVAL;\n+\n+\tif (field_size == 0 && ipv4_mask)\n+\t\treturn -EINVAL;\n+\n+\tif (field_size == 0 && !ipv4_mask)\n+\t\treturn 0;\n+\n+\tflag_dst_addr = false;\n+\tflag_src_addr = false;\n+\tflag_next_proto_id = false;\n+\tfor (j = 0; j < field_size; j++) {\n+\t\tconst char *name;\n+\n+\t\tfield = &proto->fields[j];\n+\t\tname = field->name;\n+\t\tif (strcmp(name, \"src_addr\") == 0) {\n+\t\t\tconst char *mask;\n+\n+\t\t\tmask = field->mask;\n+\t\t\tif (cpfl_check_ipv4_mask(mask, ipv4_mask->hdr.src_addr) < 0)\n+\t\t\t\treturn -EINVAL;\n+\t\t\tflag_src_addr = true;\n+\t\t} else if (strcmp(name, \"dst_addr\") == 0) {\n+\t\t\tconst char *mask;\n+\n+\t\t\tmask = field->mask;\n+\t\t\tif (cpfl_check_ipv4_mask(mask, ipv4_mask->hdr.dst_addr) < 0)\n+\t\t\t\treturn -EINVAL;\n+\t\t\tflag_dst_addr = true;\n+\t\t} else if (strcmp(name, \"next_proto_id\") == 0) {\n+\t\t\tuint8_t mask;\n+\n+\t\t\tmask = (uint8_t)field->mask_32b;\n+\t\t\tif (mask != ipv4_mask->hdr.next_proto_id)\n+\t\t\t\treturn -EINVAL;\n+\t\t\tflag_next_proto_id = true;\n+\t\t} else {\n+\t\t\tPMD_DRV_LOG(ERR, \"not support this name.\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\tif (!flag_src_addr) {\n+\t\tif (ipv4_mask->hdr.src_addr != (rte_be32_t)0)\n+\t\t\treturn -EINVAL;\n+\t}\n+\tif (!flag_dst_addr) {\n+\t\tif (ipv4_mask->hdr.dst_addr != (rte_be32_t)0)\n+\t\t\treturn -EINVAL;\n+\t}\n+\tif (!flag_next_proto_id) {\n+\t\tif (ipv4_mask->hdr.next_proto_id != (uint8_t)0)\n+\t\t\treturn -EINVAL;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_check_tcp(struct cpfl_flow_js_pr_key_proto *proto, const struct rte_flow_item_tcp *tcp_mask)\n+{\n+\tint field_size, j;\n+\tint flag_src_port, flag_dst_port;\n+\tstruct cpfl_flow_js_pr_key_proto_field *field;\n+\n+\tif (!proto)\n+\t\treturn 0;\n+\n+\tfield_size = proto->fields_size;\n+\tif (field_size != 0 && !tcp_mask)\n+\t\treturn -EINVAL;\n+\n+\tif (field_size == 0 && tcp_mask)\n+\t\treturn -EINVAL;\n+\n+\tif (field_size == 0 && !tcp_mask)\n+\t\treturn 0;\n+\n+\tflag_src_port = false;\n+\tflag_dst_port = false;\n+\tfor (j = 0; j < field_size; j++) {\n+\t\tconst char *name;\n+\t\tuint16_t mask;\n+\n+\t\tfield = &proto->fields[j];\n+\t\tname = field->name;\n+\t\tmask = (uint16_t)field->mask_32b;\n+\t\tif (strcmp(name, \"src_port\") == 0) {\n+\t\t\tif (tcp_mask->hdr.src_port != mask)\n+\t\t\t\treturn -EINVAL;\n+\t\t\tflag_src_port = true;\n+\t\t} else if (strcmp(name, \"dst_port\") == 0) {\n+\t\t\tif (tcp_mask->hdr.dst_port != mask)\n+\t\t\t\treturn -EINVAL;\n+\t\t\tflag_dst_port = true;\n+\t\t} else {\n+\t\t\tPMD_DRV_LOG(ERR, \"not support this name.\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\tif (!flag_src_port) {\n+\t\tif (tcp_mask->hdr.src_port != (rte_be16_t)0)\n+\t\t\treturn -EINVAL;\n+\t}\n+\tif (!flag_dst_port) {\n+\t\tif (tcp_mask->hdr.dst_port != (rte_be16_t)0)\n+\t\t\treturn -EINVAL;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_check_udp(struct cpfl_flow_js_pr_key_proto *proto, const struct rte_flow_item_udp *udp_mask)\n+{\n+\tint field_size, j;\n+\tbool flag_src_port, flag_dst_port;\n+\tstruct cpfl_flow_js_pr_key_proto_field *field;\n+\n+\tif (!proto)\n+\t\treturn 0;\n+\tfield_size = proto->fields_size;\n+\tif (field_size != 0 && !udp_mask)\n+\t\treturn -EINVAL;\n+\tif (field_size == 0 && udp_mask)\n+\t\treturn -EINVAL;\n+\tif (field_size == 0 && !udp_mask)\n+\t\treturn 0;\n+\tflag_src_port = false;\n+\tflag_dst_port = false;\n+\tfor (j = 0; j < field_size; j++) {\n+\t\tconst char *name;\n+\t\tuint16_t mask;\n+\n+\t\tfield = &proto->fields[j];\n+\t\t/* match: rte_flow_item_eth.dst */\n+\t\tname = field->name; /* match: rte_flow_item->mask */\n+\t\tmask = (uint16_t)field->mask_32b;\n+\t\tif (strcmp(name, \"src_port\") == 0) {\n+\t\t\tif (udp_mask->hdr.src_port != mask)\n+\t\t\t\treturn -EINVAL;\n+\t\t\tflag_src_port = true;\n+\t\t} else if (strcmp(name, \"dst_port\") == 0) {\n+\t\t\tif (udp_mask->hdr.dst_port != mask)\n+\t\t\t\treturn -EINVAL;\n+\t\t\tflag_dst_port = true;\n+\t\t} else {\n+\t\t\tPMD_DRV_LOG(ERR, \"not support this name: %s.\", name);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\tif (!flag_src_port) {\n+\t\tif (udp_mask->hdr.src_port != (rte_be16_t)0)\n+\t\t\treturn -EINVAL;\n+\t}\n+\tif (!flag_dst_port) {\n+\t\tif (udp_mask->hdr.dst_port != (rte_be16_t)0)\n+\t\t\treturn -EINVAL;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_check_vxlan(struct cpfl_flow_js_pr_key_proto *proto,\n+\t\t const struct rte_flow_item_vxlan *vxlan_mask)\n+{\n+\tint field_size, j;\n+\tstruct cpfl_flow_js_pr_key_proto_field *field;\n+\n+\tif (!proto)\n+\t\treturn 0;\n+\tfield_size = proto->fields_size;\n+\tif (field_size != 0 && !vxlan_mask)\n+\t\treturn -EINVAL;\n+\tif (field_size == 0 && vxlan_mask)\n+\t\treturn -EINVAL;\n+\tif (field_size == 0 && !vxlan_mask)\n+\t\treturn 0;\n+\tfor (j = 0; j < field_size; j++) {\n+\t\tconst char *name;\n+\t\tint64_t mask;\n+\n+\t\tfield = &proto->fields[j];\n+\t\tname = field->name;\n+\t\t/* match: rte_flow_item->mask */\n+\t\tmask = (int64_t)field->mask_32b;\n+\t\tif (strcmp(name, \"vx_vni\") == 0) {\n+\t\t\tif ((int64_t)RTE_BE32(vxlan_mask->hdr.vx_vni) != mask)\n+\t\t\t\treturn -EINVAL;\n+\t\t} else {\n+\t\t\tPMD_DRV_LOG(ERR, \"not support this name.\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_check_icmp(struct cpfl_flow_js_pr_key_proto *proto, const struct rte_flow_item_icmp *icmp_mask)\n+{\n+\tint field_size;\n+\n+\tif (!proto)\n+\t\treturn 0;\n+\tfield_size = proto->fields_size;\n+\tif ((field_size != 0 && !icmp_mask) || (field_size == 0 && icmp_mask))\n+\t\treturn -EINVAL;\n+\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_check_pattern_key_proto(struct cpfl_flow_js_pr_key_proto *protocols,\n+\t\t\t     int proto_size,\n+\t\t\t     const struct rte_flow_item *items)\n+{\n+\tint i, length;\n+\tint j = 0;\n+\n+\tlength = cpfl_get_items_length(items);\n+\tif (proto_size > length - 1)\n+\t\treturn -EINVAL;\n+\tfor (i = 0; i < proto_size; i++) {\n+\t\tstruct cpfl_flow_js_pr_key_proto *key_proto;\n+\t\tenum rte_flow_item_type type;\n+\n+\t\tkey_proto = &protocols[i];\n+\t\t/* pr->key->proto->type */\n+\t\ttype = key_proto->type;\n+\t\t/* pr->key->proto->fields */\n+\t\tswitch (type) {\n+\t\tcase RTE_FLOW_ITEM_TYPE_ETH:\n+\t\t\tif (items[j++].type == RTE_FLOW_ITEM_TYPE_ETH) {\n+\t\t\t\tconst struct rte_flow_item_eth *eth_mask;\n+\t\t\t\tint ret;\n+\n+\t\t\t\teth_mask = (const struct rte_flow_item_eth *)items[i].mask;\n+\t\t\t\tret = cpfl_check_eth(key_proto, eth_mask);\n+\t\t\t\tif (ret < 0)\n+\t\t\t\t\treturn ret;\n+\t\t\t} else {\n+\t\t\t\treturn -EINVAL;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ITEM_TYPE_IPV4:\n+\t\t\tif (items[j++].type == RTE_FLOW_ITEM_TYPE_IPV4) {\n+\t\t\t\tconst struct rte_flow_item_ipv4 *ipv4_mask;\n+\t\t\t\tint ret;\n+\n+\t\t\t\tipv4_mask = (const struct rte_flow_item_ipv4 *)items[i].mask;\n+\t\t\t\tret = cpfl_check_ipv4(key_proto, ipv4_mask);\n+\t\t\t\tif (ret < 0)\n+\t\t\t\t\treturn ret;\n+\t\t\t} else {\n+\t\t\t\treturn -EINVAL;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ITEM_TYPE_TCP:\n+\t\t\tif (items[j++].type == RTE_FLOW_ITEM_TYPE_TCP) {\n+\t\t\t\tconst struct rte_flow_item_tcp *tcp_mask;\n+\t\t\t\tint ret;\n+\n+\t\t\t\ttcp_mask = (const struct rte_flow_item_tcp *)items[i].mask;\n+\t\t\t\tret = cpfl_check_tcp(key_proto, tcp_mask);\n+\t\t\t\tif (ret < 0)\n+\t\t\t\t\treturn ret;\n+\t\t\t} else {\n+\t\t\t\treturn -EINVAL;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ITEM_TYPE_UDP:\n+\t\t\tif (items[j++].type == RTE_FLOW_ITEM_TYPE_UDP) {\n+\t\t\t\tconst struct rte_flow_item_udp *udp_mask;\n+\t\t\t\tint ret;\n+\n+\t\t\t\tudp_mask = (const struct rte_flow_item_udp *)items[i].mask;\n+\t\t\t\tret = cpfl_check_udp(key_proto, udp_mask);\n+\t\t\t\tif (ret < 0)\n+\t\t\t\t\treturn ret;\n+\t\t\t} else {\n+\t\t\t\treturn -EINVAL;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ITEM_TYPE_VXLAN:\n+\t\t\tif (items[j++].type == RTE_FLOW_ITEM_TYPE_VXLAN) {\n+\t\t\t\tconst struct rte_flow_item_vxlan *vxlan_mask;\n+\t\t\t\tint ret;\n+\n+\t\t\t\tvxlan_mask = (const struct rte_flow_item_vxlan *)items[i].mask;\n+\t\t\t\tret = cpfl_check_vxlan(key_proto, vxlan_mask);\n+\t\t\t\tif (ret < 0)\n+\t\t\t\t\treturn ret;\n+\t\t\t} else {\n+\t\t\t\treturn -EINVAL;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ITEM_TYPE_ICMP:\n+\t\t\tif (items[j++].type == RTE_FLOW_ITEM_TYPE_ICMP) {\n+\t\t\t\tconst struct rte_flow_item_icmp *icmp_mask;\n+\t\t\t\tint ret;\n+\n+\t\t\t\ticmp_mask = (const struct rte_flow_item_icmp *)items[i].mask;\n+\t\t\t\tret = cpfl_check_icmp(key_proto, icmp_mask);\n+\t\t\t\tif (ret < 0)\n+\t\t\t\t\treturn ret;\n+\t\t\t} else {\n+\t\t\t\treturn -EINVAL;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tPMD_DRV_LOG(ERR, \"Not support this type: %d.\", type);\n+\t\t\treturn -EPERM;\n+\t\t}\n+\t}\n+\tif (items[j].type != RTE_FLOW_ITEM_TYPE_END)\n+\t\treturn -EINVAL;\n+\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_check_pattern_key_attr(struct cpfl_flow_js_pr_key_attr *key_attr,\n+\t\t\t    const struct rte_flow_attr *attr)\n+{\n+\tif (key_attr->ingress != attr->ingress) {\n+\t\tPMD_DRV_LOG(DEBUG, \"ingress not match.\");\n+\t\treturn -EINVAL;\n+\t}\n+\tif (key_attr->egress != attr->egress) {\n+\t\tPMD_DRV_LOG(DEBUG, \"egress not match.\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_check_pattern_key(struct cpfl_flow_js_pr *pattern,\n+\t\t       const struct rte_flow_item *items,\n+\t\t       const struct rte_flow_attr *attr)\n+{\n+\tint ret;\n+\n+\t/* pr->key */\n+\t/* pr->key->protocols */\n+\tret = cpfl_check_pattern_key_proto(pattern->key.protocols,\n+\t\t\t\t\t   pattern->key.proto_size, items);\n+\tif (ret < 0)\n+\t\treturn -EINVAL;\n+\t/* pr->key->attributes */\n+\tret = cpfl_check_pattern_key_attr(pattern->key.attributes, attr);\n+\tif (ret < 0)\n+\t\treturn -EINVAL;\n+\n+\treturn 0;\n+}\n+\n+/* output: struct cpfl_flow_pr_action* pr_action */\n+int\n+cpfl_flow_parse_items(struct cpfl_itf *itf,\n+\t\t      struct cpfl_flow_js_parser *parser,\n+\t\t      const struct rte_flow_item *items,\n+\t\t      const struct rte_flow_attr *attr,\n+\t\t      struct cpfl_flow_pr_action *pr_action)\n+{\n+\tint i, size;\n+\tstruct cpfl_flow_js_pr *pattern;\n+\n+\tsize = parser->pr_size;\n+\tfor (i = 0; i < size; i++) {\n+\t\tint ret;\n+\n+\t\tpattern = &parser->patterns[i];\n+\t\tret = cpfl_check_pattern_key(pattern, items, attr);\n+\t\tif (ret < 0)\n+\t\t\tcontinue;\n+\t\t/* pr->actions */\n+\t\tret = cpfl_parse_pr_actions(itf, pattern->actions, pattern->actions_size,\n+\t\t\t\t\t    items, attr, pr_action);\n+\t\treturn ret;\n+\t}\n+\n+\treturn -EINVAL;\n+}\n+\n+bool\n+cpfl_metadata_write_port_id(struct cpfl_itf *itf)\n+{\n+\tuint16_t dev_id;\n+\tconst int type = 0;\n+\tconst int offset = 5;\n+\n+\tdev_id = cpfl_get_port_id(itf);\n+\tif (dev_id == CPFL_INVALID_HW_ID) {\n+\t\tPMD_DRV_LOG(ERR, \"fail to get hw ID\\n\");\n+\t\treturn false;\n+\t}\n+\tcpfl_metadata_write16(&itf->adapter->meta, type, offset, dev_id << 3);\n+\n+\treturn true;\n+}\n+\n+bool\n+cpfl_metadata_write_targetvsi(struct cpfl_itf *itf)\n+{\n+\tuint16_t dev_id;\n+\tconst int type = 6;\n+\tconst int offset = 2;\n+\n+\tdev_id = cpfl_get_vsi_id(itf);\n+\tif (dev_id == CPFL_INVALID_HW_ID) {\n+\t\tPMD_DRV_LOG(ERR, \"fail to get hw ID\");\n+\t\treturn false;\n+\t}\n+\tcpfl_metadata_write16(&itf->adapter->meta, type, offset, dev_id << 1);\n+\n+\treturn true;\n+}\n+\n+bool\n+cpfl_metadata_write_sourcevsi(struct cpfl_itf *itf)\n+{\n+\tuint16_t dev_id;\n+\tconst int type = 6;\n+\tconst int offset = 0;\n+\n+\tdev_id = cpfl_get_vsi_id(itf);\n+\tif (dev_id == CPFL_INVALID_HW_ID) {\n+\t\tPMD_DRV_LOG(ERR, \"fail to get hw ID\");\n+\t\treturn false;\n+\t}\n+\tcpfl_metadata_write16(&itf->adapter->meta, type, offset, dev_id);\n+\n+\treturn true;\n+}\n+\n+bool cpfl_metadata_write_vsi(struct cpfl_itf *itf)\n+{\n+\tuint16_t dev_id;\n+\tconst int type = 0;\n+\tconst int offset = 24;\n+\n+\tdev_id = cpfl_get_vsi_id(itf);\n+\tif (dev_id == CPFL_INVALID_HW_ID) {\n+\t\tPMD_DRV_LOG(ERR, \"fail to get hw ID\");\n+\t\treturn false;\n+\t}\n+\tcpfl_metadata_write16(&itf->adapter->meta, type, offset, dev_id);\n+\n+\treturn true;\n+}\ndiff --git a/drivers/net/cpfl/cpfl_flow_parser.h b/drivers/net/cpfl/cpfl_flow_parser.h\nnew file mode 100644\nindex 0000000000..af64a158a8\n--- /dev/null\n+++ b/drivers/net/cpfl/cpfl_flow_parser.h\n@@ -0,0 +1,167 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Intel Corporation\n+ */\n+#include <json-c/json.h>\n+#include <rte_flow.h>\n+#include \"cpfl_ethdev.h\"\n+\n+#ifndef _CPFL_FLOW_PARSER_H_\n+#define _CPFL_FLOW_PARSER_H_\n+\n+#define CPFL_FLOW_JSON_STR_SIZE_MAX 100\n+#define CPFL_MAX_SEM_FV_KEY_SIZE 64\n+#define CPFL_FLOW_JS_PROTO_SIZE 16\n+#define CPFL_MOD_KEY_NUM_MAX 8\n+\n+/* Pattern Rules Storage */\n+enum cpfl_flow_pr_action_type {\n+\tCPFL_JS_PR_ACTION_TYPE_SEM,\n+\tCPFL_JS_PR_ACTION_TYPE_UNKNOWN = -1,\n+};\n+\n+/* This structure matches a sequence of fields in struct rte_flow_attr */\n+struct cpfl_flow_js_pr_key_attr {\n+\tuint16_t ingress;\n+\tuint16_t egress;\n+};\n+\n+struct cpfl_flow_js_pr_key_proto_field {\n+\tchar name[CPFL_FLOW_JSON_STR_SIZE_MAX];\n+\tunion {\n+\t\tchar mask[CPFL_FLOW_JSON_STR_SIZE_MAX];\n+\t\tuint32_t mask_32b;\n+\t};\n+};\n+\n+/* This structure matches a sequence of \"struct rte_flow_item\" */\n+struct cpfl_flow_js_pr_key_proto {\n+\tenum rte_flow_item_type type;\n+\tstruct cpfl_flow_js_pr_key_proto_field *fields;\n+\tint fields_size;\n+};\n+\n+enum cpfl_flow_js_fv_type {\n+\tCPFL_FV_TYPE_PROTOCOL,\n+\tCPFL_FV_TYPE_IMMEDIATE,\n+\tCPFL_FV_TYPE_METADATA,\n+\tCPFL_FV_TYPE_UNKNOWN = -1,\n+};\n+\n+struct cpfl_flow_js_fv {\n+\tuint16_t offset;\n+\tenum cpfl_flow_js_fv_type type;\n+\tunion {\n+\t\t/*  a 16 bits value */\n+\t\tuint16_t immediate;\n+\t\t/* a reference to a protocol header with a <header, layer, offset, mask> tuple */\n+\t\tstruct {\n+\t\t\tenum rte_flow_item_type header;\n+\t\t\tuint16_t layer;\n+\t\t\tuint16_t offset;\n+\t\t\tuint16_t mask;\n+\t\t} proto;\n+\t\t/* a reference to a metadata */\n+\t\tstruct {\n+\t\t\tuint16_t type;\n+\t\t\tuint16_t offset;\n+\t\t\tuint16_t mask;\n+\t\t} meta;\n+\t};\n+};\n+\n+/**\n+ * This structure defines the message be used to composite the\n+ * profile / key of a SEM control packet\n+ */\n+struct cpfl_flow_js_pr_action_sem {\n+\tuint16_t prof;\t\t    /* SEM profile ID */\n+\tuint16_t subprof;\t    /* SEM subprofile ID */\n+\tuint16_t keysize;\t    /*  extract key size in bytes */\n+\tstruct cpfl_flow_js_fv *fv; /* A SEM field vector array */\n+\tint fv_size;\n+};\n+\n+/* define how to map current key to low level pipeline configuration */\n+struct cpfl_flow_js_pr_action {\n+\tenum cpfl_flow_pr_action_type type;\n+\tunion {\n+\t\tstruct cpfl_flow_js_pr_action_sem sem;\n+\t};\n+};\n+\n+/**\n+ * This structure defines a set of rules that direct PMD how to parse rte_flow\n+ * protocol headers. Each rule be described by a key object and a action array.\n+ */\n+struct cpfl_flow_js_pr {\n+\tstruct {\n+\t\tstruct cpfl_flow_js_pr_key_proto *protocols;\n+\t\tuint16_t proto_size;\n+\t\tstruct cpfl_flow_js_pr_key_attr *attributes;\n+\t\tuint16_t attr_size;\n+\t} key;\n+\t/* An array to define how to map current key to low level pipeline configuration. */\n+\tstruct cpfl_flow_js_pr_action *actions;\n+\tuint16_t actions_size;\n+};\n+\n+struct cpfl_flow_js_parser {\n+\tstruct cpfl_flow_js_pr *patterns;\n+\tint pr_size;\n+};\n+\n+/* Pattern Rules */\n+struct cpfl_flow_pr_action_sem {\n+\tuint16_t prof;\n+\tuint16_t subprof;\n+\tuint16_t keysize;\n+\tuint8_t cpfl_flow_pr_fv[CPFL_MAX_SEM_FV_KEY_SIZE];\n+};\n+\n+struct cpfl_flow_pr_action {\n+\tenum cpfl_flow_pr_action_type type;\n+\tunion {\n+\t\tstruct cpfl_flow_pr_action_sem sem;\n+\t};\n+};\n+\n+int cpfl_parser_create(struct cpfl_flow_js_parser **parser, const char *filename);\n+int cpfl_parser_destroy(struct cpfl_flow_js_parser *parser);\n+int cpfl_flow_parse_items(struct cpfl_itf *itf,\n+\t\t\t  struct cpfl_flow_js_parser *parser,\n+\t\t\t  const struct rte_flow_item *items,\n+\t\t\t  const struct rte_flow_attr *attr,\n+\t\t\t  struct cpfl_flow_pr_action *pr_action);\n+bool cpfl_metadata_write_port_id(struct cpfl_itf *itf);\n+bool cpfl_metadata_write_vsi(struct cpfl_itf *itf);\n+bool cpfl_metadata_write_targetvsi(struct cpfl_itf *itf);\n+bool cpfl_metadata_write_sourcevsi(struct cpfl_itf *itf);\n+\n+static inline void\n+cpfl_metadata_init(struct cpfl_metadata *meta)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < CPFL_META_LENGTH; i++)\n+\t\tmeta->chunks[i].type = i;\n+}\n+\n+static inline void\n+cpfl_metadata_write16(struct cpfl_metadata *meta, int type, int offset, uint16_t data)\n+{\n+\trte_memcpy(&meta->chunks[type].data[offset], &data, sizeof(uint16_t));\n+}\n+\n+static inline void\n+cpfl_metadata_write32(struct cpfl_metadata *meta, int type, int offset, uint32_t data)\n+{\n+\trte_memcpy(&meta->chunks[type].data[offset], &data, sizeof(uint32_t));\n+}\n+\n+static inline uint16_t\n+cpfl_metadata_read16(struct cpfl_metadata *meta, int type, int offset)\n+{\n+\treturn *((uint16_t *)(&meta->chunks[type].data[offset]));\n+}\n+\n+#endif\ndiff --git a/drivers/net/cpfl/meson.build b/drivers/net/cpfl/meson.build\nindex d8b92ae16a..1e0a1b0290 100644\n--- a/drivers/net/cpfl/meson.build\n+++ b/drivers/net/cpfl/meson.build\n@@ -38,3 +38,16 @@ if arch_subdir == 'x86'\n         cflags += ['-DCC_AVX512_SUPPORT']\n     endif\n endif\n+\n+js_dep = dependency('json-c', required: false, method : 'pkg-config')\n+if js_dep.found()\n+    if js_dep.version().version_compare('<0.14')\n+        message('json-c lib version is too low')\n+    else\n+        sources += files(\n+                'cpfl_flow_parser.c',\n+        )\n+        dpdk_conf.set('CPFL_FLOW_JSON_SUPPORT', true)\n+        ext_deps += js_dep\n+    endif\n+endif\n",
    "prefixes": [
        "v5",
        "1/9"
    ]
}