xref: /dpdk/lib/graph/graph_stats.c (revision 070db97e017b7ed9a5320b2f624f05562a632bd3)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  * Copyright(C) 2020 Marvell International Ltd.
399a2dd95SBruce Richardson  */
499a2dd95SBruce Richardson 
599a2dd95SBruce Richardson #include <fnmatch.h>
699a2dd95SBruce Richardson #include <stdbool.h>
772b452c5SDmitry Kozlyuk #include <stdlib.h>
899a2dd95SBruce Richardson 
999a2dd95SBruce Richardson #include <rte_common.h>
1099a2dd95SBruce Richardson #include <rte_errno.h>
1199a2dd95SBruce Richardson #include <rte_malloc.h>
1299a2dd95SBruce Richardson 
1399a2dd95SBruce Richardson #include "graph_private.h"
1499a2dd95SBruce Richardson 
1599a2dd95SBruce Richardson /* Capture all graphs of cluster */
1699a2dd95SBruce Richardson struct cluster {
1799a2dd95SBruce Richardson 	rte_graph_t nb_graphs;
1899a2dd95SBruce Richardson 	rte_graph_t size;
1999a2dd95SBruce Richardson 
2099a2dd95SBruce Richardson 	struct graph **graphs;
2199a2dd95SBruce Richardson };
2299a2dd95SBruce Richardson 
2399a2dd95SBruce Richardson /* Capture same node ID across cluster  */
2499a2dd95SBruce Richardson struct cluster_node {
2599a2dd95SBruce Richardson 	struct rte_graph_cluster_node_stats stat;
2699a2dd95SBruce Richardson 	rte_node_t nb_nodes;
2799a2dd95SBruce Richardson 
2899a2dd95SBruce Richardson 	struct rte_node *nodes[];
2999a2dd95SBruce Richardson };
3099a2dd95SBruce Richardson 
31c6552d9aSTyler Retzlaff struct __rte_cache_aligned rte_graph_cluster_stats {
3299a2dd95SBruce Richardson 	/* Header */
3399a2dd95SBruce Richardson 	rte_graph_cluster_stats_cb_t fn;
3499a2dd95SBruce Richardson 	uint32_t cluster_node_size; /* Size of struct cluster_node */
3599a2dd95SBruce Richardson 	rte_node_t max_nodes;
3699a2dd95SBruce Richardson 	int socket_id;
377d18ab56SRobin Jarry 	bool dispatch;
3899a2dd95SBruce Richardson 	void *cookie;
3999a2dd95SBruce Richardson 	size_t sz;
4099a2dd95SBruce Richardson 
4199a2dd95SBruce Richardson 	struct cluster_node clusters[];
42c6552d9aSTyler Retzlaff };
4399a2dd95SBruce Richardson 
44358ff83fSZhirun Yan #define boarder_model_dispatch()                                                              \
45358ff83fSZhirun Yan 	fprintf(f, "+-------------------------------+---------------+--------" \
46358ff83fSZhirun Yan 		   "-------+---------------+---------------+---------------+" \
47358ff83fSZhirun Yan 		   "---------------+---------------+-" \
48358ff83fSZhirun Yan 		   "----------+\n")
49358ff83fSZhirun Yan 
5099a2dd95SBruce Richardson #define boarder()                                                              \
5199a2dd95SBruce Richardson 	fprintf(f, "+-------------------------------+---------------+--------" \
5299a2dd95SBruce Richardson 		   "-------+---------------+---------------+---------------+-" \
5399a2dd95SBruce Richardson 		   "----------+\n")
5499a2dd95SBruce Richardson 
5599a2dd95SBruce Richardson static inline void
56358ff83fSZhirun Yan print_banner_default(FILE *f)
5799a2dd95SBruce Richardson {
5899a2dd95SBruce Richardson 	boarder();
5999a2dd95SBruce Richardson 	fprintf(f, "%-32s%-16s%-16s%-16s%-16s%-16s%-16s\n", "|Node", "|calls",
6099a2dd95SBruce Richardson 		"|objs", "|realloc_count", "|objs/call", "|objs/sec(10E6)",
6199a2dd95SBruce Richardson 		"|cycles/call|");
6299a2dd95SBruce Richardson 	boarder();
6399a2dd95SBruce Richardson }
6499a2dd95SBruce Richardson 
6599a2dd95SBruce Richardson static inline void
66358ff83fSZhirun Yan print_banner_dispatch(FILE *f)
67358ff83fSZhirun Yan {
68358ff83fSZhirun Yan 	boarder_model_dispatch();
69358ff83fSZhirun Yan 	fprintf(f, "%-32s%-16s%-16s%-16s%-16s%-16s%-16s%-16s%-16s\n",
70358ff83fSZhirun Yan 		"|Node", "|calls",
71358ff83fSZhirun Yan 		"|objs", "|sched objs", "|sched fail",
72358ff83fSZhirun Yan 		"|realloc_count", "|objs/call", "|objs/sec(10E6)",
73358ff83fSZhirun Yan 		"|cycles/call|");
74358ff83fSZhirun Yan 	boarder_model_dispatch();
75358ff83fSZhirun Yan }
76358ff83fSZhirun Yan 
77358ff83fSZhirun Yan static inline void
787d18ab56SRobin Jarry print_banner(FILE *f, bool dispatch)
79358ff83fSZhirun Yan {
807d18ab56SRobin Jarry 	if (dispatch)
81358ff83fSZhirun Yan 		print_banner_dispatch(f);
82358ff83fSZhirun Yan 	else
83358ff83fSZhirun Yan 		print_banner_default(f);
84358ff83fSZhirun Yan }
85358ff83fSZhirun Yan 
86358ff83fSZhirun Yan static inline void
877d18ab56SRobin Jarry print_node(FILE *f, const struct rte_graph_cluster_node_stats *stat, bool dispatch)
8899a2dd95SBruce Richardson {
8999a2dd95SBruce Richardson 	double objs_per_call, objs_per_sec, cycles_per_call, ts_per_hz;
9099a2dd95SBruce Richardson 	const uint64_t prev_calls = stat->prev_calls;
9199a2dd95SBruce Richardson 	const uint64_t prev_objs = stat->prev_objs;
9299a2dd95SBruce Richardson 	const uint64_t cycles = stat->cycles;
9399a2dd95SBruce Richardson 	const uint64_t calls = stat->calls;
9499a2dd95SBruce Richardson 	const uint64_t objs = stat->objs;
9599a2dd95SBruce Richardson 	uint64_t call_delta;
9699a2dd95SBruce Richardson 
9799a2dd95SBruce Richardson 	call_delta = calls - prev_calls;
9899a2dd95SBruce Richardson 	objs_per_call =
9999a2dd95SBruce Richardson 		call_delta ? (double)((objs - prev_objs) / call_delta) : 0;
10099a2dd95SBruce Richardson 	cycles_per_call =
10199a2dd95SBruce Richardson 		call_delta ? (double)((cycles - stat->prev_cycles) / call_delta)
10299a2dd95SBruce Richardson 			   : 0;
10399a2dd95SBruce Richardson 	ts_per_hz = (double)((stat->ts - stat->prev_ts) / stat->hz);
10499a2dd95SBruce Richardson 	objs_per_sec = ts_per_hz ? (objs - prev_objs) / ts_per_hz : 0;
10599a2dd95SBruce Richardson 	objs_per_sec /= 1000000;
10699a2dd95SBruce Richardson 
1077d18ab56SRobin Jarry 	if (dispatch) {
108358ff83fSZhirun Yan 		fprintf(f,
109358ff83fSZhirun Yan 			"|%-31s|%-15" PRIu64 "|%-15" PRIu64 "|%-15" PRIu64
110358ff83fSZhirun Yan 			"|%-15" PRIu64 "|%-15" PRIu64
111358ff83fSZhirun Yan 			"|%-15.3f|%-15.6f|%-11.4f|\n",
112358ff83fSZhirun Yan 			stat->name, calls, objs, stat->dispatch.sched_objs,
113358ff83fSZhirun Yan 			stat->dispatch.sched_fail, stat->realloc_count, objs_per_call,
114358ff83fSZhirun Yan 			objs_per_sec, cycles_per_call);
115358ff83fSZhirun Yan 	} else {
11699a2dd95SBruce Richardson 		fprintf(f,
11799a2dd95SBruce Richardson 			"|%-31s|%-15" PRIu64 "|%-15" PRIu64 "|%-15" PRIu64
11899a2dd95SBruce Richardson 			"|%-15.3f|%-15.6f|%-11.4f|\n",
11999a2dd95SBruce Richardson 			stat->name, calls, objs, stat->realloc_count, objs_per_call,
12099a2dd95SBruce Richardson 			objs_per_sec, cycles_per_call);
12199a2dd95SBruce Richardson 	}
122358ff83fSZhirun Yan }
12399a2dd95SBruce Richardson 
124*070db97eSPavan Nikhilesh static inline void
125*070db97eSPavan Nikhilesh print_xstat(FILE *f, const struct rte_graph_cluster_node_stats *stat, bool dispatch)
126*070db97eSPavan Nikhilesh {
127*070db97eSPavan Nikhilesh 	int i;
128*070db97eSPavan Nikhilesh 
129*070db97eSPavan Nikhilesh 	if (dispatch) {
130*070db97eSPavan Nikhilesh 		for (i = 0; i < stat->xstat_cntrs; i++)
131*070db97eSPavan Nikhilesh 			fprintf(f,
132*070db97eSPavan Nikhilesh 				"|\t%-24s|%15s|%-15" PRIu64 "|%15s|%15s|%15s|%15s|%15s|%11.4s|\n",
133*070db97eSPavan Nikhilesh 				stat->xstat_desc[i], "", stat->xstat_count[i], "", "", "", "", "",
134*070db97eSPavan Nikhilesh 				"");
135*070db97eSPavan Nikhilesh 	} else {
136*070db97eSPavan Nikhilesh 		for (i = 0; i < stat->xstat_cntrs; i++)
137*070db97eSPavan Nikhilesh 			fprintf(f,
138*070db97eSPavan Nikhilesh 				"|\t%-24s|%15s|%-15" PRIu64 "|%15s|%15.3s|%15.6s|%11.4s|\n",
139*070db97eSPavan Nikhilesh 				stat->xstat_desc[i], "", stat->xstat_count[i], "", "", "", "");
140*070db97eSPavan Nikhilesh 	}
141*070db97eSPavan Nikhilesh }
142*070db97eSPavan Nikhilesh 
14399a2dd95SBruce Richardson static int
1447d18ab56SRobin Jarry graph_cluster_stats_cb(bool dispatch, bool is_first, bool is_last, void *cookie,
14599a2dd95SBruce Richardson 		       const struct rte_graph_cluster_node_stats *stat)
14699a2dd95SBruce Richardson {
14799a2dd95SBruce Richardson 	FILE *f = cookie;
14899a2dd95SBruce Richardson 
14999a2dd95SBruce Richardson 	if (unlikely(is_first))
1507d18ab56SRobin Jarry 		print_banner(f, dispatch);
151*070db97eSPavan Nikhilesh 	if (stat->objs) {
1527d18ab56SRobin Jarry 		print_node(f, stat, dispatch);
153*070db97eSPavan Nikhilesh 		if (stat->xstat_cntrs)
154*070db97eSPavan Nikhilesh 			print_xstat(f, stat, dispatch);
155*070db97eSPavan Nikhilesh 	}
156358ff83fSZhirun Yan 	if (unlikely(is_last)) {
1577d18ab56SRobin Jarry 		if (dispatch)
158358ff83fSZhirun Yan 			boarder_model_dispatch();
159358ff83fSZhirun Yan 		else
16099a2dd95SBruce Richardson 			boarder();
161358ff83fSZhirun Yan 	}
16299a2dd95SBruce Richardson 
16399a2dd95SBruce Richardson 	return 0;
16499a2dd95SBruce Richardson };
16599a2dd95SBruce Richardson 
1667d18ab56SRobin Jarry static int
1677d18ab56SRobin Jarry graph_cluster_stats_cb_rtc(bool is_first, bool is_last, void *cookie,
1687d18ab56SRobin Jarry 			   const struct rte_graph_cluster_node_stats *stat)
1697d18ab56SRobin Jarry {
1707d18ab56SRobin Jarry 	return graph_cluster_stats_cb(false, is_first, is_last, cookie, stat);
1717d18ab56SRobin Jarry };
1727d18ab56SRobin Jarry 
1737d18ab56SRobin Jarry static int
1747d18ab56SRobin Jarry graph_cluster_stats_cb_dispatch(bool is_first, bool is_last, void *cookie,
1757d18ab56SRobin Jarry 				const struct rte_graph_cluster_node_stats *stat)
1767d18ab56SRobin Jarry {
1777d18ab56SRobin Jarry 	return graph_cluster_stats_cb(true, is_first, is_last, cookie, stat);
1787d18ab56SRobin Jarry };
1797d18ab56SRobin Jarry 
18099a2dd95SBruce Richardson static struct rte_graph_cluster_stats *
18199a2dd95SBruce Richardson stats_mem_init(struct cluster *cluster,
18299a2dd95SBruce Richardson 	       const struct rte_graph_cluster_stats_param *prm)
18399a2dd95SBruce Richardson {
18499a2dd95SBruce Richardson 	size_t sz = sizeof(struct rte_graph_cluster_stats);
18599a2dd95SBruce Richardson 	struct rte_graph_cluster_stats *stats;
18699a2dd95SBruce Richardson 	rte_graph_cluster_stats_cb_t fn;
18799a2dd95SBruce Richardson 	int socket_id = prm->socket_id;
18899a2dd95SBruce Richardson 	uint32_t cluster_node_size;
18999a2dd95SBruce Richardson 
19099a2dd95SBruce Richardson 	/* Fix up callback */
19199a2dd95SBruce Richardson 	fn = prm->fn;
1927d18ab56SRobin Jarry 	if (fn == NULL) {
1937d18ab56SRobin Jarry 		const struct rte_graph *graph = cluster->graphs[0]->graph;
1947d18ab56SRobin Jarry 		if (graph->model == RTE_GRAPH_MODEL_MCORE_DISPATCH)
1957d18ab56SRobin Jarry 			fn = graph_cluster_stats_cb_dispatch;
1967d18ab56SRobin Jarry 		else
1977d18ab56SRobin Jarry 			fn = graph_cluster_stats_cb_rtc;
1987d18ab56SRobin Jarry 	}
19999a2dd95SBruce Richardson 
20099a2dd95SBruce Richardson 	cluster_node_size = sizeof(struct cluster_node);
20199a2dd95SBruce Richardson 	/* For a given cluster, max nodes will be the max number of graphs */
20299a2dd95SBruce Richardson 	cluster_node_size += cluster->nb_graphs * sizeof(struct rte_node *);
20399a2dd95SBruce Richardson 	cluster_node_size = RTE_ALIGN(cluster_node_size, RTE_CACHE_LINE_SIZE);
20499a2dd95SBruce Richardson 
20599a2dd95SBruce Richardson 	stats = realloc(NULL, sz);
20699a2dd95SBruce Richardson 	if (stats) {
2072d2bf7deSHongbo Zheng 		memset(stats, 0, sz);
20899a2dd95SBruce Richardson 		stats->fn = fn;
20999a2dd95SBruce Richardson 		stats->cluster_node_size = cluster_node_size;
21099a2dd95SBruce Richardson 		stats->max_nodes = 0;
21199a2dd95SBruce Richardson 		stats->socket_id = socket_id;
21299a2dd95SBruce Richardson 		stats->cookie = prm->cookie;
21399a2dd95SBruce Richardson 		stats->sz = sz;
21499a2dd95SBruce Richardson 	}
21599a2dd95SBruce Richardson 
21699a2dd95SBruce Richardson 	return stats;
21799a2dd95SBruce Richardson }
21899a2dd95SBruce Richardson 
21999a2dd95SBruce Richardson static int
22099a2dd95SBruce Richardson stats_mem_populate(struct rte_graph_cluster_stats **stats_in,
22199a2dd95SBruce Richardson 		   struct rte_graph *graph, struct graph_node *graph_node)
22299a2dd95SBruce Richardson {
22399a2dd95SBruce Richardson 	struct rte_graph_cluster_stats *stats = *stats_in;
22499a2dd95SBruce Richardson 	rte_node_t id = graph_node->node->id;
22599a2dd95SBruce Richardson 	struct cluster_node *cluster;
22699a2dd95SBruce Richardson 	struct rte_node *node;
22799a2dd95SBruce Richardson 	rte_node_t count;
228*070db97eSPavan Nikhilesh 	uint8_t i;
22999a2dd95SBruce Richardson 
23099a2dd95SBruce Richardson 	cluster = stats->clusters;
23199a2dd95SBruce Richardson 
23299a2dd95SBruce Richardson 	/* Iterate over cluster node array to find node ID match */
23399a2dd95SBruce Richardson 	for (count = 0; count < stats->max_nodes; count++) {
23499a2dd95SBruce Richardson 		/* Found an existing node in the reel */
23599a2dd95SBruce Richardson 		if (cluster->stat.id == id) {
23699a2dd95SBruce Richardson 			node = graph_node_id_to_ptr(graph, id);
23799a2dd95SBruce Richardson 			if (node == NULL)
23899a2dd95SBruce Richardson 				SET_ERR_JMP(
23999a2dd95SBruce Richardson 					ENOENT, err,
24099a2dd95SBruce Richardson 					"Failed to find node %s in graph %s",
24199a2dd95SBruce Richardson 					graph_node->node->name, graph->name);
24299a2dd95SBruce Richardson 
24399a2dd95SBruce Richardson 			cluster->nodes[cluster->nb_nodes++] = node;
24499a2dd95SBruce Richardson 			return 0;
24599a2dd95SBruce Richardson 		}
24699a2dd95SBruce Richardson 		cluster = RTE_PTR_ADD(cluster, stats->cluster_node_size);
24799a2dd95SBruce Richardson 	}
24899a2dd95SBruce Richardson 
24999a2dd95SBruce Richardson 	/* Hey, it is a new node, allocate space for it in the reel */
25099a2dd95SBruce Richardson 	stats = realloc(stats, stats->sz + stats->cluster_node_size);
25199a2dd95SBruce Richardson 	if (stats == NULL)
25299a2dd95SBruce Richardson 		SET_ERR_JMP(ENOMEM, err, "Realloc failed");
2533b47572fSHongbo Zheng 	*stats_in = NULL;
25499a2dd95SBruce Richardson 
25599a2dd95SBruce Richardson 	/* Clear the new struct cluster_node area */
25699a2dd95SBruce Richardson 	cluster = RTE_PTR_ADD(stats, stats->sz),
25799a2dd95SBruce Richardson 	memset(cluster, 0, stats->cluster_node_size);
25899a2dd95SBruce Richardson 	memcpy(cluster->stat.name, graph_node->node->name, RTE_NODE_NAMESIZE);
25999a2dd95SBruce Richardson 	cluster->stat.id = graph_node->node->id;
26099a2dd95SBruce Richardson 	cluster->stat.hz = rte_get_timer_hz();
26199a2dd95SBruce Richardson 	node = graph_node_id_to_ptr(graph, id);
26299a2dd95SBruce Richardson 	if (node == NULL)
2633b47572fSHongbo Zheng 		SET_ERR_JMP(ENOENT, free, "Failed to find node %s in graph %s",
26499a2dd95SBruce Richardson 			    graph_node->node->name, graph->name);
26599a2dd95SBruce Richardson 	cluster->nodes[cluster->nb_nodes++] = node;
266*070db97eSPavan Nikhilesh 	if (graph_node->node->xstats) {
267*070db97eSPavan Nikhilesh 		cluster->stat.xstat_cntrs = graph_node->node->xstats->nb_xstats;
268*070db97eSPavan Nikhilesh 		cluster->stat.xstat_count = rte_zmalloc_socket(NULL,
269*070db97eSPavan Nikhilesh 			sizeof(uint64_t) * graph_node->node->xstats->nb_xstats,
270*070db97eSPavan Nikhilesh 			RTE_CACHE_LINE_SIZE, stats->socket_id);
271*070db97eSPavan Nikhilesh 		if (cluster->stat.xstat_count == NULL)
272*070db97eSPavan Nikhilesh 			SET_ERR_JMP(ENOMEM, free, "Failed to allocate memory node %s graph %s",
273*070db97eSPavan Nikhilesh 				    graph_node->node->name, graph->name);
274*070db97eSPavan Nikhilesh 
275*070db97eSPavan Nikhilesh 		cluster->stat.xstat_desc = rte_zmalloc_socket(NULL,
276*070db97eSPavan Nikhilesh 			sizeof(RTE_NODE_XSTAT_DESC_SIZE) * graph_node->node->xstats->nb_xstats,
277*070db97eSPavan Nikhilesh 			RTE_CACHE_LINE_SIZE, stats->socket_id);
278*070db97eSPavan Nikhilesh 		if (cluster->stat.xstat_desc == NULL) {
279*070db97eSPavan Nikhilesh 			rte_free(cluster->stat.xstat_count);
280*070db97eSPavan Nikhilesh 			SET_ERR_JMP(ENOMEM, free, "Failed to allocate memory node %s graph %s",
281*070db97eSPavan Nikhilesh 				    graph_node->node->name, graph->name);
282*070db97eSPavan Nikhilesh 		}
283*070db97eSPavan Nikhilesh 
284*070db97eSPavan Nikhilesh 		for (i = 0; i < cluster->stat.xstat_cntrs; i++) {
285*070db97eSPavan Nikhilesh 			if (rte_strscpy(cluster->stat.xstat_desc[i],
286*070db97eSPavan Nikhilesh 					graph_node->node->xstats->xstat_desc[i],
287*070db97eSPavan Nikhilesh 					RTE_NODE_XSTAT_DESC_SIZE) < 0) {
288*070db97eSPavan Nikhilesh 				rte_free(cluster->stat.xstat_count);
289*070db97eSPavan Nikhilesh 				rte_free(cluster->stat.xstat_desc);
290*070db97eSPavan Nikhilesh 				SET_ERR_JMP(E2BIG, free,
291*070db97eSPavan Nikhilesh 					    "Error description overflow node %s graph %s",
292*070db97eSPavan Nikhilesh 					    graph_node->node->name, graph->name);
293*070db97eSPavan Nikhilesh 			}
294*070db97eSPavan Nikhilesh 		}
295*070db97eSPavan Nikhilesh 	}
29699a2dd95SBruce Richardson 
29799a2dd95SBruce Richardson 	stats->sz += stats->cluster_node_size;
29899a2dd95SBruce Richardson 	stats->max_nodes++;
29999a2dd95SBruce Richardson 	*stats_in = stats;
30099a2dd95SBruce Richardson 
30199a2dd95SBruce Richardson 	return 0;
3023b47572fSHongbo Zheng free:
3033b47572fSHongbo Zheng 	free(stats);
30499a2dd95SBruce Richardson err:
30599a2dd95SBruce Richardson 	return -rte_errno;
30699a2dd95SBruce Richardson }
30799a2dd95SBruce Richardson 
30899a2dd95SBruce Richardson static void
30999a2dd95SBruce Richardson stats_mem_fini(struct rte_graph_cluster_stats *stats)
31099a2dd95SBruce Richardson {
31199a2dd95SBruce Richardson 	free(stats);
31299a2dd95SBruce Richardson }
31399a2dd95SBruce Richardson 
31499a2dd95SBruce Richardson static void
31599a2dd95SBruce Richardson cluster_init(struct cluster *cluster)
31699a2dd95SBruce Richardson {
31799a2dd95SBruce Richardson 	memset(cluster, 0, sizeof(*cluster));
31899a2dd95SBruce Richardson }
31999a2dd95SBruce Richardson 
32099a2dd95SBruce Richardson static int
32199a2dd95SBruce Richardson cluster_add(struct cluster *cluster, struct graph *graph)
32299a2dd95SBruce Richardson {
32399a2dd95SBruce Richardson 	rte_graph_t count;
32499a2dd95SBruce Richardson 	size_t sz;
32599a2dd95SBruce Richardson 
32699a2dd95SBruce Richardson 	/* Skip the if graph is already added to cluster */
32799a2dd95SBruce Richardson 	for (count = 0; count < cluster->nb_graphs; count++)
32899a2dd95SBruce Richardson 		if (cluster->graphs[count] == graph)
32999a2dd95SBruce Richardson 			return 0;
33099a2dd95SBruce Richardson 
33199a2dd95SBruce Richardson 	/* Expand the cluster if required to store graph objects */
33299a2dd95SBruce Richardson 	if (cluster->nb_graphs + 1 > cluster->size) {
33399a2dd95SBruce Richardson 		cluster->size = RTE_MAX(1, cluster->size * 2);
33499a2dd95SBruce Richardson 		sz = sizeof(struct graph *) * cluster->size;
33599a2dd95SBruce Richardson 		cluster->graphs = realloc(cluster->graphs, sz);
33699a2dd95SBruce Richardson 		if (cluster->graphs == NULL)
33799a2dd95SBruce Richardson 			SET_ERR_JMP(ENOMEM, free, "Failed to realloc");
33899a2dd95SBruce Richardson 	}
33999a2dd95SBruce Richardson 
34099a2dd95SBruce Richardson 	/* Add graph to cluster */
34199a2dd95SBruce Richardson 	cluster->graphs[cluster->nb_graphs++] = graph;
34299a2dd95SBruce Richardson 	return 0;
34399a2dd95SBruce Richardson 
34499a2dd95SBruce Richardson free:
34599a2dd95SBruce Richardson 	return -rte_errno;
34699a2dd95SBruce Richardson }
34799a2dd95SBruce Richardson 
34899a2dd95SBruce Richardson static void
34999a2dd95SBruce Richardson cluster_fini(struct cluster *cluster)
35099a2dd95SBruce Richardson {
35199a2dd95SBruce Richardson 	free(cluster->graphs);
35299a2dd95SBruce Richardson }
35399a2dd95SBruce Richardson 
35499a2dd95SBruce Richardson static int
35599a2dd95SBruce Richardson expand_pattern_to_cluster(struct cluster *cluster, const char *pattern)
35699a2dd95SBruce Richardson {
35799a2dd95SBruce Richardson 	struct graph_head *graph_head = graph_list_head_get();
35899a2dd95SBruce Richardson 	struct graph *graph;
35999a2dd95SBruce Richardson 	bool found = false;
36099a2dd95SBruce Richardson 
36199a2dd95SBruce Richardson 	/* Check for pattern match */
36299a2dd95SBruce Richardson 	STAILQ_FOREACH(graph, graph_head, next) {
36399a2dd95SBruce Richardson 		if (fnmatch(pattern, graph->name, 0) == 0) {
36499a2dd95SBruce Richardson 			if (cluster_add(cluster, graph))
36599a2dd95SBruce Richardson 				goto fail;
36699a2dd95SBruce Richardson 			found = true;
36799a2dd95SBruce Richardson 		}
36899a2dd95SBruce Richardson 	}
36999a2dd95SBruce Richardson 	if (found == false)
37099a2dd95SBruce Richardson 		SET_ERR_JMP(EFAULT, fail, "Pattern %s graph not found",
37199a2dd95SBruce Richardson 			    pattern);
37299a2dd95SBruce Richardson 
37399a2dd95SBruce Richardson 	return 0;
37499a2dd95SBruce Richardson fail:
37599a2dd95SBruce Richardson 	return -rte_errno;
37699a2dd95SBruce Richardson }
37799a2dd95SBruce Richardson 
37899a2dd95SBruce Richardson struct rte_graph_cluster_stats *
37999a2dd95SBruce Richardson rte_graph_cluster_stats_create(const struct rte_graph_cluster_stats_param *prm)
38099a2dd95SBruce Richardson {
38199a2dd95SBruce Richardson 	struct rte_graph_cluster_stats *stats, *rc = NULL;
38299a2dd95SBruce Richardson 	struct graph_node *graph_node;
38399a2dd95SBruce Richardson 	struct cluster cluster;
38499a2dd95SBruce Richardson 	struct graph *graph;
38599a2dd95SBruce Richardson 	const char *pattern;
38699a2dd95SBruce Richardson 	rte_graph_t i;
38799a2dd95SBruce Richardson 
38899a2dd95SBruce Richardson 	/* Sanity checks */
38999a2dd95SBruce Richardson 	if (!rte_graph_has_stats_feature())
39099a2dd95SBruce Richardson 		SET_ERR_JMP(EINVAL, fail, "Stats feature is not enabled");
39199a2dd95SBruce Richardson 
39299a2dd95SBruce Richardson 	if (prm == NULL)
39399a2dd95SBruce Richardson 		SET_ERR_JMP(EINVAL, fail, "Invalid param");
39499a2dd95SBruce Richardson 
39599a2dd95SBruce Richardson 	if (prm->graph_patterns == NULL || prm->nb_graph_patterns == 0)
39699a2dd95SBruce Richardson 		SET_ERR_JMP(EINVAL, fail, "Invalid graph param");
39799a2dd95SBruce Richardson 
39899a2dd95SBruce Richardson 	cluster_init(&cluster);
39999a2dd95SBruce Richardson 
40099a2dd95SBruce Richardson 	graph_spinlock_lock();
40199a2dd95SBruce Richardson 	/* Expand graph pattern and add the graph to the cluster */
40299a2dd95SBruce Richardson 	for (i = 0; i < prm->nb_graph_patterns; i++) {
40399a2dd95SBruce Richardson 		pattern = prm->graph_patterns[i];
40499a2dd95SBruce Richardson 		if (expand_pattern_to_cluster(&cluster, pattern))
40599a2dd95SBruce Richardson 			goto bad_pattern;
40699a2dd95SBruce Richardson 	}
40799a2dd95SBruce Richardson 
40899a2dd95SBruce Richardson 	/* Alloc the stats memory */
40999a2dd95SBruce Richardson 	stats = stats_mem_init(&cluster, prm);
41099a2dd95SBruce Richardson 	if (stats == NULL)
41199a2dd95SBruce Richardson 		SET_ERR_JMP(ENOMEM, bad_pattern, "Failed alloc stats memory");
41299a2dd95SBruce Richardson 
41399a2dd95SBruce Richardson 	/* Iterate over M(Graph) x N (Nodes in graph) */
41499a2dd95SBruce Richardson 	for (i = 0; i < cluster.nb_graphs; i++) {
41599a2dd95SBruce Richardson 		graph = cluster.graphs[i];
41699a2dd95SBruce Richardson 		STAILQ_FOREACH(graph_node, &graph->node_list, next) {
41799a2dd95SBruce Richardson 			struct rte_graph *graph_fp = graph->graph;
41899a2dd95SBruce Richardson 			if (stats_mem_populate(&stats, graph_fp, graph_node))
41999a2dd95SBruce Richardson 				goto realloc_fail;
42099a2dd95SBruce Richardson 		}
4217d18ab56SRobin Jarry 		if (graph->graph->model == RTE_GRAPH_MODEL_MCORE_DISPATCH)
4227d18ab56SRobin Jarry 			stats->dispatch = true;
42399a2dd95SBruce Richardson 	}
42499a2dd95SBruce Richardson 
42599a2dd95SBruce Richardson 	/* Finally copy to hugepage memory to avoid pressure on rte_realloc */
42699a2dd95SBruce Richardson 	rc = rte_malloc_socket(NULL, stats->sz, 0, stats->socket_id);
42799a2dd95SBruce Richardson 	if (rc)
42899a2dd95SBruce Richardson 		rte_memcpy(rc, stats, stats->sz);
42999a2dd95SBruce Richardson 	else
43099a2dd95SBruce Richardson 		SET_ERR_JMP(ENOMEM, realloc_fail, "rte_malloc failed");
43199a2dd95SBruce Richardson 
43299a2dd95SBruce Richardson realloc_fail:
43399a2dd95SBruce Richardson 	stats_mem_fini(stats);
43499a2dd95SBruce Richardson bad_pattern:
43599a2dd95SBruce Richardson 	graph_spinlock_unlock();
43699a2dd95SBruce Richardson 	cluster_fini(&cluster);
43799a2dd95SBruce Richardson fail:
43899a2dd95SBruce Richardson 	return rc;
43999a2dd95SBruce Richardson }
44099a2dd95SBruce Richardson 
44199a2dd95SBruce Richardson void
44299a2dd95SBruce Richardson rte_graph_cluster_stats_destroy(struct rte_graph_cluster_stats *stat)
44399a2dd95SBruce Richardson {
444*070db97eSPavan Nikhilesh 	struct cluster_node *cluster;
445*070db97eSPavan Nikhilesh 	rte_node_t count;
446*070db97eSPavan Nikhilesh 
447*070db97eSPavan Nikhilesh 	cluster = stat->clusters;
448*070db97eSPavan Nikhilesh 	for (count = 0; count < stat->max_nodes; count++) {
449*070db97eSPavan Nikhilesh 		if (cluster->stat.xstat_cntrs) {
450*070db97eSPavan Nikhilesh 			rte_free(cluster->stat.xstat_count);
451*070db97eSPavan Nikhilesh 			rte_free(cluster->stat.xstat_desc);
452*070db97eSPavan Nikhilesh 		}
453*070db97eSPavan Nikhilesh 
454*070db97eSPavan Nikhilesh 		cluster = RTE_PTR_ADD(cluster, stat->cluster_node_size);
455*070db97eSPavan Nikhilesh 	}
45699a2dd95SBruce Richardson 	return rte_free(stat);
45799a2dd95SBruce Richardson }
45899a2dd95SBruce Richardson 
45999a2dd95SBruce Richardson static inline void
4607d18ab56SRobin Jarry cluster_node_arregate_stats(struct cluster_node *cluster, bool dispatch)
46199a2dd95SBruce Richardson {
46299a2dd95SBruce Richardson 	uint64_t calls = 0, cycles = 0, objs = 0, realloc_count = 0;
46399a2dd95SBruce Richardson 	struct rte_graph_cluster_node_stats *stat = &cluster->stat;
464358ff83fSZhirun Yan 	uint64_t sched_objs = 0, sched_fail = 0;
46599a2dd95SBruce Richardson 	struct rte_node *node;
46699a2dd95SBruce Richardson 	rte_node_t count;
467*070db97eSPavan Nikhilesh 	uint64_t *xstat;
468*070db97eSPavan Nikhilesh 	uint8_t i;
46999a2dd95SBruce Richardson 
470*070db97eSPavan Nikhilesh 	memset(stat->xstat_count, 0, sizeof(uint64_t) * stat->xstat_cntrs);
47199a2dd95SBruce Richardson 	for (count = 0; count < cluster->nb_nodes; count++) {
47299a2dd95SBruce Richardson 		node = cluster->nodes[count];
47399a2dd95SBruce Richardson 
4747d18ab56SRobin Jarry 		if (dispatch) {
475358ff83fSZhirun Yan 			sched_objs += node->dispatch.total_sched_objs;
476358ff83fSZhirun Yan 			sched_fail += node->dispatch.total_sched_fail;
477358ff83fSZhirun Yan 		}
478358ff83fSZhirun Yan 
47999a2dd95SBruce Richardson 		calls += node->total_calls;
48099a2dd95SBruce Richardson 		objs += node->total_objs;
48199a2dd95SBruce Richardson 		cycles += node->total_cycles;
48299a2dd95SBruce Richardson 		realloc_count += node->realloc_count;
483*070db97eSPavan Nikhilesh 
484*070db97eSPavan Nikhilesh 		if (node->xstat_off == 0)
485*070db97eSPavan Nikhilesh 			continue;
486*070db97eSPavan Nikhilesh 		xstat = RTE_PTR_ADD(node, node->xstat_off);
487*070db97eSPavan Nikhilesh 		for (i = 0; i < stat->xstat_cntrs; i++)
488*070db97eSPavan Nikhilesh 			stat->xstat_count[i] += xstat[i];
48999a2dd95SBruce Richardson 	}
49099a2dd95SBruce Richardson 
49199a2dd95SBruce Richardson 	stat->calls = calls;
49299a2dd95SBruce Richardson 	stat->objs = objs;
49399a2dd95SBruce Richardson 	stat->cycles = cycles;
494358ff83fSZhirun Yan 
4957d18ab56SRobin Jarry 	if (dispatch) {
496358ff83fSZhirun Yan 		stat->dispatch.sched_objs = sched_objs;
497358ff83fSZhirun Yan 		stat->dispatch.sched_fail = sched_fail;
498358ff83fSZhirun Yan 	}
499358ff83fSZhirun Yan 
50099a2dd95SBruce Richardson 	stat->ts = rte_get_timer_cycles();
50199a2dd95SBruce Richardson 	stat->realloc_count = realloc_count;
50299a2dd95SBruce Richardson }
50399a2dd95SBruce Richardson 
50499a2dd95SBruce Richardson static inline void
50599a2dd95SBruce Richardson cluster_node_store_prev_stats(struct cluster_node *cluster)
50699a2dd95SBruce Richardson {
50799a2dd95SBruce Richardson 	struct rte_graph_cluster_node_stats *stat = &cluster->stat;
50899a2dd95SBruce Richardson 
50999a2dd95SBruce Richardson 	stat->prev_ts = stat->ts;
51099a2dd95SBruce Richardson 	stat->prev_calls = stat->calls;
51199a2dd95SBruce Richardson 	stat->prev_objs = stat->objs;
51299a2dd95SBruce Richardson 	stat->prev_cycles = stat->cycles;
51399a2dd95SBruce Richardson }
51499a2dd95SBruce Richardson 
51599a2dd95SBruce Richardson void
51699a2dd95SBruce Richardson rte_graph_cluster_stats_get(struct rte_graph_cluster_stats *stat, bool skip_cb)
51799a2dd95SBruce Richardson {
51899a2dd95SBruce Richardson 	struct cluster_node *cluster;
51999a2dd95SBruce Richardson 	rte_node_t count;
52099a2dd95SBruce Richardson 	int rc = 0;
52199a2dd95SBruce Richardson 
52299a2dd95SBruce Richardson 	cluster = stat->clusters;
52399a2dd95SBruce Richardson 
52499a2dd95SBruce Richardson 	for (count = 0; count < stat->max_nodes; count++) {
5257d18ab56SRobin Jarry 		cluster_node_arregate_stats(cluster, stat->dispatch);
52699a2dd95SBruce Richardson 		if (!skip_cb)
52799a2dd95SBruce Richardson 			rc = stat->fn(!count, (count == stat->max_nodes - 1),
52899a2dd95SBruce Richardson 				      stat->cookie, &cluster->stat);
52999a2dd95SBruce Richardson 		cluster_node_store_prev_stats(cluster);
53099a2dd95SBruce Richardson 		if (rc)
53199a2dd95SBruce Richardson 			break;
53299a2dd95SBruce Richardson 		cluster = RTE_PTR_ADD(cluster, stat->cluster_node_size);
53399a2dd95SBruce Richardson 	}
53499a2dd95SBruce Richardson }
53599a2dd95SBruce Richardson 
53699a2dd95SBruce Richardson void
53799a2dd95SBruce Richardson rte_graph_cluster_stats_reset(struct rte_graph_cluster_stats *stat)
53899a2dd95SBruce Richardson {
53999a2dd95SBruce Richardson 	struct cluster_node *cluster;
54099a2dd95SBruce Richardson 	rte_node_t count;
541*070db97eSPavan Nikhilesh 	uint8_t i;
54299a2dd95SBruce Richardson 
54399a2dd95SBruce Richardson 	cluster = stat->clusters;
54499a2dd95SBruce Richardson 
54599a2dd95SBruce Richardson 	for (count = 0; count < stat->max_nodes; count++) {
54699a2dd95SBruce Richardson 		struct rte_graph_cluster_node_stats *node = &cluster->stat;
54799a2dd95SBruce Richardson 
54899a2dd95SBruce Richardson 		node->ts = 0;
54999a2dd95SBruce Richardson 		node->calls = 0;
55099a2dd95SBruce Richardson 		node->objs = 0;
55199a2dd95SBruce Richardson 		node->cycles = 0;
55299a2dd95SBruce Richardson 		node->prev_ts = 0;
55399a2dd95SBruce Richardson 		node->prev_calls = 0;
55499a2dd95SBruce Richardson 		node->prev_objs = 0;
55599a2dd95SBruce Richardson 		node->prev_cycles = 0;
55699a2dd95SBruce Richardson 		node->realloc_count = 0;
557*070db97eSPavan Nikhilesh 		for (i = 0; i < node->xstat_cntrs; i++)
558*070db97eSPavan Nikhilesh 			node->xstat_count[i] = 0;
55999a2dd95SBruce Richardson 		cluster = RTE_PTR_ADD(cluster, stat->cluster_node_size);
56099a2dd95SBruce Richardson 	}
56199a2dd95SBruce Richardson }
562