get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 7333,
    "url": "https://patches.dpdk.org/api/patches/7333/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1443632760-25038-1-git-send-email-jasvinder.singh@intel.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": "<1443632760-25038-1-git-send-email-jasvinder.singh@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1443632760-25038-1-git-send-email-jasvinder.singh@intel.com",
    "date": "2015-09-30T17:06:00",
    "name": "[dpdk-dev] ip_pipeline: add flow actions pipeline",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "798c8ccac5e8d2d1a43bf8ccf7028dce34b54cb9",
    "submitter": {
        "id": 285,
        "url": "https://patches.dpdk.org/api/people/285/?format=api",
        "name": "Jasvinder Singh",
        "email": "jasvinder.singh@intel.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1443632760-25038-1-git-send-email-jasvinder.singh@intel.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/7333/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/7333/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 B09A88DAB;\n\tWed, 30 Sep 2015 19:06:42 +0200 (CEST)",
            "from mga09.intel.com (mga09.intel.com [134.134.136.24])\n\tby dpdk.org (Postfix) with ESMTP id 23C338DAA\n\tfor <dev@dpdk.org>; Wed, 30 Sep 2015 19:06:36 +0200 (CEST)",
            "from orsmga002.jf.intel.com ([10.7.209.21])\n\tby orsmga102.jf.intel.com with ESMTP; 30 Sep 2015 10:06:02 -0700",
            "from irvmail001.ir.intel.com ([163.33.26.43])\n\tby orsmga002.jf.intel.com with ESMTP; 30 Sep 2015 10:06:01 -0700",
            "from sivswdev02.ir.intel.com (sivswdev02.ir.intel.com\n\t[10.237.217.46])\n\tby irvmail001.ir.intel.com (8.14.3/8.13.6/MailSET/Hub) with ESMTP id\n\tt8UH60Y2031100; Wed, 30 Sep 2015 18:06:00 +0100",
            "from sivswdev02.ir.intel.com (localhost [127.0.0.1])\n\tby sivswdev02.ir.intel.com with ESMTP id t8UH60Z5025078;\n\tWed, 30 Sep 2015 18:06:00 +0100",
            "(from jasvinde@localhost)\n\tby sivswdev02.ir.intel.com with  id t8UH60qZ025074;\n\tWed, 30 Sep 2015 18:06:00 +0100"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.17,613,1437462000\"; d=\"scan'208\";a=\"816481596\"",
        "From": "Jasvinder Singh <jasvinder.singh@intel.com>",
        "To": "dev@dpdk.org",
        "Date": "Wed, 30 Sep 2015 18:06:00 +0100",
        "Message-Id": "<1443632760-25038-1-git-send-email-jasvinder.singh@intel.com>",
        "X-Mailer": "git-send-email 1.7.4.1",
        "Subject": "[dpdk-dev] [PATCH] ip_pipeline: add flow actions pipeline",
        "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": "Flow actions pipeline is an extension of\nflow-classification pipeline. Some of the\noperations of flow classification pipeline such\nas traffic metering/marking(for e.g. Single\nRate Three Color Marker (srTCM), Two Rate Three\nColor Marker trTCM)), policer can be performed\nseparately in flow action pipeline to avoid\nexcessive computational burden on the CPU core\nrunning the flow-classification pipeline. The\nFlow action pipeline implements various\nfunction such as traffic metering, policer,\nstats. Traffic mettering can configured as\nper the required context, for examples- per\nuser, per traffic class or both. These\ncontexts can be applied by specifying\nparameters in configuration file as shown\nbelow;\n\n[PIPELINE1]\ntype = FLOW_ACTIONS\ncore = 1\npktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0\npktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0\nn_flows = 65536\nn_meters_per_flow = 1\nflow_id_offset = 158\nip_hdr_offset = 142\ncolor_offset = 64\n\nThe entries of flow and dscp tables of flow\nactions pipeline can be modified through\ncommand-line interface. The commands to\nadd or delete entries to the flow table,\nDSCP(differentiated services code point) table\nand for statistics collection, etc have been\nincluded. The key functions such as\nTraffic Metering/marking and policer functions\nhave been implemented as flow-table action\nhandler.\n\nSigned-off-by: Jasvinder Singh <jasvinder.singh@intel.com>\n---\n examples/ip_pipeline/Makefile                      |    2 +\n examples/ip_pipeline/init.c                        |    2 +\n .../ip_pipeline/pipeline/pipeline_actions_common.h |   83 +\n .../ip_pipeline/pipeline/pipeline_flow_actions.c   | 1808 ++++++++++++++++++++\n .../ip_pipeline/pipeline/pipeline_flow_actions.h   |   78 +\n .../pipeline/pipeline_flow_actions_be.c            |  973 +++++++++++\n .../pipeline/pipeline_flow_actions_be.h            |  168 ++\n 7 files changed, 3114 insertions(+)\n create mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_actions.c\n create mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_actions.h\n create mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c\n create mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_actions_be.h",
    "diff": "diff --git a/examples/ip_pipeline/Makefile b/examples/ip_pipeline/Makefile\nindex f3ff1ec..13d31de 100644\n--- a/examples/ip_pipeline/Makefile\n+++ b/examples/ip_pipeline/Makefile\n@@ -66,6 +66,8 @@ SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_firewall_be.c\n SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_firewall.c\n SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_flow_classification_be.c\n SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_flow_classification.c\n+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_flow_actions_be.c\n+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_flow_actions.c\n SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_routing_be.c\n SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_routing.c\n \ndiff --git a/examples/ip_pipeline/init.c b/examples/ip_pipeline/init.c\nindex 3f9c68d..0088ece 100644\n--- a/examples/ip_pipeline/init.c\n+++ b/examples/ip_pipeline/init.c\n@@ -49,6 +49,7 @@\n #include \"pipeline_passthrough.h\"\n #include \"pipeline_firewall.h\"\n #include \"pipeline_flow_classification.h\"\n+#include \"pipeline_flow_actions.h\"\n #include \"pipeline_routing.h\"\n \n #define APP_NAME_SIZE\t32\n@@ -1291,6 +1292,7 @@ int app_init(struct app_params *app)\n \tapp_pipeline_type_register(app, &pipeline_master);\n \tapp_pipeline_type_register(app, &pipeline_passthrough);\n \tapp_pipeline_type_register(app, &pipeline_flow_classification);\n+\tapp_pipeline_type_register(app, &pipeline_flow_actions);\n \tapp_pipeline_type_register(app, &pipeline_firewall);\n \tapp_pipeline_type_register(app, &pipeline_routing);\n \ndiff --git a/examples/ip_pipeline/pipeline/pipeline_actions_common.h b/examples/ip_pipeline/pipeline/pipeline_actions_common.h\nindex 4b5d5c4..aa1dd59 100644\n--- a/examples/ip_pipeline/pipeline/pipeline_actions_common.h\n+++ b/examples/ip_pipeline/pipeline/pipeline_actions_common.h\n@@ -116,4 +116,87 @@ f_ah(\t\t\t\t\t\t\t\t\t\\\n \treturn 0;\t\t\t\t\t\t\t\\\n }\n \n+#define PIPELINE_TABLE_AH_HIT_DROP_TIME(f_ah, f_pkt_work, f_pkt4_work)\t\\\n+static int\t\t\t\t\t\t\t\t\\\n+f_ah(\t\t\t\t\t\t\t\t\t\\\n+\tstruct rte_mbuf **pkts,\t\t\t\t\t\t\\\n+\tuint64_t *pkts_mask,\t\t\t\t\t\t\\\n+\tstruct rte_pipeline_table_entry **entries,\t\t\t\\\n+\tvoid *arg)\t\t\t\t\t\t\t\\\n+{\t\t\t\t\t\t\t\t\t\\\n+\tuint64_t pkts_in_mask = *pkts_mask;\t\t\t\t\\\n+\tuint64_t pkts_out_mask = *pkts_mask;\t\t\t\t\\\n+\tuint64_t time = rte_rdtsc();\t\t\t\t\t\\\n+\t\t\t\t\t\t\t\t\t\\\n+\tif ((pkts_in_mask & (pkts_in_mask + 1)) == 0) {\t\t\t\\\n+\t\tuint64_t n_pkts = __builtin_popcountll(pkts_in_mask);\t\\\n+\t\tuint32_t i;\t\t\t\t\t\t\\\n+\t\t\t\t\t\t\t\t\t\\\n+\t\tfor (i = 0; i < (n_pkts & (~0x3LLU)); i += 4) {\t\t\\\n+\t\t\tuint64_t mask = f_pkt4_work(&pkts[i],\t\t\\\n+\t\t\t\t&entries[i], arg, time);\t\\\n+\t\t\tpkts_out_mask ^= mask << i;\t\t\t\\\n+\t\t}\t\t\t\t\t\t\t\\\n+\t\t\t\t\t\t\t\t\t\\\n+\t\tfor ( ; i < n_pkts; i++) {\t\t\t\t\\\n+\t\t\tuint64_t mask = f_pkt_work(pkts[i],\t\t\\\n+\t\t\t\tentries[i], arg, time);\t\t\\\n+\t\t\tpkts_out_mask ^= mask << i;\t\t\t\\\n+\t\t}\t\t\t\t\t\t\t\\\n+\t} else\t\t\t\t\t\t\t\t\\\n+\t\tfor ( ; pkts_in_mask; ) {\t\t\t\t\\\n+\t\t\tuint32_t pos = __builtin_ctzll(pkts_in_mask);\t\\\n+\t\t\tuint64_t pkt_mask = 1LLU << pos;\t\t\\\n+\t\t\tuint64_t mask = f_pkt_work(pkts[pos],\t\t\\\n+\t\t\t\tentries[pos], arg, time);\t\t\\\n+\t\t\t\t\t\t\t\t\t\\\n+\t\t\tpkts_in_mask &= ~pkt_mask;\t\t\t\\\n+\t\t\tpkts_out_mask ^= mask << pos;\t\t\t\\\n+\t\t}\t\t\t\t\t\t\t\\\n+\t\t\t\t\t\t\t\t\t\\\n+\t*pkts_mask = pkts_out_mask;\t\t\t\t\t\\\n+\treturn 0;\t\t\t\t\t\t\t\\\n+}\n+\n+#define PIPELINE_TABLE_AH_MISS_DROP_TIME(f_ah, f_pkt_work, f_pkt4_work)\t\\\n+static int\t\t\t\t\t\t\t\t\\\n+f_ah(\t\t\t\t\t\t\t\t\t\\\n+\tstruct rte_mbuf **pkts,\t\t\t\t\t\t\\\n+\tuint64_t *pkts_mask,\t\t\t\t\t\t\\\n+\tstruct rte_pipeline_table_entry *entry,\t\t\t\t\\\n+\tvoid *arg)\t\t\t\t\t\t\t\\\n+{\t\t\t\t\t\t\t\t\t\\\n+\tuint64_t pkts_in_mask = *pkts_mask;\t\t\t\t\\\n+\tuint64_t pkts_out_mask = *pkts_mask;\t\t\t\t\\\n+\tuint64_t time = rte_rdtsc();\t\t\t\t\t\\\n+\t\t\t\t\t\t\t\t\t\\\n+\tif ((pkts_in_mask & (pkts_in_mask + 1)) == 0) {\t\t\t\\\n+\t\tuint64_t n_pkts = __builtin_popcountll(pkts_in_mask);\t\\\n+\t\tuint32_t i;\t\t\t\t\t\t\\\n+\t\t\t\t\t\t\t\t\t\\\n+\t\tfor (i = 0; i < (n_pkts & (~0x3LLU)); i += 4) {\t\t\\\n+\t\t\tuint64_t mask = f_pkt4_work(&pkts[i],\t\t\\\n+\t\t\t\tentry, arg, time);\t\t\t\\\n+\t\t\tpkts_out_mask ^= mask << i;\t\t\t\\\n+\t\t}\t\t\t\t\t\t\t\\\n+\t\t\t\t\t\t\t\t\t\\\n+\t\tfor ( ; i < n_pkts; i++) {\t\t\t\t\\\n+\t\t\tuint64_t mask = f_pkt_work(pkts[i], entry, arg, time);\\\n+\t\t\tpkts_out_mask ^= mask << i;\t\t\t\\\n+\t\t}\t\t\t\t\t\t\t\\\n+\t} else\t\t\t\t\t\t\t\t\\\n+\t\tfor ( ; pkts_in_mask; ) {\t\t\t\t\\\n+\t\t\tuint32_t pos = __builtin_ctzll(pkts_in_mask);\t\\\n+\t\t\tuint64_t pkt_mask = 1LLU << pos;\t\t\\\n+\t\t\tuint64_t mask = f_pkt_work(pkts[pos],\t\t\\\n+\t\t\t\tentry, arg, time);\t\t\\\n+\t\t\t\t\t\t\t\t\t\\\n+\t\t\tpkts_in_mask &= ~pkt_mask;\t\t\t\\\n+\t\t\tpkts_out_mask ^= mask << pos;\t\t\t\\\n+\t\t}\t\t\t\t\t\t\t\\\n+\t\t\t\t\t\t\t\t\t\\\n+\t*pkts_mask = pkts_out_mask;\t\t\t\t\t\\\n+\treturn 0;\t\t\t\t\t\t\t\\\n+}\n+\n #endif\ndiff --git a/examples/ip_pipeline/pipeline/pipeline_flow_actions.c b/examples/ip_pipeline/pipeline/pipeline_flow_actions.c\nnew file mode 100644\nindex 0000000..c29172c\n--- /dev/null\n+++ b/examples/ip_pipeline/pipeline/pipeline_flow_actions.c\n@@ -0,0 +1,1808 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.\n+ *   All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   modification, are permitted provided that the following conditions\n+ *   are met:\n+ *\n+ *     * Redistributions of source code must retain the above copyright\n+ *       notice, this list of conditions and the following disclaimer.\n+ *     * Redistributions in binary form must reproduce the above copyright\n+ *       notice, this list of conditions and the following disclaimer in\n+ *       the documentation and/or other materials provided with the\n+ *       distribution.\n+ *     * Neither the name of Intel Corporation nor the names of its\n+ *       contributors may be used to endorse or promote products derived\n+ *       from this software without specific prior written permission.\n+ *\n+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+ *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+#include <stdio.h>\n+#include <string.h>\n+#include <sys/queue.h>\n+#include <netinet/in.h>\n+\n+#include <rte_common.h>\n+#include <rte_hexdump.h>\n+#include <rte_malloc.h>\n+#include <cmdline_rdline.h>\n+#include <cmdline_parse.h>\n+#include <cmdline_parse_num.h>\n+#include <cmdline_parse_string.h>\n+#include <cmdline_parse_ipaddr.h>\n+#include <cmdline_parse_etheraddr.h>\n+\n+#include \"app.h\"\n+#include \"pipeline_common_fe.h\"\n+#include \"pipeline_flow_actions.h\"\n+#include \"hash_func.h\"\n+\n+/*\n+ * Flow actions pipeline\n+ */\n+#ifndef N_FLOWS_BULK\n+#define N_FLOWS_BULK\t\t\t\t\t4096\n+#endif\n+\n+struct app_pipeline_fa_flow {\n+\tstruct pipeline_fa_flow_params params;\n+\tvoid *entry_ptr;\n+};\n+\n+struct app_pipeline_fa_dscp {\n+\tuint32_t traffic_class;\n+\tenum rte_meter_color color;\n+};\n+\n+struct app_pipeline_fa {\n+\t/* Parameters */\n+\tuint32_t n_ports_in;\n+\tuint32_t n_ports_out;\n+\tstruct pipeline_fa_params params;\n+\n+\t/* Flows */\n+\tstruct app_pipeline_fa_dscp dscp[PIPELINE_FA_N_DSCP];\n+\tstruct app_pipeline_fa_flow *flows;\n+} __rte_cache_aligned;\n+\n+static void*\n+app_pipeline_fa_init(struct pipeline_params *params,\n+\t__rte_unused void *arg)\n+{\n+\tstruct app_pipeline_fa *p;\n+\tuint32_t size, i;\n+\n+\t/* Check input arguments */\n+\tif ((params == NULL) ||\n+\t\t(params->n_ports_in == 0) ||\n+\t\t(params->n_ports_out == 0))\n+\t\treturn NULL;\n+\n+\t/* Memory allocation */\n+\tsize = RTE_CACHE_LINE_ROUNDUP(sizeof(struct app_pipeline_fa));\n+\tp = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);\n+\tif (p == NULL)\n+\t\treturn NULL;\n+\n+\t/* Initialization */\n+\tp->n_ports_in = params->n_ports_in;\n+\tp->n_ports_out = params->n_ports_out;\n+\tif (pipeline_fa_parse_args(&p->params, params)) {\n+\t\trte_free(p);\n+\t\treturn NULL;\n+\t}\n+\n+\t/* Memory allocation */\n+\tsize = RTE_CACHE_LINE_ROUNDUP(\n+\t\tp->params.n_flows * sizeof(struct app_pipeline_fa_flow));\n+\tp->flows = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);\n+\tif (p->flows == NULL) {\n+\t\trte_free(p);\n+\t\treturn NULL;\n+\t}\n+\n+\t/* Initialization of flow table */\n+\tfor (i = 0; i < p->params.n_flows; i++)\n+\t\tpipeline_fa_flow_params_set_default(&p->flows[i].params);\n+\n+\t/* Initialization of DSCP table */\n+\tfor (i = 0; i < RTE_DIM(p->dscp); i++) {\n+\t\tp->dscp[i].traffic_class = 0;\n+\t\tp->dscp[i].color = e_RTE_METER_GREEN;\n+\t}\n+\n+\treturn (void *) p;\n+}\n+\n+static int\n+app_pipeline_fa_free(void *pipeline)\n+{\n+\tstruct app_pipeline_fa *p = pipeline;\n+\n+\t/* Check input arguments */\n+\tif (p == NULL)\n+\t\treturn -1;\n+\n+\t/* Free resources */\n+\trte_free(p->flows);\n+\trte_free(p);\n+\n+\treturn 0;\n+}\n+\n+static int\n+flow_params_check(struct app_pipeline_fa *p,\n+\t__rte_unused uint32_t meter_update_mask,\n+\tuint32_t policer_update_mask,\n+\tuint32_t port_update,\n+\tstruct pipeline_fa_flow_params *params)\n+{\n+\tuint32_t mask, i;\n+\n+\t/* Meter */\n+\n+\t/* Policer */\n+\tfor (i = 0, mask = 1; i < PIPELINE_FA_N_TC_MAX; i++, mask <<= 1) {\n+\t\tstruct pipeline_fa_policer_params *p = &params->p[i];\n+\t\tuint32_t j;\n+\n+\t\tif ((mask & policer_update_mask) == 0)\n+\t\t\tcontinue;\n+\n+\t\tfor (j = 0; j < e_RTE_METER_COLORS; j++) {\n+\t\t\tstruct pipeline_fa_policer_action *action =\n+\t\t\t\t&p->action[j];\n+\n+\t\t\tif ((action->drop == 0) &&\n+\t\t\t\t(action->color >= e_RTE_METER_COLORS))\n+\t\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\t/* Port */\n+\tif (port_update && (params->port_id >= p->n_ports_out))\n+\t\treturn -1;\n+\n+\treturn 0;\n+}\n+\n+int\n+app_pipeline_fa_flow_config(struct app_params *app,\n+\tuint32_t pipeline_id,\n+\tuint32_t flow_id,\n+\tuint32_t meter_update_mask,\n+\tuint32_t policer_update_mask,\n+\tuint32_t port_update,\n+\tstruct pipeline_fa_flow_params *params)\n+{\n+\tstruct app_pipeline_fa *p;\n+\tstruct app_pipeline_fa_flow *flow;\n+\n+\tstruct pipeline_fa_flow_config_msg_req *req;\n+\tstruct pipeline_fa_flow_config_msg_rsp *rsp;\n+\n+\tuint32_t i, mask;\n+\n+\t/* Check input arguments */\n+\tif ((app == NULL) ||\n+\t\t((meter_update_mask == 0) &&\n+\t\t(policer_update_mask == 0) &&\n+\t\t(port_update == 0)) ||\n+\t\t(meter_update_mask >= (1 << PIPELINE_FA_N_TC_MAX)) ||\n+\t\t(policer_update_mask >= (1 << PIPELINE_FA_N_TC_MAX)) ||\n+\t\t(params == NULL))\n+\t\treturn -1;\n+\n+\tp = app_pipeline_data_fe(app, pipeline_id);\n+\tif (p == NULL)\n+\t\treturn -1;\n+\n+\tif (flow_params_check(p,\n+\t\tmeter_update_mask,\n+\t\tpolicer_update_mask,\n+\t\tport_update,\n+\t\tparams) != 0)\n+\t\treturn -1;\n+\n+\tflow_id %= p->params.n_flows;\n+\tflow = &p->flows[flow_id];\n+\n+\t/* Allocate and write request */\n+\treq = app_msg_alloc(app);\n+\tif (req == NULL)\n+\t\treturn -1;\n+\n+\treq->type = PIPELINE_MSG_REQ_CUSTOM;\n+\treq->subtype = PIPELINE_FA_MSG_REQ_FLOW_CONFIG;\n+\treq->entry_ptr = flow->entry_ptr;\n+\treq->flow_id = flow_id;\n+\treq->meter_update_mask = meter_update_mask;\n+\treq->policer_update_mask = policer_update_mask;\n+\treq->port_update = port_update;\n+\tmemcpy(&req->params, params, sizeof(*params));\n+\n+\t/* Send request and wait for response */\n+\trsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);\n+\tif (rsp == NULL)\n+\t\treturn -1;\n+\n+\t/* Read response */\n+\tif (rsp->status ||\n+\t\t(rsp->entry_ptr == NULL)) {\n+\t\tapp_msg_free(app, rsp);\n+\t\treturn -1;\n+\t}\n+\n+\t/* Commit flow */\n+\tfor (i = 0, mask = 1; i < PIPELINE_FA_N_TC_MAX; i++, mask <<= 1) {\n+\t\tif ((mask & meter_update_mask) == 0)\n+\t\t\tcontinue;\n+\n+\t\tmemcpy(&flow->params.m[i], &params->m[i], sizeof(params->m[i]));\n+\t}\n+\n+\tfor (i = 0, mask = 1; i < PIPELINE_FA_N_TC_MAX; i++, mask <<= 1) {\n+\t\tif ((mask & policer_update_mask) == 0)\n+\t\t\tcontinue;\n+\n+\t\tmemcpy(&flow->params.p[i], &params->p[i], sizeof(params->p[i]));\n+\t}\n+\n+\tif (port_update)\n+\t\tflow->params.port_id = params->port_id;\n+\n+\tflow->entry_ptr = rsp->entry_ptr;\n+\n+\t/* Free response */\n+\tapp_msg_free(app, rsp);\n+\n+\treturn 0;\n+}\n+\n+int\n+app_pipeline_fa_flow_config_bulk(struct app_params *app,\n+\tuint32_t pipeline_id,\n+\tuint32_t *flow_id,\n+\tuint32_t n_flows,\n+\tuint32_t meter_update_mask,\n+\tuint32_t policer_update_mask,\n+\tuint32_t port_update,\n+\tstruct pipeline_fa_flow_params *params)\n+{\n+\tstruct app_pipeline_fa *p;\n+\tstruct pipeline_fa_flow_config_bulk_msg_req *req;\n+\tstruct pipeline_fa_flow_config_bulk_msg_rsp *rsp;\n+\tvoid **req_entry_ptr;\n+\tuint32_t *req_flow_id;\n+\tuint32_t i;\n+\n+\t/* Check input arguments */\n+\tif ((app == NULL) ||\n+\t\t(flow_id == NULL) ||\n+\t\t(n_flows == 0) ||\n+\t\t((meter_update_mask == 0) &&\n+\t\t(policer_update_mask == 0) &&\n+\t\t(port_update == 0)) ||\n+\t\t(meter_update_mask >= (1 << PIPELINE_FA_N_TC_MAX)) ||\n+\t\t(policer_update_mask >= (1 << PIPELINE_FA_N_TC_MAX)) ||\n+\t\t(params == NULL))\n+\t\treturn -1;\n+\n+\tp = app_pipeline_data_fe(app, pipeline_id);\n+\tif (p == NULL)\n+\t\treturn -1;\n+\n+\tfor (i = 0; i < n_flows; i++) {\n+\t\tstruct pipeline_fa_flow_params *flow_params = &params[i];\n+\n+\t\tif (flow_params_check(p,\n+\t\t\tmeter_update_mask,\n+\t\t\tpolicer_update_mask,\n+\t\t\tport_update,\n+\t\t\tflow_params) != 0)\n+\t\t\treturn -1;\n+\t}\n+\n+\t/* Allocate and write request */\n+\treq_entry_ptr = (void **) rte_malloc(NULL,\n+\t\tn_flows * sizeof(void *),\n+\t\tRTE_CACHE_LINE_SIZE);\n+\tif (req_entry_ptr == NULL)\n+\t\treturn -1;\n+\n+\treq_flow_id = (uint32_t *) rte_malloc(NULL,\n+\t\tn_flows * sizeof(uint32_t),\n+\t\tRTE_CACHE_LINE_SIZE);\n+\tif (req_flow_id == NULL) {\n+\t\trte_free(req_entry_ptr);\n+\t\treturn -1;\n+\t}\n+\n+\tfor (i = 0; i < n_flows; i++) {\n+\t\tuint32_t fid = flow_id[i] % p->params.n_flows;\n+\t\tstruct app_pipeline_fa_flow *flow = &p->flows[fid];\n+\n+\t\treq_flow_id[i] = fid;\n+\t\treq_entry_ptr[i] = flow->entry_ptr;\n+\t}\n+\n+\treq = app_msg_alloc(app);\n+\tif (req == NULL) {\n+\t\trte_free(req_flow_id);\n+\t\trte_free(req_entry_ptr);\n+\t\treturn -1;\n+\t}\n+\n+\treq->type = PIPELINE_MSG_REQ_CUSTOM;\n+\treq->subtype = PIPELINE_FA_MSG_REQ_FLOW_CONFIG_BULK;\n+\treq->entry_ptr = req_entry_ptr;\n+\treq->flow_id = req_flow_id;\n+\treq->n_flows = n_flows;\n+\treq->meter_update_mask = meter_update_mask;\n+\treq->policer_update_mask = policer_update_mask;\n+\treq->port_update = port_update;\n+\treq->params = params;\n+\n+\t/* Send request and wait for response */\n+\trsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);\n+\tif (rsp == NULL) {\n+\t\trte_free(req_flow_id);\n+\t\trte_free(req_entry_ptr);\n+\t\treturn -1;\n+\t}\n+\n+\t/* Read response */\n+\n+\t/* Commit flows */\n+\tfor (i = 0; i < rsp->n_flows; i++) {\n+\t\tuint32_t fid = flow_id[i] % p->params.n_flows;\n+\t\tstruct app_pipeline_fa_flow *flow = &p->flows[fid];\n+\t\tstruct pipeline_fa_flow_params *flow_params = &params[i];\n+\t\tvoid *entry_ptr = req_entry_ptr[i];\n+\t\tuint32_t j, mask;\n+\n+\t\tfor (j = 0, mask = 1; j < PIPELINE_FA_N_TC_MAX;\n+\t\t\tj++, mask <<= 1) {\n+\t\t\tif ((mask & meter_update_mask) == 0)\n+\t\t\t\tcontinue;\n+\n+\t\t\tmemcpy(&flow->params.m[j],\n+\t\t\t\t&flow_params->m[j],\n+\t\t\t\tsizeof(flow_params->m[j]));\n+\t\t}\n+\n+\t\tfor (j = 0, mask = 1; j < PIPELINE_FA_N_TC_MAX;\n+\t\t\tj++, mask <<= 1) {\n+\t\t\tif ((mask & policer_update_mask) == 0)\n+\t\t\t\tcontinue;\n+\n+\t\t\tmemcpy(&flow->params.p[j],\n+\t\t\t\t&flow_params->p[j],\n+\t\t\t\tsizeof(flow_params->p[j]));\n+\t\t}\n+\n+\t\tif (port_update)\n+\t\t\tflow->params.port_id = flow_params->port_id;\n+\n+\t\tflow->entry_ptr = entry_ptr;\n+\t}\n+\n+\t/* Free response */\n+\tapp_msg_free(app, rsp);\n+\trte_free(req_flow_id);\n+\trte_free(req_entry_ptr);\n+\n+\treturn (rsp->n_flows == n_flows) ? 0 : -1;\n+}\n+\n+int\n+app_pipeline_fa_dscp_config(struct app_params *app,\n+\tuint32_t pipeline_id,\n+\tuint32_t dscp,\n+\tuint32_t traffic_class,\n+\tenum rte_meter_color color)\n+{\n+\tstruct app_pipeline_fa *p;\n+\n+\tstruct pipeline_fa_dscp_config_msg_req *req;\n+\tstruct pipeline_fa_dscp_config_msg_rsp *rsp;\n+\n+\t/* Check input arguments */\n+\tif ((app == NULL) ||\n+\t\t(dscp >= PIPELINE_FA_N_DSCP) ||\n+\t\t(traffic_class >= PIPELINE_FA_N_TC_MAX) ||\n+\t\t(color >= e_RTE_METER_COLORS))\n+\t\treturn -1;\n+\n+\tp = app_pipeline_data_fe(app, pipeline_id);\n+\tif (p == NULL)\n+\t\treturn -1;\n+\n+\tif (p->params.dscp_enabled == 0)\n+\t\treturn -1;\n+\n+\t/* Allocate and write request */\n+\treq = app_msg_alloc(app);\n+\tif (req == NULL)\n+\t\treturn -1;\n+\n+\treq->type = PIPELINE_MSG_REQ_CUSTOM;\n+\treq->subtype = PIPELINE_FA_MSG_REQ_DSCP_CONFIG;\n+\treq->dscp = dscp;\n+\treq->traffic_class = traffic_class;\n+\treq->color = color;\n+\n+\t/* Send request and wait for response */\n+\trsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);\n+\tif (rsp == NULL)\n+\t\treturn -1;\n+\n+\t/* Read response */\n+\tif (rsp->status) {\n+\t\tapp_msg_free(app, rsp);\n+\t\treturn -1;\n+\t}\n+\n+\t/* Commit DSCP */\n+\tp->dscp[dscp].traffic_class = traffic_class;\n+\tp->dscp[dscp].color = color;\n+\n+\t/* Free response */\n+\tapp_msg_free(app, rsp);\n+\n+\treturn 0;\n+}\n+\n+int\n+app_pipeline_fa_flow_policer_stats_read(struct app_params *app,\n+\tuint32_t pipeline_id,\n+\tuint32_t flow_id,\n+\tuint32_t policer_id,\n+\tint clear,\n+\tstruct pipeline_fa_policer_stats *stats)\n+{\n+\tstruct app_pipeline_fa *p;\n+\tstruct app_pipeline_fa_flow *flow;\n+\n+\tstruct pipeline_fa_policer_stats_msg_req *req;\n+\tstruct pipeline_fa_policer_stats_msg_rsp *rsp;\n+\n+\t/* Check input arguments */\n+\tif ((app == NULL) || (stats == NULL))\n+\t\treturn -1;\n+\n+\tp = app_pipeline_data_fe(app, pipeline_id);\n+\tif (p == NULL)\n+\t\treturn -1;\n+\n+\tflow_id %= p->params.n_flows;\n+\tflow = &p->flows[flow_id];\n+\n+\tif ((policer_id >= p->params.n_meters_per_flow) ||\n+\t\t(flow->entry_ptr == NULL))\n+\t\treturn -1;\n+\n+\t/* Allocate and write request */\n+\treq = app_msg_alloc(app);\n+\tif (req == NULL)\n+\t\treturn -1;\n+\n+\treq->type = PIPELINE_MSG_REQ_CUSTOM;\n+\treq->subtype = PIPELINE_FA_MSG_REQ_POLICER_STATS_READ;\n+\treq->entry_ptr = flow->entry_ptr;\n+\treq->policer_id = policer_id;\n+\treq->clear = clear;\n+\n+\t/* Send request and wait for response */\n+\trsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);\n+\tif (rsp == NULL)\n+\t\treturn -1;\n+\n+\t/* Read response */\n+\tif (rsp->status) {\n+\t\tapp_msg_free(app, rsp);\n+\t\treturn -1;\n+\t}\n+\n+\tmemcpy(stats, &rsp->stats, sizeof(*stats));\n+\n+\t/* Free response */\n+\tapp_msg_free(app, rsp);\n+\n+\treturn 0;\n+}\n+\n+static const char *\n+color_to_string(enum rte_meter_color color)\n+{\n+\tswitch (color) {\n+\tcase e_RTE_METER_GREEN: return \"G\";\n+\tcase e_RTE_METER_YELLOW: return \"Y\";\n+\tcase e_RTE_METER_RED: return \"R\";\n+\tdefault: return \"?\";\n+\t}\n+}\n+\n+static int\n+string_to_color(char *s, enum rte_meter_color *c)\n+{\n+\tif (strcmp(s, \"G\") == 0) {\n+\t\t*c = e_RTE_METER_GREEN;\n+\t\treturn 0;\n+\t}\n+\n+\tif (strcmp(s, \"Y\") == 0) {\n+\t\t*c = e_RTE_METER_YELLOW;\n+\t\treturn 0;\n+\t}\n+\n+\tif (strcmp(s, \"R\") == 0) {\n+\t\t*c = e_RTE_METER_RED;\n+\t\treturn 0;\n+\t}\n+\n+\treturn -1;\n+}\n+\n+static const char *\n+policer_action_to_string(struct pipeline_fa_policer_action *a)\n+{\n+\tif (a->drop)\n+\t\treturn \"D\";\n+\n+\treturn color_to_string(a->color);\n+}\n+\n+static int\n+string_to_policer_action(char *s, struct pipeline_fa_policer_action *a)\n+{\n+\tif (strcmp(s, \"G\") == 0) {\n+\t\ta->drop = 0;\n+\t\ta->color = e_RTE_METER_GREEN;\n+\t\treturn 0;\n+\t}\n+\n+\tif (strcmp(s, \"Y\") == 0) {\n+\t\ta->drop = 0;\n+\t\ta->color = e_RTE_METER_YELLOW;\n+\t\treturn 0;\n+\t}\n+\n+\tif (strcmp(s, \"R\") == 0) {\n+\t\ta->drop = 0;\n+\t\ta->color = e_RTE_METER_RED;\n+\t\treturn 0;\n+\t}\n+\n+\tif (strcmp(s, \"D\") == 0) {\n+\t\ta->drop = 1;\n+\t\ta->color = e_RTE_METER_GREEN;\n+\t\treturn 0;\n+\t}\n+\n+\treturn -1;\n+}\n+\n+static void\n+print_flow(struct app_pipeline_fa *p,\n+\tuint32_t flow_id,\n+\tstruct app_pipeline_fa_flow *flow)\n+{\n+\tuint32_t i;\n+\n+\tprintf(\"Flow ID = %\" PRIu32 \"\\n\", flow_id);\n+\n+\tfor (i = 0; i < p->params.n_meters_per_flow; i++) {\n+\t\tstruct rte_meter_trtcm_params *meter = &flow->params.m[i];\n+\t\tstruct pipeline_fa_policer_params *policer = &flow->params.p[i];\n+\n+\tprintf(\"\\ttrTCM [CIR = %\" PRIu64\n+\t\t\", CBS = %\" PRIu64 \", PIR = %\" PRIu64\n+\t\t\", PBS = %\" PRIu64\t\"] Policer [G : %s, Y : %s, R : %s]\\n\",\n+\t\tmeter->cir,\n+\t\tmeter->cbs,\n+\t\tmeter->pir,\n+\t\tmeter->pbs,\n+\t\tpolicer_action_to_string(&policer->action[e_RTE_METER_GREEN]),\n+\t\tpolicer_action_to_string(&policer->action[e_RTE_METER_YELLOW]),\n+\t\tpolicer_action_to_string(&policer->action[e_RTE_METER_RED]));\n+\t}\n+\n+\tprintf(\"\\tPort %u (entry_ptr = %p)\\n\",\n+\t\tflow->params.port_id,\n+\t\tflow->entry_ptr);\n+}\n+\n+\n+static int\n+app_pipeline_fa_flow_ls(struct app_params *app,\n+\t\tuint32_t pipeline_id)\n+{\n+\tstruct app_pipeline_fa *p;\n+\tuint32_t i;\n+\n+\t/* Check input arguments */\n+\tif (app == NULL)\n+\t\treturn -1;\n+\n+\tp = app_pipeline_data_fe(app, pipeline_id);\n+\tif (p == NULL)\n+\t\treturn -1;\n+\n+\tfor (i = 0; i < p->params.n_flows; i++) {\n+\t\tstruct app_pipeline_fa_flow *flow = &p->flows[i];\n+\n+\t\tprint_flow(p, i, flow);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+app_pipeline_fa_dscp_ls(struct app_params *app,\n+\t\tuint32_t pipeline_id)\n+{\n+\tstruct app_pipeline_fa *p;\n+\tuint32_t i;\n+\n+\t/* Check input arguments */\n+\tif (app == NULL)\n+\t\treturn -1;\n+\n+\tp = app_pipeline_data_fe(app, pipeline_id);\n+\tif (p == NULL)\n+\t\treturn -1;\n+\n+\tif (p->params.dscp_enabled == 0)\n+\t\treturn -1;\n+\n+\tfor (i = 0; i < RTE_DIM(p->dscp); i++) {\n+\t\tstruct app_pipeline_fa_dscp *dscp =\t&p->dscp[i];\n+\n+\t\tprintf(\"DSCP = %2\" PRIu32 \": Traffic class = %\" PRIu32\n+\t\t\t\", Color = %s\\n\",\n+\t\t\ti,\n+\t\t\tdscp->traffic_class,\n+\t\t\tcolor_to_string(dscp->color));\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * Flow meter configuration (single flow)\n+ *\n+ * p <pipeline ID> flow <flow ID> meter <meter ID> trtcm <trtcm params>\n+ */\n+\n+struct cmd_fa_meter_config_result {\n+\tcmdline_fixed_string_t p_string;\n+\tuint32_t pipeline_id;\n+\tcmdline_fixed_string_t flow_string;\n+\tuint32_t flow_id;\n+\tcmdline_fixed_string_t meter_string;\n+\tuint32_t meter_id;\n+\tcmdline_fixed_string_t trtcm_string;\n+\tuint64_t cir;\n+\tuint64_t pir;\n+\tuint64_t cbs;\n+\tuint64_t pbs;\n+};\n+\n+static void\n+cmd_fa_meter_config_parsed(\n+\tvoid *parsed_result,\n+\t__rte_unused struct cmdline *cl,\n+\tvoid *data)\n+{\n+\tstruct cmd_fa_meter_config_result *params = parsed_result;\n+\tstruct app_params *app = data;\n+\tstruct pipeline_fa_flow_params flow_params;\n+\tint status;\n+\n+\tif (params->meter_id >= PIPELINE_FA_N_TC_MAX) {\n+\t\tprintf(\"Command failed\\n\");\n+\t\treturn;\n+\t}\n+\n+\tflow_params.m[params->meter_id].cir = params->cir;\n+\tflow_params.m[params->meter_id].pir = params->pir;\n+\tflow_params.m[params->meter_id].cbs = params->cbs;\n+\tflow_params.m[params->meter_id].pbs = params->pbs;\n+\n+\tstatus = app_pipeline_fa_flow_config(app,\n+\t\tparams->pipeline_id,\n+\t\tparams->flow_id,\n+\t\t1 << params->meter_id,\n+\t\t0,\n+\t\t0,\n+\t\t&flow_params);\n+\n+\tif (status != 0)\n+\t\tprintf(\"Command failed\\n\");\n+}\n+\n+cmdline_parse_token_string_t cmd_fa_meter_config_p_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_result,\n+\tp_string, \"p\");\n+\n+cmdline_parse_token_num_t cmd_fa_meter_config_pipeline_id =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result,\n+\tpipeline_id, UINT32);\n+\n+cmdline_parse_token_string_t cmd_fa_meter_config_flow_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_result,\n+\tflow_string, \"flow\");\n+\n+cmdline_parse_token_num_t cmd_fa_meter_config_flow_id =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result,\n+\tflow_id, UINT32);\n+\n+cmdline_parse_token_string_t cmd_fa_meter_config_meter_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_result,\n+\tmeter_string, \"meter\");\n+\n+cmdline_parse_token_num_t cmd_fa_meter_config_meter_id =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result,\n+\tmeter_id, UINT32);\n+\n+cmdline_parse_token_string_t cmd_fa_meter_config_trtcm_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_result,\n+\ttrtcm_string, \"trtcm\");\n+\n+cmdline_parse_token_num_t cmd_fa_meter_config_cir =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result, cir, UINT64);\n+\n+cmdline_parse_token_num_t cmd_fa_meter_config_pir =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result, pir, UINT64);\n+\n+cmdline_parse_token_num_t cmd_fa_meter_config_cbs =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result, cbs, UINT64);\n+\n+cmdline_parse_token_num_t cmd_fa_meter_config_pbs =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result, pbs, UINT64);\n+\n+cmdline_parse_inst_t cmd_fa_meter_config = {\n+\t.f = cmd_fa_meter_config_parsed,\n+\t.data = NULL,\n+\t.help_str = \"Flow meter configuration (single flow) \",\n+\t.tokens = {\n+\t\t(void *) &cmd_fa_meter_config_p_string,\n+\t\t(void *) &cmd_fa_meter_config_pipeline_id,\n+\t\t(void *) &cmd_fa_meter_config_flow_string,\n+\t\t(void *) &cmd_fa_meter_config_flow_id,\n+\t\t(void *) &cmd_fa_meter_config_meter_string,\n+\t\t(void *) &cmd_fa_meter_config_meter_id,\n+\t\t(void *) &cmd_fa_meter_config_trtcm_string,\n+\t\t(void *) &cmd_fa_meter_config_cir,\n+\t\t(void *) &cmd_fa_meter_config_pir,\n+\t\t(void *) &cmd_fa_meter_config_cbs,\n+\t\t(void *) &cmd_fa_meter_config_pbs,\n+\t\tNULL,\n+\t},\n+};\n+\n+/*\n+ * Flow meter configuration (multiple flows)\n+ *\n+ * p <pipeline ID> flows <n_flows> meter <meter ID> trtcm <trtcm params>\n+ */\n+\n+struct cmd_fa_meter_config_bulk_result {\n+\tcmdline_fixed_string_t p_string;\n+\tuint32_t pipeline_id;\n+\tcmdline_fixed_string_t flows_string;\n+\tuint32_t n_flows;\n+\tcmdline_fixed_string_t meter_string;\n+\tuint32_t meter_id;\n+\tcmdline_fixed_string_t trtcm_string;\n+\tuint64_t cir;\n+\tuint64_t pir;\n+\tuint64_t cbs;\n+\tuint64_t pbs;\n+};\n+\n+static void\n+cmd_fa_meter_config_bulk_parsed(\n+\tvoid *parsed_result,\n+\t__rte_unused struct cmdline *cl,\n+\tvoid *data)\n+{\n+\tstruct cmd_fa_meter_config_bulk_result *params = parsed_result;\n+\tstruct app_params *app = data;\n+\tstruct pipeline_fa_flow_params flow_template, *flow_params;\n+\tuint32_t *flow_id;\n+\tuint32_t i;\n+\n+\tif ((params->n_flows == 0) ||\n+\t\t(params->meter_id >= PIPELINE_FA_N_TC_MAX)) {\n+\t\tprintf(\"Invalid arguments\\n\");\n+\t\treturn;\n+\t}\n+\n+\tflow_id = (uint32_t *) rte_malloc(NULL,\n+\t\tN_FLOWS_BULK * sizeof(uint32_t),\n+\t\tRTE_CACHE_LINE_SIZE);\n+\tif (flow_id == NULL) {\n+\t\tprintf(\"Memory allocation failed\\n\");\n+\t\treturn;\n+\t}\n+\n+\tflow_params = (struct pipeline_fa_flow_params *) rte_malloc(NULL,\n+\t\tN_FLOWS_BULK * sizeof(struct pipeline_fa_flow_params),\n+\t\tRTE_CACHE_LINE_SIZE);\n+\tif (flow_params == NULL) {\n+\t\trte_free(flow_id);\n+\t\tprintf(\"Memory allocation failed\\n\");\n+\t\treturn;\n+\t}\n+\n+\tmemset(&flow_template, 0, sizeof(flow_template));\n+\tflow_template.m[params->meter_id].cir = params->cir;\n+\tflow_template.m[params->meter_id].pir = params->pir;\n+\tflow_template.m[params->meter_id].cbs = params->cbs;\n+\tflow_template.m[params->meter_id].pbs = params->pbs;\n+\n+\tfor (i = 0; i < params->n_flows; i++) {\n+\t\tuint32_t pos = i % N_FLOWS_BULK;\n+\n+\t\tflow_id[pos] = i;\n+\t\tmemcpy(&flow_params[pos],\n+\t\t\t&flow_template,\n+\t\t\tsizeof(flow_template));\n+\n+\t\tif ((pos == N_FLOWS_BULK - 1) ||\n+\t\t\t(i == params->n_flows - 1)) {\n+\t\t\tint status;\n+\n+\t\t\tstatus = app_pipeline_fa_flow_config_bulk(app,\n+\t\t\t\tparams->pipeline_id,\n+\t\t\t\tflow_id,\n+\t\t\t\tpos + 1,\n+\t\t\t\t1 << params->meter_id,\n+\t\t\t\t0,\n+\t\t\t\t0,\n+\t\t\t\tflow_params);\n+\n+\t\t\tif (status != 0) {\n+\t\t\t\tprintf(\"Command failed\\n\");\n+\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\trte_free(flow_params);\n+\trte_free(flow_id);\n+\n+}\n+\n+cmdline_parse_token_string_t cmd_fa_meter_config_bulk_p_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_bulk_result,\n+\tp_string, \"p\");\n+\n+cmdline_parse_token_num_t cmd_fa_meter_config_bulk_pipeline_id =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result,\n+\tpipeline_id, UINT32);\n+\n+cmdline_parse_token_string_t cmd_fa_meter_config_bulk_flows_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_bulk_result,\n+\tflows_string, \"flows\");\n+\n+cmdline_parse_token_num_t cmd_fa_meter_config_bulk_n_flows =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result,\n+\tn_flows, UINT32);\n+\n+cmdline_parse_token_string_t cmd_fa_meter_config_bulk_meter_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_bulk_result,\n+\tmeter_string, \"meter\");\n+\n+cmdline_parse_token_num_t cmd_fa_meter_config_bulk_meter_id =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result,\n+\tmeter_id, UINT32);\n+\n+cmdline_parse_token_string_t cmd_fa_meter_config_bulk_trtcm_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_bulk_result,\n+\ttrtcm_string, \"trtcm\");\n+\n+cmdline_parse_token_num_t cmd_fa_meter_config_bulk_cir =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result,\n+\tcir, UINT64);\n+\n+cmdline_parse_token_num_t cmd_fa_meter_config_bulk_pir =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result,\n+\tpir, UINT64);\n+\n+cmdline_parse_token_num_t cmd_fa_meter_config_bulk_cbs =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result,\n+\tcbs, UINT64);\n+\n+cmdline_parse_token_num_t cmd_fa_meter_config_bulk_pbs =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result,\n+\tpbs, UINT64);\n+\n+cmdline_parse_inst_t cmd_fa_meter_config_bulk = {\n+\t.f = cmd_fa_meter_config_bulk_parsed,\n+\t.data = NULL,\n+\t.help_str = \"Flow meter configuration (multiple flows)\",\n+\t.tokens = {\n+\t\t(void *) &cmd_fa_meter_config_bulk_p_string,\n+\t\t(void *) &cmd_fa_meter_config_bulk_pipeline_id,\n+\t\t(void *) &cmd_fa_meter_config_bulk_flows_string,\n+\t\t(void *) &cmd_fa_meter_config_bulk_n_flows,\n+\t\t(void *) &cmd_fa_meter_config_bulk_meter_string,\n+\t\t(void *) &cmd_fa_meter_config_bulk_meter_id,\n+\t\t(void *) &cmd_fa_meter_config_bulk_trtcm_string,\n+\t\t(void *) &cmd_fa_meter_config_cir,\n+\t\t(void *) &cmd_fa_meter_config_pir,\n+\t\t(void *) &cmd_fa_meter_config_cbs,\n+\t\t(void *) &cmd_fa_meter_config_pbs,\n+\t\tNULL,\n+\t},\n+};\n+\n+/*\n+ * Flow policer configuration (single flow)\n+ *\n+ * p <pipeline ID> flow <flow ID> policer <policer ID>\n+ *    G <action> Y <action> R <action>\n+ *\n+ * <action> = G (green) | Y (yellow) | R (red) | D (drop)\n+ */\n+\n+struct cmd_fa_policer_config_result {\n+\tcmdline_fixed_string_t p_string;\n+\tuint32_t pipeline_id;\n+\tcmdline_fixed_string_t flow_string;\n+\tuint32_t flow_id;\n+\tcmdline_fixed_string_t policer_string;\n+\tuint32_t policer_id;\n+\tcmdline_fixed_string_t green_string;\n+\tcmdline_fixed_string_t g_action;\n+\tcmdline_fixed_string_t yellow_string;\n+\tcmdline_fixed_string_t y_action;\n+\tcmdline_fixed_string_t red_string;\n+\tcmdline_fixed_string_t r_action;\n+};\n+\n+static void\n+cmd_fa_policer_config_parsed(\n+\tvoid *parsed_result,\n+\t__rte_unused struct cmdline *cl,\n+\tvoid *data)\n+{\n+\tstruct cmd_fa_policer_config_result *params = parsed_result;\n+\tstruct app_params *app = data;\n+\tstruct pipeline_fa_flow_params flow_params;\n+\tint status;\n+\n+\tif (params->policer_id >= PIPELINE_FA_N_TC_MAX) {\n+\t\tprintf(\"Command failed\\n\");\n+\t\treturn;\n+\t}\n+\n+\tstatus = string_to_policer_action(params->g_action,\n+\t\t&flow_params.p[params->policer_id].action[e_RTE_METER_GREEN]);\n+\tif (status)\n+\t\tprintf(\"Invalid policer green action\\n\");\n+\n+\tstatus = string_to_policer_action(params->y_action,\n+\t\t&flow_params.p[params->policer_id].action[e_RTE_METER_YELLOW]);\n+\tif (status)\n+\t\tprintf(\"Invalid policer yellow action\\n\");\n+\n+\tstatus = string_to_policer_action(params->r_action,\n+\t\t&flow_params.p[params->policer_id].action[e_RTE_METER_RED]);\n+\tif (status)\n+\t\tprintf(\"Invalid policer red action\\n\");\n+\n+\tstatus = app_pipeline_fa_flow_config(app,\n+\t\tparams->pipeline_id,\n+\t\tparams->flow_id,\n+\t\t0,\n+\t\t1 << params->policer_id,\n+\t\t0,\n+\t\t&flow_params);\n+\n+\tif (status != 0)\n+\t\tprintf(\"Command failed\\n\");\n+\n+}\n+\n+cmdline_parse_token_string_t cmd_fa_policer_config_p_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,\n+\tp_string, \"p\");\n+\n+cmdline_parse_token_num_t cmd_fa_policer_config_pipeline_id =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_result,\n+\tpipeline_id, UINT32);\n+\n+cmdline_parse_token_string_t cmd_fa_policer_config_flow_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,\n+\tflow_string, \"flow\");\n+\n+cmdline_parse_token_num_t cmd_fa_policer_config_flow_id =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_result,\n+\tflow_id, UINT32);\n+\n+cmdline_parse_token_string_t cmd_fa_policer_config_policer_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,\n+\tpolicer_string, \"policer\");\n+\n+cmdline_parse_token_num_t cmd_fa_policer_config_policer_id =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_result,\n+\tpolicer_id, UINT32);\n+\n+cmdline_parse_token_string_t cmd_fa_policer_config_green_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,\n+\tgreen_string, \"G\");\n+\n+cmdline_parse_token_string_t cmd_fa_policer_config_g_action =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,\n+\tg_action, \"R#Y#G#D\");\n+\n+cmdline_parse_token_string_t cmd_fa_policer_config_yellow_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,\n+\tyellow_string, \"Y\");\n+\n+cmdline_parse_token_string_t cmd_fa_policer_config_y_action =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,\n+\ty_action, \"R#Y#G#D\");\n+\n+cmdline_parse_token_string_t cmd_fa_policer_config_red_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,\n+\tred_string, \"R\");\n+\n+cmdline_parse_token_string_t cmd_fa_policer_config_r_action =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,\n+\tr_action, \"R#Y#G#D\");\n+\n+cmdline_parse_inst_t cmd_fa_policer_config = {\n+\t.f = cmd_fa_policer_config_parsed,\n+\t.data = NULL,\n+\t.help_str = \"Flow policer configuration (single flow)\",\n+\t.tokens = {\n+\t\t(void *) &cmd_fa_policer_config_p_string,\n+\t\t(void *) &cmd_fa_policer_config_pipeline_id,\n+\t\t(void *) &cmd_fa_policer_config_flow_string,\n+\t\t(void *) &cmd_fa_policer_config_flow_id,\n+\t\t(void *) &cmd_fa_policer_config_policer_string,\n+\t\t(void *) &cmd_fa_policer_config_policer_id,\n+\t\t(void *) &cmd_fa_policer_config_green_string,\n+\t\t(void *) &cmd_fa_policer_config_g_action,\n+\t\t(void *) &cmd_fa_policer_config_yellow_string,\n+\t\t(void *) &cmd_fa_policer_config_y_action,\n+\t\t(void *) &cmd_fa_policer_config_red_string,\n+\t\t(void *) &cmd_fa_policer_config_r_action,\n+\t\tNULL,\n+\t},\n+};\n+\n+/*\n+ * Flow policer configuration (multiple flows)\n+ *\n+ * p <pipeline ID> flows <n_flows> policer <policer ID>\n+ *    G <action> Y <action> R <action>\n+ *\n+ * <action> = G (green) | Y (yellow) | R (red) | D (drop)\n+ */\n+\n+struct cmd_fa_policer_config_bulk_result {\n+\tcmdline_fixed_string_t p_string;\n+\tuint32_t pipeline_id;\n+\tcmdline_fixed_string_t flows_string;\n+\tuint32_t n_flows;\n+\tcmdline_fixed_string_t policer_string;\n+\tuint32_t policer_id;\n+\tcmdline_fixed_string_t green_string;\n+\tcmdline_fixed_string_t g_action;\n+\tcmdline_fixed_string_t yellow_string;\n+\tcmdline_fixed_string_t y_action;\n+\tcmdline_fixed_string_t red_string;\n+\tcmdline_fixed_string_t r_action;\n+};\n+\n+static void\n+cmd_fa_policer_config_bulk_parsed(\n+\tvoid *parsed_result,\n+\t__rte_unused struct cmdline *cl,\n+\tvoid *data)\n+{\n+\tstruct cmd_fa_policer_config_bulk_result *params = parsed_result;\n+\tstruct app_params *app = data;\n+\tstruct pipeline_fa_flow_params flow_template, *flow_params;\n+\tuint32_t *flow_id, i;\n+\tint status;\n+\n+\tif ((params->n_flows == 0) ||\n+\t\t(params->policer_id >= PIPELINE_FA_N_TC_MAX)) {\n+\t\tprintf(\"Invalid arguments\\n\");\n+\t\treturn;\n+\t}\n+\n+\tflow_id = (uint32_t *) rte_malloc(NULL,\n+\t\tN_FLOWS_BULK * sizeof(uint32_t),\n+\t\tRTE_CACHE_LINE_SIZE);\n+\tif (flow_id == NULL) {\n+\t\tprintf(\"Memory allocation failed\\n\");\n+\t\treturn;\n+\t}\n+\n+\tflow_params = (struct pipeline_fa_flow_params *) rte_malloc(NULL,\n+\t\tN_FLOWS_BULK * sizeof(struct pipeline_fa_flow_params),\n+\t\tRTE_CACHE_LINE_SIZE);\n+\tif (flow_params == NULL) {\n+\t\trte_free(flow_id);\n+\t\tprintf(\"Memory allocation failed\\n\");\n+\t\treturn;\n+\t}\n+\n+\tmemset(&flow_template, 0, sizeof(flow_template));\n+\n+\tstatus = string_to_policer_action(params->g_action,\n+\t\t&flow_template.p[params->policer_id].action[e_RTE_METER_GREEN]);\n+\tif (status)\n+\t\tprintf(\"Invalid policer green action\\n\");\n+\n+\tstatus = string_to_policer_action(params->y_action,\n+\t &flow_template.p[params->policer_id].action[e_RTE_METER_YELLOW]);\n+\tif (status)\n+\t\tprintf(\"Invalid policer yellow action\\n\");\n+\n+\tstatus = string_to_policer_action(params->r_action,\n+\t\t&flow_template.p[params->policer_id].action[e_RTE_METER_RED]);\n+\tif (status)\n+\t\tprintf(\"Invalid policer red action\\n\");\n+\n+\tfor (i = 0; i < params->n_flows; i++) {\n+\t\tuint32_t pos = i % N_FLOWS_BULK;\n+\n+\t\tflow_id[pos] = i;\n+\t\tmemcpy(&flow_params[pos], &flow_template,\n+\t\t\tsizeof(flow_template));\n+\n+\t\tif ((pos == N_FLOWS_BULK - 1) ||\n+\t\t\t(i == params->n_flows - 1)) {\n+\t\t\tint status;\n+\n+\t\t\tstatus = app_pipeline_fa_flow_config_bulk(app,\n+\t\t\t\tparams->pipeline_id,\n+\t\t\t\tflow_id,\n+\t\t\t\tpos + 1,\n+\t\t\t\t0,\n+\t\t\t\t1 << params->policer_id,\n+\t\t\t\t0,\n+\t\t\t\tflow_params);\n+\n+\t\t\tif (status != 0) {\n+\t\t\t\tprintf(\"Command failed\\n\");\n+\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\trte_free(flow_params);\n+\trte_free(flow_id);\n+\n+}\n+\n+cmdline_parse_token_string_t cmd_fa_policer_config_bulk_p_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,\n+\tp_string, \"p\");\n+\n+cmdline_parse_token_num_t cmd_fa_policer_config_bulk_pipeline_id =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_bulk_result,\n+\tpipeline_id, UINT32);\n+\n+cmdline_parse_token_string_t cmd_fa_policer_config_bulk_flows_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,\n+\tflows_string, \"flows\");\n+\n+cmdline_parse_token_num_t cmd_fa_policer_config_bulk_n_flows =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_bulk_result,\n+\tn_flows, UINT32);\n+\n+cmdline_parse_token_string_t cmd_fa_policer_config_bulk_policer_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,\n+\tpolicer_string, \"policer\");\n+\n+cmdline_parse_token_num_t cmd_fa_policer_config_bulk_policer_id =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_bulk_result,\n+\tpolicer_id, UINT32);\n+\n+cmdline_parse_token_string_t cmd_fa_policer_config_bulk_green_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,\n+\tgreen_string, \"G\");\n+\n+cmdline_parse_token_string_t cmd_fa_policer_config_bulk_g_action =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,\n+\tg_action, \"R#Y#G#D\");\n+\n+cmdline_parse_token_string_t cmd_fa_policer_config_bulk_yellow_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,\n+\tyellow_string, \"Y\");\n+\n+cmdline_parse_token_string_t cmd_fa_policer_config_bulk_y_action =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,\n+\ty_action, \"R#Y#G#D\");\n+\n+cmdline_parse_token_string_t cmd_fa_policer_config_bulk_red_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,\n+\tred_string, \"R\");\n+\n+cmdline_parse_token_string_t cmd_fa_policer_config_bulk_r_action =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,\n+\tr_action, \"R#Y#G#D\");\n+\n+cmdline_parse_inst_t cmd_fa_policer_config_bulk = {\n+\t.f = cmd_fa_policer_config_bulk_parsed,\n+\t.data = NULL,\n+\t.help_str = \"Flow policer configuration (multiple flows)\",\n+\t.tokens = {\n+\t\t(void *) &cmd_fa_policer_config_bulk_p_string,\n+\t\t(void *) &cmd_fa_policer_config_bulk_pipeline_id,\n+\t\t(void *) &cmd_fa_policer_config_bulk_flows_string,\n+\t\t(void *) &cmd_fa_policer_config_bulk_n_flows,\n+\t\t(void *) &cmd_fa_policer_config_bulk_policer_string,\n+\t\t(void *) &cmd_fa_policer_config_bulk_policer_id,\n+\t\t(void *) &cmd_fa_policer_config_bulk_green_string,\n+\t\t(void *) &cmd_fa_policer_config_bulk_g_action,\n+\t\t(void *) &cmd_fa_policer_config_bulk_yellow_string,\n+\t\t(void *) &cmd_fa_policer_config_bulk_y_action,\n+\t\t(void *) &cmd_fa_policer_config_bulk_red_string,\n+\t\t(void *) &cmd_fa_policer_config_bulk_r_action,\n+\t\tNULL,\n+\t},\n+};\n+\n+/*\n+ * Flow output port configuration (single flow)\n+ *\n+ * p <pipeline ID> flow <flow ID> port <port ID>\n+ */\n+\n+struct cmd_fa_output_port_config_result {\n+\tcmdline_fixed_string_t p_string;\n+\tuint32_t pipeline_id;\n+\tcmdline_fixed_string_t flow_string;\n+\tuint32_t flow_id;\n+\tcmdline_fixed_string_t port_string;\n+\tuint32_t port_id;\n+};\n+\n+static void\n+cmd_fa_output_port_config_parsed(\n+\tvoid *parsed_result,\n+\t__rte_unused struct cmdline *cl,\n+\tvoid *data)\n+{\n+\tstruct cmd_fa_output_port_config_result *params = parsed_result;\n+\tstruct app_params *app = data;\n+\tstruct pipeline_fa_flow_params flow_params;\n+\tint status;\n+\n+\tflow_params.port_id = params->port_id;\n+\n+\tstatus = app_pipeline_fa_flow_config(app,\n+\t\tparams->pipeline_id,\n+\t\tparams->flow_id,\n+\t\t0,\n+\t\t0,\n+\t\t1,\n+\t\t&flow_params);\n+\n+\tif (status != 0)\n+\t\tprintf(\"Command failed\\n\");\n+}\n+\n+cmdline_parse_token_string_t cmd_fa_output_port_config_p_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_result,\n+\tp_string, \"p\");\n+\n+cmdline_parse_token_num_t cmd_fa_output_port_config_pipeline_id =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_result,\n+\tpipeline_id, UINT32);\n+\n+cmdline_parse_token_string_t cmd_fa_output_port_config_flow_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_result,\n+\tflow_string, \"flow\");\n+\n+cmdline_parse_token_num_t cmd_fa_output_port_config_flow_id =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_result,\n+\tflow_id, UINT32);\n+\n+cmdline_parse_token_string_t cmd_fa_output_port_config_port_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_result,\n+\tport_string, \"port\");\n+\n+cmdline_parse_token_num_t cmd_fa_output_port_config_port_id =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_result,\n+\tport_id, UINT32);\n+\n+cmdline_parse_inst_t cmd_fa_output_port_config = {\n+\t.f = cmd_fa_output_port_config_parsed,\n+\t.data = NULL,\n+\t.help_str = \"Flow output port configuration (single flow)\",\n+\t.tokens = {\n+\t\t(void *) &cmd_fa_output_port_config_p_string,\n+\t\t(void *) &cmd_fa_output_port_config_pipeline_id,\n+\t\t(void *) &cmd_fa_output_port_config_flow_string,\n+\t\t(void *) &cmd_fa_output_port_config_flow_id,\n+\t\t(void *) &cmd_fa_output_port_config_port_string,\n+\t\t(void *) &cmd_fa_output_port_config_port_id,\n+\t\tNULL,\n+\t},\n+};\n+\n+/*\n+ * Flow output port configuration (multiple flows)\n+ *\n+ * p <pipeline ID> flows <n_flows> ports <n_ports>\n+ */\n+\n+struct cmd_fa_output_port_config_bulk_result {\n+\tcmdline_fixed_string_t p_string;\n+\tuint32_t pipeline_id;\n+\tcmdline_fixed_string_t flows_string;\n+\tuint32_t n_flows;\n+\tcmdline_fixed_string_t ports_string;\n+\tuint32_t n_ports;\n+};\n+\n+static void\n+cmd_fa_output_port_config_bulk_parsed(\n+\tvoid *parsed_result,\n+\t__rte_unused struct cmdline *cl,\n+\tvoid *data)\n+{\n+\tstruct cmd_fa_output_port_config_bulk_result *params = parsed_result;\n+\tstruct app_params *app = data;\n+\tstruct pipeline_fa_flow_params *flow_params;\n+\tuint32_t *flow_id;\n+\tuint32_t i;\n+\n+\tif (params->n_flows == 0) {\n+\t\tprintf(\"Invalid arguments\\n\");\n+\t\treturn;\n+\t}\n+\n+\tflow_id = (uint32_t *) rte_malloc(NULL,\n+\t\tN_FLOWS_BULK * sizeof(uint32_t),\n+\t\tRTE_CACHE_LINE_SIZE);\n+\tif (flow_id == NULL) {\n+\t\tprintf(\"Memory allocation failed\\n\");\n+\t\treturn;\n+\t}\n+\n+\tflow_params = (struct pipeline_fa_flow_params *) rte_malloc(NULL,\n+\t\tN_FLOWS_BULK * sizeof(struct pipeline_fa_flow_params),\n+\t\tRTE_CACHE_LINE_SIZE);\n+\tif (flow_params == NULL) {\n+\t\trte_free(flow_id);\n+\t\tprintf(\"Memory allocation failed\\n\");\n+\t\treturn;\n+\t}\n+\n+\tfor (i = 0; i < params->n_flows; i++) {\n+\t\tuint32_t pos = i % N_FLOWS_BULK;\n+\t\tuint32_t port_id = i % params->n_ports;\n+\n+\t\tflow_id[pos] = i;\n+\n+\t\tmemset(&flow_params[pos], 0, sizeof(flow_params[pos]));\n+\t\tflow_params[pos].port_id = port_id;\n+\n+\t\tif ((pos == N_FLOWS_BULK - 1) ||\n+\t\t\t(i == params->n_flows - 1)) {\n+\t\t\tint status;\n+\n+\t\t\tstatus = app_pipeline_fa_flow_config_bulk(app,\n+\t\t\t\tparams->pipeline_id,\n+\t\t\t\tflow_id,\n+\t\t\t\tpos + 1,\n+\t\t\t\t0,\n+\t\t\t\t0,\n+\t\t\t\t1,\n+\t\t\t\tflow_params);\n+\n+\t\t\tif (status != 0) {\n+\t\t\t\tprintf(\"Command failed\\n\");\n+\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\trte_free(flow_params);\n+\trte_free(flow_id);\n+\n+}\n+\n+cmdline_parse_token_string_t cmd_fa_output_port_config_bulk_p_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_bulk_result,\n+\tp_string, \"p\");\n+\n+cmdline_parse_token_num_t cmd_fa_output_port_config_bulk_pipeline_id =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_bulk_result,\n+\tpipeline_id, UINT32);\n+\n+cmdline_parse_token_string_t cmd_fa_output_port_config_bulk_flows_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_bulk_result,\n+\tflows_string, \"flows\");\n+\n+cmdline_parse_token_num_t cmd_fa_output_port_config_bulk_n_flows =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_bulk_result,\n+\tn_flows, UINT32);\n+\n+cmdline_parse_token_string_t cmd_fa_output_port_config_bulk_ports_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_bulk_result,\n+\tports_string, \"ports\");\n+\n+cmdline_parse_token_num_t cmd_fa_output_port_config_bulk_n_ports =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_bulk_result,\n+\tn_ports, UINT32);\n+\n+cmdline_parse_inst_t cmd_fa_output_port_config_bulk = {\n+\t.f = cmd_fa_output_port_config_bulk_parsed,\n+\t.data = NULL,\n+\t.help_str = \"Flow output port configuration (multiple flows)\",\n+\t.tokens = {\n+\t\t(void *) &cmd_fa_output_port_config_bulk_p_string,\n+\t\t(void *) &cmd_fa_output_port_config_bulk_pipeline_id,\n+\t\t(void *) &cmd_fa_output_port_config_bulk_flows_string,\n+\t\t(void *) &cmd_fa_output_port_config_bulk_n_flows,\n+\t\t(void *) &cmd_fa_output_port_config_bulk_ports_string,\n+\t\t(void *) &cmd_fa_output_port_config_bulk_n_ports,\n+\t\tNULL,\n+\t},\n+};\n+\n+/*\n+ * Flow DiffServ Code Point (DSCP) translation table configuration\n+ *\n+ * p <pipeline ID> dscp <DSCP ID> class <traffic class ID> color <color>\n+ *\n+ * <color> = G (green) | Y (yellow) | R (red)\n+*/\n+\n+struct cmd_fa_dscp_config_result {\n+\tcmdline_fixed_string_t p_string;\n+\tuint32_t pipeline_id;\n+\tcmdline_fixed_string_t dscp_string;\n+\tuint32_t dscp_id;\n+\tcmdline_fixed_string_t class_string;\n+\tuint32_t traffic_class_id;\n+\tcmdline_fixed_string_t color_string;\n+\tcmdline_fixed_string_t color;\n+\n+};\n+\n+static void\n+cmd_fa_dscp_config_parsed(\n+\tvoid *parsed_result,\n+\t__rte_unused struct cmdline *cl,\n+\tvoid *data)\n+{\n+\tstruct cmd_fa_dscp_config_result *params = parsed_result;\n+\tstruct app_params *app = data;\n+\tenum rte_meter_color color;\n+\tint status;\n+\n+\tstatus = string_to_color(params->color, &color);\n+\tif (status) {\n+\t\tprintf(\"Invalid color\\n\");\n+\t\treturn;\n+\t}\n+\n+\tstatus = app_pipeline_fa_dscp_config(app,\n+\t\tparams->pipeline_id,\n+\t\tparams->dscp_id,\n+\t\tparams->traffic_class_id,\n+\t\tcolor);\n+\n+\tif (status != 0)\n+\t\tprintf(\"Command failed\\n\");\n+}\n+\n+cmdline_parse_token_string_t cmd_fa_dscp_config_p_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_config_result,\n+\tp_string, \"p\");\n+\n+cmdline_parse_token_num_t cmd_fa_dscp_config_pipeline_id =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_dscp_config_result,\n+\tpipeline_id, UINT32);\n+\n+cmdline_parse_token_string_t cmd_fa_dscp_config_dscp_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_config_result,\n+\tdscp_string, \"dscp\");\n+\n+cmdline_parse_token_num_t cmd_fa_dscp_config_dscp_id =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_dscp_config_result,\n+\tdscp_id, UINT32);\n+\n+cmdline_parse_token_string_t cmd_fa_dscp_config_class_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_config_result,\n+\tclass_string, \"class\");\n+\n+cmdline_parse_token_num_t cmd_fa_dscp_config_traffic_class_id =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_dscp_config_result,\n+\ttraffic_class_id, UINT32);\n+\n+cmdline_parse_token_string_t cmd_fa_dscp_config_color_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_config_result,\n+\tcolor_string, \"color\");\n+\n+cmdline_parse_token_string_t cmd_fa_dscp_config_color =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_config_result,\n+\tcolor, \"G#Y#R\");\n+\n+cmdline_parse_inst_t cmd_fa_dscp_config = {\n+\t.f = cmd_fa_dscp_config_parsed,\n+\t.data = NULL,\n+\t.help_str = \"Flow DSCP translation table configuration\",\n+\t.tokens = {\n+\t\t(void *) &cmd_fa_dscp_config_p_string,\n+\t\t(void *) &cmd_fa_dscp_config_pipeline_id,\n+\t\t(void *) &cmd_fa_dscp_config_dscp_string,\n+\t\t(void *) &cmd_fa_dscp_config_dscp_id,\n+\t\t(void *) &cmd_fa_dscp_config_class_string,\n+\t\t(void *) &cmd_fa_dscp_config_traffic_class_id,\n+\t\t(void *) &cmd_fa_dscp_config_color_string,\n+\t\t(void *) &cmd_fa_dscp_config_color,\n+\t\tNULL,\n+\t},\n+};\n+\n+/*\n+ * Flow policer stats read\n+ *\n+ * p <pipeline ID> flow <flow ID> policer <policer ID> stats\n+ */\n+\n+struct cmd_fa_policer_stats_result {\n+\tcmdline_fixed_string_t p_string;\n+\tuint32_t pipeline_id;\n+\tcmdline_fixed_string_t flow_string;\n+\tuint32_t flow_id;\n+\tcmdline_fixed_string_t policer_string;\n+\tuint32_t policer_id;\n+\tcmdline_fixed_string_t stats_string;\n+};\n+\n+static void\n+cmd_fa_policer_stats_parsed(\n+\tvoid *parsed_result,\n+\t__rte_unused struct cmdline *cl,\n+\tvoid *data)\n+{\n+\tstruct cmd_fa_policer_stats_result *params = parsed_result;\n+\tstruct app_params *app = data;\n+\tstruct pipeline_fa_policer_stats stats;\n+\tint status;\n+\n+\tstatus = app_pipeline_fa_flow_policer_stats_read(app,\n+\t\tparams->pipeline_id,\n+\t\tparams->flow_id,\n+\t\tparams->policer_id,\n+\t\t1,\n+\t\t&stats);\n+\tif (status != 0) {\n+\t\tprintf(\"Command failed\\n\");\n+\t\treturn;\n+\t}\n+\n+\t/* Display stats */\n+\tprintf(\"\\tPkts G: %\" PRIu64\n+\t\t\"\\tPkts Y: %\" PRIu64\n+\t\t\"\\tPkts R: %\" PRIu64\n+\t\t\"\\tPkts D: %\" PRIu64 \"\\n\",\n+\t\tstats.n_pkts[e_RTE_METER_GREEN],\n+\t\tstats.n_pkts[e_RTE_METER_YELLOW],\n+\t\tstats.n_pkts[e_RTE_METER_RED],\n+\t\tstats.n_pkts_drop);\n+}\n+\n+cmdline_parse_token_string_t cmd_fa_policer_stats_p_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_policer_stats_result,\n+\tp_string, \"p\");\n+\n+cmdline_parse_token_num_t cmd_fa_policer_stats_pipeline_id =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_policer_stats_result,\n+\tpipeline_id, UINT32);\n+\n+cmdline_parse_token_string_t cmd_fa_policer_stats_flow_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_policer_stats_result,\n+\tflow_string, \"flow\");\n+\n+cmdline_parse_token_num_t cmd_fa_policer_stats_flow_id =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_policer_stats_result,\n+\tflow_id, UINT32);\n+\n+cmdline_parse_token_string_t cmd_fa_policer_stats_policer_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_policer_stats_result,\n+\tpolicer_string, \"policer\");\n+\n+cmdline_parse_token_num_t cmd_fa_policer_stats_policer_id =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_policer_stats_result,\n+\tpolicer_id, UINT32);\n+\n+cmdline_parse_token_string_t cmd_fa_policer_stats_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_policer_stats_result,\n+\tstats_string, \"stats\");\n+\n+cmdline_parse_inst_t cmd_fa_policer_stats = {\n+\t.f = cmd_fa_policer_stats_parsed,\n+\t.data = NULL,\n+\t.help_str = \"Flow policer stats read\",\n+\t.tokens = {\n+\t\t(void *) &cmd_fa_policer_stats_p_string,\n+\t\t(void *) &cmd_fa_policer_stats_pipeline_id,\n+\t\t(void *) &cmd_fa_policer_stats_flow_string,\n+\t\t(void *) &cmd_fa_policer_stats_flow_id,\n+\t\t(void *) &cmd_fa_policer_stats_policer_string,\n+\t\t(void *) &cmd_fa_policer_stats_policer_id,\n+\t\t(void *) &cmd_fa_policer_stats_string,\n+\t\tNULL,\n+\t},\n+};\n+\n+/*\n+ * Flow list\n+ *\n+ * p <pipeline ID> flow ls\n+ */\n+\n+struct cmd_fa_flow_ls_result {\n+\tcmdline_fixed_string_t p_string;\n+\tuint32_t pipeline_id;\n+\tcmdline_fixed_string_t flow_string;\n+\tcmdline_fixed_string_t actions_string;\n+\tcmdline_fixed_string_t ls_string;\n+};\n+\n+static void\n+cmd_fa_flow_ls_parsed(\n+\tvoid *parsed_result,\n+\t__rte_unused struct cmdline *cl,\n+\tvoid *data)\n+{\n+\tstruct cmd_fa_flow_ls_result *params = parsed_result;\n+\tstruct app_params *app = data;\n+\tint status;\n+\n+\tstatus = app_pipeline_fa_flow_ls(app, params->pipeline_id);\n+\tif (status != 0)\n+\t\tprintf(\"Command failed\\n\");\n+}\n+\n+cmdline_parse_token_string_t cmd_fa_flow_ls_p_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_flow_ls_result,\n+\tp_string, \"p\");\n+\n+cmdline_parse_token_num_t cmd_fa_flow_ls_pipeline_id =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_flow_ls_result,\n+\tpipeline_id, UINT32);\n+\n+cmdline_parse_token_string_t cmd_fa_flow_ls_flow_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_flow_ls_result,\n+\tflow_string, \"flow\");\n+\n+cmdline_parse_token_string_t cmd_fa_flow_ls_actions_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_flow_ls_result,\n+\tactions_string, \"actions\");\n+\n+cmdline_parse_token_string_t cmd_fa_flow_ls_ls_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_flow_ls_result,\n+\tls_string, \"ls\");\n+\n+cmdline_parse_inst_t cmd_fa_flow_ls = {\n+\t.f = cmd_fa_flow_ls_parsed,\n+\t.data = NULL,\n+\t.help_str = \"Flow actions list\",\n+\t.tokens = {\n+\t\t(void *) &cmd_fa_flow_ls_p_string,\n+\t\t(void *) &cmd_fa_flow_ls_pipeline_id,\n+\t\t(void *) &cmd_fa_flow_ls_flow_string,\n+\t\t(void *) &cmd_fa_flow_ls_actions_string,\n+\t\t(void *) &cmd_fa_flow_ls_ls_string,\n+\t\tNULL,\n+\t},\n+};\n+\n+/*\n+ * Flow DiffServ Code Point (DSCP) translation table list\n+ *\n+ * p <pipeline ID> dscp ls\n+ */\n+\n+struct cmd_fa_dscp_ls_result {\n+\tcmdline_fixed_string_t p_string;\n+\tuint32_t pipeline_id;\n+\tcmdline_fixed_string_t dscp_string;\n+\tcmdline_fixed_string_t ls_string;\n+};\n+\n+static void\n+cmd_fa_dscp_ls_parsed(\n+\tvoid *parsed_result,\n+\t__rte_unused struct cmdline *cl,\n+\tvoid *data)\n+{\n+\tstruct cmd_fa_dscp_ls_result *params = parsed_result;\n+\tstruct app_params *app = data;\n+\tint status;\n+\n+\tstatus = app_pipeline_fa_dscp_ls(app, params->pipeline_id);\n+\tif (status != 0)\n+\t\tprintf(\"Command failed\\n\");\n+}\n+\n+cmdline_parse_token_string_t cmd_fa_dscp_ls_p_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_ls_result,\n+\tp_string, \"p\");\n+\n+cmdline_parse_token_num_t cmd_fa_dscp_ls_pipeline_id =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_fa_dscp_ls_result,\n+\tpipeline_id, UINT32);\n+\n+cmdline_parse_token_string_t cmd_fa_dscp_ls_dscp_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_ls_result,\n+\tdscp_string, \"dscp\");\n+\n+cmdline_parse_token_string_t cmd_fa_dscp_ls_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_ls_result, ls_string,\n+\t\"ls\");\n+\n+cmdline_parse_inst_t cmd_fa_dscp_ls = {\n+\t.f = cmd_fa_dscp_ls_parsed,\n+\t.data = NULL,\n+\t.help_str = \"Flow DSCP translaton table list\",\n+\t.tokens = {\n+\t\t(void *) &cmd_fa_dscp_ls_p_string,\n+\t\t(void *) &cmd_fa_dscp_ls_pipeline_id,\n+\t\t(void *) &cmd_fa_dscp_ls_dscp_string,\n+\t\t(void *) &cmd_fa_dscp_ls_string,\n+\t\tNULL,\n+\t},\n+};\n+\n+static cmdline_parse_ctx_t pipeline_cmds[] = {\n+\t(cmdline_parse_inst_t *) &cmd_fa_meter_config,\n+\t(cmdline_parse_inst_t *) &cmd_fa_meter_config_bulk,\n+\t(cmdline_parse_inst_t *) &cmd_fa_policer_config,\n+\t(cmdline_parse_inst_t *) &cmd_fa_policer_config_bulk,\n+\t(cmdline_parse_inst_t *) &cmd_fa_output_port_config,\n+\t(cmdline_parse_inst_t *) &cmd_fa_output_port_config_bulk,\n+\t(cmdline_parse_inst_t *) &cmd_fa_dscp_config,\n+\t(cmdline_parse_inst_t *) &cmd_fa_policer_stats,\n+\t(cmdline_parse_inst_t *) &cmd_fa_flow_ls,\n+\t(cmdline_parse_inst_t *) &cmd_fa_dscp_ls,\n+\tNULL,\n+};\n+\n+static struct pipeline_fe_ops pipeline_flow_actions_fe_ops = {\n+\t.f_init = app_pipeline_fa_init,\n+\t.f_free = app_pipeline_fa_free,\n+\t.cmds = pipeline_cmds,\n+};\n+\n+struct pipeline_type pipeline_flow_actions = {\n+\t.name = \"FLOW_ACTIONS\",\n+\t.be_ops = &pipeline_flow_actions_be_ops,\n+\t.fe_ops = &pipeline_flow_actions_fe_ops,\n+};\ndiff --git a/examples/ip_pipeline/pipeline/pipeline_flow_actions.h b/examples/ip_pipeline/pipeline/pipeline_flow_actions.h\nnew file mode 100644\nindex 0000000..f2cd0cb\n--- /dev/null\n+++ b/examples/ip_pipeline/pipeline/pipeline_flow_actions.h\n@@ -0,0 +1,78 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.\n+ *   All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   modification, are permitted provided that the following conditions\n+ *   are met:\n+ *\n+ *     * Redistributions of source code must retain the above copyright\n+ *       notice, this list of conditions and the following disclaimer.\n+ *     * Redistributions in binary form must reproduce the above copyright\n+ *       notice, this list of conditions and the following disclaimer in\n+ *       the documentation and/or other materials provided with the\n+ *       distribution.\n+ *     * Neither the name of Intel Corporation nor the names of its\n+ *       contributors may be used to endorse or promote products derived\n+ *       from this software without specific prior written permission.\n+ *\n+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+ *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+#ifndef __INCLUDE_PIPELINE_FLOW_ACTIONS_H__\n+#define __INCLUDE_PIPELINE_FLOW_ACTIONS_H__\n+\n+#include <rte_meter.h>\n+\n+#include \"pipeline.h\"\n+#include \"pipeline_flow_actions_be.h\"\n+\n+int\n+app_pipeline_fa_flow_config(struct app_params *app,\n+\tuint32_t pipeline_id,\n+\tuint32_t flow_id,\n+\tuint32_t meter_update_mask,\n+\tuint32_t policer_update_mask,\n+\tuint32_t port_update,\n+\tstruct pipeline_fa_flow_params *params);\n+\n+int\n+app_pipeline_fa_flow_config_bulk(struct app_params *app,\n+\tuint32_t pipeline_id,\n+\tuint32_t *flow_id,\n+\tuint32_t n_flows,\n+\tuint32_t meter_update_mask,\n+\tuint32_t policer_update_mask,\n+\tuint32_t port_update,\n+\tstruct pipeline_fa_flow_params *params);\n+\n+int\n+app_pipeline_fa_dscp_config(struct app_params *app,\n+\tuint32_t pipeline_id,\n+\tuint32_t dscp,\n+\tuint32_t traffic_class,\n+\tenum rte_meter_color color);\n+\n+int\n+app_pipeline_fa_flow_policer_stats_read(struct app_params *app,\n+\tuint32_t pipeline_id,\n+\tuint32_t flow_id,\n+\tuint32_t policer_id,\n+\tint clear,\n+\tstruct pipeline_fa_policer_stats *stats);\n+\n+extern struct pipeline_type pipeline_flow_actions;\n+\n+#endif\ndiff --git a/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c b/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c\nnew file mode 100644\nindex 0000000..73dbe7a\n--- /dev/null\n+++ b/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c\n@@ -0,0 +1,973 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.\n+ *   All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   modification, are permitted provided that the following conditions\n+ *   are met:\n+ *\n+ *     * Redistributions of source code must retain the above copyright\n+ *       notice, this list of conditions and the following disclaimer.\n+ *     * Redistributions in binary form must reproduce the above copyright\n+ *       notice, this list of conditions and the following disclaimer in\n+ *       the documentation and/or other materials provided with the\n+ *       distribution.\n+ *     * Neither the name of Intel Corporation nor the names of its\n+ *       contributors may be used to endorse or promote products derived\n+ *       from this software without specific prior written permission.\n+ *\n+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+ *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+#include <string.h>\n+\n+#include <rte_common.h>\n+#include <rte_malloc.h>\n+#include <rte_cycles.h>\n+#include <rte_table_array.h>\n+#include <rte_byteorder.h>\n+#include <rte_ip.h>\n+\n+#include \"pipeline_actions_common.h\"\n+#include \"pipeline_flow_actions_be.h\"\n+#include \"hash_func.h\"\n+\n+int\n+pipeline_fa_flow_params_set_default(struct pipeline_fa_flow_params *params)\n+{\n+\tuint32_t i;\n+\n+\tif (params == NULL)\n+\t\treturn -1;\n+\n+\tfor (i = 0; i < PIPELINE_FA_N_TC_MAX; i++) {\n+\t\tstruct rte_meter_trtcm_params *m = &params->m[i];\n+\n+\t\tm->cir = 1;\n+\t\tm->cbs = 1;\n+\t\tm->pir = 1;\n+\t\tm->pbs = 2;\n+\t}\n+\n+\tfor (i = 0; i < PIPELINE_FA_N_TC_MAX; i++) {\n+\t\tstruct pipeline_fa_policer_params *p = &params->p[i];\n+\t\tuint32_t j;\n+\n+\t\tfor (j = 0; j < e_RTE_METER_COLORS; j++) {\n+\t\t\tstruct pipeline_fa_policer_action *a = &p->action[j];\n+\n+\t\t\ta->drop = 0;\n+\t\t\ta->color = (enum rte_meter_color) j;\n+\t\t}\n+\t}\n+\n+\tparams->port_id = 0;\n+\n+\treturn 0;\n+}\n+\n+struct dscp_entry {\n+\tuint32_t traffic_class;\n+\tenum rte_meter_color color;\n+};\n+\n+struct pipeline_flow_actions {\n+\tstruct pipeline p;\n+\tstruct pipeline_fa_params params;\n+\tpipeline_msg_req_handler custom_handlers[PIPELINE_FA_MSG_REQS];\n+\n+\tstruct dscp_entry dscp[PIPELINE_FA_N_DSCP];\n+} __rte_cache_aligned;\n+\n+static void *\n+pipeline_fa_msg_req_custom_handler(struct pipeline *p, void *msg);\n+\n+static pipeline_msg_req_handler handlers[] = {\n+\t[PIPELINE_MSG_REQ_PING] =\n+\t\tpipeline_msg_req_ping_handler,\n+\t[PIPELINE_MSG_REQ_STATS_PORT_IN] =\n+\t\tpipeline_msg_req_stats_port_in_handler,\n+\t[PIPELINE_MSG_REQ_STATS_PORT_OUT] =\n+\t\tpipeline_msg_req_stats_port_out_handler,\n+\t[PIPELINE_MSG_REQ_STATS_TABLE] =\n+\t\tpipeline_msg_req_stats_table_handler,\n+\t[PIPELINE_MSG_REQ_PORT_IN_ENABLE] =\n+\t\tpipeline_msg_req_port_in_enable_handler,\n+\t[PIPELINE_MSG_REQ_PORT_IN_DISABLE] =\n+\t\tpipeline_msg_req_port_in_disable_handler,\n+\t[PIPELINE_MSG_REQ_CUSTOM] =\n+\t\tpipeline_fa_msg_req_custom_handler,\n+};\n+\n+static void *\n+pipeline_fa_msg_req_flow_config_handler(struct pipeline *p, void *msg);\n+\n+static void *\n+pipeline_fa_msg_req_flow_config_bulk_handler(struct pipeline *p, void *msg);\n+\n+static void *\n+pipeline_fa_msg_req_dscp_config_handler(struct pipeline *p, void *msg);\n+\n+static void *\n+pipeline_fa_msg_req_policer_stats_read_handler(struct pipeline *p, void *msg);\n+\n+static pipeline_msg_req_handler custom_handlers[] = {\n+\t[PIPELINE_FA_MSG_REQ_FLOW_CONFIG] =\n+\t\tpipeline_fa_msg_req_flow_config_handler,\n+\t[PIPELINE_FA_MSG_REQ_FLOW_CONFIG_BULK] =\n+\t\tpipeline_fa_msg_req_flow_config_bulk_handler,\n+\t[PIPELINE_FA_MSG_REQ_DSCP_CONFIG] =\n+\t\tpipeline_fa_msg_req_dscp_config_handler,\n+\t[PIPELINE_FA_MSG_REQ_POLICER_STATS_READ] =\n+\t\tpipeline_fa_msg_req_policer_stats_read_handler,\n+};\n+\n+/*\n+ * Flow table\n+ */\n+struct meter_policer {\n+\tstruct rte_meter_trtcm meter;\n+\tstruct pipeline_fa_policer_params policer;\n+\tstruct pipeline_fa_policer_stats stats;\n+};\n+\n+struct flow_table_entry {\n+\tstruct rte_pipeline_table_entry head;\n+\tstruct meter_policer mp[PIPELINE_FA_N_TC_MAX];\n+};\n+\n+static int\n+flow_table_entry_set_meter(struct flow_table_entry *entry,\n+\tuint32_t meter_id,\n+\tstruct pipeline_fa_flow_params *params)\n+{\n+\tstruct rte_meter_trtcm *meter = &entry->mp[meter_id].meter;\n+\tstruct rte_meter_trtcm_params *meter_params = &params->m[meter_id];\n+\n+\treturn rte_meter_trtcm_config(meter, meter_params);\n+}\n+\n+static void\n+flow_table_entry_set_policer(struct flow_table_entry *entry,\n+\tuint32_t policer_id,\n+\tstruct pipeline_fa_flow_params *params)\n+{\n+\tstruct pipeline_fa_policer_params *p0 = &entry->mp[policer_id].policer;\n+\tstruct pipeline_fa_policer_params *p1 = &params->p[policer_id];\n+\n+\tmemcpy(p0, p1, sizeof(*p0));\n+}\n+\n+static void\n+flow_table_entry_set_port_id(struct pipeline_flow_actions *p,\n+\tstruct flow_table_entry *entry,\n+\tstruct pipeline_fa_flow_params *params)\n+{\n+\tentry->head.action = RTE_PIPELINE_ACTION_PORT;\n+\tentry->head.port_id = p->p.port_out_id[params->port_id];\n+}\n+\n+static int\n+flow_table_entry_set_default(struct pipeline_flow_actions *p,\n+\tstruct flow_table_entry *entry)\n+{\n+\tstruct pipeline_fa_flow_params params;\n+\tuint32_t i;\n+\n+\tpipeline_fa_flow_params_set_default(&params);\n+\n+\tmemset(entry, 0, sizeof(*entry));\n+\n+\tflow_table_entry_set_port_id(p, entry, &params);\n+\n+\tfor (i = 0; i < PIPELINE_FA_N_TC_MAX; i++) {\n+\t\tint status;\n+\n+\t\tstatus = flow_table_entry_set_meter(entry, i, &params);\n+\t\tif (status)\n+\t\t\treturn status;\n+\t}\n+\n+\tfor (i = 0; i < PIPELINE_FA_N_TC_MAX; i++)\n+\t\tflow_table_entry_set_policer(entry, i, &params);\n+\n+\treturn 0;\n+}\n+\n+static inline uint64_t\n+pkt_work(\n+\tstruct rte_mbuf *pkt,\n+\tstruct rte_pipeline_table_entry *table_entry,\n+\tvoid *arg,\n+\tuint64_t time)\n+{\n+\tstruct pipeline_flow_actions *p = arg;\n+\tstruct flow_table_entry *entry =\n+\t\t(struct flow_table_entry *) table_entry;\n+\n+\tstruct ipv4_hdr *pkt_ip = (struct ipv4_hdr *)\n+\t\tRTE_MBUF_METADATA_UINT32_PTR(pkt, p->params.ip_hdr_offset);\n+\tenum rte_meter_color *pkt_color = (enum rte_meter_color *)\n+\t\tRTE_MBUF_METADATA_UINT32_PTR(pkt, p->params.color_offset);\n+\n+\t/* Read (IP header) */\n+\tuint32_t total_length = rte_bswap16(pkt_ip->total_length);\n+\tuint32_t dscp = pkt_ip->type_of_service >> 2;\n+\n+\tuint32_t tc = p->dscp[dscp].traffic_class;\n+\tenum rte_meter_color color = p->dscp[dscp].color;\n+\n+\tstruct rte_meter_trtcm *meter = &entry->mp[tc].meter;\n+\tstruct pipeline_fa_policer_params *policer = &entry->mp[tc].policer;\n+\tstruct pipeline_fa_policer_stats *stats = &entry->mp[tc].stats;\n+\n+\t/* Read (entry), compute */\n+\tenum rte_meter_color color2 = rte_meter_trtcm_color_aware_check(meter,\n+\t\ttime,\n+\t\ttotal_length,\n+\t\tcolor);\n+\n+\tenum rte_meter_color color3 = policer->action[color2].color;\n+\tuint64_t drop = policer->action[color2].drop;\n+\n+\t/* Read (entry), write (entry, color) */\n+\tstats->n_pkts[color3] += drop ^ 1LLU;\n+\tstats->n_pkts_drop += drop;\n+\t*pkt_color = color3;\n+\n+\treturn drop;\n+}\n+\n+static inline uint64_t\n+pkt4_work(\n+\tstruct rte_mbuf **pkts,\n+\tstruct rte_pipeline_table_entry **table_entries,\n+\tvoid *arg,\n+\tuint64_t time)\n+{\n+\tstruct pipeline_flow_actions *p = arg;\n+\n+\tstruct flow_table_entry *entry0 =\n+\t\t(struct flow_table_entry *) table_entries[0];\n+\tstruct flow_table_entry *entry1 =\n+\t\t(struct flow_table_entry *) table_entries[1];\n+\tstruct flow_table_entry *entry2 =\n+\t\t(struct flow_table_entry *) table_entries[2];\n+\tstruct flow_table_entry *entry3 =\n+\t\t(struct flow_table_entry *) table_entries[3];\n+\n+\tstruct ipv4_hdr *pkt0_ip = (struct ipv4_hdr *)\n+\t\tRTE_MBUF_METADATA_UINT32_PTR(pkts[0], p->params.ip_hdr_offset);\n+\tstruct ipv4_hdr *pkt1_ip = (struct ipv4_hdr *)\n+\t\tRTE_MBUF_METADATA_UINT32_PTR(pkts[1], p->params.ip_hdr_offset);\n+\tstruct ipv4_hdr *pkt2_ip = (struct ipv4_hdr *)\n+\t\tRTE_MBUF_METADATA_UINT32_PTR(pkts[2], p->params.ip_hdr_offset);\n+\tstruct ipv4_hdr *pkt3_ip = (struct ipv4_hdr *)\n+\t\tRTE_MBUF_METADATA_UINT32_PTR(pkts[3], p->params.ip_hdr_offset);\n+\n+\tenum rte_meter_color *pkt0_color = (enum rte_meter_color *)\n+\t\tRTE_MBUF_METADATA_UINT32_PTR(pkts[0], p->params.color_offset);\n+\tenum rte_meter_color *pkt1_color = (enum rte_meter_color *)\n+\t\tRTE_MBUF_METADATA_UINT32_PTR(pkts[1], p->params.color_offset);\n+\tenum rte_meter_color *pkt2_color = (enum rte_meter_color *)\n+\t\tRTE_MBUF_METADATA_UINT32_PTR(pkts[2], p->params.color_offset);\n+\tenum rte_meter_color *pkt3_color = (enum rte_meter_color *)\n+\t\tRTE_MBUF_METADATA_UINT32_PTR(pkts[3], p->params.color_offset);\n+\n+\t/* Read (IP header) */\n+\tuint32_t total_length0 = rte_bswap16(pkt0_ip->total_length);\n+\tuint32_t dscp0 = pkt0_ip->type_of_service >> 2;\n+\n+\tuint32_t total_length1 = rte_bswap16(pkt1_ip->total_length);\n+\tuint32_t dscp1 = pkt1_ip->type_of_service >> 2;\n+\n+\tuint32_t total_length2 = rte_bswap16(pkt2_ip->total_length);\n+\tuint32_t dscp2 = pkt2_ip->type_of_service >> 2;\n+\n+\tuint32_t total_length3 = rte_bswap16(pkt3_ip->total_length);\n+\tuint32_t dscp3 = pkt3_ip->type_of_service >> 2;\n+\n+\tuint32_t tc0 = p->dscp[dscp0].traffic_class;\n+\tenum rte_meter_color color0 = p->dscp[dscp0].color;\n+\n+\tuint32_t tc1 = p->dscp[dscp1].traffic_class;\n+\tenum rte_meter_color color1 = p->dscp[dscp1].color;\n+\n+\tuint32_t tc2 = p->dscp[dscp2].traffic_class;\n+\tenum rte_meter_color color2 = p->dscp[dscp2].color;\n+\n+\tuint32_t tc3 = p->dscp[dscp3].traffic_class;\n+\tenum rte_meter_color color3 = p->dscp[dscp3].color;\n+\n+\tstruct rte_meter_trtcm *meter0 = &entry0->mp[tc0].meter;\n+\tstruct pipeline_fa_policer_params *policer0 = &entry0->mp[tc0].policer;\n+\tstruct pipeline_fa_policer_stats *stats0 = &entry0->mp[tc0].stats;\n+\n+\tstruct rte_meter_trtcm *meter1 = &entry1->mp[tc1].meter;\n+\tstruct pipeline_fa_policer_params *policer1 = &entry1->mp[tc1].policer;\n+\tstruct pipeline_fa_policer_stats *stats1 = &entry1->mp[tc1].stats;\n+\n+\tstruct rte_meter_trtcm *meter2 = &entry2->mp[tc2].meter;\n+\tstruct pipeline_fa_policer_params *policer2 = &entry2->mp[tc2].policer;\n+\tstruct pipeline_fa_policer_stats *stats2 = &entry2->mp[tc2].stats;\n+\n+\tstruct rte_meter_trtcm *meter3 = &entry3->mp[tc3].meter;\n+\tstruct pipeline_fa_policer_params *policer3 = &entry3->mp[tc3].policer;\n+\tstruct pipeline_fa_policer_stats *stats3 = &entry3->mp[tc3].stats;\n+\n+\t/* Read (entry), compute, write (entry) */\n+\tenum rte_meter_color color2_0 = rte_meter_trtcm_color_aware_check(\n+\t\tmeter0,\n+\t\ttime,\n+\t\ttotal_length0,\n+\t\tcolor0);\n+\n+\tenum rte_meter_color color2_1 = rte_meter_trtcm_color_aware_check(\n+\t\tmeter1,\n+\t\ttime,\n+\t\ttotal_length1,\n+\t\tcolor1);\n+\n+\tenum rte_meter_color color2_2 = rte_meter_trtcm_color_aware_check(\n+\t\tmeter2,\n+\t\ttime,\n+\t\ttotal_length2,\n+\t\tcolor2);\n+\n+\tenum rte_meter_color color2_3 = rte_meter_trtcm_color_aware_check(\n+\t\tmeter3,\n+\t\ttime,\n+\t\ttotal_length3,\n+\t\tcolor3);\n+\n+\tenum rte_meter_color color3_0 = policer0->action[color2_0].color;\n+\tenum rte_meter_color color3_1 = policer1->action[color2_1].color;\n+\tenum rte_meter_color color3_2 = policer2->action[color2_2].color;\n+\tenum rte_meter_color color3_3 = policer3->action[color2_3].color;\n+\n+\tuint64_t drop0 = policer0->action[color2_0].drop;\n+\tuint64_t drop1 = policer1->action[color2_1].drop;\n+\tuint64_t drop2 = policer2->action[color2_2].drop;\n+\tuint64_t drop3 = policer3->action[color2_3].drop;\n+\n+\t/* Read (entry), write (entry, color) */\n+\tstats0->n_pkts[color3_0] += drop0 ^ 1LLU;\n+\tstats0->n_pkts_drop += drop0;\n+\n+\tstats1->n_pkts[color3_1] += drop1 ^ 1LLU;\n+\tstats1->n_pkts_drop += drop1;\n+\n+\tstats2->n_pkts[color3_2] += drop2 ^ 1LLU;\n+\tstats2->n_pkts_drop += drop2;\n+\n+\tstats3->n_pkts[color3_3] += drop3 ^ 1LLU;\n+\tstats3->n_pkts_drop += drop3;\n+\n+\t*pkt0_color = color3_0;\n+\t*pkt1_color = color3_1;\n+\t*pkt2_color = color3_2;\n+\t*pkt3_color = color3_3;\n+\n+\treturn (drop0 | (drop1 << 1) | (drop2 << 2) | (drop3 << 3));\n+}\n+\n+PIPELINE_TABLE_AH_HIT_DROP_TIME(fa_table_ah_hit, pkt_work, pkt4_work);\n+\n+static rte_pipeline_table_action_handler_hit\n+get_fa_table_ah_hit(__rte_unused struct pipeline_flow_actions *p)\n+{\n+\treturn fa_table_ah_hit;\n+}\n+\n+/*\n+ * Argument parsing\n+ */\n+int\n+pipeline_fa_parse_args(struct pipeline_fa_params *p,\n+\tstruct pipeline_params *params)\n+{\n+\tuint32_t n_flows_present = 0;\n+\tuint32_t n_meters_per_flow_present = 0;\n+\tuint32_t flow_id_offset_present = 0;\n+\tuint32_t ip_hdr_offset_present = 0;\n+\tuint32_t color_offset_present = 0;\n+\tuint32_t i;\n+\n+\t/* Default values */\n+\tp->n_meters_per_flow = 1;\n+\tp->dscp_enabled = 0;\n+\n+\tfor (i = 0; i < params->n_args; i++) {\n+\t\tchar *arg_name = params->args_name[i];\n+\t\tchar *arg_value = params->args_value[i];\n+\n+\t\t/* n_flows */\n+\t\tif (strcmp(arg_name, \"n_flows\") == 0) {\n+\t\t\tif (n_flows_present)\n+\t\t\t\treturn -1;\n+\n+\t\t\tn_flows_present = 1;\n+\n+\t\t\tp->n_flows = atoi(arg_value);\n+\t\t\tif (p->n_flows == 0)\n+\t\t\t\treturn -1;\n+\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/* n_meters_per_flow */\n+\t\tif (strcmp(arg_name, \"n_meters_per_flow\") == 0) {\n+\t\t\tif (n_meters_per_flow_present)\n+\t\t\t\treturn -1;\n+\n+\t\t\tn_meters_per_flow_present = 1;\n+\n+\t\t\tp->n_meters_per_flow = atoi(arg_value);\n+\t\t\tif ((p->n_meters_per_flow == 0) ||\n+\t\t\t\t(p->n_meters_per_flow > PIPELINE_FA_N_TC_MAX))\n+\t\t\t\treturn -1;\n+\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/* flow_id_offset */\n+\t\tif (strcmp(arg_name, \"flow_id_offset\") == 0) {\n+\t\t\tif (flow_id_offset_present)\n+\t\t\t\treturn -1;\n+\n+\t\t\tflow_id_offset_present = 1;\n+\n+\t\t\tp->flow_id_offset = atoi(arg_value);\n+\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/* ip_hdr_offset */\n+\t\tif (strcmp(arg_name, \"ip_hdr_offset\") == 0) {\n+\t\t\tif (ip_hdr_offset_present)\n+\t\t\t\treturn -1;\n+\n+\t\t\tip_hdr_offset_present = 1;\n+\n+\t\t\tp->ip_hdr_offset = atoi(arg_value);\n+\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/* color_offset */\n+\t\tif (strcmp(arg_name, \"color_offset\") == 0) {\n+\t\t\tif (color_offset_present)\n+\t\t\t\treturn -1;\n+\n+\t\t\tcolor_offset_present = 1;\n+\n+\t\t\tp->dscp_enabled = 1;\n+\t\t\tp->color_offset = atoi(arg_value);\n+\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/* Unknown argument */\n+\t\treturn -1;\n+\t}\n+\n+\t/* Check that mandatory arguments are present */\n+\tif ((n_flows_present == 0) ||\n+\t\t(flow_id_offset_present == 0) ||\n+\t\t(ip_hdr_offset_present == 0) ||\n+\t\t(color_offset_present == 0))\n+\t\treturn -1;\n+\n+\treturn 0;\n+}\n+\n+static void\n+dscp_init(struct pipeline_flow_actions *p)\n+{\n+\tuint32_t i;\n+\n+\tfor (i = 0; i < PIPELINE_FA_N_DSCP; i++) {\n+\t\tp->dscp[i].traffic_class = 0;\n+\t\tp->dscp[i].color = e_RTE_METER_GREEN;\n+\t}\n+}\n+\n+static void *pipeline_fa_init(struct pipeline_params *params,\n+\t__rte_unused void *arg)\n+{\n+\tstruct pipeline *p;\n+\tstruct pipeline_flow_actions *p_fa;\n+\tuint32_t size, i;\n+\n+\t/* Check input arguments */\n+\tif (params == NULL)\n+\t\treturn NULL;\n+\n+\tif (params->n_ports_in != params->n_ports_out)\n+\t\treturn NULL;\n+\n+\t/* Memory allocation */\n+\tsize = RTE_CACHE_LINE_ROUNDUP(\n+\t\tsizeof(struct pipeline_flow_actions));\n+\tp = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);\n+\tif (p == NULL)\n+\t\treturn NULL;\n+\tp_fa = (struct pipeline_flow_actions *) p;\n+\n+\tstrcpy(p->name, params->name);\n+\tp->log_level = params->log_level;\n+\n+\tPLOG(p, HIGH, \"Flow actions\");\n+\n+\t/* Parse arguments */\n+\tif (pipeline_fa_parse_args(&p_fa->params, params))\n+\t\treturn NULL;\n+\n+\tdscp_init(p_fa);\n+\n+\t/* Pipeline */\n+\t{\n+\t\tstruct rte_pipeline_params pipeline_params = {\n+\t\t\t.name = params->name,\n+\t\t\t.socket_id = params->socket_id,\n+\t\t\t.offset_port_id = 0,\n+\t\t};\n+\n+\t\tp->p = rte_pipeline_create(&pipeline_params);\n+\t\tif (p->p == NULL) {\n+\t\t\trte_free(p);\n+\t\t\treturn NULL;\n+\t\t}\n+\t}\n+\n+\t/* Input ports */\n+\tp->n_ports_in = params->n_ports_in;\n+\tfor (i = 0; i < p->n_ports_in; i++) {\n+\t\tstruct rte_pipeline_port_in_params port_params = {\n+\t\t\t.ops = pipeline_port_in_params_get_ops(\n+\t\t\t\t&params->port_in[i]),\n+\t\t\t.arg_create = pipeline_port_in_params_convert(\n+\t\t\t\t&params->port_in[i]),\n+\t\t\t.f_action = NULL,\n+\t\t\t.arg_ah = NULL,\n+\t\t\t.burst_size = params->port_in[i].burst_size,\n+\t\t};\n+\n+\t\tint status = rte_pipeline_port_in_create(p->p,\n+\t\t\t&port_params,\n+\t\t\t&p->port_in_id[i]);\n+\n+\t\tif (status) {\n+\t\t\trte_pipeline_free(p->p);\n+\t\t\trte_free(p);\n+\t\t\treturn NULL;\n+\t\t}\n+\t}\n+\n+\t/* Output ports */\n+\tp->n_ports_out = params->n_ports_out;\n+\tfor (i = 0; i < p->n_ports_out; i++) {\n+\t\tstruct rte_pipeline_port_out_params port_params = {\n+\t\t\t.ops = pipeline_port_out_params_get_ops(\n+\t\t\t\t&params->port_out[i]),\n+\t\t\t.arg_create = pipeline_port_out_params_convert(\n+\t\t\t\t&params->port_out[i]),\n+\t\t\t.f_action = NULL,\n+\t\t\t.f_action_bulk = NULL,\n+\t\t\t.arg_ah = NULL,\n+\t\t};\n+\n+\t\tint status = rte_pipeline_port_out_create(p->p,\n+\t\t\t&port_params,\n+\t\t\t&p->port_out_id[i]);\n+\n+\t\tif (status) {\n+\t\t\trte_pipeline_free(p->p);\n+\t\t\trte_free(p);\n+\t\t\treturn NULL;\n+\t\t}\n+\t}\n+\n+\t/* Tables */\n+\tp->n_tables = 1;\n+\t{\n+\t\tstruct rte_table_array_params table_array_params = {\n+\t\t\t.n_entries = p_fa->params.n_flows,\n+\t\t\t.offset = p_fa->params.flow_id_offset,\n+\t\t};\n+\n+\t\tstruct rte_pipeline_table_params table_params = {\n+\t\t\t.ops = &rte_table_array_ops,\n+\t\t\t.arg_create = &table_array_params,\n+\t\t\t.f_action_hit = get_fa_table_ah_hit(p_fa),\n+\t\t\t.f_action_miss = NULL,\n+\t\t\t.arg_ah = p_fa,\n+\t\t\t.action_data_size =\n+\t\t\t\tsizeof(struct flow_table_entry) -\n+\t\t\t\tsizeof(struct rte_pipeline_table_entry),\n+\t\t};\n+\n+\t\tint status;\n+\n+\t\tstatus = rte_pipeline_table_create(p->p,\n+\t\t\t&table_params,\n+\t\t\t&p->table_id[0]);\n+\n+\t\tif (status) {\n+\t\t\trte_pipeline_free(p->p);\n+\t\t\trte_free(p);\n+\t\t\treturn NULL;\n+\t\t}\n+\t}\n+\n+\t/* Connecting input ports to tables */\n+\tfor (i = 0; i < p->n_ports_in; i++) {\n+\t\tint status = rte_pipeline_port_in_connect_to_table(p->p,\n+\t\t\tp->port_in_id[i],\n+\t\t\tp->table_id[0]);\n+\n+\t\tif (status) {\n+\t\t\trte_pipeline_free(p->p);\n+\t\t\trte_free(p);\n+\t\t\treturn NULL;\n+\t\t}\n+\t}\n+\n+\t/* Enable input ports */\n+\tfor (i = 0; i < p->n_ports_in; i++) {\n+\t\tint status = rte_pipeline_port_in_enable(p->p,\n+\t\t\tp->port_in_id[i]);\n+\n+\t\tif (status) {\n+\t\t\trte_pipeline_free(p->p);\n+\t\t\trte_free(p);\n+\t\t\treturn NULL;\n+\t\t}\n+\t}\n+\n+\t/* Initialize table entries */\n+\tfor (i = 0; i < p_fa->params.n_flows; i++) {\n+\t\tstruct rte_table_array_key key = {\n+\t\t\t.pos = i,\n+\t\t};\n+\n+\t\tstruct flow_table_entry entry;\n+\t\tstruct rte_pipeline_table_entry *entry_ptr;\n+\t\tint key_found, status;\n+\n+\t\tflow_table_entry_set_default(p_fa, &entry);\n+\n+\t\tstatus = rte_pipeline_table_entry_add(p->p,\n+\t\t\tp->table_id[0],\n+\t\t\t&key,\n+\t\t\t(struct rte_pipeline_table_entry *) &entry,\n+\t\t\t&key_found,\n+\t\t\t&entry_ptr);\n+\n+\t\tif (status) {\n+\t\t\trte_pipeline_free(p->p);\n+\t\t\trte_free(p);\n+\t\t\treturn NULL;\n+\t\t}\n+\t}\n+\n+\t/* Check pipeline consistency */\n+\tif (rte_pipeline_check(p->p) < 0) {\n+\t\trte_pipeline_free(p->p);\n+\t\trte_free(p);\n+\t\treturn NULL;\n+\t}\n+\n+\t/* Message queues */\n+\tp->n_msgq = params->n_msgq;\n+\tfor (i = 0; i < p->n_msgq; i++)\n+\t\tp->msgq_in[i] = params->msgq_in[i];\n+\tfor (i = 0; i < p->n_msgq; i++)\n+\t\tp->msgq_out[i] = params->msgq_out[i];\n+\n+\t/* Message handlers */\n+\tmemcpy(p->handlers, handlers, sizeof(p->handlers));\n+\tmemcpy(p_fa->custom_handlers,\n+\t\tcustom_handlers,\n+\t\tsizeof(p_fa->custom_handlers));\n+\n+\treturn p;\n+}\n+\n+static int\n+pipeline_fa_free(void *pipeline)\n+{\n+\tstruct pipeline *p = (struct pipeline *) pipeline;\n+\n+\t/* Check input arguments */\n+\tif (p == NULL)\n+\t\treturn -1;\n+\n+\t/* Free resources */\n+\trte_pipeline_free(p->p);\n+\trte_free(p);\n+\treturn 0;\n+}\n+\n+static int\n+pipeline_fa_track(void *pipeline,\n+\t__rte_unused uint32_t port_in,\n+\tuint32_t *port_out)\n+{\n+\tstruct pipeline *p = (struct pipeline *) pipeline;\n+\n+\t/* Check input arguments */\n+\tif ((p == NULL) ||\n+\t\t(port_in >= p->n_ports_in) ||\n+\t\t(port_out == NULL))\n+\t\treturn -1;\n+\n+\tif (p->n_ports_in == 1) {\n+\t\t*port_out = 0;\n+\t\treturn 0;\n+\t}\n+\n+\treturn -1;\n+}\n+\n+static int\n+pipeline_fa_timer(void *pipeline)\n+{\n+\tstruct pipeline *p = (struct pipeline *) pipeline;\n+\n+\tpipeline_msg_req_handle(p);\n+\trte_pipeline_flush(p->p);\n+\n+\treturn 0;\n+}\n+\n+void *\n+pipeline_fa_msg_req_custom_handler(struct pipeline *p, void *msg)\n+{\n+\tstruct pipeline_flow_actions *p_fa =\n+\t\t\t(struct pipeline_flow_actions *) p;\n+\tstruct pipeline_custom_msg_req *req = msg;\n+\tpipeline_msg_req_handler f_handle;\n+\n+\tf_handle = (req->subtype < PIPELINE_FA_MSG_REQS) ?\n+\t\tp_fa->custom_handlers[req->subtype] :\n+\t\tpipeline_msg_req_invalid_handler;\n+\n+\tif (f_handle == NULL)\n+\t\tf_handle = pipeline_msg_req_invalid_handler;\n+\n+\treturn f_handle(p, req);\n+}\n+\n+void *\n+pipeline_fa_msg_req_flow_config_handler(struct pipeline *p, void *msg)\n+{\n+\tstruct pipeline_flow_actions *p_fa = (struct pipeline_flow_actions *) p;\n+\tstruct pipeline_fa_flow_config_msg_req *req = msg;\n+\tstruct pipeline_fa_flow_config_msg_rsp *rsp = msg;\n+\tstruct flow_table_entry *entry;\n+\tuint32_t mask, i;\n+\n+\t/* Set flow table entry to default if not configured before */\n+\tif (req->entry_ptr == NULL) {\n+\t\tstruct rte_table_array_key key = {\n+\t\t\t.pos = req->flow_id % p_fa->params.n_flows,\n+\t\t};\n+\n+\t\tstruct flow_table_entry default_entry;\n+\n+\t\tint key_found, status;\n+\n+\t\tflow_table_entry_set_default(p_fa, &default_entry);\n+\n+\t\tstatus = rte_pipeline_table_entry_add(p->p,\n+\t\t\tp->table_id[0],\n+\t\t\t&key,\n+\t\t\t(struct rte_pipeline_table_entry *) &default_entry,\n+\t\t\t&key_found,\n+\t\t\t(struct rte_pipeline_table_entry **) &entry);\n+\t\tif (status) {\n+\t\t\trsp->status = -1;\n+\t\t\treturn rsp;\n+\t\t}\n+\t} else\n+\t\tentry = (struct flow_table_entry *) req->entry_ptr;\n+\n+\t/* Meter */\n+\tfor (i = 0, mask = 1; i < PIPELINE_FA_N_TC_MAX; i++, mask <<= 1) {\n+\t\tint status;\n+\n+\t\tif ((mask & req->meter_update_mask) == 0)\n+\t\t\tcontinue;\n+\n+\t\tstatus = flow_table_entry_set_meter(entry, i, &req->params);\n+\t\tif (status) {\n+\t\t\trsp->status = -1;\n+\t\t\treturn rsp;\n+\t\t}\n+\t}\n+\n+\t/* Policer */\n+\tfor (i = 0, mask = 1; i < PIPELINE_FA_N_TC_MAX; i++, mask <<= 1) {\n+\t\tif ((mask & req->policer_update_mask) == 0)\n+\t\t\tcontinue;\n+\n+\t\tflow_table_entry_set_policer(entry, i, &req->params);\n+\t}\n+\n+\t/* Port */\n+\tif (req->port_update)\n+\t\tflow_table_entry_set_port_id(p_fa, entry, &req->params);\n+\n+\t/* Response */\n+\trsp->status = 0;\n+\trsp->entry_ptr = (void *) entry;\n+\treturn rsp;\n+}\n+\n+void *\n+pipeline_fa_msg_req_flow_config_bulk_handler(struct pipeline *p, void *msg)\n+{\n+\tstruct pipeline_flow_actions *p_fa = (struct pipeline_flow_actions *) p;\n+\tstruct pipeline_fa_flow_config_bulk_msg_req *req = msg;\n+\tstruct pipeline_fa_flow_config_bulk_msg_rsp *rsp = msg;\n+\tuint32_t i;\n+\n+\tfor (i = 0; i < req->n_flows; i++) {\n+\t\tstruct flow_table_entry *entry;\n+\t\tuint32_t j, mask;\n+\n+\t\t/* Set flow table entry to default if not configured before */\n+\t\tif (req->entry_ptr[i] == NULL) {\n+\t\t\tstruct rte_table_array_key key = {\n+\t\t\t\t.pos = req->flow_id[i] % p_fa->params.n_flows,\n+\t\t\t};\n+\n+\t\t\tstruct flow_table_entry entry_to_add;\n+\n+\t\t\tint key_found, status;\n+\n+\t\t\tflow_table_entry_set_default(p_fa, &entry_to_add);\n+\n+\t\t\tstatus = rte_pipeline_table_entry_add(p->p,\n+\t\t\t p->table_id[0],\n+\t\t\t &key,\n+\t\t\t (struct rte_pipeline_table_entry *) &entry_to_add,\n+\t\t\t &key_found,\n+\t\t\t (struct rte_pipeline_table_entry **) &entry);\n+\t\t\tif (status) {\n+\t\t\t\trsp->n_flows = i;\n+\t\t\t\treturn rsp;\n+\t\t\t}\n+\n+\t\t\treq->entry_ptr[i] = (void *) entry;\n+\t\t} else\n+\t\t\tentry = (struct flow_table_entry *) req->entry_ptr[i];\n+\n+\t\t/* Meter */\n+\t\tfor (j = 0, mask = 1;\n+\t\t\tj < PIPELINE_FA_N_TC_MAX;\n+\t\t\tj++, mask <<= 1) {\n+\t\t\tint status;\n+\n+\t\t\tif ((mask & req->meter_update_mask) == 0)\n+\t\t\t\tcontinue;\n+\n+\t\t\tstatus = flow_table_entry_set_meter(entry,\n+\t\t\t\tj, &req->params[i]);\n+\t\t\tif (status) {\n+\t\t\t\trsp->n_flows = i;\n+\t\t\t\treturn rsp;\n+\t\t\t}\n+\t\t}\n+\n+\t\t/* Policer */\n+\t\tfor (j = 0, mask = 1;\n+\t\t\tj < PIPELINE_FA_N_TC_MAX;\n+\t\t\tj++, mask <<= 1) {\n+\t\t\tif ((mask & req->policer_update_mask) == 0)\n+\t\t\t\tcontinue;\n+\n+\t\t\tflow_table_entry_set_policer(entry,\n+\t\t\t j, &req->params[i]);\n+\t\t}\n+\n+\t\t/* Port */\n+\t\tif (req->port_update)\n+\t\t\tflow_table_entry_set_port_id(p_fa,\n+\t\t\t entry, &req->params[i]);\n+\t}\n+\n+\t/* Response */\n+\trsp->n_flows = i;\n+\treturn rsp;\n+}\n+\n+void *\n+pipeline_fa_msg_req_dscp_config_handler(struct pipeline *p, void *msg)\n+{\n+\tstruct pipeline_flow_actions *p_fa = (struct pipeline_flow_actions *) p;\n+\tstruct pipeline_fa_dscp_config_msg_req *req = msg;\n+\tstruct pipeline_fa_dscp_config_msg_rsp *rsp = msg;\n+\n+\t/* Check request */\n+\tif ((req->dscp >= PIPELINE_FA_N_DSCP) ||\n+\t\t(req->traffic_class >= PIPELINE_FA_N_TC_MAX) ||\n+\t\t(req->color >= e_RTE_METER_COLORS)) {\n+\t\trsp->status = -1;\n+\t\treturn rsp;\n+\t}\n+\n+\tp_fa->dscp[req->dscp].traffic_class = req->traffic_class;\n+\tp_fa->dscp[req->dscp].color = req->color;\n+\trsp->status = 0;\n+\treturn rsp;\n+}\n+\n+void *\n+pipeline_fa_msg_req_policer_stats_read_handler(__rte_unused struct pipeline *p,\n+\tvoid *msg)\n+{\n+\tstruct pipeline_fa_policer_stats_msg_req *req = msg;\n+\tstruct pipeline_fa_policer_stats_msg_rsp *rsp = msg;\n+\n+\tstruct flow_table_entry *entry = req->entry_ptr;\n+\tuint32_t policer_id = req->policer_id;\n+\tint clear = req->clear;\n+\n+\t/* Check request */\n+\tif ((req->entry_ptr == NULL) ||\n+\t\t(req->policer_id >= PIPELINE_FA_N_TC_MAX)) {\n+\t\trsp->status = -1;\n+\t\treturn rsp;\n+\t}\n+\n+\tmemcpy(&rsp->stats,\n+\t\t&entry->mp[policer_id].stats,\n+\t\tsizeof(rsp->stats));\n+\tif (clear)\n+\t\tmemset(&entry->mp[policer_id].stats,\n+\t\t\t0, sizeof(entry->mp[policer_id].stats));\n+\trsp->status = 0;\n+\treturn rsp;\n+}\n+\n+struct pipeline_be_ops pipeline_flow_actions_be_ops = {\n+\t.f_init = pipeline_fa_init,\n+\t.f_free = pipeline_fa_free,\n+\t.f_run = NULL,\n+\t.f_timer = pipeline_fa_timer,\n+\t.f_track = pipeline_fa_track,\n+};\ndiff --git a/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.h b/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.h\nnew file mode 100644\nindex 0000000..456f2cc\n--- /dev/null\n+++ b/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.h\n@@ -0,0 +1,168 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.\n+ *   All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   modification, are permitted provided that the following conditions\n+ *   are met:\n+ *\n+ *     * Redistributions of source code must retain the above copyright\n+ *       notice, this list of conditions and the following disclaimer.\n+ *     * Redistributions in binary form must reproduce the above copyright\n+ *       notice, this list of conditions and the following disclaimer in\n+ *       the documentation and/or other materials provided with the\n+ *       distribution.\n+ *     * Neither the name of Intel Corporation nor the names of its\n+ *       contributors may be used to endorse or promote products derived\n+ *       from this software without specific prior written permission.\n+ *\n+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+ *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+#ifndef __INCLUDE_PIPELINE_FLOW_ACTIONS_BE_H__\n+#define __INCLUDE_PIPELINE_FLOW_ACTIONS_BE_H__\n+\n+#include <rte_meter.h>\n+\n+#include \"pipeline_common_be.h\"\n+\n+#ifndef PIPELINE_FA_N_TC_MAX\n+#define PIPELINE_FA_N_TC_MAX                               4\n+#endif\n+\n+#define PIPELINE_FA_N_DSCP                                 64\n+\n+struct pipeline_fa_params {\n+\tuint32_t n_flows;\n+\tuint32_t n_meters_per_flow;\n+\tuint32_t flow_id_offset;\n+\tuint32_t ip_hdr_offset;\n+\tuint32_t color_offset;\n+\tuint32_t dscp_enabled;\n+};\n+\n+int\n+pipeline_fa_parse_args(struct pipeline_fa_params *p,\n+\tstruct pipeline_params *params);\n+\n+struct pipeline_fa_policer_action {\n+\tuint32_t drop;\n+\tenum rte_meter_color color;\n+};\n+\n+struct pipeline_fa_policer_params {\n+\tstruct pipeline_fa_policer_action action[e_RTE_METER_COLORS];\n+};\n+\n+struct pipeline_fa_flow_params {\n+\tstruct rte_meter_trtcm_params m[PIPELINE_FA_N_TC_MAX];\n+\tstruct pipeline_fa_policer_params p[PIPELINE_FA_N_TC_MAX];\n+\tuint32_t port_id;\n+};\n+\n+int\n+pipeline_fa_flow_params_set_default(struct pipeline_fa_flow_params *params);\n+\n+struct pipeline_fa_policer_stats {\n+\tuint64_t n_pkts[e_RTE_METER_COLORS];\n+\tuint64_t n_pkts_drop;\n+};\n+\n+enum pipeline_fa_msg_req_type {\n+\tPIPELINE_FA_MSG_REQ_FLOW_CONFIG = 0,\n+\tPIPELINE_FA_MSG_REQ_FLOW_CONFIG_BULK,\n+\tPIPELINE_FA_MSG_REQ_DSCP_CONFIG,\n+\tPIPELINE_FA_MSG_REQ_POLICER_STATS_READ,\n+\tPIPELINE_FA_MSG_REQS,\n+};\n+\n+/*\n+ * MSG FLOW CONFIG\n+ */\n+struct pipeline_fa_flow_config_msg_req {\n+\tenum pipeline_msg_req_type type;\n+\tenum pipeline_fa_msg_req_type subtype;\n+\n+\tvoid *entry_ptr;\n+\tuint32_t flow_id;\n+\n+\tuint32_t meter_update_mask;\n+\tuint32_t policer_update_mask;\n+\tuint32_t port_update;\n+\tstruct pipeline_fa_flow_params params;\n+};\n+\n+struct pipeline_fa_flow_config_msg_rsp {\n+\tint status;\n+\tvoid *entry_ptr;\n+};\n+\n+/*\n+ * MSG FLOW CONFIG BULK\n+ */\n+struct pipeline_fa_flow_config_bulk_msg_req {\n+\tenum pipeline_msg_req_type type;\n+\tenum pipeline_fa_msg_req_type subtype;\n+\n+\tvoid **entry_ptr;\n+\tuint32_t *flow_id;\n+\tuint32_t n_flows;\n+\n+\tuint32_t meter_update_mask;\n+\tuint32_t policer_update_mask;\n+\tuint32_t port_update;\n+\tstruct pipeline_fa_flow_params *params;\n+};\n+\n+struct pipeline_fa_flow_config_bulk_msg_rsp {\n+\tuint32_t n_flows;\n+};\n+\n+/*\n+ * MSG DSCP CONFIG\n+ */\n+struct pipeline_fa_dscp_config_msg_req {\n+\tenum pipeline_msg_req_type type;\n+\tenum pipeline_fa_msg_req_type subtype;\n+\n+\tuint32_t dscp;\n+\tuint32_t traffic_class;\n+\tenum rte_meter_color color;\n+};\n+\n+struct pipeline_fa_dscp_config_msg_rsp {\n+\tint status;\n+};\n+\n+/*\n+ * MSG POLICER STATS READ\n+ */\n+struct pipeline_fa_policer_stats_msg_req {\n+\tenum pipeline_msg_req_type type;\n+\tenum pipeline_fa_msg_req_type subtype;\n+\n+\tvoid *entry_ptr;\n+\tuint32_t policer_id;\n+\tint clear;\n+};\n+\n+struct pipeline_fa_policer_stats_msg_rsp {\n+\tint status;\n+\tstruct pipeline_fa_policer_stats stats;\n+};\n+\n+extern struct pipeline_be_ops pipeline_flow_actions_be_ops;\n+\n+#endif\n",
    "prefixes": [
        "dpdk-dev"
    ]
}