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