get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 83972,
    "url": "http://patches.dpdk.org/api/patches/83972/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20201111064936.768604-31-jiawenwu@trustnetic.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": "<20201111064936.768604-31-jiawenwu@trustnetic.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20201111064936.768604-31-jiawenwu@trustnetic.com",
    "date": "2020-11-11T06:49:29",
    "name": "[v2,30/37] net/txgbe: support TM node add and delete",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "0e1ce258280f62072db936548b54270b1bb8a628",
    "submitter": {
        "id": 1932,
        "url": "http://patches.dpdk.org/api/people/1932/?format=api",
        "name": "Jiawen Wu",
        "email": "jiawenwu@trustnetic.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/20201111064936.768604-31-jiawenwu@trustnetic.com/mbox/",
    "series": [
        {
            "id": 13798,
            "url": "http://patches.dpdk.org/api/series/13798/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=13798",
            "date": "2020-11-11T06:49:00",
            "name": "net: add txgbe PMD part 2",
            "version": 2,
            "mbox": "http://patches.dpdk.org/series/13798/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/83972/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/83972/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 063A8A09D2;\n\tWed, 11 Nov 2020 07:58:14 +0100 (CET)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 7E338C834;\n\tWed, 11 Nov 2020 07:48:23 +0100 (CET)",
            "from smtpbgau1.qq.com (smtpbgau1.qq.com [54.206.16.166])\n by dpdk.org (Postfix) with ESMTP id BF84DBE49\n for <dev@dpdk.org>; Wed, 11 Nov 2020 07:48:05 +0100 (CET)",
            "from localhost.localdomain.com (unknown [183.129.236.74])\n by esmtp10.qq.com (ESMTP) with\n id ; Wed, 11 Nov 2020 14:47:58 +0800 (CST)"
        ],
        "X-QQ-mid": "bizesmtp27t1605077279trqola97",
        "X-QQ-SSF": "01400000000000C0C000B00A0000000",
        "X-QQ-FEAT": "zcltNTR4xiASoILHwF7fIw2/hdOxe8D9u7EUa1UKNaU62jixdF2SOczlNEQHD\n NTuElv1sJ+3Mm4NIReiaXs20IyEyAzwlSY1PyZZ59TO/ySrSSuwIFyAOCT3mxtGK5RiCsYR\n yhyJwsqVwGtrARwoYY3M+R6hZ/FQDPq/dX18FzbVvoVWH3/WmA+bkeCF04v/I9q38GU62dD\n VdJypgJWBQsxLCqAuwk2jGZ2dGFU2Qq47Brb0cCY6v6RS/d2M22LrKskDfXISFOd4WblxT7\n EkYI1d5dNdzb+ZgO0xQWN6hFCLuly+syicniW/2Y3FEEajV4uEVMnbluZ7QUBhwwoxl6rsx\n 465/6hqEnGsgiEmZco=",
        "X-QQ-GoodBg": "2",
        "From": "Jiawen Wu <jiawenwu@trustnetic.com>",
        "To": "dev@dpdk.org",
        "Cc": "Jiawen Wu <jiawenwu@trustnetic.com>",
        "Date": "Wed, 11 Nov 2020 14:49:29 +0800",
        "Message-Id": "<20201111064936.768604-31-jiawenwu@trustnetic.com>",
        "X-Mailer": "git-send-email 2.18.4",
        "In-Reply-To": "<20201111064936.768604-1-jiawenwu@trustnetic.com>",
        "References": "<20201111064936.768604-1-jiawenwu@trustnetic.com>",
        "X-QQ-SENDSIZE": "520",
        "Feedback-ID": "bizesmtp:trustnetic.com:qybgforeign:qybgforeign5",
        "X-QQ-Bgrelay": "1",
        "Subject": "[dpdk-dev] [PATCH v2 30/37] net/txgbe: support TM node add and\n\tdelete",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Support traffic manager node add and delete operations.\n\nSigned-off-by: Jiawen Wu <jiawenwu@trustnetic.com>\n---\n drivers/net/txgbe/txgbe_ethdev.h |   1 +\n drivers/net/txgbe/txgbe_tm.c     | 488 +++++++++++++++++++++++++++++++\n 2 files changed, 489 insertions(+)",
    "diff": "diff --git a/drivers/net/txgbe/txgbe_ethdev.h b/drivers/net/txgbe/txgbe_ethdev.h\nindex 533d85617..5f988eead 100644\n--- a/drivers/net/txgbe/txgbe_ethdev.h\n+++ b/drivers/net/txgbe/txgbe_ethdev.h\n@@ -14,6 +14,7 @@\n #include <rte_hash.h>\n #include <rte_hash_crc.h>\n #include <rte_ethdev.h>\n+#include <rte_bus_pci.h>\n #include <rte_tm_driver.h>\n \n /* need update link, bit flag */\ndiff --git a/drivers/net/txgbe/txgbe_tm.c b/drivers/net/txgbe/txgbe_tm.c\nindex 8adb03825..6dd593e54 100644\n--- a/drivers/net/txgbe/txgbe_tm.c\n+++ b/drivers/net/txgbe/txgbe_tm.c\n@@ -16,6 +16,15 @@ static int txgbe_shaper_profile_add(struct rte_eth_dev *dev,\n static int txgbe_shaper_profile_del(struct rte_eth_dev *dev,\n \t\t\t\t    uint32_t shaper_profile_id,\n \t\t\t\t    struct rte_tm_error *error);\n+static int txgbe_node_add(struct rte_eth_dev *dev, uint32_t node_id,\n+\t\t\t  uint32_t parent_node_id, uint32_t priority,\n+\t\t\t  uint32_t weight, uint32_t level_id,\n+\t\t\t  struct rte_tm_node_params *params,\n+\t\t\t  struct rte_tm_error *error);\n+static int txgbe_node_delete(struct rte_eth_dev *dev, uint32_t node_id,\n+\t\t\t     struct rte_tm_error *error);\n+static int txgbe_node_type_get(struct rte_eth_dev *dev, uint32_t node_id,\n+\t\t\t       int *is_leaf, struct rte_tm_error *error);\n static int txgbe_level_capabilities_get(struct rte_eth_dev *dev,\n \t\t\t\t\tuint32_t level_id,\n \t\t\t\t\tstruct rte_tm_level_capabilities *cap,\n@@ -29,6 +38,9 @@ const struct rte_tm_ops txgbe_tm_ops = {\n \t.capabilities_get = txgbe_tm_capabilities_get,\n \t.shaper_profile_add = txgbe_shaper_profile_add,\n \t.shaper_profile_delete = txgbe_shaper_profile_del,\n+\t.node_add = txgbe_node_add,\n+\t.node_delete = txgbe_node_delete,\n+\t.node_type_get = txgbe_node_type_get,\n \t.level_capabilities_get = txgbe_level_capabilities_get,\n \t.node_capabilities_get = txgbe_node_capabilities_get,\n };\n@@ -332,6 +344,482 @@ txgbe_tm_node_search(struct rte_eth_dev *dev, uint32_t node_id,\n \treturn NULL;\n }\n \n+static void\n+txgbe_queue_base_nb_get(struct rte_eth_dev *dev, uint16_t tc_node_no,\n+\t\t\tuint16_t *base, uint16_t *nb)\n+{\n+\tuint8_t nb_tcs = txgbe_tc_nb_get(dev);\n+\tstruct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);\n+\tuint16_t vf_num = pci_dev->max_vfs;\n+\n+\t*base = 0;\n+\t*nb = 0;\n+\n+\t/* VT on */\n+\tif (vf_num) {\n+\t\t/* no DCB */\n+\t\tif (nb_tcs == 1) {\n+\t\t\tif (vf_num >= ETH_32_POOLS) {\n+\t\t\t\t*nb = 2;\n+\t\t\t\t*base = vf_num * 2;\n+\t\t\t} else if (vf_num >= ETH_16_POOLS) {\n+\t\t\t\t*nb = 4;\n+\t\t\t\t*base = vf_num * 4;\n+\t\t\t} else {\n+\t\t\t\t*nb = 8;\n+\t\t\t\t*base = vf_num * 8;\n+\t\t\t}\n+\t\t} else {\n+\t\t\t/* DCB */\n+\t\t\t*nb = 1;\n+\t\t\t*base = vf_num * nb_tcs + tc_node_no;\n+\t\t}\n+\t} else {\n+\t\t/* VT off */\n+\t\tif (nb_tcs == ETH_8_TCS) {\n+\t\t\tswitch (tc_node_no) {\n+\t\t\tcase 0:\n+\t\t\t\t*base = 0;\n+\t\t\t\t*nb = 32;\n+\t\t\t\tbreak;\n+\t\t\tcase 1:\n+\t\t\t\t*base = 32;\n+\t\t\t\t*nb = 32;\n+\t\t\t\tbreak;\n+\t\t\tcase 2:\n+\t\t\t\t*base = 64;\n+\t\t\t\t*nb = 16;\n+\t\t\t\tbreak;\n+\t\t\tcase 3:\n+\t\t\t\t*base = 80;\n+\t\t\t\t*nb = 16;\n+\t\t\t\tbreak;\n+\t\t\tcase 4:\n+\t\t\t\t*base = 96;\n+\t\t\t\t*nb = 8;\n+\t\t\t\tbreak;\n+\t\t\tcase 5:\n+\t\t\t\t*base = 104;\n+\t\t\t\t*nb = 8;\n+\t\t\t\tbreak;\n+\t\t\tcase 6:\n+\t\t\t\t*base = 112;\n+\t\t\t\t*nb = 8;\n+\t\t\t\tbreak;\n+\t\t\tcase 7:\n+\t\t\t\t*base = 120;\n+\t\t\t\t*nb = 8;\n+\t\t\t\tbreak;\n+\t\t\tdefault:\n+\t\t\t\treturn;\n+\t\t\t}\n+\t\t} else {\n+\t\t\tswitch (tc_node_no) {\n+\t\t\t/**\n+\t\t\t * If no VF and no DCB, only 64 queues can be used.\n+\t\t\t * This case also be covered by this \"case 0\".\n+\t\t\t */\n+\t\t\tcase 0:\n+\t\t\t\t*base = 0;\n+\t\t\t\t*nb = 64;\n+\t\t\t\tbreak;\n+\t\t\tcase 1:\n+\t\t\t\t*base = 64;\n+\t\t\t\t*nb = 32;\n+\t\t\t\tbreak;\n+\t\t\tcase 2:\n+\t\t\t\t*base = 96;\n+\t\t\t\t*nb = 16;\n+\t\t\t\tbreak;\n+\t\t\tcase 3:\n+\t\t\t\t*base = 112;\n+\t\t\t\t*nb = 16;\n+\t\t\t\tbreak;\n+\t\t\tdefault:\n+\t\t\t\treturn;\n+\t\t\t}\n+\t\t}\n+\t}\n+}\n+\n+static int\n+txgbe_node_param_check(struct rte_eth_dev *dev, uint32_t node_id,\n+\t\t       uint32_t priority, uint32_t weight,\n+\t\t       struct rte_tm_node_params *params,\n+\t\t       struct rte_tm_error *error)\n+{\n+\tif (node_id == RTE_TM_NODE_ID_NULL) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_ID;\n+\t\terror->message = \"invalid node id\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (priority) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_PRIORITY;\n+\t\terror->message = \"priority should be 0\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (weight != 1) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_WEIGHT;\n+\t\terror->message = \"weight must be 1\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* not support shared shaper */\n+\tif (params->shared_shaper_id) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_SHAPER_ID;\n+\t\terror->message = \"shared shaper not supported\";\n+\t\treturn -EINVAL;\n+\t}\n+\tif (params->n_shared_shapers) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS;\n+\t\terror->message = \"shared shaper not supported\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* for non-leaf node */\n+\tif (node_id >= dev->data->nb_tx_queues) {\n+\t\t/* check the unsupported parameters */\n+\t\tif (params->nonleaf.wfq_weight_mode) {\n+\t\t\terror->type =\n+\t\t\t\tRTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE;\n+\t\t\terror->message = \"WFQ not supported\";\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tif (params->nonleaf.n_sp_priorities != 1) {\n+\t\t\terror->type =\n+\t\t\t\tRTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES;\n+\t\t\terror->message = \"SP priority not supported\";\n+\t\t\treturn -EINVAL;\n+\t\t} else if (params->nonleaf.wfq_weight_mode &&\n+\t\t\t   !(*params->nonleaf.wfq_weight_mode)) {\n+\t\t\terror->type =\n+\t\t\t\tRTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE;\n+\t\t\terror->message = \"WFP should be byte mode\";\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\treturn 0;\n+\t}\n+\n+\t/* for leaf node */\n+\t/* check the unsupported parameters */\n+\tif (params->leaf.cman) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_CMAN;\n+\t\terror->message = \"Congestion management not supported\";\n+\t\treturn -EINVAL;\n+\t}\n+\tif (params->leaf.wred.wred_profile_id !=\n+\t    RTE_TM_WRED_PROFILE_ID_NONE) {\n+\t\terror->type =\n+\t\t\tRTE_TM_ERROR_TYPE_NODE_PARAMS_WRED_PROFILE_ID;\n+\t\terror->message = \"WRED not supported\";\n+\t\treturn -EINVAL;\n+\t}\n+\tif (params->leaf.wred.shared_wred_context_id) {\n+\t\terror->type =\n+\t\t\tRTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_WRED_CONTEXT_ID;\n+\t\terror->message = \"WRED not supported\";\n+\t\treturn -EINVAL;\n+\t}\n+\tif (params->leaf.wred.n_shared_wred_contexts) {\n+\t\terror->type =\n+\t\t\tRTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_WRED_CONTEXTS;\n+\t\terror->message = \"WRED not supported\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * Now the TC and queue configuration is controlled by DCB.\n+ * We need check if the node configuration follows the DCB configuration.\n+ * In the future, we may use TM to cover DCB.\n+ */\n+static int\n+txgbe_node_add(struct rte_eth_dev *dev, uint32_t node_id,\n+\t       uint32_t parent_node_id, uint32_t priority,\n+\t       uint32_t weight, uint32_t level_id,\n+\t       struct rte_tm_node_params *params,\n+\t       struct rte_tm_error *error)\n+{\n+\tstruct txgbe_tm_conf *tm_conf = TXGBE_DEV_TM_CONF(dev);\n+\tenum txgbe_tm_node_type node_type = TXGBE_TM_NODE_TYPE_MAX;\n+\tenum txgbe_tm_node_type parent_node_type = TXGBE_TM_NODE_TYPE_MAX;\n+\tstruct txgbe_tm_shaper_profile *shaper_profile = NULL;\n+\tstruct txgbe_tm_node *tm_node;\n+\tstruct txgbe_tm_node *parent_node;\n+\tuint8_t nb_tcs;\n+\tuint16_t q_base = 0;\n+\tuint16_t q_nb = 0;\n+\tint ret;\n+\n+\tif (!params || !error)\n+\t\treturn -EINVAL;\n+\n+\t/* if already committed */\n+\tif (tm_conf->committed) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;\n+\t\terror->message = \"already committed\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tret = txgbe_node_param_check(dev, node_id, priority, weight,\n+\t\t\t\t     params, error);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* check if the node ID is already used */\n+\tif (txgbe_tm_node_search(dev, node_id, &node_type)) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_ID;\n+\t\terror->message = \"node id already used\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* check the shaper profile id */\n+\tif (params->shaper_profile_id != RTE_TM_SHAPER_PROFILE_ID_NONE) {\n+\t\tshaper_profile = txgbe_shaper_profile_search(dev,\n+\t\t\t\t\tparams->shaper_profile_id);\n+\t\tif (!shaper_profile) {\n+\t\t\terror->type =\n+\t\t\t\tRTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID;\n+\t\t\terror->message = \"shaper profile not exist\";\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\n+\t/* root node if not have a parent */\n+\tif (parent_node_id == RTE_TM_NODE_ID_NULL) {\n+\t\t/* check level */\n+\t\tif (level_id != RTE_TM_NODE_LEVEL_ID_ANY &&\n+\t\t    level_id > TXGBE_TM_NODE_TYPE_PORT) {\n+\t\t\terror->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;\n+\t\t\terror->message = \"Wrong level\";\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\t/* obviously no more than one root */\n+\t\tif (tm_conf->root) {\n+\t\t\terror->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;\n+\t\t\terror->message = \"already have a root\";\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\t/* add the root node */\n+\t\ttm_node = rte_zmalloc(\"txgbe_tm_node\",\n+\t\t\t\t      sizeof(struct txgbe_tm_node),\n+\t\t\t\t      0);\n+\t\tif (!tm_node)\n+\t\t\treturn -ENOMEM;\n+\t\ttm_node->id = node_id;\n+\t\ttm_node->priority = priority;\n+\t\ttm_node->weight = weight;\n+\t\ttm_node->reference_count = 0;\n+\t\ttm_node->no = 0;\n+\t\ttm_node->parent = NULL;\n+\t\ttm_node->shaper_profile = shaper_profile;\n+\t\trte_memcpy(&tm_node->params, params,\n+\t\t\t\t sizeof(struct rte_tm_node_params));\n+\t\ttm_conf->root = tm_node;\n+\n+\t\t/* increase the reference counter of the shaper profile */\n+\t\tif (shaper_profile)\n+\t\t\tshaper_profile->reference_count++;\n+\n+\t\treturn 0;\n+\t}\n+\n+\t/* TC or queue node */\n+\t/* check the parent node */\n+\tparent_node = txgbe_tm_node_search(dev, parent_node_id,\n+\t\t\t\t\t   &parent_node_type);\n+\tif (!parent_node) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;\n+\t\terror->message = \"parent not exist\";\n+\t\treturn -EINVAL;\n+\t}\n+\tif (parent_node_type != TXGBE_TM_NODE_TYPE_PORT &&\n+\t    parent_node_type != TXGBE_TM_NODE_TYPE_TC) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;\n+\t\terror->message = \"parent is not port or TC\";\n+\t\treturn -EINVAL;\n+\t}\n+\t/* check level */\n+\tif (level_id != RTE_TM_NODE_LEVEL_ID_ANY &&\n+\t    level_id != parent_node_type + 1) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;\n+\t\terror->message = \"Wrong level\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* check the node number */\n+\tif (parent_node_type == TXGBE_TM_NODE_TYPE_PORT) {\n+\t\t/* check TC number */\n+\t\tnb_tcs = txgbe_tc_nb_get(dev);\n+\t\tif (tm_conf->nb_tc_node >= nb_tcs) {\n+\t\t\terror->type = RTE_TM_ERROR_TYPE_NODE_ID;\n+\t\t\terror->message = \"too many TCs\";\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t} else {\n+\t\t/* check queue number */\n+\t\tif (tm_conf->nb_queue_node >= dev->data->nb_tx_queues) {\n+\t\t\terror->type = RTE_TM_ERROR_TYPE_NODE_ID;\n+\t\t\terror->message = \"too many queues\";\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\ttxgbe_queue_base_nb_get(dev, parent_node->no, &q_base, &q_nb);\n+\t\tif (parent_node->reference_count >= q_nb) {\n+\t\t\terror->type = RTE_TM_ERROR_TYPE_NODE_ID;\n+\t\t\terror->message = \"too many queues than TC supported\";\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\t/**\n+\t\t * check the node id.\n+\t\t * For queue, the node id means queue id.\n+\t\t */\n+\t\tif (node_id >= dev->data->nb_tx_queues) {\n+\t\t\terror->type = RTE_TM_ERROR_TYPE_NODE_ID;\n+\t\t\terror->message = \"too large queue id\";\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\n+\t/* add the TC or queue node */\n+\ttm_node = rte_zmalloc(\"txgbe_tm_node\",\n+\t\t\t      sizeof(struct txgbe_tm_node),\n+\t\t\t      0);\n+\tif (!tm_node)\n+\t\treturn -ENOMEM;\n+\ttm_node->id = node_id;\n+\ttm_node->priority = priority;\n+\ttm_node->weight = weight;\n+\ttm_node->reference_count = 0;\n+\ttm_node->parent = parent_node;\n+\ttm_node->shaper_profile = shaper_profile;\n+\trte_memcpy(&tm_node->params, params,\n+\t\t\t sizeof(struct rte_tm_node_params));\n+\tif (parent_node_type == TXGBE_TM_NODE_TYPE_PORT) {\n+\t\ttm_node->no = parent_node->reference_count;\n+\t\tTAILQ_INSERT_TAIL(&tm_conf->tc_list,\n+\t\t\t\t  tm_node, node);\n+\t\ttm_conf->nb_tc_node++;\n+\t} else {\n+\t\ttm_node->no = q_base + parent_node->reference_count;\n+\t\tTAILQ_INSERT_TAIL(&tm_conf->queue_list,\n+\t\t\t\t  tm_node, node);\n+\t\ttm_conf->nb_queue_node++;\n+\t}\n+\ttm_node->parent->reference_count++;\n+\n+\t/* increase the reference counter of the shaper profile */\n+\tif (shaper_profile)\n+\t\tshaper_profile->reference_count++;\n+\n+\treturn 0;\n+}\n+\n+static int\n+txgbe_node_delete(struct rte_eth_dev *dev, uint32_t node_id,\n+\t\t  struct rte_tm_error *error)\n+{\n+\tstruct txgbe_tm_conf *tm_conf = TXGBE_DEV_TM_CONF(dev);\n+\tenum txgbe_tm_node_type node_type = TXGBE_TM_NODE_TYPE_MAX;\n+\tstruct txgbe_tm_node *tm_node;\n+\n+\tif (!error)\n+\t\treturn -EINVAL;\n+\n+\t/* if already committed */\n+\tif (tm_conf->committed) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;\n+\t\terror->message = \"already committed\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (node_id == RTE_TM_NODE_ID_NULL) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_ID;\n+\t\terror->message = \"invalid node id\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* check the if the node id exists */\n+\ttm_node = txgbe_tm_node_search(dev, node_id, &node_type);\n+\tif (!tm_node) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_ID;\n+\t\terror->message = \"no such node\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* the node should have no child */\n+\tif (tm_node->reference_count) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_ID;\n+\t\terror->message =\n+\t\t\t\"cannot delete a node which has children\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* root node */\n+\tif (node_type == TXGBE_TM_NODE_TYPE_PORT) {\n+\t\tif (tm_node->shaper_profile)\n+\t\t\ttm_node->shaper_profile->reference_count--;\n+\t\trte_free(tm_node);\n+\t\ttm_conf->root = NULL;\n+\t\treturn 0;\n+\t}\n+\n+\t/* TC or queue node */\n+\tif (tm_node->shaper_profile)\n+\t\ttm_node->shaper_profile->reference_count--;\n+\ttm_node->parent->reference_count--;\n+\tif (node_type == TXGBE_TM_NODE_TYPE_TC) {\n+\t\tTAILQ_REMOVE(&tm_conf->tc_list, tm_node, node);\n+\t\ttm_conf->nb_tc_node--;\n+\t} else {\n+\t\tTAILQ_REMOVE(&tm_conf->queue_list, tm_node, node);\n+\t\ttm_conf->nb_queue_node--;\n+\t}\n+\trte_free(tm_node);\n+\n+\treturn 0;\n+}\n+\n+static int\n+txgbe_node_type_get(struct rte_eth_dev *dev, uint32_t node_id,\n+\t\t    int *is_leaf, struct rte_tm_error *error)\n+{\n+\tenum txgbe_tm_node_type node_type = TXGBE_TM_NODE_TYPE_MAX;\n+\tstruct txgbe_tm_node *tm_node;\n+\n+\tif (!is_leaf || !error)\n+\t\treturn -EINVAL;\n+\n+\tif (node_id == RTE_TM_NODE_ID_NULL) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_ID;\n+\t\terror->message = \"invalid node id\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* check if the node id exists */\n+\ttm_node = txgbe_tm_node_search(dev, node_id, &node_type);\n+\tif (!tm_node) {\n+\t\terror->type = RTE_TM_ERROR_TYPE_NODE_ID;\n+\t\terror->message = \"no such node\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (node_type == TXGBE_TM_NODE_TYPE_QUEUE)\n+\t\t*is_leaf = true;\n+\telse\n+\t\t*is_leaf = false;\n+\n+\treturn 0;\n+}\n+\n static int\n txgbe_level_capabilities_get(struct rte_eth_dev *dev,\n \t\t\t     uint32_t level_id,\n",
    "prefixes": [
        "v2",
        "30/37"
    ]
}