get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 68199,
    "url": "http://patches.dpdk.org/api/patches/68199/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20200411141428.1987768-12-jerinj@marvell.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": "<20200411141428.1987768-12-jerinj@marvell.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20200411141428.1987768-12-jerinj@marvell.com",
    "date": "2020-04-11T14:14:10",
    "name": "[v5,11/29] graph: implement stats support",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "d766d1c51f16e978b2026ed4b14a2ac93f81a444",
    "submitter": {
        "id": 1188,
        "url": "http://patches.dpdk.org/api/people/1188/?format=api",
        "name": "Jerin Jacob Kollanukkaran",
        "email": "jerinj@marvell.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20200411141428.1987768-12-jerinj@marvell.com/mbox/",
    "series": [
        {
            "id": 9314,
            "url": "http://patches.dpdk.org/api/series/9314/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=9314",
            "date": "2020-04-11T14:13:59",
            "name": "graph: introduce graph subsystem",
            "version": 5,
            "mbox": "http://patches.dpdk.org/series/9314/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/68199/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/68199/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 6B48EA059F;\n\tSat, 11 Apr 2020 16:16:16 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 8416B1C222;\n\tSat, 11 Apr 2020 16:15:15 +0200 (CEST)",
            "from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com\n [67.231.148.174]) by dpdk.org (Postfix) with ESMTP id 154881C1B1\n for <dev@dpdk.org>; Sat, 11 Apr 2020 16:15:12 +0200 (CEST)",
            "from pps.filterd (m0045849.ppops.net [127.0.0.1])\n by mx0a-0016f401.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id\n 03BEAM5f016872; Sat, 11 Apr 2020 07:15:10 -0700",
            "from sc-exch04.marvell.com ([199.233.58.184])\n by mx0a-0016f401.pphosted.com with ESMTP id 30bb8q8n59-1\n (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT);\n Sat, 11 Apr 2020 07:15:10 -0700",
            "from DC5-EXCH02.marvell.com (10.69.176.39) by SC-EXCH04.marvell.com\n (10.93.176.84) with Microsoft SMTP Server (TLS) id 15.0.1497.2;\n Sat, 11 Apr 2020 07:15:09 -0700",
            "from DC5-EXCH02.marvell.com (10.69.176.39) by DC5-EXCH02.marvell.com\n (10.69.176.39) with Microsoft SMTP Server (TLS) id 15.0.1497.2;\n Sat, 11 Apr 2020 07:15:08 -0700",
            "from maili.marvell.com (10.69.176.80) by DC5-EXCH02.marvell.com\n (10.69.176.39) with Microsoft SMTP Server id 15.0.1497.2 via Frontend\n Transport; Sat, 11 Apr 2020 07:15:08 -0700",
            "from jerin-lab.marvell.com (jerin-lab.marvell.com [10.28.34.14])\n by maili.marvell.com (Postfix) with ESMTP id 2E88E3F7040;\n Sat, 11 Apr 2020 07:15:04 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com;\n h=from : to : cc :\n subject : date : message-id : in-reply-to : references : mime-version :\n content-transfer-encoding : content-type; s=pfpt0818;\n bh=39sxVdZosq2OvgvEwM6ImbTsvFFhKrSY92dbRNcmhTA=;\n b=j0bAv3YyRGR7GAhboDtoZ87yNlrVGMCjXsffCwdeF9pdkjYL1U80qAjfAbS48qRFVHV2\n wcj7j85u45zuhyWsfGK/rR620yI7rBqBNqCm1Eda8r+JW6LzzRZRc28run/FXRMeOUII\n zef8/ltRAMy6ZumP9ifOxJsl8nc5nycb1EmRf+oUOks6AIjCAfcOMdnQOcT/RIVrelr4\n /30L8q7rcuxnsnl2DRj3Y6zE1ws1CRasfa39DVEg6Lk8Z4SUrA5ghoKziCE0HQdPGFdB\n svLNlXjBSh9aUBL4JLmOdEiGn/80hWrqwJ5deqLv9aSOxD2cNBHQviwig50P40bnko6S BA==",
        "From": "<jerinj@marvell.com>",
        "To": "Jerin Jacob <jerinj@marvell.com>, Kiran Kumar K <kirankumark@marvell.com>",
        "CC": "<dev@dpdk.org>, <thomas@monjalon.net>, <david.marchand@redhat.com>,\n <mdr@ashroe.eu>, <mattias.ronnblom@ericsson.com>,\n <pbhagavatula@marvell.com>, <ndabilpuram@marvell.com>,\n <xiao.w.wang@intel.com>, <amo@semihalf.com>",
        "Date": "Sat, 11 Apr 2020 19:44:10 +0530",
        "Message-ID": "<20200411141428.1987768-12-jerinj@marvell.com>",
        "X-Mailer": "git-send-email 2.25.1",
        "In-Reply-To": "<20200411141428.1987768-1-jerinj@marvell.com>",
        "References": "<20200405085613.1336841-1-jerinj@marvell.com>\n <20200411141428.1987768-1-jerinj@marvell.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Content-Type": "text/plain",
        "X-Proofpoint-Virus-Version": "vendor=fsecure engine=2.50.10434:6.0.138, 18.0.676\n definitions=2020-04-11_04:2020-04-09,\n 2020-04-11 signatures=0",
        "Subject": "[dpdk-dev]  [PATCH v5 11/29] graph: implement stats support",
        "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": "From: Jerin Jacob <jerinj@marvell.com>\n\nAdding implementation for graph stats collection API. This API will\ncreate a cluster for a specified node pattern and aggregate the node\nruntime stats.\n\nSigned-off-by: Jerin Jacob <jerinj@marvell.com>\nSigned-off-by: Kiran Kumar K <kirankumark@marvell.com>\nSigned-off-by: Pavan Nikhilesh <pbhagavatula@marvell.com>\nSigned-off-by: Nithin Dabilpuram <ndabilpuram@marvell.com>\n---\n lib/librte_graph/Makefile              |   1 +\n lib/librte_graph/graph_stats.c         | 406 +++++++++++++++++++++++++\n lib/librte_graph/meson.build           |   2 +-\n lib/librte_graph/rte_graph_version.map |   5 +\n 4 files changed, 413 insertions(+), 1 deletion(-)\n create mode 100644 lib/librte_graph/graph_stats.c",
    "diff": "diff --git a/lib/librte_graph/Makefile b/lib/librte_graph/Makefile\nindex 7bfd7d51f..967c8d9bc 100644\n--- a/lib/librte_graph/Makefile\n+++ b/lib/librte_graph/Makefile\n@@ -18,6 +18,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_GRAPH) += node.c\n SRCS-$(CONFIG_RTE_LIBRTE_GRAPH) += graph.c\n SRCS-$(CONFIG_RTE_LIBRTE_GRAPH) += graph_ops.c\n SRCS-$(CONFIG_RTE_LIBRTE_GRAPH) += graph_debug.c\n+SRCS-$(CONFIG_RTE_LIBRTE_GRAPH) += graph_stats.c\n SRCS-$(CONFIG_RTE_LIBRTE_GRAPH) += graph_populate.c\n \n # install header files\ndiff --git a/lib/librte_graph/graph_stats.c b/lib/librte_graph/graph_stats.c\nnew file mode 100644\nindex 000000000..125e08d73\n--- /dev/null\n+++ b/lib/librte_graph/graph_stats.c\n@@ -0,0 +1,406 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(C) 2020 Marvell International Ltd.\n+ */\n+\n+#include <fnmatch.h>\n+#include <stdbool.h>\n+\n+#include <rte_common.h>\n+#include <rte_errno.h>\n+#include <rte_malloc.h>\n+\n+#include \"graph_private.h\"\n+\n+/* Capture all graphs of cluster */\n+struct cluster {\n+\trte_graph_t nb_graphs;\n+\trte_graph_t size;\n+\n+\tstruct graph **graphs;\n+};\n+\n+/* Capture same node ID across cluster  */\n+struct cluster_node {\n+\tstruct rte_graph_cluster_node_stats stat;\n+\trte_node_t nb_nodes;\n+\n+\tstruct rte_node *nodes[];\n+};\n+\n+struct rte_graph_cluster_stats {\n+\t/* Header */\n+\trte_graph_cluster_stats_cb_t fn;\n+\tuint32_t cluster_node_size; /* Size of struct cluster_node */\n+\trte_node_t max_nodes;\n+\tint socket_id;\n+\tvoid *cookie;\n+\tsize_t sz;\n+\n+\tstruct cluster_node clusters[];\n+} __rte_cache_aligned;\n+\n+#define boarder()                                                              \\\n+\tfprintf(f, \"+-------------------------------+---------------+--------\" \\\n+\t\t   \"-------+---------------+---------------+---------------+-\" \\\n+\t\t   \"----------+\\n\")\n+\n+static inline void\n+print_banner(FILE *f)\n+{\n+\tboarder();\n+\tfprintf(f, \"%-32s%-16s%-16s%-16s%-16s%-16s%-16s\\n\", \"|Node\", \"|calls\",\n+\t\t\"|objs\", \"|realloc_count\", \"|objs/call\", \"|objs/sec(10E6)\",\n+\t\t\"|cycles/call|\");\n+\tboarder();\n+}\n+\n+static inline void\n+print_node(FILE *f, const struct rte_graph_cluster_node_stats *stat)\n+{\n+\tdouble objs_per_call, objs_per_sec, cycles_per_call, ts_per_hz;\n+\tconst uint64_t prev_calls = stat->prev_calls;\n+\tconst uint64_t prev_objs = stat->prev_objs;\n+\tconst uint64_t cycles = stat->cycles;\n+\tconst uint64_t calls = stat->calls;\n+\tconst uint64_t objs = stat->objs;\n+\tuint64_t call_delta;\n+\n+\tcall_delta = calls - prev_calls;\n+\tobjs_per_call =\n+\t\tcall_delta ? (double)((objs - prev_objs) / call_delta) : 0;\n+\tcycles_per_call =\n+\t\tcall_delta ? (double)((cycles - stat->prev_cycles) / call_delta)\n+\t\t\t   : 0;\n+\tts_per_hz = (double)((stat->ts - stat->prev_ts) / stat->hz);\n+\tobjs_per_sec = ts_per_hz ? (objs - prev_objs) / ts_per_hz : 0;\n+\tobjs_per_sec /= 1000000;\n+\n+\tfprintf(f,\n+\t\t\"|%-31s|%-15\" PRIu64 \"|%-15\" PRIu64 \"|%-15\" PRIu64\n+\t\t\"|%-15.3f|%-15.6f|%-11.4f|\\n\",\n+\t\tstat->name, calls, objs, stat->realloc_count, objs_per_call,\n+\t\tobjs_per_sec, cycles_per_call);\n+}\n+\n+static int\n+graph_cluster_stats_cb(bool is_first, bool is_last, void *cookie,\n+\t\t       const struct rte_graph_cluster_node_stats *stat)\n+{\n+\tFILE *f = cookie;\n+\n+\tif (unlikely(is_first))\n+\t\tprint_banner(f);\n+\tif (stat->objs)\n+\t\tprint_node(f, stat);\n+\tif (unlikely(is_last))\n+\t\tboarder();\n+\n+\treturn 0;\n+};\n+\n+static struct rte_graph_cluster_stats *\n+stats_mem_init(struct cluster *cluster,\n+\t       const struct rte_graph_cluster_stats_param *prm)\n+{\n+\tsize_t sz = sizeof(struct rte_graph_cluster_stats);\n+\tstruct rte_graph_cluster_stats *stats;\n+\trte_graph_cluster_stats_cb_t fn;\n+\tint socket_id = prm->socket_id;\n+\tuint32_t cluster_node_size;\n+\n+\t/* Fix up callback */\n+\tfn = prm->fn;\n+\tif (fn == NULL)\n+\t\tfn = graph_cluster_stats_cb;\n+\n+\tcluster_node_size = sizeof(struct cluster_node);\n+\t/* For a given cluster, max nodes will be the max number of graphs */\n+\tcluster_node_size += cluster->nb_graphs * sizeof(struct rte_node *);\n+\tcluster_node_size = RTE_ALIGN(cluster_node_size, RTE_CACHE_LINE_SIZE);\n+\n+\tstats = realloc(NULL, sz);\n+\tmemset(stats, 0, sz);\n+\tif (stats) {\n+\t\tstats->fn = fn;\n+\t\tstats->cluster_node_size = cluster_node_size;\n+\t\tstats->max_nodes = 0;\n+\t\tstats->socket_id = socket_id;\n+\t\tstats->cookie = prm->cookie;\n+\t\tstats->sz = sz;\n+\t}\n+\n+\treturn stats;\n+}\n+\n+static int\n+stats_mem_populate(struct rte_graph_cluster_stats **stats_in,\n+\t\t   struct rte_graph *graph, struct graph_node *graph_node)\n+{\n+\tstruct rte_graph_cluster_stats *stats = *stats_in;\n+\trte_node_t id = graph_node->node->id;\n+\tstruct cluster_node *cluster;\n+\tstruct rte_node *node;\n+\trte_node_t count;\n+\n+\tcluster = stats->clusters;\n+\n+\t/* Iterate over cluster node array to find node ID match */\n+\tfor (count = 0; count < stats->max_nodes; count++) {\n+\t\t/* Found an existing node in the reel */\n+\t\tif (cluster->stat.id == id) {\n+\t\t\tnode = graph_node_id_to_ptr(graph, id);\n+\t\t\tif (node == NULL)\n+\t\t\t\tSET_ERR_JMP(\n+\t\t\t\t\tENOENT, err,\n+\t\t\t\t\t\"Failed to find node %s in graph %s\",\n+\t\t\t\t\tgraph_node->node->name, graph->name);\n+\n+\t\t\tcluster->nodes[cluster->nb_nodes++] = node;\n+\t\t\treturn 0;\n+\t\t}\n+\t\tcluster = RTE_PTR_ADD(cluster, stats->cluster_node_size);\n+\t}\n+\n+\t/* Hey, it is a new node, allocate space for it in the reel */\n+\tstats = realloc(stats, stats->sz + stats->cluster_node_size);\n+\tif (stats == NULL)\n+\t\tSET_ERR_JMP(ENOMEM, err, \"Realloc failed\");\n+\n+\t/* Clear the new struct cluster_node area */\n+\tcluster = RTE_PTR_ADD(stats, stats->sz),\n+\tmemset(cluster, 0, stats->cluster_node_size);\n+\tmemcpy(cluster->stat.name, graph_node->node->name, RTE_NODE_NAMESIZE);\n+\tcluster->stat.id = graph_node->node->id;\n+\tcluster->stat.hz = rte_get_timer_hz();\n+\tnode = graph_node_id_to_ptr(graph, id);\n+\tif (node == NULL)\n+\t\tSET_ERR_JMP(ENOENT, err, \"Failed to find node %s in graph %s\",\n+\t\t\t    graph_node->node->name, graph->name);\n+\tcluster->nodes[cluster->nb_nodes++] = node;\n+\n+\tstats->sz += stats->cluster_node_size;\n+\tstats->max_nodes++;\n+\t*stats_in = stats;\n+\n+\treturn 0;\n+err:\n+\treturn -rte_errno;\n+}\n+\n+static void\n+stats_mem_fini(struct rte_graph_cluster_stats *stats)\n+{\n+\tfree(stats);\n+}\n+\n+static void\n+cluster_init(struct cluster *cluster)\n+{\n+\tmemset(cluster, 0, sizeof(*cluster));\n+}\n+\n+static int\n+cluster_add(struct cluster *cluster, struct graph *graph)\n+{\n+\trte_graph_t count;\n+\tsize_t sz;\n+\n+\t/* Skip the if graph is already added to cluster */\n+\tfor (count = 0; count < cluster->nb_graphs; count++)\n+\t\tif (cluster->graphs[count] == graph)\n+\t\t\treturn 0;\n+\n+\t/* Expand the cluster if required to store graph objects */\n+\tif (cluster->nb_graphs + 1 > cluster->size) {\n+\t\tcluster->size = RTE_MAX(1, cluster->size * 2);\n+\t\tsz = sizeof(struct graph *) * cluster->size;\n+\t\tcluster->graphs = realloc(cluster->graphs, sz);\n+\t\tif (cluster->graphs == NULL)\n+\t\t\tSET_ERR_JMP(ENOMEM, free, \"Failed to realloc\");\n+\t}\n+\n+\t/* Add graph to cluster */\n+\tcluster->graphs[cluster->nb_graphs++] = graph;\n+\treturn 0;\n+\n+free:\n+\treturn -rte_errno;\n+}\n+\n+static void\n+cluster_fini(struct cluster *cluster)\n+{\n+\tif (cluster->graphs)\n+\t\tfree(cluster->graphs);\n+}\n+\n+static int\n+expand_pattern_to_cluster(struct cluster *cluster, const char *pattern)\n+{\n+\tstruct graph_head *graph_head = graph_list_head_get();\n+\tstruct graph *graph;\n+\tbool found = false;\n+\n+\t/* Check for pattern match */\n+\tSTAILQ_FOREACH(graph, graph_head, next) {\n+\t\tif (fnmatch(pattern, graph->name, 0) == 0) {\n+\t\t\tif (cluster_add(cluster, graph))\n+\t\t\t\tgoto fail;\n+\t\t\tfound = true;\n+\t\t}\n+\t}\n+\tif (found == false)\n+\t\tSET_ERR_JMP(EFAULT, fail, \"Pattern %s graph not found\",\n+\t\t\t    pattern);\n+\n+\treturn 0;\n+fail:\n+\treturn -rte_errno;\n+}\n+\n+struct rte_graph_cluster_stats *\n+rte_graph_cluster_stats_create(const struct rte_graph_cluster_stats_param *prm)\n+{\n+\tstruct rte_graph_cluster_stats *stats, *rc = NULL;\n+\tstruct graph_node *graph_node;\n+\tstruct cluster cluster;\n+\tstruct graph *graph;\n+\tconst char *pattern;\n+\trte_graph_t i;\n+\n+\t/* Sanity checks */\n+\tif (!rte_graph_has_stats_feature())\n+\t\tSET_ERR_JMP(EINVAL, fail, \"Stats feature is not enabled\");\n+\n+\tif (prm == NULL)\n+\t\tSET_ERR_JMP(EINVAL, fail, \"Invalid param\");\n+\n+\tif (prm->graph_patterns == NULL || prm->nb_graph_patterns == 0)\n+\t\tSET_ERR_JMP(EINVAL, fail, \"Invalid graph param\");\n+\n+\tcluster_init(&cluster);\n+\n+\tgraph_spinlock_lock();\n+\t/* Expand graph pattern and add the graph to the cluster */\n+\tfor (i = 0; i < prm->nb_graph_patterns; i++) {\n+\t\tpattern = prm->graph_patterns[i];\n+\t\tif (expand_pattern_to_cluster(&cluster, pattern))\n+\t\t\tgoto bad_pattern;\n+\t}\n+\n+\t/* Alloc the stats memory */\n+\tstats = stats_mem_init(&cluster, prm);\n+\tif (stats == NULL)\n+\t\tSET_ERR_JMP(ENOMEM, bad_pattern, \"Failed alloc stats memory\");\n+\n+\t/* Iterate over M(Graph) x N (Nodes in graph) */\n+\tfor (i = 0; i < cluster.nb_graphs; i++) {\n+\t\tgraph = cluster.graphs[i];\n+\t\tSTAILQ_FOREACH(graph_node, &graph->node_list, next) {\n+\t\t\tstruct rte_graph *graph_fp = graph->graph;\n+\t\t\tif (stats_mem_populate(&stats, graph_fp, graph_node))\n+\t\t\t\tgoto realloc_fail;\n+\t\t}\n+\t}\n+\n+\t/* Finally copy to hugepage memory to avoid pressure on rte_realloc */\n+\trc = rte_malloc_socket(NULL, stats->sz, 0, stats->socket_id);\n+\tif (rc)\n+\t\trte_memcpy(rc, stats, stats->sz);\n+\telse\n+\t\tSET_ERR_JMP(ENOMEM, realloc_fail, \"rte_malloc failed\");\n+\n+realloc_fail:\n+\tstats_mem_fini(stats);\n+bad_pattern:\n+\tgraph_spinlock_unlock();\n+\tcluster_fini(&cluster);\n+fail:\n+\treturn rc;\n+}\n+\n+void\n+rte_graph_cluster_stats_destroy(struct rte_graph_cluster_stats *stat)\n+{\n+\treturn rte_free(stat);\n+}\n+\n+static inline void\n+cluster_node_arregate_stats(struct cluster_node *cluster)\n+{\n+\tuint64_t calls = 0, cycles = 0, objs = 0, realloc_count = 0;\n+\tstruct rte_graph_cluster_node_stats *stat = &cluster->stat;\n+\tstruct rte_node *node;\n+\trte_node_t count;\n+\n+\tfor (count = 0; count < cluster->nb_nodes; count++) {\n+\t\tnode = cluster->nodes[count];\n+\n+\t\tcalls += node->total_calls;\n+\t\tobjs += node->total_objs;\n+\t\tcycles += node->total_cycles;\n+\t\trealloc_count += node->realloc_count;\n+\t}\n+\n+\tstat->calls = calls;\n+\tstat->objs = objs;\n+\tstat->cycles = cycles;\n+\tstat->ts = rte_get_timer_cycles();\n+\tstat->realloc_count = realloc_count;\n+}\n+\n+static inline void\n+cluster_node_store_prev_stats(struct cluster_node *cluster)\n+{\n+\tstruct rte_graph_cluster_node_stats *stat = &cluster->stat;\n+\n+\tstat->prev_ts = stat->ts;\n+\tstat->prev_calls = stat->calls;\n+\tstat->prev_objs = stat->objs;\n+\tstat->prev_cycles = stat->cycles;\n+}\n+\n+void\n+rte_graph_cluster_stats_get(struct rte_graph_cluster_stats *stat, bool skip_cb)\n+{\n+\tstruct cluster_node *cluster;\n+\trte_node_t count;\n+\tint rc = 0;\n+\n+\tcluster = stat->clusters;\n+\n+\tfor (count = 0; count < stat->max_nodes; count++) {\n+\t\tcluster_node_arregate_stats(cluster);\n+\t\tif (!skip_cb)\n+\t\t\trc = stat->fn(!count, (count == stat->max_nodes - 1),\n+\t\t\t\t      stat->cookie, &cluster->stat);\n+\t\tcluster_node_store_prev_stats(cluster);\n+\t\tif (rc)\n+\t\t\tbreak;\n+\t\tcluster = RTE_PTR_ADD(cluster, stat->cluster_node_size);\n+\t}\n+}\n+\n+void\n+rte_graph_cluster_stats_reset(struct rte_graph_cluster_stats *stat)\n+{\n+\tstruct cluster_node *cluster;\n+\trte_node_t count;\n+\n+\tcluster = stat->clusters;\n+\n+\tfor (count = 0; count < stat->max_nodes; count++) {\n+\t\tstruct rte_graph_cluster_node_stats *node = &cluster->stat;\n+\n+\t\tnode->ts = 0;\n+\t\tnode->calls = 0;\n+\t\tnode->objs = 0;\n+\t\tnode->cycles = 0;\n+\t\tnode->prev_ts = 0;\n+\t\tnode->prev_calls = 0;\n+\t\tnode->prev_objs = 0;\n+\t\tnode->prev_cycles = 0;\n+\t\tnode->realloc_count = 0;\n+\t\tcluster = RTE_PTR_ADD(cluster, stat->cluster_node_size);\n+\t}\n+}\ndiff --git a/lib/librte_graph/meson.build b/lib/librte_graph/meson.build\nindex fb203a5e2..929a17f84 100644\n--- a/lib/librte_graph/meson.build\n+++ b/lib/librte_graph/meson.build\n@@ -4,7 +4,7 @@\n \n name = 'graph'\n \n-sources = files('node.c', 'graph.c', 'graph_ops.c', 'graph_debug.c', 'graph_populate.c')\n+sources = files('node.c', 'graph.c', 'graph_ops.c', 'graph_debug.c', 'graph_stats.c', 'graph_populate.c')\n headers = files('rte_graph.h', 'rte_graph_worker.h')\n allow_experimental_apis = true\n \ndiff --git a/lib/librte_graph/rte_graph_version.map b/lib/librte_graph/rte_graph_version.map\nindex 851f4772e..adf55d406 100644\n--- a/lib/librte_graph/rte_graph_version.map\n+++ b/lib/librte_graph/rte_graph_version.map\n@@ -17,6 +17,11 @@ EXPERIMENTAL {\n \trte_graph_node_get_by_name;\n \trte_graph_obj_dump;\n \n+\trte_graph_cluster_stats_create;\n+\trte_graph_cluster_stats_destroy;\n+\trte_graph_cluster_stats_get;\n+\trte_graph_cluster_stats_reset;\n+\n \trte_node_clone;\n \trte_node_dump;\n \trte_node_edge_count;\n",
    "prefixes": [
        "v5",
        "11/29"
    ]
}