get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 130147,
    "url": "http://patchwork.dpdk.org/api/patches/130147/?format=api",
    "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/20230811093032.2065099-3-wenjing.qiao@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": "<20230811093032.2065099-3-wenjing.qiao@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20230811093032.2065099-3-wenjing.qiao@intel.com",
    "date": "2023-08-11T09:30:33",
    "name": "[2/4] net/cpfl: add flow json parser",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "7e0e00539bd1ea762d5b6e20bbde994f6f106a14",
    "submitter": {
        "id": 2680,
        "url": "http://patchwork.dpdk.org/api/people/2680/?format=api",
        "name": "Wenjing Qiao",
        "email": "wenjing.qiao@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/20230811093032.2065099-3-wenjing.qiao@intel.com/mbox/",
    "series": [
        {
            "id": 29178,
            "url": "http://patchwork.dpdk.org/api/series/29178/?format=api",
            "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=29178",
            "date": "2023-08-11T09:30:29",
            "name": "net/cpfl: add basic support for rte_flow",
            "version": 1,
            "mbox": "http://patchwork.dpdk.org/series/29178/mbox/"
        }
    ],
    "comments": "http://patchwork.dpdk.org/api/patches/130147/comments/",
    "check": "success",
    "checks": "http://patchwork.dpdk.org/api/patches/130147/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 0DBC443032;\n\tFri, 11 Aug 2023 11:31:46 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id EC3BD40F16;\n\tFri, 11 Aug 2023 11:31:45 +0200 (CEST)",
            "from mgamail.intel.com (mgamail.intel.com [192.55.52.151])\n by mails.dpdk.org (Postfix) with ESMTP id 4E51B40E03\n for <dev@dpdk.org>; Fri, 11 Aug 2023 11:31:44 +0200 (CEST)",
            "from orsmga007.jf.intel.com ([10.7.209.58])\n by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 11 Aug 2023 02:31:42 -0700",
            "from dpdk-wenjing-02.sh.intel.com ([10.67.119.75])\n by orsmga007.jf.intel.com with ESMTP; 11 Aug 2023 02:31:39 -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=1691746304; x=1723282304;\n h=from:to:cc:subject:date:message-id:in-reply-to:\n references:mime-version:content-transfer-encoding;\n bh=8k7vMO7o8qpHljtF4DwI8tqp0R1O0apdgeO+9nxInoI=;\n b=WAYYocWYlqi0jIf18nVZM0xArHWatgIUVkXUqo8UT7gMFZOViUelm95X\n g59KKPpVmLMv17IU+wONzLuOJkC76GNbzjdI8pia4qIMQ1R2Hm0J/IPan\n fnMNj8JmKwuaCbHtHxxM1RgJfVQ1sPD8qzlqN26B+kIAjf8aKzJ0W/83r\n b0dHx5XaPylf9PdmOIKvoP9sXIklmiz0jJLkk28Xn1t8gzkP0KM+4uZAb\n oDOHTgKLxeJHhmCkaZTPFwxXlrB9EJT3/VkAFKXGB7mCXI7na0xfgFCJh\n ql7XPye5z9NgBbr7xLRkQkFZMbdKkLqePN0yn6n+CfWBlv/bUfVj95DSf g==;",
        "X-IronPort-AV": [
            "E=McAfee;i=\"6600,9927,10798\"; a=\"351960071\"",
            "E=Sophos;i=\"6.01,165,1684825200\"; d=\"scan'208\";a=\"351960071\"",
            "E=McAfee;i=\"6600,9927,10798\"; a=\"726199851\"",
            "E=Sophos;i=\"6.01,165,1684825200\"; d=\"scan'208\";a=\"726199851\""
        ],
        "X-ExtLoop1": "1",
        "From": "Wenjing Qiao <wenjing.qiao@intel.com>",
        "To": "yuying.zhang@intel.com,\n\tbeilei.xing@intel.com",
        "Cc": "dev@dpdk.org, mingxia.liu@intel.com, Wenjing Qiao <wenjing.qiao@intel.com>",
        "Subject": "[PATCH 2/4] net/cpfl: add flow json parser",
        "Date": "Fri, 11 Aug 2023 09:30:33 +0000",
        "Message-Id": "<20230811093032.2065099-3-wenjing.qiao@intel.com>",
        "X-Mailer": "git-send-email 2.34.1",
        "In-Reply-To": "<20230811093032.2065099-1-wenjing.qiao@intel.com>",
        "References": "<20230811093032.2065099-1-wenjing.qiao@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": "A JSON file will be used to direct DPDK CPF PMD to\nparse rte_flow tokens into low level hardware resources\ndefined in a DDP package file.\n\nSigned-off-by: Wenjing Qiao <wenjing.qiao@intel.com>\n---\n drivers/net/cpfl/cpfl_flow_parser.c | 1758 +++++++++++++++++++++++++++\n drivers/net/cpfl/cpfl_flow_parser.h |  205 ++++\n drivers/net/cpfl/meson.build        |    3 +\n 3 files changed, 1966 insertions(+)\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/drivers/net/cpfl/cpfl_flow_parser.c b/drivers/net/cpfl/cpfl_flow_parser.c\nnew file mode 100644\nindex 0000000000..b4635813ff\n--- /dev/null\n+++ b/drivers/net/cpfl/cpfl_flow_parser.c\n@@ -0,0 +1,1758 @@\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 enum rte_flow_action_type\n+cpfl_get_action_type_by_str(const char *type)\n+{\n+\tif (strcmp(type, \"vxlan_encap\") == 0)\n+\t\treturn RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP;\n+\n+\tPMD_DRV_LOG(ERR, \"Not support this type: %s.\", type);\n+\treturn RTE_FLOW_ACTION_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 0;\n+\t}\n+\treturn json_object_get_string(subobject);\n+}\n+\n+static int\n+cpfl_json_object_to_int(json_object *object, const char *name, int *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+\treturn 0;\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+\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+\treturn 0;\n+}\n+\n+static int\n+cpfl_flow_js_pattern_key_attr(json_object *cjson_pr_key_attr, 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(cjson_pr_key_attr);\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+\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(cjson_pr_key_attr, i);\n+\t\tname = cpfl_json_object_to_string(object, \"Name\");\n+\t\tif (!name) {\n+\t\t\trte_free(js_pr->key.attributes);\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse string 'Name'.\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tret = cpfl_json_object_to_uint16(object, \"Value\", &value);\n+\t\tif (ret < 0) {\n+\t\t\trte_free(js_pr->key.attributes);\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse 'value'.\");\n+\t\t\treturn -EINVAL;\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\trte_free(js_pr->key.attributes);\n+\t\t\tPMD_DRV_LOG(ERR, \"Not support attr name: %s.\", name);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_flow_js_pattern_key_proto_field(json_object *cjson_field,\n+\t\t\t\t     struct cpfl_flow_js_pr_key_proto *js_field)\n+{\n+\tif (cjson_field) {\n+\t\tint len, i;\n+\n+\t\tlen = json_object_array_length(cjson_field);\n+\t\tjs_field->fields_size = len;\n+\t\tif (len == 0)\n+\t\t\treturn 0;\n+\t\tjs_field->fields =\n+\t\t    rte_malloc(NULL, sizeof(struct cpfl_flow_js_pr_key_proto_field) * len, 0);\n+\t\tif (!js_field->fields) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Failed to alloc memory.\");\n+\t\t\treturn -ENOMEM;\n+\t\t}\n+\t\tfor (i = 0; i < len; i++) {\n+\t\t\tjson_object *object;\n+\t\t\tconst char *name, *mask;\n+\n+\t\t\tobject = json_object_array_get_idx(cjson_field, i);\n+\t\t\tname = cpfl_json_object_to_string(object, \"name\");\n+\t\t\tif (!name) {\n+\t\t\t\trte_free(js_field->fields);\n+\t\t\t\tPMD_DRV_LOG(ERR, \"Can not parse string 'name'.\");\n+\t\t\t\treturn -EINVAL;\n+\t\t\t}\n+\t\t\tif (strlen(name) > CPFL_FLOW_JSON_STR_SIZE_MAX) {\n+\t\t\t\trte_free(js_field->fields);\n+\t\t\t\tPMD_DRV_LOG(ERR, \"The 'name' is too long.\");\n+\t\t\t\treturn -EINVAL;\n+\t\t\t}\n+\t\t\tmemcpy(js_field->fields[i].name, name, strlen(name));\n+\n+\t\t\tif (js_field->type == RTE_FLOW_ITEM_TYPE_ETH ||\n+\t\t\t    js_field->type == RTE_FLOW_ITEM_TYPE_IPV4) {\n+\t\t\t\tmask = cpfl_json_object_to_string(object, \"mask\");\n+\t\t\t\tif (!mask) {\n+\t\t\t\t\trte_free(js_field->fields);\n+\t\t\t\t\tPMD_DRV_LOG(ERR, \"Can not parse string 'mask'.\");\n+\t\t\t\t\treturn -EINVAL;\n+\t\t\t\t}\n+\t\t\t\tmemcpy(js_field->fields[i].mask, mask, strlen(mask));\n+\t\t\t} else {\n+\t\t\t\tuint32_t mask_32b;\n+\t\t\t\tint ret;\n+\n+\t\t\t\tret = cpfl_json_object_to_uint32(object, \"mask\", &mask_32b);\n+\t\t\t\tif (ret < 0) {\n+\t\t\t\t\trte_free(js_field->fields);\n+\t\t\t\t\tPMD_DRV_LOG(ERR, \"Can not parse uint32 'mask'.\");\n+\t\t\t\t\treturn -EINVAL;\n+\t\t\t\t}\n+\t\t\t\tjs_field->fields[i].mask_32b = mask_32b;\n+\t\t\t}\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_flow_js_pattern_key_proto(json_object *cjson_pr_key_proto, struct cpfl_flow_js_pr *js_pr)\n+{\n+\tint len, i, ret;\n+\n+\tlen = json_object_array_length(cjson_pr_key_proto);\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, *cjson_pr_key_proto_fields;\n+\t\tconst char *type;\n+\t\tenum rte_flow_item_type item_type;\n+\n+\t\tobject = json_object_array_get_idx(cjson_pr_key_proto, 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\trte_free(js_pr->key.protocols);\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse string 'type'.\");\n+\t\t\treturn -EINVAL;\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\trte_free(js_pr->key.protocols);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tjs_pr->key.protocols[i].type = item_type;\n+\t\t/* pr->key->proto->fields */\n+\t\tcjson_pr_key_proto_fields = json_object_object_get(object, \"fields\");\n+\t\tret = cpfl_flow_js_pattern_key_proto_field(cjson_pr_key_proto_fields,\n+\t\t\t\t\t\t\t   &js_pr->key.protocols[i]);\n+\t\tif (ret < 0) {\n+\t\t\trte_free(js_pr->key.protocols);\n+\t\t\treturn ret;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_flow_js_pattern_act_fv_proto(json_object *cjson_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(cjson_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(cjson_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(cjson_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(cjson_value, \"mask\", &mask);\n+\tif (ret < 0) {\n+\t\tPMD_DRV_LOG(ERR, \"Can not parse 'mask'.\");\n+\t\treturn -EINVAL;\n+\t}\n+\tjs_fv->proto.layer = layer;\n+\tjs_fv->proto.offset = offset;\n+\tjs_fv->proto.mask = mask;\n+\ttype = cpfl_get_item_type_by_str(header);\n+\tif (type == RTE_FLOW_ITEM_TYPE_VOID)\n+\t\treturn -EINVAL;\n+\n+\telse\n+\t\tjs_fv->proto.header = type;\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_flow_js_pattern_act_fv(json_object *cjson_fv, struct cpfl_flow_js_pr_action *js_act)\n+{\n+\tint len, i;\n+\n+\tlen = json_object_array_length(cjson_fv);\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, *cjson_value;\n+\t\tuint16_t offset = 0;\n+\t\tconst char *type;\n+\t\tint ret;\n+\n+\t\tobject = json_object_array_get_idx(cjson_fv, i);\n+\t\tjs_fv = &js_act->sem.fv[i];\n+\t\tret = cpfl_json_object_to_uint16(object, \"offset\", &offset);\n+\t\tif (ret < 0) {\n+\t\t\trte_free(js_act->sem.fv);\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse 'offset'.\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tjs_fv->offset = offset;\n+\t\ttype = cpfl_json_object_to_string(object, \"type\");\n+\t\tif (!type) {\n+\t\t\trte_free(js_act->sem.fv);\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse string 'type'.\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tcjson_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(cjson_value);\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(cjson_value, js_fv);\n+\t\t} else {\n+\t\t\trte_free(js_act->sem.fv);\n+\t\t\tPMD_DRV_LOG(ERR, \"Not support this type: %s.\", type);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_flow_js_pattern_per_act(json_object *cjson_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(cjson_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 *cjson_fv, *cjson_pr_action_sem;\n+\n+\t\tjs_act->type = CPFL_JS_PR_ACTION_TYPE_SEM;\n+\t\tcjson_pr_action_sem = json_object_object_get(cjson_per_act, \"data\");\n+\t\tret = cpfl_json_object_to_uint16(cjson_pr_action_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(cjson_pr_action_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(cjson_pr_action_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\tcjson_fv = json_object_object_get(cjson_pr_action_sem, \"fieldvectors\");\n+\t\tret = cpfl_flow_js_pattern_act_fv(cjson_fv, 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+\treturn 0;\n+}\n+\n+static int\n+cpfl_flow_js_pattern_act(json_object *cjson_pr_act, struct cpfl_flow_js_pr *js_pr)\n+{\n+\tint i, len, ret;\n+\n+\tlen = json_object_array_length(cjson_pr_act);\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(cjson_pr_act, 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+\treturn 0;\n+}\n+\n+static int\n+cpfl_flow_js_pattern_rule(json_object *json_root, struct cpfl_flow_js_parser *parser)\n+{\n+\tjson_object *cjson_pr;\n+\tint i, len;\n+\n+\t/* Pattern Rules */\n+\tcjson_pr = json_object_object_get(json_root, \"patterns\");\n+\tif (!cjson_pr) {\n+\t\tPMD_DRV_LOG(ERR, \"The patterns is mandatory.\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tlen = json_object_array_length(cjson_pr);\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, *cjson_pr_actions, *cjson_pr_key, *cjson_pr_key_proto,\n+\t\t    *cjson_pr_key_attr;\n+\t\tint ret;\n+\n+\t\tobject = json_object_array_get_idx(cjson_pr, i);\n+\t\t/* pr->key */\n+\t\tcjson_pr_key = json_object_object_get(object, \"key\");\n+\t\t/* pr->key->protocols */\n+\t\tcjson_pr_key_proto = json_object_object_get(cjson_pr_key, \"protocols\");\n+\t\tret = cpfl_flow_js_pattern_key_proto(cjson_pr_key_proto, &parser->patterns[i]);\n+\t\tif (ret < 0) {\n+\t\t\trte_free(parser->patterns);\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse key->protocols.\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\t/* pr->key->attributes */\n+\t\tcjson_pr_key_attr = json_object_object_get(cjson_pr_key, \"attributes\");\n+\t\tret = cpfl_flow_js_pattern_key_attr(cjson_pr_key_attr, &parser->patterns[i]);\n+\t\tif (ret < 0) {\n+\t\t\trte_free(parser->patterns);\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse key->attributes.\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\t/* pr->actions */\n+\t\tcjson_pr_actions = json_object_object_get(object, \"actions\");\n+\t\tret = cpfl_flow_js_pattern_act(cjson_pr_actions, &parser->patterns[i]);\n+\t\tif (ret < 0) {\n+\t\t\trte_free(parser->patterns);\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse pattern action.\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_flow_js_mr_key(json_object *cjson_mr_key, struct cpfl_flow_js_mr_key *js_mr_key)\n+{\n+\tint len, i;\n+\n+\tlen = json_object_array_length(cjson_mr_key);\n+\tjs_mr_key->actions = rte_malloc(NULL, sizeof(struct cpfl_flow_js_mr_key_action) * len, 0);\n+\tif (!js_mr_key->actions) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to alloc memory.\");\n+\t\treturn -ENOMEM;\n+\t}\n+\tjs_mr_key->actions_size = len;\n+\tfor (i = 0; i < len; i++) {\n+\t\tjson_object *object, *cjson_mr_key_data;\n+\t\tconst char *type;\n+\t\tenum rte_flow_action_type act_type;\n+\n+\t\tobject = json_object_array_get_idx(cjson_mr_key, i);\n+\t\t/* mr->key->actions->type */\n+\t\ttype = cpfl_json_object_to_string(object, \"type\");\n+\t\tif (!type) {\n+\t\t\trte_free(js_mr_key->actions);\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse string 'type'.\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tact_type = cpfl_get_action_type_by_str(type);\n+\t\tif (act_type == RTE_FLOW_ACTION_TYPE_VOID) {\n+\t\t\trte_free(js_mr_key->actions);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tjs_mr_key->actions[i].type = act_type;\n+\t\t/* mr->key->actions->data */\n+\t\tcjson_mr_key_data = json_object_object_get(object, \"data\");\n+\t\tif (js_mr_key->actions[i].type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP) {\n+\t\t\tjson_object *cjson_mr_key_proto;\n+\t\t\tint proto_size, j;\n+\t\t\tstruct cpfl_flow_js_mr_key_action_vxlan_encap *encap;\n+\n+\t\t\tcjson_mr_key_proto = json_object_object_get(cjson_mr_key_data, \"protocols\");\n+\t\t\tencap = &js_mr_key->actions[i].encap;\n+\t\t\tif (!cjson_mr_key_proto) {\n+\t\t\t\tencap->proto_size = 0;\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tproto_size = json_object_array_length(cjson_mr_key_proto);\n+\t\t\tencap->proto_size = proto_size;\n+\t\t\tfor (j = 0; j < proto_size; j++) {\n+\t\t\t\tconst char *s;\n+\t\t\t\tjson_object *subobject;\n+\t\t\t\tenum rte_flow_item_type proto_type;\n+\n+\t\t\t\tsubobject = json_object_array_get_idx(cjson_mr_key_proto, j);\n+\t\t\t\ts = json_object_get_string(subobject);\n+\t\t\t\tproto_type = cpfl_get_item_type_by_str(s);\n+\t\t\t\tif (proto_type == RTE_FLOW_ITEM_TYPE_VOID) {\n+\t\t\t\t\trte_free(js_mr_key->actions);\n+\t\t\t\t\tPMD_DRV_LOG(ERR, \"parse VXLAN_ENCAP failed.\");\n+\t\t\t\t\treturn -EINVAL;\n+\t\t\t\t}\n+\t\t\t\tencap->protocols[j] = proto_type;\n+\t\t\t}\n+\n+\t\t} else {\n+\t\t\tPMD_DRV_LOG(ERR, \"not support this type: %d.\", js_mr_key->actions[i].type);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_flow_js_mr_layout(json_object *cjson_layout, struct cpfl_flow_js_mr_action_mod *js_mod)\n+{\n+\tint len, i;\n+\n+\tlen = json_object_array_length(cjson_layout);\n+\tjs_mod->layout_size = len;\n+\tif (len == 0)\n+\t\treturn 0;\n+\tjs_mod->layout = rte_malloc(NULL, sizeof(struct cpfl_flow_js_mr_layout) * len, 0);\n+\tif (!js_mod->layout) {\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;\n+\t\tint index = 0, size = 0, offset = 0, ret;\n+\t\tconst char *hint;\n+\n+\t\tobject = json_object_array_get_idx(cjson_layout, i);\n+\t\tret = cpfl_json_object_to_int(object, \"index\", &index);\n+\t\tif (ret < 0) {\n+\t\t\trte_free(js_mod->layout);\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse 'index'.\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tjs_mod->layout[i].index = index;\n+\t\tret = cpfl_json_object_to_int(object, \"size\", &size);\n+\t\tif (ret < 0) {\n+\t\t\trte_free(js_mod->layout);\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse 'size'.\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tjs_mod->layout[i].size = size;\n+\t\tret = cpfl_json_object_to_int(object, \"offset\", &offset);\n+\t\tif (ret < 0) {\n+\t\t\trte_free(js_mod->layout);\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse 'offset'.\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tjs_mod->layout[i].offset = offset;\n+\t\thint = cpfl_json_object_to_string(object, \"hint\");\n+\t\tif (!hint) {\n+\t\t\trte_free(js_mod->layout);\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse string 'hint'.\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tmemcpy(js_mod->layout[i].hint, hint, strlen(hint));\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_flow_js_mr_action(json_object *cjson_mr_act, struct cpfl_flow_js_mr_action *js_mr_act)\n+{\n+\tjson_object *cjson_mr_action_data;\n+\tconst char *type;\n+\n+\t/* mr->action->type */\n+\ttype = cpfl_json_object_to_string(cjson_mr_act, \"type\");\n+\tif (!type) {\n+\t\tPMD_DRV_LOG(ERR, \"Can not parse string 'type'.\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* mr->action->data */\n+\tcjson_mr_action_data = json_object_object_get(cjson_mr_act, \"data\");\n+\tif (strcmp(type, \"mod\") == 0) {\n+\t\tjson_object *layout;\n+\t\tuint16_t profile = 0;\n+\t\tint ret;\n+\n+\t\tjs_mr_act->type = CPFL_JS_MR_ACTION_TYPE_MOD;\n+\t\tret = cpfl_json_object_to_uint16(cjson_mr_action_data, \"profile\", &profile);\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\tjs_mr_act->mod.prof = profile;\n+\t\tlayout = json_object_object_get(cjson_mr_action_data, \"layout\");\n+\t\tret = cpfl_flow_js_mr_layout(layout, &js_mr_act->mod);\n+\t\tif (ret < 0) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse layout.\");\n+\t\t\treturn ret;\n+\t\t}\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_mod_rule(json_object *json_root, struct cpfl_flow_js_parser *parser)\n+{\n+\tjson_object *cjson_mr;\n+\tint i, len;\n+\n+\tcjson_mr = json_object_object_get(json_root, \"modifications\");\n+\tif (!cjson_mr) {\n+\t\tPMD_DRV_LOG(INFO, \"The modifications is optional.\");\n+\t\treturn 0;\n+\t}\n+\n+\tlen = json_object_array_length(cjson_mr);\n+\tparser->mr_size = len;\n+\tif (len == 0)\n+\t\treturn 0;\n+\tparser->modifications = rte_malloc(NULL, sizeof(struct cpfl_flow_js_mr) * len, 0);\n+\tif (!parser->modifications) {\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\tint ret;\n+\t\tjson_object *object, *cjson_mr_key, *cjson_mr_action, *cjson_mr_key_action;\n+\n+\t\tobject = json_object_array_get_idx(cjson_mr, i);\n+\t\t/* mr->key */\n+\t\tcjson_mr_key = json_object_object_get(object, \"key\");\n+\t\t/* mr->key->actions */\n+\t\tcjson_mr_key_action = json_object_object_get(cjson_mr_key, \"actions\");\n+\n+\t\tret = cpfl_flow_js_mr_key(cjson_mr_key_action, &parser->modifications[i].key);\n+\t\tif (ret < 0) {\n+\t\t\trte_free(parser->modifications);\n+\t\t\tPMD_DRV_LOG(ERR, \"parse mr_key failed.\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\t/* mr->action */\n+\t\tcjson_mr_action = json_object_object_get(object, \"action\");\n+\t\tret = cpfl_flow_js_mr_action(cjson_mr_action, &parser->modifications[i].action);\n+\t\tif (ret < 0) {\n+\t\t\trte_free(parser->modifications);\n+\t\t\tPMD_DRV_LOG(ERR, \"parse mr_action failed.\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_parser_init(json_object *json_root, struct cpfl_flow_js_parser *parser)\n+{\n+\tint ret = 0;\n+\n+\tret = cpfl_flow_js_pattern_rule(json_root, parser);\n+\tif (ret < 0) {\n+\t\tPMD_DRV_LOG(ERR, \"parse pattern_rule failed.\");\n+\t\treturn ret;\n+\t}\n+\tret = cpfl_flow_js_mod_rule(json_root, parser);\n+\tif (ret < 0) {\n+\t\tPMD_DRV_LOG(ERR, \"parse mod_rule failed.\");\n+\t\treturn ret;\n+\t}\n+\n+\treturn ret;\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\trte_free(parser);\n+\t\treturn -EINVAL;\n+\t}\n+\t*flow_parser = parser;\n+\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+}\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\tif (pr_act->sem.fv)\n+\t\t\trte_free(pr_act->sem.fv);\n+\t}\n+}\n+\n+int\n+cpfl_parser_destroy(struct cpfl_flow_js_parser *parser)\n+{\n+\tint i, j;\n+\n+\tfor (i = 0; i < parser->pr_size; i++) {\n+\t\tstruct cpfl_flow_js_pr *pattern = &parser->patterns[i];\n+\n+\t\tfor (j = 0; j < pattern->key.proto_size; j++) {\n+\t\t\tif (pattern->key.protocols[j].fields)\n+\t\t\t\trte_free(pattern->key.protocols[j].fields);\n+\t\t}\n+\t\tif (pattern->key.protocols)\n+\t\t\trte_free(pattern->key.protocols);\n+\n+\t\tif (pattern->key.attributes)\n+\t\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+\n+\t\tif (pattern->actions)\n+\t\t\trte_free(pattern->actions);\n+\t}\n+\tif (parser->patterns)\n+\t\trte_free(parser->patterns);\n+\n+\tfor (i = 0; i < parser->mr_size; i++) {\n+\t\tstruct cpfl_flow_js_mr *mr = &parser->modifications[i];\n+\n+\t\tif (mr->key.actions)\n+\t\t\trte_free(mr->key.actions);\n+\t\tif (mr->action.type == CPFL_JS_MR_ACTION_TYPE_MOD && mr->action.mod.layout)\n+\t\t\trte_free(mr->action.mod.layout);\n+\t}\n+\tif (parser->modifications)\n+\t\trte_free(parser->modifications);\n+\n+\trte_free(parser);\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_get_actions_length(const struct rte_flow_action *actions)\n+{\n+\tint length = 0;\n+\tconst struct rte_flow_action *action = actions;\n+\n+\twhile ((action + length++)->type != RTE_FLOW_ACTION_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+\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 & 0xff00) >> 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+\treturn 0;\n+}\n+\n+static int\n+cpfl_parse_fieldvectors(struct cpfl_flow_js_fv *js_fvs, int size, uint8_t *fv,\n+\t\t\tconst 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\t/* type = int */\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 & 0xff00) >> 8);\n+\t\t\tfv[2 * offset + 1] = (uint8_t)(temp_fv & 0x00ff);\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+\treturn 0;\n+}\n+\n+static int\n+cpfl_parse_pr_actions(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 % 10 == 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(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+\treturn 0;\n+}\n+\n+static int\n+str2MAC(const char *mask, uint8_t *addr_bytes)\n+{\n+\tint i, size, j;\n+\tuint8_t n;\n+\n+\tsize = strlen(mask);\n+\tn = 0;\n+\tj = 0;\n+\tfor (i = 0; i < size; i++) {\n+\t\tchar ch = mask[i];\n+\n+\t\tif (ch == ':') {\n+\t\t\tif (j >= RTE_ETHER_ADDR_LEN)\n+\t\t\t\treturn -EINVAL;\n+\t\t\taddr_bytes[j++] = n;\n+\t\t\tn = 0;\n+\t\t} else if (ch >= 'a' && ch <= 'f') {\n+\t\t\tn = n * 16 + ch - 'a' + 10;\n+\t\t} else if (ch >= 'A' && ch <= 'F') {\n+\t\t\tn = n * 16 + ch - 'A' + 10;\n+\t\t} else if (ch >= '0' && ch <= '9') {\n+\t\t\tn = n * 16 + ch - '0';\n+\t\t} else {\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\tif (j < RTE_ETHER_ADDR_LEN)\n+\t\taddr_bytes[j++] = n;\n+\n+\tif (j != RTE_ETHER_ADDR_LEN)\n+\t\treturn -EINVAL;\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_check_eth_mask(const char *mask, const uint8_t addr_bytes[RTE_ETHER_ADDR_LEN])\n+{\n+\tint i, ret;\n+\tuint8_t mask_bytes[RTE_ETHER_ADDR_LEN] = {0};\n+\n+\tret = str2MAC(mask, mask_bytes);\n+\tif (ret < 0) {\n+\t\tPMD_DRV_LOG(ERR, \"string to mac address failed.\");\n+\t\treturn -EINVAL;\n+\t}\n+\tfor (i = 0; i < RTE_ETHER_ADDR_LEN; i++) {\n+\t\tif (mask_bytes[i] != addr_bytes[i])\n+\t\t\treturn -EINVAL;\n+\t}\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/* success return 0; invalid return -EINVAL; fail return -ENOTSUP */\n+\tint ret = inet_pton(AF_INET, mask, &out_addr);\n+\n+\tif (ret < 0)\n+\t\treturn -EINVAL;\n+\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+\t/* eth_mask->dst.addr_bytes */\n+\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.addr_bytes) < 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.addr_bytes) < 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+\tif (proto) {\n+\t\tint field_size, j;\n+\t\tint flag_next_proto_id, flag_src_addr, flag_dst_addr;\n+\t\tstruct cpfl_flow_js_pr_key_proto_field *field;\n+\n+\t\tfield_size = proto->fields_size;\n+\t\tif (field_size != 0 && !ipv4_mask)\n+\t\t\treturn -EINVAL;\n+\n+\t\tif (field_size == 0 && ipv4_mask)\n+\t\t\treturn -EINVAL;\n+\n+\t\tif (field_size == 0 && !ipv4_mask)\n+\t\t\treturn 0;\n+\n+\t\tflag_dst_addr = false;\n+\t\tflag_src_addr = false;\n+\t\tflag_next_proto_id = false;\n+\t\tfor (j = 0; j < field_size; j++) {\n+\t\t\tconst char *name;\n+\n+\t\t\tfield = &proto->fields[j];\n+\t\t\tname = field->name;\n+\t\t\tif (strcmp(name, \"src_addr\") == 0) {\n+\t\t\t\t/* match: rte_flow_item->mask */\n+\t\t\t\tconst char *mask;\n+\n+\t\t\t\tmask = field->mask;\n+\t\t\t\tif (cpfl_check_ipv4_mask(mask, ipv4_mask->hdr.src_addr) < 0)\n+\t\t\t\t\treturn -EINVAL;\n+\t\t\t\tflag_src_addr = true;\n+\t\t\t} else if (strcmp(name, \"dst_addr\") == 0) {\n+\t\t\t\tconst char *mask;\n+\n+\t\t\t\tmask = field->mask;\n+\t\t\t\tif (cpfl_check_ipv4_mask(mask, ipv4_mask->hdr.dst_addr) < 0)\n+\t\t\t\t\treturn -EINVAL;\n+\t\t\t\tflag_dst_addr = true;\n+\t\t\t} else if (strcmp(name, \"next_proto_id\") == 0) {\n+\t\t\t\tuint8_t mask;\n+\n+\t\t\t\tmask = (uint8_t)field->mask_32b;\n+\t\t\t\tif (mask != ipv4_mask->hdr.next_proto_id)\n+\t\t\t\t\treturn -EINVAL;\n+\t\t\t\tflag_next_proto_id = true;\n+\t\t\t} else {\n+\t\t\t\tPMD_DRV_LOG(ERR, \"not support this name.\");\n+\t\t\t\treturn -EINVAL;\n+\t\t\t}\n+\t\t}\n+\t\tif (!flag_src_addr) {\n+\t\t\tif (ipv4_mask->hdr.src_addr != (rte_be32_t)0)\n+\t\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tif (!flag_dst_addr) {\n+\t\t\tif (ipv4_mask->hdr.dst_addr != (rte_be32_t)0)\n+\t\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tif (!flag_next_proto_id) {\n+\t\t\tif (ipv4_mask->hdr.next_proto_id != (uint8_t)0)\n+\t\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\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+\tif (proto) {\n+\t\tint field_size, j;\n+\t\tint flag_src_port, flag_dst_port;\n+\t\tstruct cpfl_flow_js_pr_key_proto_field *field;\n+\n+\t\tfield_size = proto->fields_size;\n+\t\tif (field_size != 0 && !tcp_mask)\n+\t\t\treturn -EINVAL;\n+\n+\t\tif (field_size == 0 && tcp_mask)\n+\t\t\treturn -EINVAL;\n+\n+\t\tif (field_size == 0 && !tcp_mask)\n+\t\t\treturn 0;\n+\n+\t\tflag_src_port = false;\n+\t\tflag_dst_port = false;\n+\t\tfor (j = 0; j < field_size; j++) {\n+\t\t\tconst char *name;\n+\t\t\tuint16_t mask;\n+\n+\t\t\tfield = &proto->fields[j];\n+\t\t\t/* match: rte_flow_item_eth.dst */\n+\t\t\tname = field->name;\n+\t\t\t/* match: rte_flow_item->mask */\n+\t\t\tmask = (uint16_t)field->mask_32b;\n+\t\t\tif (strcmp(name, \"src_port\") == 0) {\n+\t\t\t\tif (tcp_mask->hdr.src_port != mask)\n+\t\t\t\t\treturn -EINVAL;\n+\t\t\t\tflag_src_port = true;\n+\t\t\t} else if (strcmp(name, \"dst_port\") == 0) {\n+\t\t\t\tif (tcp_mask->hdr.dst_port != mask)\n+\t\t\t\t\treturn -EINVAL;\n+\t\t\t\tflag_dst_port = true;\n+\t\t\t} else {\n+\t\t\t\tPMD_DRV_LOG(ERR, \"not support this name.\");\n+\t\t\t\treturn -EINVAL;\n+\t\t\t}\n+\t\t}\n+\t\tif (!flag_src_port) {\n+\t\t\tif (tcp_mask->hdr.src_port != (rte_be16_t)0)\n+\t\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tif (!flag_dst_port) {\n+\t\t\tif (tcp_mask->hdr.dst_port != (rte_be16_t)0)\n+\t\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\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+\tif (proto) {\n+\t\tint field_size, j;\n+\t\tbool flag_src_port, flag_dst_port;\n+\t\tstruct cpfl_flow_js_pr_key_proto_field *field;\n+\n+\t\tfield_size = proto->fields_size;\n+\t\tif (field_size != 0 && !udp_mask)\n+\t\t\treturn -EINVAL;\n+\n+\t\tif (field_size == 0 && udp_mask)\n+\t\t\treturn -EINVAL;\n+\n+\t\tif (field_size == 0 && !udp_mask)\n+\t\t\treturn 0;\n+\n+\t\tflag_src_port = false;\n+\t\tflag_dst_port = false;\n+\t\tfor (j = 0; j < field_size; j++) {\n+\t\t\tconst char *name;\n+\t\t\tuint16_t mask;\n+\n+\t\t\tfield = &proto->fields[j];\n+\t\t\t/* match: rte_flow_item_eth.dst */\n+\t\t\tname = field->name; /* match: rte_flow_item->mask */\n+\t\t\tmask = (uint16_t)field->mask_32b;\n+\t\t\tif (strcmp(name, \"src_port\") == 0) {\n+\t\t\t\tif (udp_mask->hdr.src_port != mask)\n+\t\t\t\t\treturn -EINVAL;\n+\t\t\t\tflag_src_port = true;\n+\t\t\t} else if (strcmp(name, \"dst_port\") == 0) {\n+\t\t\t\tif (udp_mask->hdr.dst_port != mask)\n+\t\t\t\t\treturn -EINVAL;\n+\t\t\t\tflag_dst_port = true;\n+\t\t\t} else {\n+\t\t\t\tPMD_DRV_LOG(ERR, \"not support this name.\");\n+\t\t\t\treturn -EINVAL;\n+\t\t\t}\n+\t\t}\n+\t\tif (!flag_src_port) {\n+\t\t\tif (udp_mask->hdr.src_port != (rte_be16_t)0)\n+\t\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tif (!flag_dst_port) {\n+\t\t\tif (udp_mask->hdr.dst_port != (rte_be16_t)0)\n+\t\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\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+\tif (proto) {\n+\t\tint field_size, j;\n+\t\tstruct cpfl_flow_js_pr_key_proto_field *field;\n+\n+\t\tfield_size = proto->fields_size;\n+\t\tif (field_size != 0 && !vxlan_mask)\n+\t\t\treturn -EINVAL;\n+\n+\t\tif (field_size == 0 && vxlan_mask)\n+\t\t\treturn -EINVAL;\n+\n+\t\tif (field_size == 0 && !vxlan_mask)\n+\t\t\treturn 0;\n+\n+\t\tfor (j = 0; j < field_size; j++) {\n+\t\t\tconst char *name;\n+\t\t\tint64_t mask;\n+\n+\t\t\tfield = &proto->fields[j];\n+\t\t\tname = field->name;\n+\t\t\t/* match: rte_flow_item->mask */\n+\t\t\tmask = (int64_t)field->mask_32b;\n+\t\t\tif (strcmp(name, \"vx_vni\") == 0) {\n+\t\t\t\tif ((int64_t)RTE_BE32(vxlan_mask->hdr.vx_vni) != mask)\n+\t\t\t\t\treturn -EINVAL;\n+\t\t\t} else {\n+\t\t\t\tPMD_DRV_LOG(ERR, \"not support this name.\");\n+\t\t\t\treturn -EINVAL;\n+\t\t\t}\n+\t\t}\n+\t}\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+\tif (proto) {\n+\t\tint field_size;\n+\n+\t\tfield_size = proto->fields_size;\n+\t\tif (field_size != 0 && !icmp_mask)\n+\t\t\treturn -EINVAL;\n+\n+\t\tif (field_size == 0 && icmp_mask)\n+\t\t\treturn -EINVAL;\n+\n+\t\tif (field_size == 0 && !icmp_mask)\n+\t\t\treturn 0;\n+\t}\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, j = 0;\n+\n+\tlength = cpfl_get_items_length(items);\n+\n+\tif (proto_size > length - 1)\n+\t\treturn -EINVAL;\n+\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+\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+\t/* match: struct rte_flow_attr(ingress,egress) */\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+\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+\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+\treturn 0;\n+}\n+\n+/* output: struct cpfl_flow_pr_action* pr_action */\n+static int\n+cpfl_parse_pattern_rules(struct cpfl_flow_js_parser *parser, 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+{\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(pattern->actions, pattern->actions_size, items, attr,\n+\t\t\t\t\t    pr_action);\n+\t\treturn ret;\n+\t}\n+\treturn -EINVAL;\n+}\n+\n+int\n+cpfl_flow_parse_items(struct cpfl_flow_js_parser *parser, 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 ret;\n+\n+\t/* Pattern Rules */\n+\tret = cpfl_parse_pattern_rules(parser, items, attr, pr_action);\n+\treturn ret;\n+}\n+\n+/* modifications rules */\n+static int\n+cpfl_check_actions_vxlan_encap(struct cpfl_flow_mr_key_action_vxlan_encap *encap,\n+\t\t\t       const struct rte_flow_action *action)\n+{\n+\tconst struct rte_flow_action_vxlan_encap *action_vxlan_encap;\n+\tstruct rte_flow_item *definition;\n+\tint def_length, i, proto_size;\n+\n+\taction_vxlan_encap = (const struct rte_flow_action_vxlan_encap *)action->conf;\n+\tdefinition = action_vxlan_encap->definition;\n+\tdef_length = cpfl_get_items_length(definition);\n+\tproto_size = encap->proto_size;\n+\tif (proto_size != def_length - 1) {\n+\t\tPMD_DRV_LOG(DEBUG, \"protocols not match.\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tfor (i = 0; i < proto_size; i++) {\n+\t\tenum rte_flow_item_type proto;\n+\n+\t\tproto = encap->protocols[i];\n+\t\tif (proto == RTE_FLOW_ITEM_TYPE_VLAN) {\n+\t\t\tif (definition[i].type != RTE_FLOW_ITEM_TYPE_VOID) {\n+\t\t\t\tPMD_DRV_LOG(DEBUG, \"protocols not match.\");\n+\t\t\t\treturn -EINVAL;\n+\t\t\t}\n+\t\t} else if (proto != definition[i].type) {\n+\t\t\tPMD_DRV_LOG(DEBUG, \"protocols not match.\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+/* output: struct cpfl_flow_mr_key_action *mr_key_action */\n+/* check and parse */\n+static int\n+cpfl_parse_mr_key_action(struct cpfl_flow_js_mr_key_action *key_acts, int size,\n+\t\t\t const struct rte_flow_action *actions,\n+\t\t\t struct cpfl_flow_mr_key_action *mr_key_action)\n+{\n+\tint actions_length, i;\n+\tint j = 0;\n+\tint ret;\n+\n+\tactions_length = cpfl_get_actions_length(actions);\n+\tif (size > actions_length - 1)\n+\t\treturn -EINVAL;\n+\n+\tfor (i = 0; i < size; i++) {\n+\t\tenum rte_flow_action_type type;\n+\t\tstruct cpfl_flow_js_mr_key_action *key_act;\n+\n+\t\tkey_act = &key_acts[i];\n+\t\t/* mr->key->actions->type */\n+\t\ttype = key_act->type;\n+\t\t/* mr->key->actions->data */\n+\t\t/* match: <type> action matches RTE_FLOW_ACTION_TYPE_<type> */\n+\n+\t\tif (type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP) {\n+\t\t\tint proto_size, k;\n+\t\t\tstruct cpfl_flow_mr_key_action_vxlan_encap *encap;\n+\n+\t\t\twhile (j < actions_length &&\n+\t\t\t       actions[j].type != RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP) {\n+\t\t\t\tj++;\n+\t\t\t}\n+\t\t\tif (j >= actions_length)\n+\t\t\t\treturn -EINVAL;\n+\n+\t\t\tmr_key_action[i].type = RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP;\n+\t\t\tmr_key_action[i].encap.action = &actions[j];\n+\t\t\tencap = &mr_key_action[i].encap;\n+\n+\t\t\tproto_size = key_act->encap.proto_size;\n+\t\t\tencap->proto_size = proto_size;\n+\t\t\tfor (k = 0; k < proto_size; k++) {\n+\t\t\t\tenum rte_flow_item_type proto;\n+\n+\t\t\t\tproto = key_act->encap.protocols[k];\n+\t\t\t\tencap->protocols[k] = proto;\n+\t\t\t}\n+\n+\t\t\tret = cpfl_check_actions_vxlan_encap(encap, &actions[j]);\n+\t\t\tif (ret < 0)\n+\t\t\t\treturn -EINVAL;\n+\n+\t\t\tj++;\n+\t\t} else {\n+\t\t\tPMD_DRV_LOG(ERR, \"Not support this type: %d.\", type);\n+\t\t\treturn -EPERM;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/* output: uint8_t *buffer, uint16_t *byte_len */\n+static int\n+cpfl_parse_layout(struct cpfl_flow_js_mr_layout *layouts, int layout_size,\n+\t\t  struct cpfl_flow_mr_key_action *mr_key_action,\n+\t\t  uint8_t *buffer, uint16_t *byte_len)\n+{\n+\tint i, start = 0;\n+\n+\tfor (i = 0; i < layout_size; i++) {\n+\t\tint index, size, offset;\n+\t\tconst char *hint;\n+\t\tconst uint8_t *addr;\n+\t\tstruct cpfl_flow_mr_key_action *temp;\n+\t\tstruct cpfl_flow_js_mr_layout *layout;\n+\n+\t\tlayout = &layouts[i];\n+\t\t/* index links to the element of the actions array. */\n+\t\tindex = layout->index;\n+\t\tsize = layout->size;\n+\t\toffset = layout->offset;\n+\t\tif (index == -1) {\n+\t\t\thint = \"dummpy\";\n+\t\t\tstart += size;\n+\t\t\tcontinue;\n+\t\t}\n+\t\thint = layout->hint;\n+\t\taddr = NULL;\n+\t\ttemp = mr_key_action + index;\n+\n+\t\tif (temp->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP) {\n+\t\t\tconst struct rte_flow_action_vxlan_encap *action_vxlan_encap;\n+\t\t\tstruct rte_flow_item *definition;\n+\t\t\tint def_length, k;\n+\n+\t\t\taction_vxlan_encap =\n+\t\t\t    (const struct rte_flow_action_vxlan_encap *)temp->encap.action->conf;\n+\t\t\tdefinition = action_vxlan_encap->definition;\n+\t\t\tdef_length = cpfl_get_items_length(definition);\n+\t\t\tfor (k = 0; k < def_length - 1; k++) {\n+\t\t\t\tif ((strcmp(hint, \"eth\") == 0 &&\n+\t\t\t\t     definition[k].type == RTE_FLOW_ITEM_TYPE_ETH) ||\n+\t\t\t\t    (strcmp(hint, \"ipv4\") == 0 &&\n+\t\t\t\t     definition[k].type == RTE_FLOW_ITEM_TYPE_IPV4) ||\n+\t\t\t\t    (strcmp(hint, \"udp\") == 0 &&\n+\t\t\t\t     definition[k].type == RTE_FLOW_ITEM_TYPE_UDP) ||\n+\t\t\t\t    (strcmp(hint, \"tcp\") == 0 &&\n+\t\t\t\t     definition[k].type == RTE_FLOW_ITEM_TYPE_TCP) ||\n+\t\t\t\t    (strcmp(hint, \"vxlan\") == 0 &&\n+\t\t\t\t     definition[k].type == RTE_FLOW_ITEM_TYPE_VXLAN)) {\n+\t\t\t\t\taddr = (const uint8_t *)(definition[k].spec);\n+\t\t\t\t\tif (start > 255) {\n+\t\t\t\t\t\t*byte_len = 0;\n+\t\t\t\t\t\tPMD_DRV_LOG(ERR, \"byte length is too long%s\",\n+\t\t\t\t\t\t\t    hint);\n+\t\t\t\t\t\treturn -EINVAL;\n+\t\t\t\t\t}\n+\t\t\t\t\tmemcpy(buffer + start, addr + offset, size);\n+\t\t\t\t\tbreak;\n+\t\t\t\t} /* TODO: more hint... */\n+\t\t\t}\n+\t\t\tif (k == def_length - 1) {\n+\t\t\t\t*byte_len = 0;\n+\t\t\t\tPMD_DRV_LOG(ERR, \"can not find corresponding hint: %s\", hint);\n+\t\t\t\treturn -EINVAL;\n+\t\t\t}\n+\t\t} else {\n+\t\t\t*byte_len = 0;\n+\t\t\tPMD_DRV_LOG(ERR, \"Not support this type: %d.\", temp->type);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\t/* else TODO: more type... */\n+\n+\t\tstart += size;\n+\t}\n+\t*byte_len = start;\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_parse_mr_action(struct cpfl_flow_js_mr_action *action,\n+\t\t     struct cpfl_flow_mr_key_action *mr_key_action,\n+\t\t     struct cpfl_flow_mr_action *mr_action)\n+{\n+\tenum cpfl_flow_mr_action_type type;\n+\n+\t/* mr->action->type */\n+\ttype = action->type;\n+\t/* mr->action->data */\n+\tif (type == CPFL_JS_MR_ACTION_TYPE_MOD) {\n+\t\tstruct cpfl_flow_js_mr_layout *layout;\n+\n+\t\tmr_action->type = CPFL_JS_MR_ACTION_TYPE_MOD;\n+\t\tmr_action->mod.byte_len = 0;\n+\t\tmr_action->mod.prof = action->mod.prof;\n+\t\tlayout = action->mod.layout;\n+\t\tif (layout) {\n+\t\t\tint ret;\n+\n+\t\t\tmemset(mr_action->mod.data, 0, sizeof(mr_action->mod.data));\n+\t\t\tret = cpfl_parse_layout(layout, action->mod.layout_size, mr_key_action,\n+\t\t\t\t\t\tmr_action->mod.data, &mr_action->mod.byte_len);\n+\t\t\tif (ret < 0)\n+\t\t\t\treturn -EINVAL;\n+\t\t}\n+\t\treturn 0;\n+\t}\n+\n+\tPMD_DRV_LOG(ERR, \"Not support this type: %d.\", type);\n+\treturn -EINVAL;\n+}\n+\n+static int\n+cpfl_check_mod_key(struct cpfl_flow_js_mr *mr, const struct rte_flow_action *actions,\n+\t\t   struct cpfl_flow_mr_key_action *mr_key_action)\n+{\n+\tint key_action_size;\n+\n+\t/* mr->key->actions */\n+\tkey_action_size = mr->key.actions_size;\n+\treturn cpfl_parse_mr_key_action(mr->key.actions, key_action_size, actions, mr_key_action);\n+}\n+\n+/* output: struct cpfl_flow_mr_action *mr_action */\n+static int\n+cpfl_parse_mod_rules(struct cpfl_flow_js_parser *parser, const struct rte_flow_action *actions,\n+\t\t     struct cpfl_flow_mr_action *mr_action)\n+{\n+#define CPFL_MOD_KEY_NUM_MAX 8\n+\tint i, size;\n+\tstruct cpfl_flow_mr_key_action mr_key_action[CPFL_MOD_KEY_NUM_MAX] = {0};\n+\n+\tsize = parser->mr_size;\n+\n+\tfor (i = 0; i < size; i++) {\n+\t\tint ret;\n+\t\tstruct cpfl_flow_js_mr *mr;\n+\n+\t\tmr = &parser->modifications[i];\n+\t\tret = cpfl_check_mod_key(mr, actions, mr_key_action);\n+\t\tif (ret < 0)\n+\t\t\tcontinue;\n+\t\t/* mr->action */\n+\t\tret = cpfl_parse_mr_action(&mr->action, mr_key_action, mr_action);\n+\t\tif (!ret)\n+\t\t\treturn 0;\n+\t}\n+\treturn -EINVAL;\n+}\n+\n+int\n+cpfl_flow_parse_actions(struct cpfl_flow_js_parser *parser, const struct rte_flow_action *actions,\n+\t\t\tstruct cpfl_flow_mr_action *mr_action)\n+{\n+\t/* modifications rules */\n+\tif (!parser->modifications) {\n+\t\tPMD_DRV_LOG(INFO, \"The modifications is optional.\");\n+\t\treturn 0;\n+\t}\n+\n+\treturn cpfl_parse_mod_rules(parser, actions, mr_action);\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..af33051ce2\n--- /dev/null\n+++ b/drivers/net/cpfl/cpfl_flow_parser.h\n@@ -0,0 +1,205 @@\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+\n+#ifndef _CPFL_FLOW_PARSER_H_\n+#define _CPFL_FLOW_PARSER_H_\n+\n+#define CPFL_FLOW_JSON_STR_SIZE_MAX 100\n+\n+/* Pattern Rules Storage Begin*/\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+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+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_UNKNOWN = -1,\n+\n+};\n+\n+struct cpfl_flow_js_fv {\n+\tuint16_t offset;\n+\tenum cpfl_flow_js_fv_type type;\n+\tunion {\n+\t\tuint16_t immediate;\n+\t\tstruct {\n+\t\t\tuint16_t layer;\n+\t\t\tenum rte_flow_item_type header;\n+\t\t\tuint16_t offset;\n+\t\t\tuint16_t mask;\n+\t\t} proto;\n+\t};\n+};\n+\n+#define CPFL_MAX_SEM_FV_KEY_SIZE 64\n+struct cpfl_flow_js_pr_action_sem {\n+\tuint16_t prof;\n+\tuint16_t subprof;\n+\tuint16_t keysize;\n+\tstruct cpfl_flow_js_fv *fv;\n+\tint fv_size;\n+};\n+\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+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+\tstruct cpfl_flow_js_pr_action *actions;\n+\tuint16_t actions_size;\n+};\n+\n+/* Pattern Rules Storage End */\n+\n+/* Modification Rules Storage Begin */\n+#define CPFL_FLOW_JS_PROTO_SIZE 16\n+struct cpfl_flow_js_mr_key_action_vxlan_encap {\n+\tenum rte_flow_item_type protocols[CPFL_FLOW_JS_PROTO_SIZE];\n+\tint proto_size;\n+};\n+\n+struct cpfl_flow_js_mr_key_action {\n+\tenum rte_flow_action_type type;\n+\tunion {\n+\t\tstruct cpfl_flow_js_mr_key_action_vxlan_encap encap;\n+\t};\n+};\n+\n+struct cpfl_flow_js_mr_key {\n+\tstruct cpfl_flow_js_mr_key_action *actions;\n+\tint actions_size;\n+};\n+\n+struct cpfl_flow_js_mr_layout {\n+\tint index;\n+\tchar hint[CPFL_FLOW_JSON_STR_SIZE_MAX];\n+\tuint16_t offset;\n+\tuint16_t size;\n+};\n+\n+struct cpfl_flow_js_mr_action_mod {\n+\tuint16_t prof;\n+\tuint16_t byte_len;\n+\tstruct cpfl_flow_js_mr_layout *layout;\n+\tint layout_size;\n+};\n+\n+enum cpfl_flow_mr_action_type {\n+\tCPFL_JS_MR_ACTION_TYPE_MOD,\n+};\n+\n+struct cpfl_flow_js_mr_action {\n+\tenum cpfl_flow_mr_action_type type;\n+\tunion {\n+\t\tstruct cpfl_flow_js_mr_action_mod mod;\n+\t};\n+};\n+\n+struct cpfl_flow_js_mr {\n+\tstruct cpfl_flow_js_mr_key key;\n+\tstruct cpfl_flow_js_mr_action action;\n+};\n+\n+/* Modification Rules Storage End */\n+\n+struct cpfl_flow_js_parser {\n+\tstruct cpfl_flow_js_pr *patterns;\n+\tint pr_size;\n+\tstruct cpfl_flow_js_mr *modifications;\n+\tint mr_size;\n+};\n+\n+/* Pattern Rules Begin */\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+/* Pattern Rules End */\n+\n+/* Modification Rules Begin */\n+struct cpfl_flow_mr_key_action_vxlan_encap {\n+\tenum rte_flow_item_type protocols[CPFL_FLOW_JS_PROTO_SIZE];\n+\tuint16_t proto_size;\n+\tconst struct rte_flow_action *action;\n+};\n+\n+struct cpfl_flow_mr_key_action {\n+\tenum rte_flow_action_type type;\n+\tunion {\n+\t\tstruct cpfl_flow_mr_key_action_vxlan_encap encap;\n+\t};\n+};\n+\n+struct cpfl_flow_mr_action_mod {\n+\tuint16_t prof;\n+\tuint16_t byte_len;\n+\tuint8_t data[256];\n+};\n+\n+struct cpfl_flow_mr_action {\n+\tenum cpfl_flow_mr_action_type type;\n+\tunion {\n+\t\tstruct cpfl_flow_mr_action_mod mod;\n+\t};\n+};\n+\n+/* Modification Rules End */\n+\n+struct cpfl_pipeline_stage {\n+\tint stage;\n+\tint recircle;\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_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+int cpfl_flow_parse_actions(struct cpfl_flow_js_parser *parser,\n+\t\t\t    const struct rte_flow_action *actions,\n+\t\t\t    struct cpfl_flow_mr_action *mr_action);\n+#endif\ndiff --git a/drivers/net/cpfl/meson.build b/drivers/net/cpfl/meson.build\nindex 0be25512c3..7b8d043011 100644\n--- a/drivers/net/cpfl/meson.build\n+++ b/drivers/net/cpfl/meson.build\n@@ -41,6 +41,9 @@ endif\n \n js_dep = dependency('json-c', required: false, method : 'pkg-config')\n if js_dep.found()\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\\ No newline at end of file\n",
    "prefixes": [
        "2/4"
    ]
}