get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 29946,
    "url": "http://patches.dpdk.org/api/patches/29946/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20171009125846.106218-6-jasvinder.singh@intel.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20171009125846.106218-6-jasvinder.singh@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20171009125846.106218-6-jasvinder.singh@intel.com",
    "date": "2017-10-09T12:58:46",
    "name": "[dpdk-dev,v7,5/5] app/testpmd: add traffic management forwarding mode",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "178957e001ad28ecbafbf6fec46cf59ea7a411a7",
    "submitter": {
        "id": 285,
        "url": "http://patches.dpdk.org/api/people/285/?format=api",
        "name": "Jasvinder Singh",
        "email": "jasvinder.singh@intel.com"
    },
    "delegate": {
        "id": 319,
        "url": "http://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20171009125846.106218-6-jasvinder.singh@intel.com/mbox/",
    "series": [],
    "comments": "http://patches.dpdk.org/api/patches/29946/comments/",
    "check": "fail",
    "checks": "http://patches.dpdk.org/api/patches/29946/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 [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 029FD1B1FF;\n\tMon,  9 Oct 2017 14:46:29 +0200 (CEST)",
            "from mga06.intel.com (mga06.intel.com [134.134.136.31])\n\tby dpdk.org (Postfix) with ESMTP id EC3491B1F6\n\tfor <dev@dpdk.org>; Mon,  9 Oct 2017 14:46:25 +0200 (CEST)",
            "from orsmga004.jf.intel.com ([10.7.209.38])\n\tby orsmga104.jf.intel.com with ESMTP; 09 Oct 2017 05:46:25 -0700",
            "from silpixa00381635.ir.intel.com (HELO\n\tsilpixa00381635.ger.corp.intel.com) ([10.237.222.149])\n\tby orsmga004.jf.intel.com with ESMTP; 09 Oct 2017 05:46:23 -0700"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.42,500,1500966000\"; d=\"scan'208\";a=\"136688231\"",
        "From": "Jasvinder Singh <jasvinder.singh@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "cristian.dumitrescu@intel.com, ferruh.yigit@intel.com,\n\tthomas@monjalon.net, wenzhuo.lu@intel.com",
        "Date": "Mon,  9 Oct 2017 13:58:46 +0100",
        "Message-Id": "<20171009125846.106218-6-jasvinder.singh@intel.com>",
        "X-Mailer": "git-send-email 2.9.3",
        "In-Reply-To": "<20171009125846.106218-1-jasvinder.singh@intel.com>",
        "References": "<20171006170003.77311-2-jasvinder.singh@intel.com>\n\t<20171009125846.106218-1-jasvinder.singh@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v7 5/5] app/testpmd: add traffic management\n\tforwarding mode",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <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": "This commit extends the testpmd application with new forwarding engine\nthat demonstrates the use of ethdev traffic management APIs and softnic\nPMD for QoS traffic management.\n\nIn this mode, 5-level hierarchical tree of the QoS scheduler is built\nwith the help of ethdev TM APIs such as shaper profile add/delete,\nshared shaper add/update, node add/delete, hierarchy commit, etc.\nThe hierarchical tree has following nodes; root node(x1, level 0),\nsubport node(x1, level 1), pipe node(x4096, level 2),\ntc node(x16348, level 3), queue node(x65536, level 4).\n\nDuring runtime, each received packet is first classified by mapping the\npacket fields information to 5-tuples (HQoS subport, pipe, traffic class,\nqueue within traffic class, and color) and storing it in the packet mbuf\nsched field. After classification, each packet is sent to softnic port\nwhich prioritizes the transmission of the received packets, and\naccordingly sends them on to the output interface.\n\nTo enable traffic management mode, following testpmd command is used;\n\n$ ./testpmd -c c -n 4 --vdev\n\t'net_softnic0,hard_name=0000:06:00.1,soft_tm=on' -- -i\n\t--forward-mode=tm\n\nSigned-off-by: Jasvinder Singh <jasvinder.singh@intel.com>\nAcked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>\nAcked-by: Thomas Monjalon <thomas@monjalon.net>\n\n---\nv7 change:\n- change port_id type to uint16_t\n- rebase on dpdk-next-net\n\nv5 change:\n- add CLI to enable default tm hierarchy\n \nv3 change:\n- Implements feedback from Pablo[1]\n  - add flag to check required librte_sched lib and softnic pmd\n  - code cleanup\n\nv2 change:\n- change file name softnictm.c to tm.c\n- change forward mode name to \"tm\"\n- code clean up\n\n[1] http://dpdk.org/ml/archives/dev/2017-September/075744.html\n\n app/test-pmd/Makefile  |  12 +\n app/test-pmd/cmdline.c |  88 +++++\n app/test-pmd/testpmd.c |  15 +\n app/test-pmd/testpmd.h |  46 +++\n app/test-pmd/tm.c      | 865 +++++++++++++++++++++++++++++++++++++++++++++++++\n 5 files changed, 1026 insertions(+)\n create mode 100644 app/test-pmd/tm.c",
    "diff": "diff --git a/app/test-pmd/Makefile b/app/test-pmd/Makefile\nindex b6e80dd..2c50f68 100644\n--- a/app/test-pmd/Makefile\n+++ b/app/test-pmd/Makefile\n@@ -59,6 +59,10 @@ SRCS-y += csumonly.c\n SRCS-y += icmpecho.c\n SRCS-$(CONFIG_RTE_LIBRTE_IEEE1588) += ieee1588fwd.c\n \n+ifeq ($(CONFIG_RTE_LIBRTE_PMD_SOFTNIC)$(CONFIG_RTE_LIBRTE_SCHED),yy)\n+SRCS-y += tm.c\n+endif\n+\n ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y)\n \n ifeq ($(CONFIG_RTE_LIBRTE_PMD_BOND),y)\n@@ -77,6 +81,14 @@ ifeq ($(CONFIG_RTE_LIBRTE_BNXT_PMD),y)\n LDLIBS += -lrte_pmd_bnxt\n endif\n \n+ifeq ($(CONFIG_RTE_LIBRTE_PMD_XENVIRT),y)\n+LDLIBS += -lrte_pmd_xenvirt\n+endif\n+\n+ifeq ($(CONFIG_RTE_LIBRTE_PMD_SOFTNIC),y)\n+LDLIBS += -lrte_pmd_softnic\n+endif\n+\n endif\n \n CFLAGS_cmdline.o := -D_GNU_SOURCE\ndiff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c\nindex 20e04f7..292b9be 100644\n--- a/app/test-pmd/cmdline.c\n+++ b/app/test-pmd/cmdline.c\n@@ -637,6 +637,11 @@ static void cmd_help_long_parsed(void *parsed_result,\n \t\t\t\"E-tag set filter del e-tag-id (value) port (port_id)\\n\"\n \t\t\t\"    Delete an E-tag forwarding filter on a port\\n\\n\"\n \n+#if defined RTE_LIBRTE_PMD_SOFTNIC && defined RTE_LIBRTE_SCHED\n+\t\t\t\"set port tm hierarchy default (port_id)\\n\"\n+\t\t\t\"\tSet default traffic Management hierarchy on a port\\n\\n\"\n+\n+#endif\n \t\t\t\"ddp add (port_id) (profile_path[,output_path])\\n\"\n \t\t\t\"    Load a profile package on a port\\n\\n\"\n \n@@ -13424,6 +13429,86 @@ cmdline_parse_inst_t cmd_vf_tc_max_bw = {\n \t},\n };\n \n+\n+#if defined RTE_LIBRTE_PMD_SOFTNIC && defined RTE_LIBRTE_SCHED\n+\n+/* *** Set Port default Traffic Management Hierarchy *** */\n+struct cmd_set_port_tm_hierarchy_default_result {\n+\tcmdline_fixed_string_t set;\n+\tcmdline_fixed_string_t port;\n+\tcmdline_fixed_string_t tm;\n+\tcmdline_fixed_string_t hierarchy;\n+\tcmdline_fixed_string_t def;\n+\tuint16_t port_id;\n+};\n+\n+cmdline_parse_token_string_t cmd_set_port_tm_hierarchy_default_set =\n+\tTOKEN_STRING_INITIALIZER(\n+\t\tstruct cmd_set_port_tm_hierarchy_default_result, set, \"set\");\n+cmdline_parse_token_string_t cmd_set_port_tm_hierarchy_default_port =\n+\tTOKEN_STRING_INITIALIZER(\n+\t\tstruct cmd_set_port_tm_hierarchy_default_result, port, \"port\");\n+cmdline_parse_token_string_t cmd_set_port_tm_hierarchy_default_tm =\n+\tTOKEN_STRING_INITIALIZER(\n+\t\tstruct cmd_set_port_tm_hierarchy_default_result, tm, \"tm\");\n+cmdline_parse_token_string_t cmd_set_port_tm_hierarchy_default_hierarchy =\n+\tTOKEN_STRING_INITIALIZER(\n+\t\tstruct cmd_set_port_tm_hierarchy_default_result,\n+\t\t\thierarchy, \"hierarchy\");\n+cmdline_parse_token_string_t cmd_set_port_tm_hierarchy_default_default =\n+\tTOKEN_STRING_INITIALIZER(\n+\t\tstruct cmd_set_port_tm_hierarchy_default_result,\n+\t\t\tdef, \"default\");\n+cmdline_parse_token_num_t cmd_set_port_tm_hierarchy_default_port_id =\n+\tTOKEN_NUM_INITIALIZER(\n+\t\tstruct cmd_set_port_tm_hierarchy_default_result,\n+\t\t\tport_id, UINT8);\n+\n+static void cmd_set_port_tm_hierarchy_default_parsed(void *parsed_result,\n+\t__attribute__((unused)) struct cmdline *cl,\n+\t__attribute__((unused)) void *data)\n+{\n+\tstruct cmd_set_port_tm_hierarchy_default_result *res = parsed_result;\n+\tstruct rte_port *p;\n+\tuint16_t port_id = res->port_id;\n+\n+\tif (port_id_is_invalid(port_id, ENABLED_WARN))\n+\t\treturn;\n+\n+\tp = &ports[port_id];\n+\n+\t/* Port tm flag */\n+\tif (p->softport.tm_flag == 0) {\n+\t\tprintf(\"  tm not enabled on port %u (error)\\n\", port_id);\n+\t\treturn;\n+\t}\n+\n+\t/* Forward mode: tm */\n+\tif (strcmp(cur_fwd_config.fwd_eng->fwd_mode_name, \"tm\")) {\n+\t\tprintf(\"  tm mode not enabled(error)\\n\");\n+\t\treturn;\n+\t}\n+\n+\t/* Set the default tm hierarchy */\n+\tp->softport.tm.default_hierarchy_enable = 1;\n+}\n+\n+cmdline_parse_inst_t cmd_set_port_tm_hierarchy_default = {\n+\t.f = cmd_set_port_tm_hierarchy_default_parsed,\n+\t.data = NULL,\n+\t.help_str = \"set port tm hierarchy default <port_id>\",\n+\t.tokens = {\n+\t\t(void *)&cmd_set_port_tm_hierarchy_default_set,\n+\t\t(void *)&cmd_set_port_tm_hierarchy_default_port,\n+\t\t(void *)&cmd_set_port_tm_hierarchy_default_tm,\n+\t\t(void *)&cmd_set_port_tm_hierarchy_default_hierarchy,\n+\t\t(void *)&cmd_set_port_tm_hierarchy_default_default,\n+\t\t(void *)&cmd_set_port_tm_hierarchy_default_port_id,\n+\t\tNULL,\n+\t},\n+};\n+#endif\n+\n /* Strict link priority scheduling mode setting */\n static void\n cmd_strict_link_prio_parsed(\n@@ -15020,6 +15105,9 @@ cmdline_parse_ctx_t main_ctx[] = {\n \t(cmdline_parse_inst_t *)&cmd_vf_tc_max_bw,\n \t(cmdline_parse_inst_t *)&cmd_strict_link_prio,\n \t(cmdline_parse_inst_t *)&cmd_tc_min_bw,\n+#if defined RTE_LIBRTE_PMD_SOFTNIC && defined RTE_LIBRTE_SCHED\n+\t(cmdline_parse_inst_t *)&cmd_set_port_tm_hierarchy_default,\n+#endif\n \t(cmdline_parse_inst_t *)&cmd_ddp_add,\n \t(cmdline_parse_inst_t *)&cmd_ddp_del,\n \t(cmdline_parse_inst_t *)&cmd_ddp_get_list,\ndiff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c\nindex 3dcc325..552abdf 100644\n--- a/app/test-pmd/testpmd.c\n+++ b/app/test-pmd/testpmd.c\n@@ -163,6 +163,10 @@ struct fwd_engine * fwd_engines[] = {\n \t&tx_only_engine,\n \t&csum_fwd_engine,\n \t&icmp_echo_engine,\n+#if defined RTE_LIBRTE_PMD_SOFTNIC && defined RTE_LIBRTE_SCHED\n+\t&softnic_tm_engine,\n+\t&softnic_tm_bypass_engine,\n+#endif\n #ifdef RTE_LIBRTE_IEEE1588\n \t&ieee1588_fwd_engine,\n #endif\n@@ -2108,6 +2112,17 @@ init_port_config(void)\n \t\t    (rte_eth_devices[pid].data->dev_flags &\n \t\t     RTE_ETH_DEV_INTR_RMV))\n \t\t\tport->dev_conf.intr_conf.rmv = 1;\n+\n+#if defined RTE_LIBRTE_PMD_SOFTNIC && defined RTE_LIBRTE_SCHED\n+\t\t/* Detect softnic port */\n+\t\tif (!strcmp(port->dev_info.driver_name, \"net_softnic\")) {\n+\t\t\tport->softnic_enable = 1;\n+\t\t\tmemset(&port->softport, 0, sizeof(struct softnic_port));\n+\n+\t\t\tif (!strcmp(cur_fwd_eng->fwd_mode_name, \"tm\"))\n+\t\t\t\tport->softport.tm_flag = 1;\n+\t\t}\n+#endif\n \t}\n }\n \ndiff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h\nindex e2d9e34..7c79f17 100644\n--- a/app/test-pmd/testpmd.h\n+++ b/app/test-pmd/testpmd.h\n@@ -85,6 +85,12 @@ typedef uint16_t streamid_t;\n \n #define MAX_QUEUE_ID ((1 << (sizeof(queueid_t) * 8)) - 1)\n \n+#if defined RTE_LIBRTE_PMD_SOFTNIC && defined RTE_LIBRTE_SCHED\n+#define TM_MODE\t\t\t1\n+#else\n+#define TM_MODE\t\t\t0\n+#endif\n+\n enum {\n \tPORT_TOPOLOGY_PAIRED,\n \tPORT_TOPOLOGY_CHAINED,\n@@ -164,6 +170,38 @@ struct port_flow {\n \tuint8_t data[]; /**< Storage for pattern/actions. */\n };\n \n+#ifdef TM_MODE\n+/**\n+ * Soft port tm related parameters\n+ */\n+struct softnic_port_tm {\n+\tuint32_t default_hierarchy_enable; /**< def hierarchy enable flag */\n+\tuint32_t hierarchy_config;  /**< set to 1 if hierarchy configured */\n+\n+\tuint32_t n_subports_per_port;  /**< Num of subport nodes per port */\n+\tuint32_t n_pipes_per_subport;  /**< Num of pipe nodes per subport */\n+\n+\tuint64_t tm_pktfield0_slabpos;\t/**< Pkt field position for subport */\n+\tuint64_t tm_pktfield0_slabmask; /**< Pkt field mask for the subport */\n+\tuint64_t tm_pktfield0_slabshr;\n+\tuint64_t tm_pktfield1_slabpos; /**< Pkt field position for the pipe */\n+\tuint64_t tm_pktfield1_slabmask; /**< Pkt field mask for the pipe */\n+\tuint64_t tm_pktfield1_slabshr;\n+\tuint64_t tm_pktfield2_slabpos; /**< Pkt field position table index */\n+\tuint64_t tm_pktfield2_slabmask;\t/**< Pkt field mask for tc table idx */\n+\tuint64_t tm_pktfield2_slabshr;\n+\tuint64_t tm_tc_table[64];  /**< TC translation table */\n+};\n+\n+/**\n+ * The data structure associate with softnic port\n+ */\n+struct softnic_port {\n+\tunsigned int tm_flag;\t/**< set to 1 if tm feature is enabled */\n+\tstruct softnic_port_tm tm;\t/**< softnic port tm parameters */\n+};\n+#endif\n+\n /**\n  * The data structure associated with each port.\n  */\n@@ -197,6 +235,10 @@ struct rte_port {\n \tuint32_t                mc_addr_nb; /**< nb. of addr. in mc_addr_pool */\n \tuint8_t                 slave_flag; /**< bonding slave port */\n \tstruct port_flow        *flow_list; /**< Associated flows. */\n+#ifdef TM_MODE\n+\tunsigned int\t\t\tsoftnic_enable;\t/**< softnic flag */\n+\tstruct softnic_port     softport;  /**< softnic port params */\n+#endif\n };\n \n /**\n@@ -257,6 +299,10 @@ extern struct fwd_engine rx_only_engine;\n extern struct fwd_engine tx_only_engine;\n extern struct fwd_engine csum_fwd_engine;\n extern struct fwd_engine icmp_echo_engine;\n+#ifdef TM_MODE\n+extern struct fwd_engine softnic_tm_engine;\n+extern struct fwd_engine softnic_tm_bypass_engine;\n+#endif\n #ifdef RTE_LIBRTE_IEEE1588\n extern struct fwd_engine ieee1588_fwd_engine;\n #endif\ndiff --git a/app/test-pmd/tm.c b/app/test-pmd/tm.c\nnew file mode 100644\nindex 0000000..9021e26\n--- /dev/null\n+++ b/app/test-pmd/tm.c\n@@ -0,0 +1,865 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2017 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+#include <stdio.h>\n+#include <sys/stat.h>\n+\n+#include <rte_cycles.h>\n+#include <rte_mbuf.h>\n+#include <rte_ethdev.h>\n+#include <rte_flow.h>\n+#include <rte_meter.h>\n+#include <rte_eth_softnic.h>\n+#include <rte_tm.h>\n+\n+#include \"testpmd.h\"\n+\n+#define SUBPORT_NODES_PER_PORT\t\t1\n+#define PIPE_NODES_PER_SUBPORT\t\t4096\n+#define TC_NODES_PER_PIPE\t\t\t4\n+#define QUEUE_NODES_PER_TC\t\t\t4\n+\n+#define NUM_PIPE_NODES\t\t\t\t\t\t\\\n+\t(SUBPORT_NODES_PER_PORT * PIPE_NODES_PER_SUBPORT)\n+\n+#define NUM_TC_NODES\t\t\t\t\t\t\\\n+\t(NUM_PIPE_NODES * TC_NODES_PER_PIPE)\n+\n+#define ROOT_NODE_ID\t\t\t\t1000000\n+#define SUBPORT_NODES_START_ID\t\t900000\n+#define PIPE_NODES_START_ID\t\t\t800000\n+#define TC_NODES_START_ID\t\t\t700000\n+\n+#define STATS_MASK_DEFAULT\t\t\t\t\t\\\n+\t(RTE_TM_STATS_N_PKTS |\t\t\t\t\t\\\n+\tRTE_TM_STATS_N_BYTES |\t\t\t\t\t\\\n+\tRTE_TM_STATS_N_PKTS_GREEN_DROPPED |\t\t\t\\\n+\tRTE_TM_STATS_N_BYTES_GREEN_DROPPED)\n+\n+#define STATS_MASK_QUEUE\t\t\t\t\t\\\n+\t(STATS_MASK_DEFAULT |\t\t\t\t\t\\\n+\tRTE_TM_STATS_N_PKTS_QUEUED)\n+\n+#define BYTES_IN_MBPS\t\t\t\t(1000 * 1000 / 8)\n+#define TOKEN_BUCKET_SIZE\t\t\t1000000\n+\n+/* TM Hierarchy Levels */\n+enum tm_hierarchy_level {\n+\tTM_NODE_LEVEL_PORT = 0,\n+\tTM_NODE_LEVEL_SUBPORT,\n+\tTM_NODE_LEVEL_PIPE,\n+\tTM_NODE_LEVEL_TC,\n+\tTM_NODE_LEVEL_QUEUE,\n+\tTM_NODE_LEVEL_MAX,\n+};\n+\n+struct tm_hierarchy {\n+\t/* TM Nodes */\n+\tuint32_t root_node_id;\n+\tuint32_t subport_node_id[SUBPORT_NODES_PER_PORT];\n+\tuint32_t pipe_node_id[SUBPORT_NODES_PER_PORT][PIPE_NODES_PER_SUBPORT];\n+\tuint32_t tc_node_id[NUM_PIPE_NODES][TC_NODES_PER_PIPE];\n+\tuint32_t queue_node_id[NUM_TC_NODES][QUEUE_NODES_PER_TC];\n+\n+\t/* TM Hierarchy Nodes Shaper Rates */\n+\tuint32_t root_node_shaper_rate;\n+\tuint32_t subport_node_shaper_rate;\n+\tuint32_t pipe_node_shaper_rate;\n+\tuint32_t tc_node_shaper_rate;\n+\tuint32_t tc_node_shared_shaper_rate;\n+\n+\tuint32_t n_shapers;\n+};\n+\n+#define BITFIELD(byte_array, slab_pos, slab_mask, slab_shr)\t\\\n+({\t\t\t\t\t\t\t\t\\\n+\tuint64_t slab = *((uint64_t *) &byte_array[slab_pos]);\t\\\n+\tuint64_t val =\t\t\t\t\\\n+\t\t(rte_be_to_cpu_64(slab) & slab_mask) >> slab_shr;\t\\\n+\tval;\t\t\t\t\t\t\\\n+})\n+\n+#define RTE_SCHED_PORT_HIERARCHY(subport, pipe,           \\\n+\ttraffic_class, queue, color)                          \\\n+\t((((uint64_t) (queue)) & 0x3) |                       \\\n+\t((((uint64_t) (traffic_class)) & 0x3) << 2) |         \\\n+\t((((uint64_t) (color)) & 0x3) << 4) |                 \\\n+\t((((uint64_t) (subport)) & 0xFFFF) << 16) |           \\\n+\t((((uint64_t) (pipe)) & 0xFFFFFFFF) << 32))\n+\n+\n+static void\n+pkt_metadata_set(struct rte_port *p, struct rte_mbuf **pkts,\n+\tuint32_t n_pkts)\n+{\n+\tstruct softnic_port_tm *tm = &p->softport.tm;\n+\tuint32_t i;\n+\n+\tfor (i = 0; i < (n_pkts & (~0x3)); i += 4) {\n+\t\tstruct rte_mbuf *pkt0 = pkts[i];\n+\t\tstruct rte_mbuf *pkt1 = pkts[i + 1];\n+\t\tstruct rte_mbuf *pkt2 = pkts[i + 2];\n+\t\tstruct rte_mbuf *pkt3 = pkts[i + 3];\n+\n+\t\tuint8_t *pkt0_data = rte_pktmbuf_mtod(pkt0, uint8_t *);\n+\t\tuint8_t *pkt1_data = rte_pktmbuf_mtod(pkt1, uint8_t *);\n+\t\tuint8_t *pkt2_data = rte_pktmbuf_mtod(pkt2, uint8_t *);\n+\t\tuint8_t *pkt3_data = rte_pktmbuf_mtod(pkt3, uint8_t *);\n+\n+\t\tuint64_t pkt0_subport = BITFIELD(pkt0_data,\n+\t\t\t\t\ttm->tm_pktfield0_slabpos,\n+\t\t\t\t\ttm->tm_pktfield0_slabmask,\n+\t\t\t\t\ttm->tm_pktfield0_slabshr);\n+\t\tuint64_t pkt0_pipe = BITFIELD(pkt0_data,\n+\t\t\t\t\ttm->tm_pktfield1_slabpos,\n+\t\t\t\t\ttm->tm_pktfield1_slabmask,\n+\t\t\t\t\ttm->tm_pktfield1_slabshr);\n+\t\tuint64_t pkt0_dscp = BITFIELD(pkt0_data,\n+\t\t\t\t\ttm->tm_pktfield2_slabpos,\n+\t\t\t\t\ttm->tm_pktfield2_slabmask,\n+\t\t\t\t\ttm->tm_pktfield2_slabshr);\n+\t\tuint32_t pkt0_tc = tm->tm_tc_table[pkt0_dscp & 0x3F] >> 2;\n+\t\tuint32_t pkt0_tc_q = tm->tm_tc_table[pkt0_dscp & 0x3F] & 0x3;\n+\t\tuint64_t pkt1_subport = BITFIELD(pkt1_data,\n+\t\t\t\t\ttm->tm_pktfield0_slabpos,\n+\t\t\t\t\ttm->tm_pktfield0_slabmask,\n+\t\t\t\t\ttm->tm_pktfield0_slabshr);\n+\t\tuint64_t pkt1_pipe = BITFIELD(pkt1_data,\n+\t\t\t\t\ttm->tm_pktfield1_slabpos,\n+\t\t\t\t\ttm->tm_pktfield1_slabmask,\n+\t\t\t\t\ttm->tm_pktfield1_slabshr);\n+\t\tuint64_t pkt1_dscp = BITFIELD(pkt1_data,\n+\t\t\t\t\ttm->tm_pktfield2_slabpos,\n+\t\t\t\t\ttm->tm_pktfield2_slabmask,\n+\t\t\t\t\ttm->tm_pktfield2_slabshr);\n+\t\tuint32_t pkt1_tc = tm->tm_tc_table[pkt1_dscp & 0x3F] >> 2;\n+\t\tuint32_t pkt1_tc_q = tm->tm_tc_table[pkt1_dscp & 0x3F] & 0x3;\n+\n+\t\tuint64_t pkt2_subport = BITFIELD(pkt2_data,\n+\t\t\t\t\ttm->tm_pktfield0_slabpos,\n+\t\t\t\t\ttm->tm_pktfield0_slabmask,\n+\t\t\t\t\ttm->tm_pktfield0_slabshr);\n+\t\tuint64_t pkt2_pipe = BITFIELD(pkt2_data,\n+\t\t\t\t\ttm->tm_pktfield1_slabpos,\n+\t\t\t\t\ttm->tm_pktfield1_slabmask,\n+\t\t\t\t\ttm->tm_pktfield1_slabshr);\n+\t\tuint64_t pkt2_dscp = BITFIELD(pkt2_data,\n+\t\t\t\t\ttm->tm_pktfield2_slabpos,\n+\t\t\t\t\ttm->tm_pktfield2_slabmask,\n+\t\t\t\t\ttm->tm_pktfield2_slabshr);\n+\t\tuint32_t pkt2_tc = tm->tm_tc_table[pkt2_dscp & 0x3F] >> 2;\n+\t\tuint32_t pkt2_tc_q = tm->tm_tc_table[pkt2_dscp & 0x3F] & 0x3;\n+\n+\t\tuint64_t pkt3_subport = BITFIELD(pkt3_data,\n+\t\t\t\t\ttm->tm_pktfield0_slabpos,\n+\t\t\t\t\ttm->tm_pktfield0_slabmask,\n+\t\t\t\t\ttm->tm_pktfield0_slabshr);\n+\t\tuint64_t pkt3_pipe = BITFIELD(pkt3_data,\n+\t\t\t\t\ttm->tm_pktfield1_slabpos,\n+\t\t\t\t\ttm->tm_pktfield1_slabmask,\n+\t\t\t\t\ttm->tm_pktfield1_slabshr);\n+\t\tuint64_t pkt3_dscp = BITFIELD(pkt3_data,\n+\t\t\t\t\ttm->tm_pktfield2_slabpos,\n+\t\t\t\t\ttm->tm_pktfield2_slabmask,\n+\t\t\t\t\ttm->tm_pktfield2_slabshr);\n+\t\tuint32_t pkt3_tc = tm->tm_tc_table[pkt3_dscp & 0x3F] >> 2;\n+\t\tuint32_t pkt3_tc_q = tm->tm_tc_table[pkt3_dscp & 0x3F] & 0x3;\n+\n+\t\tuint64_t pkt0_sched = RTE_SCHED_PORT_HIERARCHY(pkt0_subport,\n+\t\t\t\t\t\tpkt0_pipe,\n+\t\t\t\t\t\tpkt0_tc,\n+\t\t\t\t\t\tpkt0_tc_q,\n+\t\t\t\t\t\t0);\n+\t\tuint64_t pkt1_sched = RTE_SCHED_PORT_HIERARCHY(pkt1_subport,\n+\t\t\t\t\t\tpkt1_pipe,\n+\t\t\t\t\t\tpkt1_tc,\n+\t\t\t\t\t\tpkt1_tc_q,\n+\t\t\t\t\t\t0);\n+\t\tuint64_t pkt2_sched = RTE_SCHED_PORT_HIERARCHY(pkt2_subport,\n+\t\t\t\t\t\tpkt2_pipe,\n+\t\t\t\t\t\tpkt2_tc,\n+\t\t\t\t\t\tpkt2_tc_q,\n+\t\t\t\t\t\t0);\n+\t\tuint64_t pkt3_sched = RTE_SCHED_PORT_HIERARCHY(pkt3_subport,\n+\t\t\t\t\t\tpkt3_pipe,\n+\t\t\t\t\t\tpkt3_tc,\n+\t\t\t\t\t\tpkt3_tc_q,\n+\t\t\t\t\t\t0);\n+\n+\t\tpkt0->hash.sched.lo = pkt0_sched & 0xFFFFFFFF;\n+\t\tpkt0->hash.sched.hi = pkt0_sched >> 32;\n+\t\tpkt1->hash.sched.lo = pkt1_sched & 0xFFFFFFFF;\n+\t\tpkt1->hash.sched.hi = pkt1_sched >> 32;\n+\t\tpkt2->hash.sched.lo = pkt2_sched & 0xFFFFFFFF;\n+\t\tpkt2->hash.sched.hi = pkt2_sched >> 32;\n+\t\tpkt3->hash.sched.lo = pkt3_sched & 0xFFFFFFFF;\n+\t\tpkt3->hash.sched.hi = pkt3_sched >> 32;\n+\t}\n+\n+\tfor (; i < n_pkts; i++)\t{\n+\t\tstruct rte_mbuf *pkt = pkts[i];\n+\n+\t\tuint8_t *pkt_data = rte_pktmbuf_mtod(pkt, uint8_t *);\n+\n+\t\tuint64_t pkt_subport = BITFIELD(pkt_data,\n+\t\t\t\t\ttm->tm_pktfield0_slabpos,\n+\t\t\t\t\ttm->tm_pktfield0_slabmask,\n+\t\t\t\t\ttm->tm_pktfield0_slabshr);\n+\t\tuint64_t pkt_pipe = BITFIELD(pkt_data,\n+\t\t\t\t\ttm->tm_pktfield1_slabpos,\n+\t\t\t\t\ttm->tm_pktfield1_slabmask,\n+\t\t\t\t\ttm->tm_pktfield1_slabshr);\n+\t\tuint64_t pkt_dscp = BITFIELD(pkt_data,\n+\t\t\t\t\ttm->tm_pktfield2_slabpos,\n+\t\t\t\t\ttm->tm_pktfield2_slabmask,\n+\t\t\t\t\ttm->tm_pktfield2_slabshr);\n+\t\tuint32_t pkt_tc = tm->tm_tc_table[pkt_dscp & 0x3F] >> 2;\n+\t\tuint32_t pkt_tc_q = tm->tm_tc_table[pkt_dscp & 0x3F] & 0x3;\n+\n+\t\tuint64_t pkt_sched = RTE_SCHED_PORT_HIERARCHY(pkt_subport,\n+\t\t\t\t\t\tpkt_pipe,\n+\t\t\t\t\t\tpkt_tc,\n+\t\t\t\t\t\tpkt_tc_q,\n+\t\t\t\t\t\t0);\n+\n+\t\tpkt->hash.sched.lo = pkt_sched & 0xFFFFFFFF;\n+\t\tpkt->hash.sched.hi = pkt_sched >> 32;\n+\t}\n+}\n+\n+/*\n+ * Soft port packet forward\n+ */\n+static void\n+softport_packet_fwd(struct fwd_stream *fs)\n+{\n+\tstruct rte_mbuf *pkts_burst[MAX_PKT_BURST];\n+\tstruct rte_port *rte_tx_port = &ports[fs->tx_port];\n+\tuint16_t nb_rx;\n+\tuint16_t nb_tx;\n+\tuint32_t retry;\n+\n+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES\n+\tuint64_t start_tsc;\n+\tuint64_t end_tsc;\n+\tuint64_t core_cycles;\n+#endif\n+\n+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES\n+\tstart_tsc = rte_rdtsc();\n+#endif\n+\n+\t/*  Packets Receive */\n+\tnb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue,\n+\t\t\tpkts_burst, nb_pkt_per_burst);\n+\tfs->rx_packets += nb_rx;\n+\n+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS\n+\tfs->rx_burst_stats.pkt_burst_spread[nb_rx]++;\n+#endif\n+\n+\tif (rte_tx_port->softnic_enable) {\n+\t\t/* Set packet metadata if tm flag enabled */\n+\t\tif (rte_tx_port->softport.tm_flag)\n+\t\t\tpkt_metadata_set(rte_tx_port, pkts_burst, nb_rx);\n+\n+\t\t/* Softport run */\n+\t\trte_pmd_softnic_run(fs->tx_port);\n+\t}\n+\tnb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue,\n+\t\t\tpkts_burst, nb_rx);\n+\n+\t/* Retry if necessary */\n+\tif (unlikely(nb_tx < nb_rx) && fs->retry_enabled) {\n+\t\tretry = 0;\n+\t\twhile (nb_tx < nb_rx && retry++ < burst_tx_retry_num) {\n+\t\t\trte_delay_us(burst_tx_delay_time);\n+\t\t\tnb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue,\n+\t\t\t\t\t&pkts_burst[nb_tx], nb_rx - nb_tx);\n+\t\t}\n+\t}\n+\tfs->tx_packets += nb_tx;\n+\n+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS\n+\tfs->tx_burst_stats.pkt_burst_spread[nb_tx]++;\n+#endif\n+\n+\tif (unlikely(nb_tx < nb_rx)) {\n+\t\tfs->fwd_dropped += (nb_rx - nb_tx);\n+\t\tdo {\n+\t\t\trte_pktmbuf_free(pkts_burst[nb_tx]);\n+\t\t} while (++nb_tx < nb_rx);\n+\t}\n+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES\n+\tend_tsc = rte_rdtsc();\n+\tcore_cycles = (end_tsc - start_tsc);\n+\tfs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles);\n+#endif\n+}\n+\n+static void\n+set_tm_hiearchy_nodes_shaper_rate(portid_t port_id, struct tm_hierarchy *h)\n+{\n+\tstruct rte_eth_link link_params;\n+\tuint64_t tm_port_rate;\n+\n+\tmemset(&link_params, 0, sizeof(link_params));\n+\n+\trte_eth_link_get(port_id, &link_params);\n+\ttm_port_rate = link_params.link_speed * BYTES_IN_MBPS;\n+\n+\tif (tm_port_rate > UINT32_MAX)\n+\t\ttm_port_rate = UINT32_MAX;\n+\n+\t/* Set tm hierarchy shapers rate */\n+\th->root_node_shaper_rate = tm_port_rate;\n+\th->subport_node_shaper_rate =\n+\t\ttm_port_rate / SUBPORT_NODES_PER_PORT;\n+\th->pipe_node_shaper_rate\n+\t\t= h->subport_node_shaper_rate / PIPE_NODES_PER_SUBPORT;\n+\th->tc_node_shaper_rate = h->pipe_node_shaper_rate;\n+\th->tc_node_shared_shaper_rate = h->subport_node_shaper_rate;\n+}\n+\n+static int\n+softport_tm_root_node_add(portid_t port_id, struct tm_hierarchy *h,\n+\tstruct rte_tm_error *error)\n+{\n+\tstruct rte_tm_node_params rnp;\n+\tstruct rte_tm_shaper_params rsp;\n+\tuint32_t priority, weight, level_id, shaper_profile_id;\n+\n+\tmemset(&rsp, 0, sizeof(struct rte_tm_shaper_params));\n+\tmemset(&rnp, 0, sizeof(struct rte_tm_node_params));\n+\n+\t/* Shaper profile Parameters */\n+\trsp.peak.rate = h->root_node_shaper_rate;\n+\trsp.peak.size = TOKEN_BUCKET_SIZE;\n+\trsp.pkt_length_adjust = RTE_TM_ETH_FRAMING_OVERHEAD_FCS;\n+\tshaper_profile_id = 0;\n+\n+\tif (rte_tm_shaper_profile_add(port_id, shaper_profile_id,\n+\t\t&rsp, error)) {\n+\t\tprintf(\"%s ERROR(%d)-%s!(shaper_id %u)\\n \",\n+\t\t\t__func__, error->type, error->message,\n+\t\t\tshaper_profile_id);\n+\t\treturn -1;\n+\t}\n+\n+\t/* Root Node Parameters */\n+\th->root_node_id = ROOT_NODE_ID;\n+\tweight = 1;\n+\tpriority = 0;\n+\tlevel_id = TM_NODE_LEVEL_PORT;\n+\trnp.shaper_profile_id = shaper_profile_id;\n+\trnp.nonleaf.n_sp_priorities = 1;\n+\trnp.stats_mask = STATS_MASK_DEFAULT;\n+\n+\t/* Add Node to TM Hierarchy */\n+\tif (rte_tm_node_add(port_id, h->root_node_id, RTE_TM_NODE_ID_NULL,\n+\t\tpriority, weight, level_id, &rnp, error)) {\n+\t\tprintf(\"%s ERROR(%d)-%s!(node_id %u, parent_id %u, level %u)\\n\",\n+\t\t\t__func__, error->type, error->message,\n+\t\t\th->root_node_id, RTE_TM_NODE_ID_NULL,\n+\t\t\tlevel_id);\n+\t\treturn -1;\n+\t}\n+\t/* Update */\n+\th->n_shapers++;\n+\n+\tprintf(\"  Root node added (Start id %u, Count %u, level %u)\\n\",\n+\t\th->root_node_id, 1, level_id);\n+\n+\treturn 0;\n+}\n+\n+static int\n+softport_tm_subport_node_add(portid_t port_id, struct tm_hierarchy *h,\n+\tstruct rte_tm_error *error)\n+{\n+\tuint32_t subport_parent_node_id, subport_node_id;\n+\tstruct rte_tm_node_params snp;\n+\tstruct rte_tm_shaper_params ssp;\n+\tuint32_t priority, weight, level_id, shaper_profile_id;\n+\tuint32_t i;\n+\n+\tmemset(&ssp, 0, sizeof(struct rte_tm_shaper_params));\n+\tmemset(&snp, 0, sizeof(struct rte_tm_node_params));\n+\n+\tshaper_profile_id = h->n_shapers;\n+\n+\t/* Add Shaper Profile to TM Hierarchy */\n+\tfor (i = 0; i < SUBPORT_NODES_PER_PORT; i++) {\n+\t\tssp.peak.rate = h->subport_node_shaper_rate;\n+\t\tssp.peak.size = TOKEN_BUCKET_SIZE;\n+\t\tssp.pkt_length_adjust = RTE_TM_ETH_FRAMING_OVERHEAD_FCS;\n+\n+\t\tif (rte_tm_shaper_profile_add(port_id, shaper_profile_id,\n+\t\t\t&ssp, error)) {\n+\t\t\tprintf(\"%s ERROR(%d)-%s!(shaper_id %u)\\n \",\n+\t\t\t\t__func__, error->type, error->message,\n+\t\t\t\tshaper_profile_id);\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\t/* Node Parameters */\n+\t\th->subport_node_id[i] = SUBPORT_NODES_START_ID + i;\n+\t\tsubport_parent_node_id = h->root_node_id;\n+\t\tweight = 1;\n+\t\tpriority = 0;\n+\t\tlevel_id = TM_NODE_LEVEL_SUBPORT;\n+\t\tsnp.shaper_profile_id = shaper_profile_id;\n+\t\tsnp.nonleaf.n_sp_priorities = 1;\n+\t\tsnp.stats_mask = STATS_MASK_DEFAULT;\n+\n+\t\t/* Add Node to TM Hiearchy */\n+\t\tif (rte_tm_node_add(port_id,\n+\t\t\t\th->subport_node_id[i],\n+\t\t\t\tsubport_parent_node_id,\n+\t\t\t\tpriority, weight,\n+\t\t\t\tlevel_id,\n+\t\t\t\t&snp,\n+\t\t\t\terror)) {\n+\t\t\tprintf(\"%s ERROR(%d)-%s!(node %u,parent %u,level %u)\\n\",\n+\t\t\t\t\t__func__,\n+\t\t\t\t\terror->type,\n+\t\t\t\t\terror->message,\n+\t\t\t\t\th->subport_node_id[i],\n+\t\t\t\t\tsubport_parent_node_id,\n+\t\t\t\t\tlevel_id);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tshaper_profile_id++;\n+\t\tsubport_node_id++;\n+\t}\n+\t/* Update */\n+\th->n_shapers = shaper_profile_id;\n+\n+\tprintf(\"  Subport nodes added (Start id %u, Count %u, level %u)\\n\",\n+\t\th->subport_node_id[0], SUBPORT_NODES_PER_PORT, level_id);\n+\n+\treturn 0;\n+}\n+\n+static int\n+softport_tm_pipe_node_add(portid_t port_id, struct tm_hierarchy *h,\n+\tstruct rte_tm_error *error)\n+{\n+\tuint32_t pipe_parent_node_id;\n+\tstruct rte_tm_node_params pnp;\n+\tstruct rte_tm_shaper_params psp;\n+\tuint32_t priority, weight, level_id, shaper_profile_id;\n+\tuint32_t i, j;\n+\n+\tmemset(&psp, 0, sizeof(struct rte_tm_shaper_params));\n+\tmemset(&pnp, 0, sizeof(struct rte_tm_node_params));\n+\n+\tshaper_profile_id = h->n_shapers;\n+\n+\t/* Shaper Profile Parameters */\n+\tpsp.peak.rate = h->pipe_node_shaper_rate;\n+\tpsp.peak.size = TOKEN_BUCKET_SIZE;\n+\tpsp.pkt_length_adjust = RTE_TM_ETH_FRAMING_OVERHEAD_FCS;\n+\n+\t/* Pipe Node Parameters */\n+\tweight = 1;\n+\tpriority = 0;\n+\tlevel_id = TM_NODE_LEVEL_PIPE;\n+\tpnp.nonleaf.n_sp_priorities = 4;\n+\tpnp.stats_mask = STATS_MASK_DEFAULT;\n+\n+\t/* Add Shaper Profiles and Nodes to TM Hierarchy */\n+\tfor (i = 0; i < SUBPORT_NODES_PER_PORT; i++) {\n+\t\tfor (j = 0; j < PIPE_NODES_PER_SUBPORT; j++) {\n+\t\t\tif (rte_tm_shaper_profile_add(port_id,\n+\t\t\t\tshaper_profile_id, &psp, error)) {\n+\t\t\t\tprintf(\"%s ERROR(%d)-%s!(shaper_id %u)\\n \",\n+\t\t\t\t\t__func__, error->type, error->message,\n+\t\t\t\t\tshaper_profile_id);\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tpnp.shaper_profile_id = shaper_profile_id;\n+\t\t\tpipe_parent_node_id = h->subport_node_id[i];\n+\t\t\th->pipe_node_id[i][j] = PIPE_NODES_START_ID +\n+\t\t\t\t(i * PIPE_NODES_PER_SUBPORT) + j;\n+\n+\t\t\tif (rte_tm_node_add(port_id,\n+\t\t\t\t\th->pipe_node_id[i][j],\n+\t\t\t\t\tpipe_parent_node_id,\n+\t\t\t\t\tpriority, weight, level_id,\n+\t\t\t\t\t&pnp,\n+\t\t\t\t\terror)) {\n+\t\t\t\tprintf(\"%s ERROR(%d)-%s!(node %u,parent %u )\\n\",\n+\t\t\t\t\t__func__,\n+\t\t\t\t\terror->type,\n+\t\t\t\t\terror->message,\n+\t\t\t\t\th->pipe_node_id[i][j],\n+\t\t\t\t\tpipe_parent_node_id);\n+\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tshaper_profile_id++;\n+\t\t}\n+\t}\n+\t/* Update */\n+\th->n_shapers = shaper_profile_id;\n+\n+\tprintf(\"  Pipe nodes added (Start id %u, Count %u, level %u)\\n\",\n+\t\th->pipe_node_id[0][0], NUM_PIPE_NODES, level_id);\n+\n+\treturn 0;\n+}\n+\n+static int\n+softport_tm_tc_node_add(portid_t port_id, struct tm_hierarchy *h,\n+\tstruct rte_tm_error *error)\n+{\n+\tuint32_t tc_parent_node_id;\n+\tstruct rte_tm_node_params tnp;\n+\tstruct rte_tm_shaper_params tsp, tssp;\n+\tuint32_t shared_shaper_profile_id[TC_NODES_PER_PIPE];\n+\tuint32_t priority, weight, level_id, shaper_profile_id;\n+\tuint32_t pos, n_tc_nodes, i, j, k;\n+\n+\tmemset(&tsp, 0, sizeof(struct rte_tm_shaper_params));\n+\tmemset(&tssp, 0, sizeof(struct rte_tm_shaper_params));\n+\tmemset(&tnp, 0, sizeof(struct rte_tm_node_params));\n+\n+\tshaper_profile_id = h->n_shapers;\n+\n+\t/* Private Shaper Profile (TC) Parameters */\n+\ttsp.peak.rate = h->tc_node_shaper_rate;\n+\ttsp.peak.size = TOKEN_BUCKET_SIZE;\n+\ttsp.pkt_length_adjust = RTE_TM_ETH_FRAMING_OVERHEAD_FCS;\n+\n+\t/* Shared Shaper Profile (TC) Parameters */\n+\ttssp.peak.rate = h->tc_node_shared_shaper_rate;\n+\ttssp.peak.size = TOKEN_BUCKET_SIZE;\n+\ttssp.pkt_length_adjust = RTE_TM_ETH_FRAMING_OVERHEAD_FCS;\n+\n+\t/* TC Node Parameters */\n+\tweight = 1;\n+\tlevel_id = TM_NODE_LEVEL_TC;\n+\ttnp.n_shared_shapers = 1;\n+\ttnp.nonleaf.n_sp_priorities = 1;\n+\ttnp.stats_mask = STATS_MASK_DEFAULT;\n+\n+\t/* Add Shared Shaper Profiles to TM Hierarchy */\n+\tfor (i = 0; i < TC_NODES_PER_PIPE; i++) {\n+\t\tshared_shaper_profile_id[i] = shaper_profile_id;\n+\n+\t\tif (rte_tm_shaper_profile_add(port_id,\n+\t\t\tshared_shaper_profile_id[i], &tssp, error)) {\n+\t\t\tprintf(\"%s ERROR(%d)-%s!(Shared shaper profileid %u)\\n\",\n+\t\t\t\t__func__, error->type, error->message,\n+\t\t\t\tshared_shaper_profile_id[i]);\n+\n+\t\t\treturn -1;\n+\t\t}\n+\t\tif (rte_tm_shared_shaper_add_update(port_id,  i,\n+\t\t\tshared_shaper_profile_id[i], error)) {\n+\t\t\tprintf(\"%s ERROR(%d)-%s!(Shared shaper id %u)\\n\",\n+\t\t\t\t__func__, error->type, error->message, i);\n+\n+\t\t\treturn -1;\n+\t\t}\n+\t\tshaper_profile_id++;\n+\t}\n+\n+\t/* Add Shaper Profiles and Nodes to TM Hierarchy */\n+\tn_tc_nodes = 0;\n+\tfor (i = 0; i < SUBPORT_NODES_PER_PORT; i++) {\n+\t\tfor (j = 0; j < PIPE_NODES_PER_SUBPORT; j++) {\n+\t\t\tfor (k = 0; k < TC_NODES_PER_PIPE ; k++) {\n+\t\t\t\tpriority = k;\n+\t\t\t\ttc_parent_node_id = h->pipe_node_id[i][j];\n+\t\t\t\ttnp.shared_shaper_id =\n+\t\t\t\t\t(uint32_t *)calloc(1, sizeof(uint32_t));\n+\t\t\t\ttnp.shared_shaper_id[0] = k;\n+\t\t\t\tpos = j + (i * PIPE_NODES_PER_SUBPORT);\n+\t\t\t\th->tc_node_id[pos][k] =\n+\t\t\t\t\tTC_NODES_START_ID + n_tc_nodes;\n+\n+\t\t\t\tif (rte_tm_shaper_profile_add(port_id,\n+\t\t\t\t\tshaper_profile_id, &tsp, error)) {\n+\t\t\t\t\tprintf(\"%s ERROR(%d)-%s!(shaper %u)\\n\",\n+\t\t\t\t\t\t__func__, error->type,\n+\t\t\t\t\t\terror->message,\n+\t\t\t\t\t\tshaper_profile_id);\n+\n+\t\t\t\t\treturn -1;\n+\t\t\t\t}\n+\t\t\t\ttnp.shaper_profile_id = shaper_profile_id;\n+\t\t\t\tif (rte_tm_node_add(port_id,\n+\t\t\t\t\t\th->tc_node_id[pos][k],\n+\t\t\t\t\t\ttc_parent_node_id,\n+\t\t\t\t\t\tpriority, weight,\n+\t\t\t\t\t\tlevel_id,\n+\t\t\t\t\t\t&tnp, error)) {\n+\t\t\t\t\tprintf(\"%s ERROR(%d)-%s!(node id %u)\\n\",\n+\t\t\t\t\t\t__func__,\n+\t\t\t\t\t\terror->type,\n+\t\t\t\t\t\terror->message,\n+\t\t\t\t\t\th->tc_node_id[pos][k]);\n+\n+\t\t\t\t\treturn -1;\n+\t\t\t\t}\n+\t\t\t\tshaper_profile_id++;\n+\t\t\t\tn_tc_nodes++;\n+\t\t\t}\n+\t\t}\n+\t}\n+\t/* Update */\n+\th->n_shapers = shaper_profile_id;\n+\n+\tprintf(\"  TC nodes added (Start id %u, Count %u, level %u)\\n\",\n+\t\th->tc_node_id[0][0], n_tc_nodes, level_id);\n+\n+\treturn 0;\n+}\n+\n+static int\n+softport_tm_queue_node_add(portid_t port_id, struct tm_hierarchy *h,\n+\tstruct rte_tm_error *error)\n+{\n+\tuint32_t queue_parent_node_id;\n+\tstruct rte_tm_node_params qnp;\n+\tuint32_t priority, weight, level_id, pos;\n+\tuint32_t n_queue_nodes, i, j, k;\n+\n+\tmemset(&qnp, 0, sizeof(struct rte_tm_node_params));\n+\n+\t/* Queue Node Parameters */\n+\tpriority = 0;\n+\tweight = 1;\n+\tlevel_id = TM_NODE_LEVEL_QUEUE;\n+\tqnp.shaper_profile_id = RTE_TM_SHAPER_PROFILE_ID_NONE;\n+\tqnp.leaf.cman = RTE_TM_CMAN_TAIL_DROP;\n+\tqnp.stats_mask = STATS_MASK_QUEUE;\n+\n+\t/* Add Queue Nodes to TM Hierarchy */\n+\tn_queue_nodes = 0;\n+\tfor (i = 0; i < NUM_PIPE_NODES; i++) {\n+\t\tfor (j = 0; j < TC_NODES_PER_PIPE; j++) {\n+\t\t\tqueue_parent_node_id = h->tc_node_id[i][j];\n+\t\t\tfor (k = 0; k < QUEUE_NODES_PER_TC; k++) {\n+\t\t\t\tpos = j + (i * TC_NODES_PER_PIPE);\n+\t\t\t\th->queue_node_id[pos][k] = n_queue_nodes;\n+\t\t\t\tif (rte_tm_node_add(port_id,\n+\t\t\t\t\t\th->queue_node_id[pos][k],\n+\t\t\t\t\t\tqueue_parent_node_id,\n+\t\t\t\t\t\tpriority,\n+\t\t\t\t\t\tweight,\n+\t\t\t\t\t\tlevel_id,\n+\t\t\t\t\t\t&qnp, error)) {\n+\t\t\t\t\tprintf(\"%s ERROR(%d)-%s!(node %u)\\n\",\n+\t\t\t\t\t\t__func__,\n+\t\t\t\t\t\terror->type,\n+\t\t\t\t\t\terror->message,\n+\t\t\t\t\t\th->queue_node_id[pos][k]);\n+\n+\t\t\t\t\treturn -1;\n+\t\t\t\t}\n+\t\t\t\tn_queue_nodes++;\n+\t\t\t}\n+\t\t}\n+\t}\n+\tprintf(\"  Queue nodes added (Start id %u, Count %u, level %u)\\n\",\n+\t\th->queue_node_id[0][0], n_queue_nodes, level_id);\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * TM Packet Field Setup\n+ */\n+static void\n+softport_tm_pktfield_setup(portid_t port_id)\n+{\n+\tstruct rte_port *p = &ports[port_id];\n+\tuint64_t pktfield0_mask = 0;\n+\tuint64_t pktfield1_mask = 0x0000000FFF000000LLU;\n+\tuint64_t pktfield2_mask = 0x00000000000000FCLLU;\n+\n+\tp->softport.tm = (struct softnic_port_tm) {\n+\t\t.n_subports_per_port = SUBPORT_NODES_PER_PORT,\n+\t\t.n_pipes_per_subport = PIPE_NODES_PER_SUBPORT,\n+\n+\t\t/* Packet field to identify subport\n+\t\t *\n+\t\t * Default configuration assumes only one subport, thus\n+\t\t * the subport ID is hardcoded to 0\n+\t\t */\n+\t\t.tm_pktfield0_slabpos = 0,\n+\t\t.tm_pktfield0_slabmask = pktfield0_mask,\n+\t\t.tm_pktfield0_slabshr =\n+\t\t\t__builtin_ctzll(pktfield0_mask),\n+\n+\t\t/* Packet field to identify pipe.\n+\t\t *\n+\t\t * Default value assumes Ethernet/IPv4/UDP packets,\n+\t\t * UDP payload bits 12 .. 23\n+\t\t */\n+\t\t.tm_pktfield1_slabpos = 40,\n+\t\t.tm_pktfield1_slabmask = pktfield1_mask,\n+\t\t.tm_pktfield1_slabshr =\n+\t\t\t__builtin_ctzll(pktfield1_mask),\n+\n+\t\t/* Packet field used as index into TC translation table\n+\t\t * to identify the traffic class and queue.\n+\t\t *\n+\t\t * Default value assumes Ethernet/IPv4 packets, IPv4\n+\t\t * DSCP field\n+\t\t */\n+\t\t.tm_pktfield2_slabpos = 8,\n+\t\t.tm_pktfield2_slabmask = pktfield2_mask,\n+\t\t.tm_pktfield2_slabshr =\n+\t\t\t__builtin_ctzll(pktfield2_mask),\n+\n+\t\t.tm_tc_table = {\n+\t\t\t0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,\n+\t\t\t0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,\n+\t\t\t0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,\n+\t\t\t0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,\n+\t\t}, /**< TC translation table */\n+\t};\n+}\n+\n+static int\n+softport_tm_hierarchy_specify(portid_t port_id, struct rte_tm_error *error)\n+{\n+\n+\tstruct tm_hierarchy h;\n+\tint status;\n+\n+\tmemset(&h, 0, sizeof(struct tm_hierarchy));\n+\n+\t/* TM hierarchy shapers rate */\n+\tset_tm_hiearchy_nodes_shaper_rate(port_id, &h);\n+\n+\t/* Add root node (level 0) */\n+\tstatus = softport_tm_root_node_add(port_id, &h, error);\n+\tif (status)\n+\t\treturn status;\n+\n+\t/* Add subport node (level 1) */\n+\tstatus = softport_tm_subport_node_add(port_id, &h, error);\n+\tif (status)\n+\t\treturn status;\n+\n+\t/* Add pipe nodes (level 2) */\n+\tstatus = softport_tm_pipe_node_add(port_id, &h, error);\n+\tif (status)\n+\t\treturn status;\n+\n+\t/* Add traffic class nodes (level 3) */\n+\tstatus = softport_tm_tc_node_add(port_id, &h, error);\n+\tif (status)\n+\t\treturn status;\n+\n+\t/* Add queue nodes (level 4) */\n+\tstatus = softport_tm_queue_node_add(port_id, &h, error);\n+\tif (status)\n+\t\treturn status;\n+\n+\t/* TM packet fields setup */\n+\tsoftport_tm_pktfield_setup(port_id);\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * Soft port Init\n+ */\n+static void\n+softport_tm_begin(portid_t pi)\n+{\n+\tstruct rte_port *port = &ports[pi];\n+\n+\t/* Soft port TM flag */\n+\tif (port->softport.tm_flag == 1) {\n+\t\tprintf(\"\\n\\n  TM feature available on port %u\\n\", pi);\n+\n+\t\t/* Soft port TM hierarchy configuration */\n+\t\tif ((port->softport.tm.hierarchy_config == 0) &&\n+\t\t\t(port->softport.tm.default_hierarchy_enable == 1)) {\n+\t\t\tstruct rte_tm_error error;\n+\t\t\tint status;\n+\n+\t\t\t/* Stop port */\n+\t\t\trte_eth_dev_stop(pi);\n+\n+\t\t\t/* TM hierarchy specification */\n+\t\t\tstatus = softport_tm_hierarchy_specify(pi, &error);\n+\t\t\tif (status) {\n+\t\t\t\tprintf(\"  TM Hierarchy built error(%d) - %s\\n\",\n+\t\t\t\t\terror.type, error.message);\n+\t\t\t\treturn;\n+\t\t\t}\n+\t\t\tprintf(\"\\n  TM Hierarchy Specified!\\n\\v\");\n+\n+\t\t\t/* TM hierarchy commit */\n+\t\t\tstatus = rte_tm_hierarchy_commit(pi, 0, &error);\n+\t\t\tif (status) {\n+\t\t\t\tprintf(\"  Hierarchy commit error(%d) - %s\\n\",\n+\t\t\t\t\terror.type, error.message);\n+\t\t\t\treturn;\n+\t\t\t}\n+\t\t\tprintf(\"  Hierarchy Committed (port %u)!\", pi);\n+\t\t\tport->softport.tm.hierarchy_config = 1;\n+\n+\t\t\t/* Start port */\n+\t\t\tstatus = rte_eth_dev_start(pi);\n+\t\t\tif (status) {\n+\t\t\t\tprintf(\"\\n  Port %u start error!\\n\", pi);\n+\t\t\t\treturn;\n+\t\t\t}\n+\t\t\tprintf(\"\\n  Port %u started!\\n\", pi);\n+\t\t\treturn;\n+\t\t}\n+\t}\n+\tprintf(\"\\n  TM feature not available on port %u\", pi);\n+}\n+\n+struct fwd_engine softnic_tm_engine = {\n+\t.fwd_mode_name  = \"tm\",\n+\t.port_fwd_begin = softport_tm_begin,\n+\t.port_fwd_end   = NULL,\n+\t.packet_fwd     = softport_packet_fwd,\n+};\n+\n+struct fwd_engine softnic_tm_bypass_engine = {\n+\t.fwd_mode_name  = \"tm-bypass\",\n+\t.port_fwd_begin = NULL,\n+\t.port_fwd_end   = NULL,\n+\t.packet_fwd     = softport_packet_fwd,\n+};\n",
    "prefixes": [
        "dpdk-dev",
        "v7",
        "5/5"
    ]
}