get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 132402,
    "url": "http://patchwork.dpdk.org/api/patches/132402/?format=api",
    "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/20230908160552.148060-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": "<20230908160552.148060-2-yuying.zhang@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20230908160552.148060-2-yuying.zhang@intel.com",
    "date": "2023-09-08T16:05:44",
    "name": "[v10,1/9] net/cpfl: parse flow offloading hint from JSON",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "c76f6abe548635662493a38ecdc2721016d7713c",
    "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/20230908160552.148060-2-yuying.zhang@intel.com/mbox/",
    "series": [
        {
            "id": 29766,
            "url": "http://patchwork.dpdk.org/api/series/29766/?format=api",
            "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=29766",
            "date": "2023-09-08T16:05:43",
            "name": "add rte flow support for cpfl",
            "version": 10,
            "mbox": "http://patchwork.dpdk.org/series/29766/mbox/"
        }
    ],
    "comments": "http://patchwork.dpdk.org/api/patches/132402/comments/",
    "check": "success",
    "checks": "http://patchwork.dpdk.org/api/patches/132402/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 1EB0C42338;\n\tMon,  9 Oct 2023 10:02:18 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 53823402EC;\n\tMon,  9 Oct 2023 10:02:17 +0200 (CEST)",
            "from mgamail.intel.com (mgamail.intel.com [134.134.136.126])\n by mails.dpdk.org (Postfix) with ESMTP id 89FCD402EA\n for <dev@dpdk.org>; Mon,  9 Oct 2023 10:02:14 +0200 (CEST)",
            "from orsmga005.jf.intel.com ([10.7.209.41])\n by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 09 Oct 2023 01:02:13 -0700",
            "from dpdk-pengyuan-mev.sh.intel.com ([10.67.119.132])\n by orsmga005.jf.intel.com with ESMTP; 09 Oct 2023 01:02:10 -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=1696838534; x=1728374534;\n h=from:to:cc:subject:date:message-id:in-reply-to:\n references:mime-version:content-transfer-encoding;\n bh=EHVGs2n3kdQApQJsu680BtdD5tadHUlKnmgA/b4BlcQ=;\n b=A6dYTeMncXQ0hhI1gSxiNiovzhjCh328kHJgNU1dRtemYPbDZA0aC1UZ\n Lh5IkXOUYax+T7uxhsKF8Y4+i/VlzcVnyFdug+ngmywT3dgB+c83Vg9lD\n SDXXK8SRtz7H/YIPTKgb0sKgXszVNJdU7ylOic+GdxpuA1UxXlzeziPOW\n QvifkWVevPHXs3YsvL9rxb4O39VMcpAydP63YnX1554vLcDdZqsZQtIM2\n HEWK5fh1/wi1Uat375K4g3W9xbhovmSEkw+hVL34zoTIOHuRsyQalZGi5\n QAajuCKf5Y1+D1f+0VGOoBE+bjKMHDQrNmepb8jvNK+uX0w9+O1iHHTTi A==;",
        "X-IronPort-AV": [
            "E=McAfee;i=\"6600,9927,10857\"; a=\"369155042\"",
            "E=Sophos;i=\"6.03,209,1694761200\"; d=\"scan'208\";a=\"369155042\"",
            "E=McAfee;i=\"6600,9927,10857\"; a=\"926675812\"",
            "E=Sophos;i=\"6.03,209,1694761200\"; d=\"scan'208\";a=\"926675812\""
        ],
        "X-ExtLoop1": "1",
        "From": "\"Zhang, Yuying\" <yuying.zhang@intel.com>",
        "To": "yuying.zhang@intel.com, dev@dpdk.org, qi.z.zhang@intel.com,\n jingjing.wu@intel.com, beilei.xing@intel.com",
        "Cc": "Wenjing Qiao <wenjing.qiao@intel.com>",
        "Subject": "[PATCH v10 1/9] net/cpfl: parse flow offloading hint from JSON",
        "Date": "Fri,  8 Sep 2023 16:05:44 +0000",
        "Message-Id": "<20230908160552.148060-2-yuying.zhang@intel.com>",
        "X-Mailer": "git-send-email 2.25.1",
        "In-Reply-To": "<20230908160552.148060-1-yuying.zhang@intel.com>",
        "References": "<20230928084458.2333663-1-yuying.zhang@intel.com>\n <20230908160552.148060-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\" to specify the path of a JSON\nconfigure file. The cpfl PMD use the JSON configuration file\nto translate rte_flow tokens into low level hardware\nrepresentation.\n\nExample:\n    -a ca:00.0,flow_parser=\"refpkg.json\"\n\njansson library is used to parse JSON syntax.\n\nIn this patch, The parser only builds rules which maps from\na set of rte_flow items to hardware representations. The rules\nthat maps from rte_flow actions will be enabled in a separate\npatch to avoid a big size patch.\n\nNote, the JSON configuration file is provided by the hardware vendor\nand is intended to work exclusively with a specific P4 pipeline\nconfiguration, which must be compiled and programmed into the hardware.\n\nThe format of the JSON file strictly follows the internal specifications\nof the hardware vendor and is not meant to be modified directly by\nusers.\n\nSigned-off-by: Wenjing Qiao <wenjing.qiao@intel.com>\nAcked-by: Qi Zhang <qi.z.zhang@intel.com>\n---\n doc/guides/nics/cpfl.rst            |   38 +\n drivers/net/cpfl/cpfl_ethdev.c      |   38 +-\n drivers/net/cpfl/cpfl_ethdev.h      |   76 ++\n drivers/net/cpfl/cpfl_flow_parser.c | 1299 +++++++++++++++++++++++++++\n drivers/net/cpfl/cpfl_flow_parser.h |  168 ++++\n drivers/net/cpfl/meson.build        |    7 +\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..e17347d15c 100644\n--- a/doc/guides/nics/cpfl.rst\n+++ b/doc/guides/nics/cpfl.rst\n@@ -128,12 +128,32 @@ 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+\n+  The JSON configuration file is provided by the hardware vendor and is intended to work\n+  exclusively with a specific P4 pipeline configuration, which must be compiled and programmed\n+  into the hardware.\n+\n+  The format of the JSON file strictly follows the internal specifications of the hardware\n+  vendor and is not meant to be modified directly by users.\n+\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 jansson library must be installed to use rte_flow.\n \n Features\n --------\n@@ -164,3 +184,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+  * jansson\n+\n+    * For Ubuntu, it can be installed using `apt install libjansson-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..1745f703c8 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 RTE_HAS_JANSSON\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 RTE_HAS_JANSSON\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 RTE_HAS_JANSSON\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 RTE_HAS_JANSSON\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..a5fff5a857\n--- /dev/null\n+++ b/drivers/net/cpfl/cpfl_flow_parser.c\n@@ -0,0 +1,1299 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Intel Corporation\n+ */\n+\n+#include <arpa/inet.h>\n+\n+#include \"cpfl_flow_parser.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_t_to_string(json_t *object, const char *name)\n+{\n+\tjson_t *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_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_string_value(subobject);\n+}\n+\n+static int\n+cpfl_json_t_to_uint16(json_t *object, const char *name, uint16_t *value)\n+{\n+\tjson_t *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_get(object, name);\n+\tif (!subobject) {\n+\t\tPMD_DRV_LOG(ERR, \"%s doesn't exist.\", name);\n+\t\treturn -EINVAL;\n+\t}\n+\tif (!json_is_integer(subobject)) {\n+\t\tPMD_DRV_LOG(ERR, \"%s is not an integer.\", name);\n+\t\treturn -EINVAL;\n+\t}\n+\t*value = (uint16_t)json_integer_value(subobject);\n+\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_json_t_to_uint32(json_t *object, const char *name, uint32_t *value)\n+{\n+\tjson_t *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_get(object, name);\n+\tif (!subobject) {\n+\t\tPMD_DRV_LOG(ERR, \"%s doesn't exist.\", name);\n+\t\treturn -EINVAL;\n+\t}\n+\tif (!json_is_integer(subobject)) {\n+\t\tPMD_DRV_LOG(ERR, \"%s is not an integer.\", name);\n+\t\treturn -EINVAL;\n+\t}\n+\t*value = (uint32_t)json_integer_value(subobject);\n+\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_flow_js_pattern_key_attr(json_t *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_array_size(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_t *object;\n+\t\tconst char *name;\n+\t\tuint16_t value = 0;\n+\t\tint ret;\n+\n+\t\tobject = json_array_get(ob_pr_key_attrs, i);\n+\t\tname = cpfl_json_t_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_t_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_t *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_array_size(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_t *object;\n+\t\tconst char *name, *mask;\n+\n+\t\tobject = json_array_get(ob_fields, i);\n+\t\tname = cpfl_json_t_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_t_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_t_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_t *ob_pr_key_protos, struct cpfl_flow_js_pr *js_pr)\n+{\n+\tint len, i, ret;\n+\n+\tlen = json_array_size(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_t *object, *ob_fields;\n+\t\tconst char *type;\n+\t\tenum rte_flow_item_type item_type;\n+\n+\t\tobject = json_array_get(ob_pr_key_protos, i);\n+\t\t/* pr->key->proto->type */\n+\t\ttype = cpfl_json_t_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_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_t *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_t_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_t_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_t_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_t_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_t *ob_value, struct cpfl_flow_js_fv *js_fv)\n+{\n+\tint ret;\n+\n+\tret = cpfl_json_t_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_t_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_t_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_t *ob_fvs, struct cpfl_flow_js_pr_action *js_act)\n+{\n+\tint len, i;\n+\n+\tlen = json_array_size(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_t *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_array_get(ob_fvs, i);\n+\t\tret = cpfl_json_t_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_t_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_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_integer_value(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_t *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_t_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_t *ob_fvs, *ob_sem;\n+\n+\t\tjs_act->type = CPFL_JS_PR_ACTION_TYPE_SEM;\n+\t\tob_sem = json_object_get(ob_per_act, \"data\");\n+\t\tret = cpfl_json_t_to_uint16(ob_sem, \"profile\", &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_t_to_uint16(ob_sem, \"subprofile\", &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_t_to_uint16(ob_sem, \"keysize\", &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_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_t *ob_pr_acts, struct cpfl_flow_js_pr *js_pr)\n+{\n+\tint i, len, ret;\n+\n+\tlen = json_array_size(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_t *object;\n+\n+\t\tobject = json_array_get(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_t *ob_root, struct cpfl_flow_js_parser *parser)\n+{\n+\tjson_t *ob_prs;\n+\tint i, len;\n+\n+\t/* Pattern Rules */\n+\tob_prs = json_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_array_size(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_t *object;\n+\t\tjson_t *ob_pr_actions;\n+\t\tjson_t *ob_pr_key;\n+\t\tjson_t *ob_pr_key_protos;\n+\t\tjson_t *ob_pr_key_attrs;\n+\t\tint ret;\n+\n+\t\tobject = json_array_get(ob_prs, i);\n+\t\t/* pr->key */\n+\t\tob_pr_key = json_object_get(object, \"key\");\n+\t\t/* pr->key->protocols */\n+\t\tob_pr_key_protos = json_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_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_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_t *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_error_t json_error;\n+\tjson_t *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_load_file(filename, 0, &json_error);\n+\tif (!root) {\n+\t\tPMD_DRV_LOG(ERR, \"Bad JSON file \\\"%s\\\": %s\", filename, json_error.text);\n+\t\tgoto free_parser;\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+\tjson_decref(root);\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..268e1bc89f\n--- /dev/null\n+++ b/drivers/net/cpfl/cpfl_flow_parser.h\n@@ -0,0 +1,168 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Intel Corporation\n+ */\n+#include <jansson.h>\n+#include <rte_flow.h>\n+\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+\tmemcpy(&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+\tmemcpy(&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..d767818eb7 100644\n--- a/drivers/net/cpfl/meson.build\n+++ b/drivers/net/cpfl/meson.build\n@@ -38,3 +38,10 @@ if arch_subdir == 'x86'\n         cflags += ['-DCC_AVX512_SUPPORT']\n     endif\n endif\n+\n+if dpdk_conf.has('RTE_HAS_JANSSON')\n+    sources += files(\n+            'cpfl_flow_parser.c',\n+    )\n+    ext_deps += jansson_dep\n+endif\n",
    "prefixes": [
        "v10",
        "1/9"
    ]
}