get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 17034,
    "url": "https://patches.dpdk.org/api/patches/17034/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/ce5a7a7855e4add72bdb094ae28d2c53a6e0297e.1479309720.git.adrien.mazarguil@6wind.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<ce5a7a7855e4add72bdb094ae28d2c53a6e0297e.1479309720.git.adrien.mazarguil@6wind.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/ce5a7a7855e4add72bdb094ae28d2c53a6e0297e.1479309720.git.adrien.mazarguil@6wind.com",
    "date": "2016-11-16T16:23:36",
    "name": "[dpdk-dev,10/22] app/testpmd: add flow validate/create commands",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "b583caff7236595757dfb38901b15063791ee02e",
    "submitter": {
        "id": 165,
        "url": "https://patches.dpdk.org/api/people/165/?format=api",
        "name": "Adrien Mazarguil",
        "email": "adrien.mazarguil@6wind.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/ce5a7a7855e4add72bdb094ae28d2c53a6e0297e.1479309720.git.adrien.mazarguil@6wind.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/17034/comments/",
    "check": "success",
    "checks": "https://patches.dpdk.org/api/patches/17034/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id 1084ED49A;\n\tWed, 16 Nov 2016 17:25:24 +0100 (CET)",
            "from mail-wm0-f45.google.com (mail-wm0-f45.google.com\n\t[74.125.82.45]) by dpdk.org (Postfix) with ESMTP id B33D95681\n\tfor <dev@dpdk.org>; Wed, 16 Nov 2016 17:24:29 +0100 (CET)",
            "by mail-wm0-f45.google.com with SMTP id a197so249922477wmd.0\n\tfor <dev@dpdk.org>; Wed, 16 Nov 2016 08:24:29 -0800 (PST)",
            "from 6wind.com (guy78-3-82-239-227-177.fbx.proxad.net.\n\t[82.239.227.177]) by smtp.gmail.com with ESMTPSA id\n\te5sm10945074wma.12.2016.11.16.08.24.27\n\t(version=TLS1_2 cipher=AES128-SHA bits=128/128);\n\tWed, 16 Nov 2016 08:24:28 -0800 (PST)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=6wind-com.20150623.gappssmtp.com; s=20150623;\n\th=from:to:cc:subject:date:message-id:in-reply-to:references;\n\tbh=BdeR6yzyp8lgjkF1TLlcQ7ywn3llu4p6NnbR5eKh2Xw=;\n\tb=dJ3pXayarQiVC3f3cKkej51WnbMMLdz6pblgho/L9DHDdiB6xyki/HFz92G9beHUOw\n\taUxxEOLBW/Szl9sHqMHz4KHv+jzzw4Txb+Hi4Q2V2y8DPu+AM5cmvKb07PcP0ROrWc/Y\n\tGXHVfJYjIHRdeGKcqX3y/cajkIZnMIvRtmGZTJqHWdm9yH7rXnmbBSWMpZFVA3E1xdnF\n\tSn+YxV5mcAUMJdyf3gj+zYy8FWnmEiAACozvBCwn5gB+2wbDfRH17oFHFJ9EQcfTAWUX\n\toxdy9F6t6FuWBJldPjHCnj2bOUj4thgkPAUMH07+l9XUx2b9KTbl6w2uxw2ggus5QazD\n\tkGIA==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20130820;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references;\n\tbh=BdeR6yzyp8lgjkF1TLlcQ7ywn3llu4p6NnbR5eKh2Xw=;\n\tb=HbqVWptfw4GBVa2/MuAgwV0lOSDaD9c44qZfZoOWXB2Sw78LGJ+C7kgWwgsgCV2I1z\n\ta8vBGcASpAuzVpSAJOQmn6b2jMmDfjWnrKmRMI3TNFJWr5FHA5ORVjxmz6BYVpsveTc3\n\tHdqz0WiMYdsXWPKfrrgdrsXO8y9E80Ep8U4mBqCrWwVJzfYSJg2/8rb5bUyCrtiE5tOK\n\tyhv84mfmv+apI1jm3FWHS56OitktdKc2OCzFPFL/qPqKBiomUEPYTNzJQhv8cDJPYW6c\n\t4CffEE3+h3Lbzee0TKPPcr6S/i+YXwW4XWQtrhEbcQ9hyDC9yIxWkkja0+/r2pVf5xgS\n\twq3Q==",
        "X-Gm-Message-State": "ABUngvf20B521nrFuPojeGPf59GncYgrg8/wVQD0FcGl7vJT7lJNm0diKfgIzzoUI9Xw5Dqs",
        "X-Received": "by 10.28.173.131 with SMTP id w125mr6727003wme.0.1479313469114; \n\tWed, 16 Nov 2016 08:24:29 -0800 (PST)",
        "From": "Adrien Mazarguil <adrien.mazarguil@6wind.com>",
        "To": "dev@dpdk.org",
        "Cc": "Thomas Monjalon <thomas.monjalon@6wind.com>,\n\tPablo de Lara <pablo.de.lara.guarch@intel.com>,\n\tOlivier Matz <olivier.matz@6wind.com>",
        "Date": "Wed, 16 Nov 2016 17:23:36 +0100",
        "Message-Id": "<ce5a7a7855e4add72bdb094ae28d2c53a6e0297e.1479309720.git.adrien.mazarguil@6wind.com>",
        "X-Mailer": "git-send-email 2.1.4",
        "In-Reply-To": "<cover.1479309719.git.adrien.mazarguil@6wind.com>",
        "References": "<cover.1471632644.git.adrien.mazarguil@6wind.com>\n\t<cover.1479309719.git.adrien.mazarguil@6wind.com>",
        "Subject": "[dpdk-dev] [PATCH 10/22] app/testpmd: add flow validate/create\n\tcommands",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Syntax:\n\n flow (validate|create) {port_id}\n    [group {group_id}] [priority {level}] [ingress] [egress]\n    pattern {item} [/ {item} [...]] / end\n    actions {action} [/ {action} [...]] / end\n\nEither check the validity of a flow rule or create it. Any number of\npattern items and actions can be provided in any order. Completion is\navailable for convenience.\n\nThis commit only adds support for the most basic item and action types,\nnamely:\n\n- END: terminates pattern items and actions lists.\n- VOID: item/action filler, no operation.\n- INVERT: inverted pattern matching, process packets that do not match.\n- PASSTHRU: action that leaves packets up for additional processing by\n  subsequent flow rules.\n\nSigned-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>\n---\n app/test-pmd/cmdline.c      |  14 ++\n app/test-pmd/cmdline_flow.c | 314 ++++++++++++++++++++++++++++++++++++++-\n 2 files changed, 327 insertions(+), 1 deletion(-)",
    "diff": "diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c\nindex 20a64b6..851cc16 100644\n--- a/app/test-pmd/cmdline.c\n+++ b/app/test-pmd/cmdline.c\n@@ -811,6 +811,20 @@ static void cmd_help_long_parsed(void *parsed_result,\n \t\t\t\" (select|add)\\n\"\n \t\t\t\"    Set the input set for FDir.\\n\\n\"\n \n+\t\t\t\"flow validate {port_id}\"\n+\t\t\t\" [group {group_id}] [priority {level}]\"\n+\t\t\t\" [ingress] [egress]\"\n+\t\t\t\" pattern {item} [/ {item} [...]] / end\"\n+\t\t\t\" actions {action} [/ {action} [...]] / end\\n\"\n+\t\t\t\"    Check whether a flow rule can be created.\\n\\n\"\n+\n+\t\t\t\"flow create {port_id}\"\n+\t\t\t\" [group {group_id}] [priority {level}]\"\n+\t\t\t\" [ingress] [egress]\"\n+\t\t\t\" pattern {item} [{item} [...]] end\"\n+\t\t\t\" actions {action} [{action} [...]] end\\n\"\n+\t\t\t\"    Create a flow rule.\\n\\n\"\n+\n \t\t\t\"flow destroy {port_id} rule {rule_id} [...]\\n\"\n \t\t\t\"    Destroy specific flow rules.\\n\\n\"\n \ndiff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c\nindex 5a8980c..1874849 100644\n--- a/app/test-pmd/cmdline_flow.c\n+++ b/app/test-pmd/cmdline_flow.c\n@@ -59,11 +59,14 @@ enum index {\n \tRULE_ID,\n \tPORT_ID,\n \tGROUP_ID,\n+\tPRIORITY_LEVEL,\n \n \t/* Top-level command. */\n \tFLOW,\n \n \t/* Sub-level commands. */\n+\tVALIDATE,\n+\tCREATE,\n \tDESTROY,\n \tFLUSH,\n \tLIST,\n@@ -73,6 +76,26 @@ enum index {\n \n \t/* List arguments. */\n \tLIST_GROUP,\n+\n+\t/* Validate/create arguments. */\n+\tGROUP,\n+\tPRIORITY,\n+\tINGRESS,\n+\tEGRESS,\n+\n+\t/* Validate/create pattern. */\n+\tPATTERN,\n+\tITEM_NEXT,\n+\tITEM_END,\n+\tITEM_VOID,\n+\tITEM_INVERT,\n+\n+\t/* Validate/create actions. */\n+\tACTIONS,\n+\tACTION_NEXT,\n+\tACTION_END,\n+\tACTION_VOID,\n+\tACTION_PASSTHRU,\n };\n \n /** Maximum number of subsequent tokens and arguments on the stack. */\n@@ -92,6 +115,7 @@ struct context {\n \tuint32_t eol:1; /**< EOL has been detected. */\n \tuint32_t last:1; /**< No more arguments. */\n \tuint16_t port; /**< Current port ID (for completions). */\n+\tuint32_t objdata; /**< Object-specific data. */\n \tvoid *object; /**< Address of current object for relative offsets. */\n };\n \n@@ -109,6 +133,8 @@ struct token {\n \tconst char *type;\n \t/** Help displayed during completion (defaults to token name). */\n \tconst char *help;\n+\t/** Private data used by parser functions. */\n+\tconst void *priv;\n \t/**\n \t * Lists of subsequent tokens to push on the stack. Each call to the\n \t * parser consumes the last entry of that stack.\n@@ -170,6 +196,14 @@ struct buffer {\n \tuint16_t port; /**< Affected port ID. */\n \tunion {\n \t\tstruct {\n+\t\t\tstruct rte_flow_attr attr;\n+\t\t\tstruct rte_flow_item *pattern;\n+\t\t\tstruct rte_flow_action *actions;\n+\t\t\tuint32_t pattern_n;\n+\t\t\tuint32_t actions_n;\n+\t\t\tuint8_t *data;\n+\t\t} vc; /**< Validate/create arguments. */\n+\t\tstruct {\n \t\t\tuint32_t *rule;\n \t\t\tuint32_t rule_n;\n \t\t} destroy; /**< Destroy arguments. */\n@@ -180,6 +214,39 @@ struct buffer {\n \t} args; /**< Command arguments. */\n };\n \n+/** Private data for pattern items. */\n+struct parse_item_priv {\n+\tenum rte_flow_item_type type; /**< Item type. */\n+\tuint32_t size; /**< Size of item specification structure. */\n+};\n+\n+#define PRIV_ITEM(t, s) \\\n+\t(&(const struct parse_item_priv){ \\\n+\t\t.type = RTE_FLOW_ITEM_TYPE_ ## t, \\\n+\t\t.size = s, \\\n+\t})\n+\n+/** Private data for actions. */\n+struct parse_action_priv {\n+\tenum rte_flow_action_type type; /**< Action type. */\n+\tuint32_t size; /**< Size of action configuration structure. */\n+};\n+\n+#define PRIV_ACTION(t, s) \\\n+\t(&(const struct parse_action_priv){ \\\n+\t\t.type = RTE_FLOW_ACTION_TYPE_ ## t, \\\n+\t\t.size = s, \\\n+\t})\n+\n+static const enum index next_vc_attr[] = {\n+\tGROUP,\n+\tPRIORITY,\n+\tINGRESS,\n+\tEGRESS,\n+\tPATTERN,\n+\t0,\n+};\n+\n static const enum index next_destroy_attr[] = {\n \tDESTROY_RULE,\n \tEND,\n@@ -192,9 +259,26 @@ static const enum index next_list_attr[] = {\n \t0,\n };\n \n+static const enum index next_item[] = {\n+\tITEM_END,\n+\tITEM_VOID,\n+\tITEM_INVERT,\n+\t0,\n+};\n+\n+static const enum index next_action[] = {\n+\tACTION_END,\n+\tACTION_VOID,\n+\tACTION_PASSTHRU,\n+\t0,\n+};\n+\n static int parse_init(struct context *, const struct token *,\n \t\t      const char *, unsigned int,\n \t\t      void *, unsigned int);\n+static int parse_vc(struct context *, const struct token *,\n+\t\t    const char *, unsigned int,\n+\t\t    void *, unsigned int);\n static int parse_destroy(struct context *, const struct token *,\n \t\t\t const char *, unsigned int,\n \t\t\t void *, unsigned int);\n@@ -266,18 +350,41 @@ static const struct token token_list[] = {\n \t\t.call = parse_int,\n \t\t.comp = comp_none,\n \t},\n+\t[PRIORITY_LEVEL] = {\n+\t\t.name = \"{level}\",\n+\t\t.type = \"PRIORITY\",\n+\t\t.help = \"priority level\",\n+\t\t.call = parse_int,\n+\t\t.comp = comp_none,\n+\t},\n \t/* Top-level command. */\n \t[FLOW] = {\n \t\t.name = \"flow\",\n \t\t.type = \"{command} {port_id} [{arg} [...]]\",\n \t\t.help = \"manage ingress/egress flow rules\",\n \t\t.next = NEXT(NEXT_ENTRY\n-\t\t\t     (DESTROY,\n+\t\t\t     (VALIDATE,\n+\t\t\t      CREATE,\n+\t\t\t      DESTROY,\n \t\t\t      FLUSH,\n \t\t\t      LIST)),\n \t\t.call = parse_init,\n \t},\n \t/* Sub-level commands. */\n+\t[VALIDATE] = {\n+\t\t.name = \"validate\",\n+\t\t.help = \"check whether a flow rule can be created\",\n+\t\t.next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)),\n+\t\t.args = ARGS(ARGS_ENTRY(struct buffer, port)),\n+\t\t.call = parse_vc,\n+\t},\n+\t[CREATE] = {\n+\t\t.name = \"create\",\n+\t\t.help = \"create a flow rule\",\n+\t\t.next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)),\n+\t\t.args = ARGS(ARGS_ENTRY(struct buffer, port)),\n+\t\t.call = parse_vc,\n+\t},\n \t[DESTROY] = {\n \t\t.name = \"destroy\",\n \t\t.help = \"destroy specific flow rules\",\n@@ -315,6 +422,98 @@ static const struct token token_list[] = {\n \t\t.args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),\n \t\t.call = parse_list,\n \t},\n+\t/* Validate/create attributes. */\n+\t[GROUP] = {\n+\t\t.name = \"group\",\n+\t\t.help = \"specify a group\",\n+\t\t.next = NEXT(next_vc_attr, NEXT_ENTRY(GROUP_ID)),\n+\t\t.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),\n+\t\t.call = parse_vc,\n+\t},\n+\t[PRIORITY] = {\n+\t\t.name = \"priority\",\n+\t\t.help = \"specify a priority level\",\n+\t\t.next = NEXT(next_vc_attr, NEXT_ENTRY(PRIORITY_LEVEL)),\n+\t\t.args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),\n+\t\t.call = parse_vc,\n+\t},\n+\t[INGRESS] = {\n+\t\t.name = \"ingress\",\n+\t\t.help = \"affect rule to ingress\",\n+\t\t.next = NEXT(next_vc_attr),\n+\t\t.call = parse_vc,\n+\t},\n+\t[EGRESS] = {\n+\t\t.name = \"egress\",\n+\t\t.help = \"affect rule to egress\",\n+\t\t.next = NEXT(next_vc_attr),\n+\t\t.call = parse_vc,\n+\t},\n+\t/* Validate/create pattern. */\n+\t[PATTERN] = {\n+\t\t.name = \"pattern\",\n+\t\t.help = \"submit a list of pattern items\",\n+\t\t.next = NEXT(next_item),\n+\t\t.call = parse_vc,\n+\t},\n+\t[ITEM_NEXT] = {\n+\t\t.name = \"/\",\n+\t\t.help = \"specify next pattern item\",\n+\t\t.next = NEXT(next_item),\n+\t},\n+\t[ITEM_END] = {\n+\t\t.name = \"end\",\n+\t\t.help = \"end list of pattern items\",\n+\t\t.priv = PRIV_ITEM(END, 0),\n+\t\t.next = NEXT(NEXT_ENTRY(ACTIONS)),\n+\t\t.call = parse_vc,\n+\t},\n+\t[ITEM_VOID] = {\n+\t\t.name = \"void\",\n+\t\t.help = \"no-op pattern item\",\n+\t\t.priv = PRIV_ITEM(VOID, 0),\n+\t\t.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),\n+\t\t.call = parse_vc,\n+\t},\n+\t[ITEM_INVERT] = {\n+\t\t.name = \"invert\",\n+\t\t.help = \"perform actions when pattern does not match\",\n+\t\t.priv = PRIV_ITEM(INVERT, 0),\n+\t\t.next = NEXT(NEXT_ENTRY(ITEM_NEXT)),\n+\t\t.call = parse_vc,\n+\t},\n+\t/* Validate/create actions. */\n+\t[ACTIONS] = {\n+\t\t.name = \"actions\",\n+\t\t.help = \"submit a list of associated actions\",\n+\t\t.next = NEXT(next_action),\n+\t\t.call = parse_vc,\n+\t},\n+\t[ACTION_NEXT] = {\n+\t\t.name = \"/\",\n+\t\t.help = \"specify next action\",\n+\t\t.next = NEXT(next_action),\n+\t},\n+\t[ACTION_END] = {\n+\t\t.name = \"end\",\n+\t\t.help = \"end list of actions\",\n+\t\t.priv = PRIV_ACTION(END, 0),\n+\t\t.call = parse_vc,\n+\t},\n+\t[ACTION_VOID] = {\n+\t\t.name = \"void\",\n+\t\t.help = \"no-op action\",\n+\t\t.priv = PRIV_ACTION(VOID, 0),\n+\t\t.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),\n+\t\t.call = parse_vc,\n+\t},\n+\t[ACTION_PASSTHRU] = {\n+\t\t.name = \"passthru\",\n+\t\t.help = \"let subsequent rule process matched packets\",\n+\t\t.priv = PRIV_ACTION(PASSTHRU, 0),\n+\t\t.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),\n+\t\t.call = parse_vc,\n+\t},\n };\n \n /** Remove and return last entry from argument stack. */\n@@ -368,10 +567,108 @@ parse_init(struct context *ctx, const struct token *token,\n \t/* Initialize buffer. */\n \tmemset(out, 0x00, sizeof(*out));\n \tmemset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));\n+\tctx->objdata = 0;\n \tctx->object = out;\n \treturn len;\n }\n \n+/** Parse tokens for validate/create commands. */\n+static int\n+parse_vc(struct context *ctx, const struct token *token,\n+\t const char *str, unsigned int len,\n+\t void *buf, unsigned int size)\n+{\n+\tstruct buffer *out = buf;\n+\tuint8_t *data;\n+\tuint32_t data_size;\n+\n+\t/* Token name must match. */\n+\tif (parse_default(ctx, token, str, len, NULL, 0) < 0)\n+\t\treturn -1;\n+\t/* Nothing else to do if there is no buffer. */\n+\tif (!out)\n+\t\treturn len;\n+\tif (!out->command) {\n+\t\tif (ctx->curr != VALIDATE && ctx->curr != CREATE)\n+\t\t\treturn -1;\n+\t\tif (sizeof(*out) > size)\n+\t\t\treturn -1;\n+\t\tout->command = ctx->curr;\n+\t\tctx->objdata = 0;\n+\t\tctx->object = out;\n+\t\tout->args.vc.data = (uint8_t *)out + size;\n+\t\treturn len;\n+\t}\n+\tctx->objdata = 0;\n+\tctx->object = &out->args.vc.attr;\n+\tswitch (ctx->curr) {\n+\tcase GROUP:\n+\tcase PRIORITY:\n+\t\treturn len;\n+\tcase INGRESS:\n+\t\tout->args.vc.attr.ingress = 1;\n+\t\treturn len;\n+\tcase EGRESS:\n+\t\tout->args.vc.attr.egress = 1;\n+\t\treturn len;\n+\tcase PATTERN:\n+\t\tout->args.vc.pattern =\n+\t\t\t(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),\n+\t\t\t\t\t       sizeof(double));\n+\t\tctx->object = out->args.vc.pattern;\n+\t\treturn len;\n+\tcase ACTIONS:\n+\t\tout->args.vc.actions =\n+\t\t\t(void *)RTE_ALIGN_CEIL((uintptr_t)\n+\t\t\t\t\t       (out->args.vc.pattern +\n+\t\t\t\t\t\tout->args.vc.pattern_n),\n+\t\t\t\t\t       sizeof(double));\n+\t\tctx->object = out->args.vc.actions;\n+\t\treturn len;\n+\tdefault:\n+\t\tif (!token->priv)\n+\t\t\treturn -1;\n+\t\tbreak;\n+\t}\n+\tif (!out->args.vc.actions) {\n+\t\tconst struct parse_item_priv *priv = token->priv;\n+\t\tstruct rte_flow_item *item =\n+\t\t\tout->args.vc.pattern + out->args.vc.pattern_n;\n+\n+\t\tdata_size = priv->size * 3; /* spec, last, mask */\n+\t\tdata = (void *)RTE_ALIGN_FLOOR((uintptr_t)\n+\t\t\t\t\t       (out->args.vc.data - data_size),\n+\t\t\t\t\t       sizeof(double));\n+\t\tif ((uint8_t *)item + sizeof(*item) > data)\n+\t\t\treturn -1;\n+\t\t*item = (struct rte_flow_item){\n+\t\t\t.type = priv->type,\n+\t\t};\n+\t\t++out->args.vc.pattern_n;\n+\t\tctx->object = item;\n+\t} else {\n+\t\tconst struct parse_action_priv *priv = token->priv;\n+\t\tstruct rte_flow_action *action =\n+\t\t\tout->args.vc.actions + out->args.vc.actions_n;\n+\n+\t\tdata_size = priv->size; /* configuration */\n+\t\tdata = (void *)RTE_ALIGN_FLOOR((uintptr_t)\n+\t\t\t\t\t       (out->args.vc.data - data_size),\n+\t\t\t\t\t       sizeof(double));\n+\t\tif ((uint8_t *)action + sizeof(*action) > data)\n+\t\t\treturn -1;\n+\t\t*action = (struct rte_flow_action){\n+\t\t\t.type = priv->type,\n+\t\t};\n+\t\t++out->args.vc.actions_n;\n+\t\tctx->object = action;\n+\t}\n+\tmemset(data, 0, data_size);\n+\tout->args.vc.data = data;\n+\tctx->objdata = data_size;\n+\treturn len;\n+}\n+\n /** Parse tokens for destroy command. */\n static int\n parse_destroy(struct context *ctx, const struct token *token,\n@@ -392,6 +689,7 @@ parse_destroy(struct context *ctx, const struct token *token,\n \t\tif (sizeof(*out) > size)\n \t\t\treturn -1;\n \t\tout->command = ctx->curr;\n+\t\tctx->objdata = 0;\n \t\tctx->object = out;\n \t\tout->args.destroy.rule =\n \t\t\t(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),\n@@ -401,6 +699,7 @@ parse_destroy(struct context *ctx, const struct token *token,\n \tif (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +\n \t     sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)\n \t\treturn -1;\n+\tctx->objdata = 0;\n \tctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;\n \treturn len;\n }\n@@ -425,6 +724,7 @@ parse_flush(struct context *ctx, const struct token *token,\n \t\tif (sizeof(*out) > size)\n \t\t\treturn -1;\n \t\tout->command = ctx->curr;\n+\t\tctx->objdata = 0;\n \t\tctx->object = out;\n \t}\n \treturn len;\n@@ -450,6 +750,7 @@ parse_list(struct context *ctx, const struct token *token,\n \t\tif (sizeof(*out) > size)\n \t\t\treturn -1;\n \t\tout->command = ctx->curr;\n+\t\tctx->objdata = 0;\n \t\tctx->object = out;\n \t\tout->args.list.group =\n \t\t\t(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),\n@@ -459,6 +760,7 @@ parse_list(struct context *ctx, const struct token *token,\n \tif (((uint8_t *)(out->args.list.group + out->args.list.group_n) +\n \t     sizeof(*out->args.list.group)) > (uint8_t *)out + size)\n \t\treturn -1;\n+\tctx->objdata = 0;\n \tctx->object = out->args.list.group + out->args.list.group_n++;\n \treturn len;\n }\n@@ -526,6 +828,7 @@ parse_port(struct context *ctx, const struct token *token,\n \tif (buf)\n \t\tout = buf;\n \telse {\n+\t\tctx->objdata = 0;\n \t\tctx->object = out;\n \t\tsize = sizeof(*out);\n \t}\n@@ -613,6 +916,7 @@ cmd_flow_context_init(struct context *ctx)\n \tctx->eol = 0;\n \tctx->last = 0;\n \tctx->port = 0;\n+\tctx->objdata = 0;\n \tctx->object = NULL;\n }\n \n@@ -836,6 +1140,14 @@ static void\n cmd_flow_parsed(const struct buffer *in)\n {\n \tswitch (in->command) {\n+\tcase VALIDATE:\n+\t\tport_flow_validate(in->port, &in->args.vc.attr,\n+\t\t\t\t   in->args.vc.pattern, in->args.vc.actions);\n+\t\tbreak;\n+\tcase CREATE:\n+\t\tport_flow_create(in->port, &in->args.vc.attr,\n+\t\t\t\t in->args.vc.pattern, in->args.vc.actions);\n+\t\tbreak;\n \tcase DESTROY:\n \t\tport_flow_destroy(in->port, in->args.destroy.rule_n,\n \t\t\t\t  in->args.destroy.rule);\n",
    "prefixes": [
        "dpdk-dev",
        "10/22"
    ]
}