get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 132088,
    "url": "http://patches.dpdk.org/api/patches/132088/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20230928084458.2333663-3-yuying.zhang@intel.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20230928084458.2333663-3-yuying.zhang@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20230928084458.2333663-3-yuying.zhang@intel.com",
    "date": "2023-09-28T08:44:51",
    "name": "[v9,2/9] net/cpfl: build action mapping rules from JSON",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "0171d4269377dd17d24293349fc29f430fb04aaf",
    "submitter": {
        "id": 1844,
        "url": "http://patches.dpdk.org/api/people/1844/?format=api",
        "name": "Zhang, Yuying",
        "email": "yuying.zhang@intel.com"
    },
    "delegate": {
        "id": 1540,
        "url": "http://patches.dpdk.org/api/users/1540/?format=api",
        "username": "qzhan15",
        "first_name": "Qi",
        "last_name": "Zhang",
        "email": "qi.z.zhang@intel.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20230928084458.2333663-3-yuying.zhang@intel.com/mbox/",
    "series": [
        {
            "id": 29669,
            "url": "http://patches.dpdk.org/api/series/29669/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=29669",
            "date": "2023-09-28T08:44:49",
            "name": "add rte flow support for cpfl",
            "version": 9,
            "mbox": "http://patches.dpdk.org/series/29669/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/132088/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/132088/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 271014265E;\n\tThu, 28 Sep 2023 10:45:21 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 41D15406B8;\n\tThu, 28 Sep 2023 10:45:17 +0200 (CEST)",
            "from mgamail.intel.com (mgamail.intel.com [192.55.52.43])\n by mails.dpdk.org (Postfix) with ESMTP id 58D13402F1\n for <dev@dpdk.org>; Thu, 28 Sep 2023 10:45:12 +0200 (CEST)",
            "from orsmga001.jf.intel.com ([10.7.209.18])\n by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 28 Sep 2023 01:45:11 -0700",
            "from dpdk-wenjing-02.sh.intel.com ([10.67.119.3])\n by orsmga001.jf.intel.com with ESMTP; 28 Sep 2023 01:45:09 -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=1695890712; x=1727426712;\n h=from:to:cc:subject:date:message-id:in-reply-to:\n references:mime-version:content-transfer-encoding;\n bh=IAb5GnvO23hhN7mQExNTLBrYeMXACmtB3iQLca0BLNw=;\n b=RY4HxLhTNSOmN5SG24tmfIZUi3nnrLfuJTiONRCCngaOP9nd02j2zeCJ\n CtYR0sRryfmieC0gWCLwMt4owlK0Jc7Ds2nZS55HwLeqT3cKEEa466Vob\n V8afupHnZv4FV98mkInZV8Do5kmyUl8eiJUEhflYU8EmNZ379R1Y5kxhg\n NYupUnJMQ61yB0w1vmrTuXZ9kd7CRmEQ9+lXVi1gyrkAqv5qJVHGDAjlO\n mBSkrS9qZm7uP5KI46g9W9uGMeeyqaTpPpA94ySaYAeMnwwtg39pPFRPo\n L3MPUQdmHGbgPV38jJRePyWMee2RWRAysONaocLDyJkAQXil+ah/ARKFp g==;",
        "X-IronPort-AV": [
            "E=McAfee;i=\"6600,9927,10846\"; a=\"468299486\"",
            "E=Sophos;i=\"6.03,183,1694761200\"; d=\"scan'208\";a=\"468299486\"",
            "E=McAfee;i=\"6600,9927,10846\"; a=\"784622186\"",
            "E=Sophos;i=\"6.03,183,1694761200\"; d=\"scan'208\";a=\"784622186\""
        ],
        "X-ExtLoop1": "1",
        "From": "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 v9 2/9] net/cpfl: build action mapping rules from JSON",
        "Date": "Thu, 28 Sep 2023 08:44:51 +0000",
        "Message-Id": "<20230928084458.2333663-3-yuying.zhang@intel.com>",
        "X-Mailer": "git-send-email 2.34.1",
        "In-Reply-To": "<20230928084458.2333663-1-yuying.zhang@intel.com>",
        "References": "<20230927125416.2308974-1-yuying.zhang@intel.com>\n <20230928084458.2333663-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\nBuild rules that maps from an rte flow action vxlan_encap or\nvxlan_decap to hardware representations.\n\nSigned-off-by: Wenjing Qiao <wenjing.qiao@intel.com>\n---\n drivers/net/cpfl/cpfl_flow_parser.c | 538 +++++++++++++++++++++++++++-\n drivers/net/cpfl/cpfl_flow_parser.h | 100 ++++++\n 2 files changed, 637 insertions(+), 1 deletion(-)",
    "diff": "diff --git a/drivers/net/cpfl/cpfl_flow_parser.c b/drivers/net/cpfl/cpfl_flow_parser.c\nindex 308f9c9736..81ccbbd8e5 100644\n--- a/drivers/net/cpfl/cpfl_flow_parser.c\n+++ b/drivers/net/cpfl/cpfl_flow_parser.c\n@@ -32,6 +32,18 @@ cpfl_get_item_type_by_str(const char *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+\telse if (strcmp(type, \"vxlan_decap\") == 0)\n+\t\treturn RTE_FLOW_ACTION_TYPE_VXLAN_DECAP;\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_t_to_string(json_t *object, const char *name)\n {\n@@ -50,6 +62,29 @@ cpfl_json_t_to_string(json_t *object, const char *name)\n \treturn json_string_value(subobject);\n }\n \n+static int\n+cpfl_json_t_to_int(json_t *object, const char *name, int *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 = (int)json_integer_value(subobject);\n+\n+\treturn 0;\n+}\n+\n static int\n cpfl_json_t_to_uint16(json_t *object, const char *name, uint16_t *value)\n {\n@@ -522,6 +557,228 @@ cpfl_flow_js_pattern_rule(json_t *ob_root, struct cpfl_flow_js_parser *parser)\n \treturn -EINVAL;\n }\n \n+static int\n+cpfl_flow_js_mr_key(json_t *ob_mr_keys, struct cpfl_flow_js_mr_key *js_mr_key)\n+{\n+\tint len, i;\n+\n+\tlen = json_array_size(ob_mr_keys);\n+\tif (len == 0)\n+\t\treturn 0;\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_t *object, *ob_data;\n+\t\tconst char *type;\n+\t\tenum rte_flow_action_type act_type;\n+\n+\t\tobject = json_array_get(ob_mr_keys, i);\n+\t\t/* mr->key->actions->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\tact_type = cpfl_get_action_type_by_str(type);\n+\t\tif (act_type == RTE_FLOW_ACTION_TYPE_VOID)\n+\t\t\tgoto err;\n+\t\tjs_mr_key->actions[i].type = act_type;\n+\t\t/* mr->key->actions->data */\n+\t\tob_data = json_object_get(object, \"data\");\n+\t\tif (js_mr_key->actions[i].type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP) {\n+\t\t\tjson_t *ob_protos;\n+\t\t\tint proto_size, j;\n+\t\t\tstruct cpfl_flow_js_mr_key_action_vxlan_encap *encap;\n+\n+\t\t\tob_protos = json_object_get(ob_data, \"protocols\");\n+\t\t\tencap = &js_mr_key->actions[i].encap;\n+\t\t\tif (!ob_protos) {\n+\t\t\t\tencap->proto_size = 0;\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tproto_size = json_array_size(ob_protos);\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_t *subobject;\n+\t\t\t\tenum rte_flow_item_type proto_type;\n+\n+\t\t\t\tsubobject = json_array_get(ob_protos, j);\n+\t\t\t\ts = json_string_value(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\tPMD_DRV_LOG(ERR, \"parse VXLAN_ENCAP failed.\");\n+\t\t\t\t\tgoto err;\n+\t\t\t\t}\n+\t\t\t\tencap->protocols[j] = proto_type;\n+\t\t\t}\n+\t\t} else if (js_mr_key->actions[i].type != RTE_FLOW_ACTION_TYPE_VXLAN_DECAP) {\n+\t\t\tPMD_DRV_LOG(ERR, \"not support this type: %d.\", js_mr_key->actions[i].type);\n+\t\t\tgoto err;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+\n+err:\n+\trte_free(js_mr_key->actions);\n+\treturn -EINVAL;\n+}\n+\n+static int\n+cpfl_flow_js_mr_layout(json_t *ob_layouts, struct cpfl_flow_js_mr_action_mod *js_mod)\n+{\n+\tint len, i;\n+\n+\tlen = json_array_size(ob_layouts);\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_t *object;\n+\t\tint index = 0, size = 0, offset = 0;\n+\t\tint ret;\n+\t\tconst char *hint;\n+\n+\t\tobject = json_array_get(ob_layouts, i);\n+\t\tret = cpfl_json_t_to_int(object, \"index\", &index);\n+\t\tif (ret < 0) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse 'index'.\");\n+\t\t\tgoto err;\n+\t\t}\n+\t\tjs_mod->layout[i].index = index;\n+\t\tret = cpfl_json_t_to_int(object, \"size\", &size);\n+\t\tif (ret < 0) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse 'size'.\");\n+\t\t\tgoto err;\n+\t\t}\n+\t\tjs_mod->layout[i].size = size;\n+\t\tret = cpfl_json_t_to_int(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_mod->layout[i].offset = offset;\n+\t\thint = cpfl_json_t_to_string(object, \"hint\");\n+\t\tif (!hint) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Can not parse string 'hint'.\");\n+\t\t\tgoto err;\n+\t\t}\n+\t\tmemcpy(js_mod->layout[i].hint, hint, strlen(hint));\n+\t}\n+\n+\treturn 0;\n+\n+err:\n+\trte_free(js_mod->layout);\n+\treturn -EINVAL;\n+}\n+\n+static int\n+cpfl_flow_js_mr_action(json_t *ob_mr_act, struct cpfl_flow_js_mr_action *js_mr_act)\n+{\n+\tjson_t *ob_data;\n+\tconst char *type;\n+\n+\t/* mr->action->type */\n+\ttype = cpfl_json_t_to_string(ob_mr_act, \"type\");\n+\tif (!type) {\n+\t\tPMD_DRV_LOG(ERR, \"Can not parse string 'type'.\");\n+\t\treturn -EINVAL;\n+\t}\n+\t/* mr->action->data */\n+\tob_data = json_object_get(ob_mr_act, \"data\");\n+\tif (strcmp(type, \"mod\") == 0) {\n+\t\tjson_t *ob_layouts;\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_t_to_uint16(ob_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\tob_layouts = json_object_get(ob_data, \"layout\");\n+\t\tret = cpfl_flow_js_mr_layout(ob_layouts, &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+/**\n+ * The modifications object array defines a set of rules for the PMD to match rte_flow\n+ * modification actions and translate them into the Modification profile. This object\n+ * is optional.\n+ */\n+static int\n+cpfl_flow_js_mod_rule(json_t *ob_root, struct cpfl_flow_js_parser *parser)\n+{\n+\tjson_t *ob_mrs;\n+\tint i, len;\n+\n+\tob_mrs = json_object_get(ob_root, \"modifications\");\n+\tif (!ob_mrs) {\n+\t\tPMD_DRV_LOG(INFO, \"The modifications is optional.\");\n+\t\treturn 0;\n+\t}\n+\tlen = json_array_size(ob_mrs);\n+\tif (len == 0)\n+\t\treturn 0;\n+\tparser->mr_size = len;\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+\tfor (i = 0; i < len; i++) {\n+\t\tint ret;\n+\t\tjson_t *object, *ob_mr_key, *ob_mr_action, *ob_mr_key_action;\n+\n+\t\tobject = json_array_get(ob_mrs, i);\n+\t\t/* mr->key */\n+\t\tob_mr_key = json_object_get(object, \"key\");\n+\t\t/* mr->key->actions */\n+\t\tob_mr_key_action = json_object_get(ob_mr_key, \"actions\");\n+\t\tret = cpfl_flow_js_mr_key(ob_mr_key_action, &parser->modifications[i].key);\n+\t\tif (ret < 0) {\n+\t\t\tPMD_DRV_LOG(ERR, \"parse mr_key failed.\");\n+\t\t\tgoto err;\n+\t\t}\n+\t\t/* mr->action */\n+\t\tob_mr_action = json_object_get(object, \"action\");\n+\t\tret = cpfl_flow_js_mr_action(ob_mr_action, &parser->modifications[i].action);\n+\t\tif (ret < 0) {\n+\t\t\tPMD_DRV_LOG(ERR, \"parse mr_action failed.\");\n+\t\t\tgoto err;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+\n+err:\n+\trte_free(parser->modifications);\n+\treturn -EINVAL;\n+}\n+\n static int\n cpfl_parser_init(json_t *ob_root, struct cpfl_flow_js_parser *parser)\n {\n@@ -532,6 +789,11 @@ cpfl_parser_init(json_t *ob_root, struct cpfl_flow_js_parser *parser)\n \t\tPMD_DRV_LOG(ERR, \"parse pattern_rule failed.\");\n \t\treturn ret;\n \t}\n+\tret = cpfl_flow_js_mod_rule(ob_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 0;\n }\n@@ -602,6 +864,15 @@ cpfl_parser_destroy(struct cpfl_flow_js_parser *parser)\n \t\trte_free(pattern->actions);\n \t}\n \trte_free(parser->patterns);\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)\n+\t\t\tcontinue;\n+\t\trte_free(mr->key.actions);\n+\t\trte_free(mr->action.mod.layout);\n+\t}\n+\trte_free(parser->modifications);\n \trte_free(parser);\n \n \treturn 0;\n@@ -618,6 +889,17 @@ cpfl_get_items_length(const struct rte_flow_item *items)\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@@ -646,7 +928,7 @@ cpfl_parse_fv_protocol(struct cpfl_flow_js_fv *js_fv, const struct rte_flow_item\n \t\t\t\tbreak;\n \t\t\t}\n \t\t\tlayer++;\n-\t\t} /* TODO: more type... */\n+\t\t}\n \t}\n \n \treturn 0;\n@@ -1235,6 +1517,260 @@ cpfl_flow_parse_items(struct cpfl_itf *itf,\n \treturn -EINVAL;\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+\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+\n+\treturn 0;\n+}\n+\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+\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\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+\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+\t\t\tret = cpfl_check_actions_vxlan_encap(encap, &actions[j]);\n+\t\t\tif (ret < 0)\n+\t\t\t\treturn -EINVAL;\n+\t\t\tj++;\n+\t\t} else if (type == RTE_FLOW_ACTION_TYPE_VXLAN_DECAP) {\n+\t\t\twhile (j < actions_length &&\n+\t\t\t       actions[j].type != RTE_FLOW_ACTION_TYPE_VXLAN_DECAP) {\n+\t\t\t\tj++;\n+\t\t\t}\n+\t\t\tif (j >= actions_length)\n+\t\t\t\treturn -EINVAL;\n+\t\t\tmr_key_action[i].type = RTE_FLOW_ACTION_TYPE_VXLAN_DECAP;\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;\n+\tint 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 = NULL;\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\ttemp = mr_key_action + index;\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} /* else TODO: more type... */\n+\t\tstart += size;\n+\t}\n+\t*byte_len = start;\n+\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\treturn 0;\n+\t\tmemset(mr_action->mod.data, 0, sizeof(mr_action->mod.data));\n+\n+\t\treturn cpfl_parse_layout(layout, action->mod.layout_size, mr_key_action,\n+\t\t\t\t\t mr_action->mod.data, &mr_action->mod.byte_len);\n+\t}\n+\tPMD_DRV_LOG(ERR, \"Not support this type: %d.\", type);\n+\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+\tint i;\n+\tstruct cpfl_flow_mr_key_action mr_key_action[CPFL_MOD_KEY_NUM_MAX] = {0};\n+\n+\tfor (i = 0; i < parser->mr_size; i++) {\n+\t\tint ret;\n+\t\tstruct cpfl_flow_js_mr *mr;\n+\n+\t\tmr = &parser->modifications[i];\n+\t\tif (!mr)\n+\t\t\treturn -EINVAL;\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\treturn cpfl_parse_mr_action(&mr->action, mr_key_action, mr_action);\n+\t}\n+\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+}\n+\n bool\n cpfl_metadata_write_port_id(struct cpfl_itf *itf)\n {\ndiff --git a/drivers/net/cpfl/cpfl_flow_parser.h b/drivers/net/cpfl/cpfl_flow_parser.h\nindex 367a6da574..b7bf21bd76 100644\n--- a/drivers/net/cpfl/cpfl_flow_parser.h\n+++ b/drivers/net/cpfl/cpfl_flow_parser.h\n@@ -105,9 +105,79 @@ struct cpfl_flow_js_pr {\n \tuint16_t actions_size;\n };\n \n+/* Modification Rules Storage */\n+/**\n+ * The vxlan_encap action matches RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP\n+ * and include a sequence of protocol headers defined in field protocols\n+ * of data.\n+ */\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+/* A set of modification rte_flow_action_xxx objects can be defined as a type / data pair. */\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;\t\t\t\t/* links to the element of the actions array */\n+\tchar hint[CPFL_FLOW_JSON_STR_SIZE_MAX]; /* where the data to copy from */\n+\tuint16_t offset;\t\t\t/* the start byte of the data to copy from */\n+\tuint16_t size; /*  bytes of the data to be copied to the memory region */\n+};\n+\n+/** For mod data, besides the profile ID, a layout array defines a set of hints that helps\n+ * driver composing the MOD memory region when the action need to insert/update some packet\n+ * data from user input.\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+/** Currently, the type can only be mod.\n+ *\n+ * For mod data, besides the profile ID, a layout array defines a set\n+ * of hints that helps driver composing the MOD memory region when the\n+ * action need to insert/update some packet data from user input.\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+/**\n+ * This structure defines a set of rules that direct PMD to parse rte_flow modification\n+ * actions. Each rule be described by a pair of key and action\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 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 */\n@@ -125,6 +195,33 @@ struct cpfl_flow_pr_action {\n \t};\n };\n \n+/* Modification Rules */\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 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@@ -132,6 +229,9 @@ int cpfl_flow_parse_items(struct cpfl_itf *itf,\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 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",
    "prefixes": [
        "v9",
        "2/9"
    ]
}