161d77071SPavan Nikhilesh /* SPDX-License-Identifier: BSD-3-Clause 261d77071SPavan Nikhilesh * Copyright(C) 2020 Marvell International Ltd. 361d77071SPavan Nikhilesh */ 43c60274cSJie Zhou 53c60274cSJie Zhou #include "test.h" 63c60274cSJie Zhou 761d77071SPavan Nikhilesh #include <inttypes.h> 861d77071SPavan Nikhilesh #include <signal.h> 961d77071SPavan Nikhilesh #include <stdio.h> 1061d77071SPavan Nikhilesh #include <unistd.h> 1161d77071SPavan Nikhilesh 1261d77071SPavan Nikhilesh #include <rte_common.h> 1361d77071SPavan Nikhilesh #include <rte_cycles.h> 1461d77071SPavan Nikhilesh #include <rte_errno.h> 153c60274cSJie Zhou #ifdef RTE_EXEC_ENV_WINDOWS 163c60274cSJie Zhou static int 173c60274cSJie Zhou test_graph_perf_func(void) 183c60274cSJie Zhou { 193c60274cSJie Zhou printf("graph_perf not supported on Windows, skipping test\n"); 203c60274cSJie Zhou return TEST_SKIPPED; 213c60274cSJie Zhou } 223c60274cSJie Zhou 233c60274cSJie Zhou #else 243c60274cSJie Zhou 2561d77071SPavan Nikhilesh #include <rte_graph.h> 26*a2bc0584SZhirun Yan #include <rte_graph_worker.h> 2761d77071SPavan Nikhilesh #include <rte_lcore.h> 2861d77071SPavan Nikhilesh #include <rte_malloc.h> 2961d77071SPavan Nikhilesh #include <rte_mbuf.h> 3061d77071SPavan Nikhilesh 3161d77071SPavan Nikhilesh #define TEST_GRAPH_PERF_MZ "graph_perf_data" 3261d77071SPavan Nikhilesh #define TEST_GRAPH_SRC_NAME "test_graph_perf_source" 3361d77071SPavan Nikhilesh #define TEST_GRAPH_SRC_BRST_ONE_NAME "test_graph_perf_source_one" 3461d77071SPavan Nikhilesh #define TEST_GRAPH_WRK_NAME "test_graph_perf_worker" 3561d77071SPavan Nikhilesh #define TEST_GRAPH_SNK_NAME "test_graph_perf_sink" 3661d77071SPavan Nikhilesh 3761d77071SPavan Nikhilesh #define SOURCES(map) RTE_DIM(map) 3861d77071SPavan Nikhilesh #define STAGES(map) RTE_DIM(map) 3961d77071SPavan Nikhilesh #define NODES_PER_STAGE(map) RTE_DIM(map[0]) 4061d77071SPavan Nikhilesh #define SINKS(map) RTE_DIM(map[0]) 4161d77071SPavan Nikhilesh 4261d77071SPavan Nikhilesh #define MAX_EDGES_PER_NODE 7 4361d77071SPavan Nikhilesh 4461d77071SPavan Nikhilesh struct test_node_data { 4561d77071SPavan Nikhilesh uint8_t node_id; 4661d77071SPavan Nikhilesh uint8_t is_sink; 4761d77071SPavan Nikhilesh uint8_t next_nodes[MAX_EDGES_PER_NODE]; 4861d77071SPavan Nikhilesh uint8_t next_percentage[MAX_EDGES_PER_NODE]; 4961d77071SPavan Nikhilesh }; 5061d77071SPavan Nikhilesh 5161d77071SPavan Nikhilesh struct test_graph_perf { 5261d77071SPavan Nikhilesh uint16_t nb_nodes; 5361d77071SPavan Nikhilesh rte_graph_t graph_id; 5461d77071SPavan Nikhilesh struct test_node_data *node_data; 5561d77071SPavan Nikhilesh }; 5661d77071SPavan Nikhilesh 5761d77071SPavan Nikhilesh struct graph_lcore_data { 5861d77071SPavan Nikhilesh uint8_t done; 5961d77071SPavan Nikhilesh rte_graph_t graph_id; 6061d77071SPavan Nikhilesh }; 6161d77071SPavan Nikhilesh 6261d77071SPavan Nikhilesh static struct test_node_data * 6361d77071SPavan Nikhilesh graph_get_node_data(struct test_graph_perf *graph_data, rte_node_t id) 6461d77071SPavan Nikhilesh { 6561d77071SPavan Nikhilesh struct test_node_data *node_data = NULL; 6661d77071SPavan Nikhilesh int i; 6761d77071SPavan Nikhilesh 6861d77071SPavan Nikhilesh for (i = 0; i < graph_data->nb_nodes; i++) 6961d77071SPavan Nikhilesh if (graph_data->node_data[i].node_id == id) { 7061d77071SPavan Nikhilesh node_data = &graph_data->node_data[i]; 7161d77071SPavan Nikhilesh break; 7261d77071SPavan Nikhilesh } 7361d77071SPavan Nikhilesh 7461d77071SPavan Nikhilesh return node_data; 7561d77071SPavan Nikhilesh } 7661d77071SPavan Nikhilesh 7761d77071SPavan Nikhilesh static int 7861d77071SPavan Nikhilesh test_node_ctx_init(const struct rte_graph *graph, struct rte_node *node) 7961d77071SPavan Nikhilesh { 8061d77071SPavan Nikhilesh struct test_graph_perf *graph_data; 8161d77071SPavan Nikhilesh struct test_node_data *node_data; 8261d77071SPavan Nikhilesh const struct rte_memzone *mz; 8361d77071SPavan Nikhilesh rte_node_t nid = node->id; 8461d77071SPavan Nikhilesh rte_edge_t edge = 0; 8561d77071SPavan Nikhilesh int i; 8661d77071SPavan Nikhilesh 8761d77071SPavan Nikhilesh RTE_SET_USED(graph); 8861d77071SPavan Nikhilesh 8961d77071SPavan Nikhilesh mz = rte_memzone_lookup(TEST_GRAPH_PERF_MZ); 902e908855SPavan Nikhilesh if (mz == NULL) 912e908855SPavan Nikhilesh return -ENOMEM; 9261d77071SPavan Nikhilesh graph_data = mz->addr; 9361d77071SPavan Nikhilesh node_data = graph_get_node_data(graph_data, nid); 9461d77071SPavan Nikhilesh node->ctx[0] = node->nb_edges; 9561d77071SPavan Nikhilesh for (i = 0; i < node->nb_edges && !node_data->is_sink; i++, edge++) { 9661d77071SPavan Nikhilesh node->ctx[i + 1] = edge; 9761d77071SPavan Nikhilesh node->ctx[i + 9] = node_data->next_percentage[i]; 9861d77071SPavan Nikhilesh } 9961d77071SPavan Nikhilesh 10061d77071SPavan Nikhilesh return 0; 10161d77071SPavan Nikhilesh } 10261d77071SPavan Nikhilesh 10361d77071SPavan Nikhilesh /* Source node function */ 10461d77071SPavan Nikhilesh static uint16_t 10561d77071SPavan Nikhilesh test_perf_node_worker_source(struct rte_graph *graph, struct rte_node *node, 10661d77071SPavan Nikhilesh void **objs, uint16_t nb_objs) 10761d77071SPavan Nikhilesh { 10861d77071SPavan Nikhilesh uint16_t count; 10961d77071SPavan Nikhilesh int i; 11061d77071SPavan Nikhilesh 11161d77071SPavan Nikhilesh RTE_SET_USED(objs); 11261d77071SPavan Nikhilesh RTE_SET_USED(nb_objs); 11361d77071SPavan Nikhilesh 11461d77071SPavan Nikhilesh /* Create a proportional stream for every next */ 11561d77071SPavan Nikhilesh for (i = 0; i < node->ctx[0]; i++) { 11661d77071SPavan Nikhilesh count = (node->ctx[i + 9] * RTE_GRAPH_BURST_SIZE) / 100; 11761d77071SPavan Nikhilesh rte_node_next_stream_get(graph, node, node->ctx[i + 1], count); 11861d77071SPavan Nikhilesh rte_node_next_stream_put(graph, node, node->ctx[i + 1], count); 11961d77071SPavan Nikhilesh } 12061d77071SPavan Nikhilesh 12161d77071SPavan Nikhilesh return RTE_GRAPH_BURST_SIZE; 12261d77071SPavan Nikhilesh } 12361d77071SPavan Nikhilesh 12461d77071SPavan Nikhilesh static struct rte_node_register test_graph_perf_source = { 12561d77071SPavan Nikhilesh .name = TEST_GRAPH_SRC_NAME, 12661d77071SPavan Nikhilesh .process = test_perf_node_worker_source, 12761d77071SPavan Nikhilesh .flags = RTE_NODE_SOURCE_F, 12861d77071SPavan Nikhilesh .init = test_node_ctx_init, 12961d77071SPavan Nikhilesh }; 13061d77071SPavan Nikhilesh 13161d77071SPavan Nikhilesh RTE_NODE_REGISTER(test_graph_perf_source); 13261d77071SPavan Nikhilesh 13361d77071SPavan Nikhilesh static uint16_t 13461d77071SPavan Nikhilesh test_perf_node_worker_source_burst_one(struct rte_graph *graph, 13561d77071SPavan Nikhilesh struct rte_node *node, void **objs, 13661d77071SPavan Nikhilesh uint16_t nb_objs) 13761d77071SPavan Nikhilesh { 13861d77071SPavan Nikhilesh uint16_t count; 13961d77071SPavan Nikhilesh int i; 14061d77071SPavan Nikhilesh 14161d77071SPavan Nikhilesh RTE_SET_USED(objs); 14261d77071SPavan Nikhilesh RTE_SET_USED(nb_objs); 14361d77071SPavan Nikhilesh 14461d77071SPavan Nikhilesh /* Create a proportional stream for every next */ 14561d77071SPavan Nikhilesh for (i = 0; i < node->ctx[0]; i++) { 14661d77071SPavan Nikhilesh count = (node->ctx[i + 9]) / 100; 14761d77071SPavan Nikhilesh rte_node_next_stream_get(graph, node, node->ctx[i + 1], count); 14861d77071SPavan Nikhilesh rte_node_next_stream_put(graph, node, node->ctx[i + 1], count); 14961d77071SPavan Nikhilesh } 15061d77071SPavan Nikhilesh 15161d77071SPavan Nikhilesh return 1; 15261d77071SPavan Nikhilesh } 15361d77071SPavan Nikhilesh 15461d77071SPavan Nikhilesh static struct rte_node_register test_graph_perf_source_burst_one = { 15561d77071SPavan Nikhilesh .name = TEST_GRAPH_SRC_BRST_ONE_NAME, 15661d77071SPavan Nikhilesh .process = test_perf_node_worker_source_burst_one, 15761d77071SPavan Nikhilesh .flags = RTE_NODE_SOURCE_F, 15861d77071SPavan Nikhilesh .init = test_node_ctx_init, 15961d77071SPavan Nikhilesh }; 16061d77071SPavan Nikhilesh 16161d77071SPavan Nikhilesh RTE_NODE_REGISTER(test_graph_perf_source_burst_one); 16261d77071SPavan Nikhilesh 16361d77071SPavan Nikhilesh /* Worker node function */ 16461d77071SPavan Nikhilesh static uint16_t 16561d77071SPavan Nikhilesh test_perf_node_worker(struct rte_graph *graph, struct rte_node *node, 16661d77071SPavan Nikhilesh void **objs, uint16_t nb_objs) 16761d77071SPavan Nikhilesh { 16861d77071SPavan Nikhilesh uint16_t next = 0; 16961d77071SPavan Nikhilesh uint16_t enq = 0; 17061d77071SPavan Nikhilesh uint16_t count; 17161d77071SPavan Nikhilesh int i; 17261d77071SPavan Nikhilesh 17361d77071SPavan Nikhilesh /* Move stream for single next node */ 17461d77071SPavan Nikhilesh if (node->ctx[0] == 1) { 17561d77071SPavan Nikhilesh rte_node_next_stream_move(graph, node, node->ctx[1]); 17661d77071SPavan Nikhilesh return nb_objs; 17761d77071SPavan Nikhilesh } 17861d77071SPavan Nikhilesh 17961d77071SPavan Nikhilesh /* Enqueue objects to next nodes proportionally */ 18061d77071SPavan Nikhilesh for (i = 0; i < node->ctx[0]; i++) { 18161d77071SPavan Nikhilesh next = node->ctx[i + 1]; 18261d77071SPavan Nikhilesh count = (node->ctx[i + 9] * nb_objs) / 100; 18361d77071SPavan Nikhilesh enq += count; 18461d77071SPavan Nikhilesh while (count) { 18561d77071SPavan Nikhilesh switch (count & (4 - 1)) { 18661d77071SPavan Nikhilesh case 0: 18761d77071SPavan Nikhilesh rte_node_enqueue_x4(graph, node, next, objs[0], 18861d77071SPavan Nikhilesh objs[1], objs[2], objs[3]); 18961d77071SPavan Nikhilesh objs += 4; 19061d77071SPavan Nikhilesh count -= 4; 19161d77071SPavan Nikhilesh break; 19261d77071SPavan Nikhilesh case 1: 19361d77071SPavan Nikhilesh rte_node_enqueue_x1(graph, node, next, objs[0]); 19461d77071SPavan Nikhilesh objs += 1; 19561d77071SPavan Nikhilesh count -= 1; 19661d77071SPavan Nikhilesh break; 19761d77071SPavan Nikhilesh case 2: 19861d77071SPavan Nikhilesh rte_node_enqueue_x2(graph, node, next, objs[0], 19961d77071SPavan Nikhilesh objs[1]); 20061d77071SPavan Nikhilesh objs += 2; 20161d77071SPavan Nikhilesh count -= 2; 20261d77071SPavan Nikhilesh break; 20361d77071SPavan Nikhilesh case 3: 20461d77071SPavan Nikhilesh rte_node_enqueue_x2(graph, node, next, objs[0], 20561d77071SPavan Nikhilesh objs[1]); 20661d77071SPavan Nikhilesh rte_node_enqueue_x1(graph, node, next, objs[0]); 20761d77071SPavan Nikhilesh objs += 3; 20861d77071SPavan Nikhilesh count -= 3; 20961d77071SPavan Nikhilesh break; 21061d77071SPavan Nikhilesh } 21161d77071SPavan Nikhilesh } 21261d77071SPavan Nikhilesh } 21361d77071SPavan Nikhilesh 21461d77071SPavan Nikhilesh if (enq != nb_objs) 21561d77071SPavan Nikhilesh rte_node_enqueue(graph, node, next, objs, nb_objs - enq); 21661d77071SPavan Nikhilesh 21761d77071SPavan Nikhilesh return nb_objs; 21861d77071SPavan Nikhilesh } 21961d77071SPavan Nikhilesh 22061d77071SPavan Nikhilesh static struct rte_node_register test_graph_perf_worker = { 22161d77071SPavan Nikhilesh .name = TEST_GRAPH_WRK_NAME, 22261d77071SPavan Nikhilesh .process = test_perf_node_worker, 22361d77071SPavan Nikhilesh .init = test_node_ctx_init, 22461d77071SPavan Nikhilesh }; 22561d77071SPavan Nikhilesh 22661d77071SPavan Nikhilesh RTE_NODE_REGISTER(test_graph_perf_worker); 22761d77071SPavan Nikhilesh 22861d77071SPavan Nikhilesh /* Last node in graph a.k.a sink node */ 22961d77071SPavan Nikhilesh static uint16_t 23061d77071SPavan Nikhilesh test_perf_node_sink(struct rte_graph *graph, struct rte_node *node, void **objs, 23161d77071SPavan Nikhilesh uint16_t nb_objs) 23261d77071SPavan Nikhilesh { 23361d77071SPavan Nikhilesh RTE_SET_USED(graph); 23461d77071SPavan Nikhilesh RTE_SET_USED(node); 23561d77071SPavan Nikhilesh RTE_SET_USED(objs); 23661d77071SPavan Nikhilesh RTE_SET_USED(nb_objs); 23761d77071SPavan Nikhilesh 23861d77071SPavan Nikhilesh return nb_objs; 23961d77071SPavan Nikhilesh } 24061d77071SPavan Nikhilesh 24161d77071SPavan Nikhilesh static struct rte_node_register test_graph_perf_sink = { 24261d77071SPavan Nikhilesh .name = TEST_GRAPH_SNK_NAME, 24361d77071SPavan Nikhilesh .process = test_perf_node_sink, 24461d77071SPavan Nikhilesh .init = test_node_ctx_init, 24561d77071SPavan Nikhilesh }; 24661d77071SPavan Nikhilesh 24761d77071SPavan Nikhilesh RTE_NODE_REGISTER(test_graph_perf_sink); 24861d77071SPavan Nikhilesh 24961d77071SPavan Nikhilesh static int 25061d77071SPavan Nikhilesh graph_perf_setup(void) 25161d77071SPavan Nikhilesh { 25261d77071SPavan Nikhilesh if (rte_lcore_count() < 2) { 25361d77071SPavan Nikhilesh printf("Test requires at least 2 lcores\n"); 25461d77071SPavan Nikhilesh return TEST_SKIPPED; 25561d77071SPavan Nikhilesh } 25661d77071SPavan Nikhilesh 25761d77071SPavan Nikhilesh return 0; 25861d77071SPavan Nikhilesh } 25961d77071SPavan Nikhilesh 26061d77071SPavan Nikhilesh static void 26161d77071SPavan Nikhilesh graph_perf_teardown(void) 26261d77071SPavan Nikhilesh { 26361d77071SPavan Nikhilesh } 26461d77071SPavan Nikhilesh 26561d77071SPavan Nikhilesh static inline rte_node_t 26661d77071SPavan Nikhilesh graph_node_get(const char *pname, char *nname) 26761d77071SPavan Nikhilesh { 26861d77071SPavan Nikhilesh rte_node_t pnode_id = rte_node_from_name(pname); 26961d77071SPavan Nikhilesh char lookup_name[RTE_NODE_NAMESIZE]; 27061d77071SPavan Nikhilesh rte_node_t node_id; 27161d77071SPavan Nikhilesh 27261d77071SPavan Nikhilesh snprintf(lookup_name, RTE_NODE_NAMESIZE, "%s-%s", pname, nname); 27361d77071SPavan Nikhilesh node_id = rte_node_from_name(lookup_name); 27461d77071SPavan Nikhilesh 27561d77071SPavan Nikhilesh if (node_id != RTE_NODE_ID_INVALID) { 27661d77071SPavan Nikhilesh if (rte_node_edge_count(node_id)) 27761d77071SPavan Nikhilesh rte_node_edge_shrink(node_id, 0); 27861d77071SPavan Nikhilesh return node_id; 27961d77071SPavan Nikhilesh } 28061d77071SPavan Nikhilesh 28161d77071SPavan Nikhilesh return rte_node_clone(pnode_id, nname); 28261d77071SPavan Nikhilesh } 28361d77071SPavan Nikhilesh 28461d77071SPavan Nikhilesh static uint16_t 28561d77071SPavan Nikhilesh graph_node_count_edges(uint32_t stage, uint16_t node, uint16_t nodes_per_stage, 28661d77071SPavan Nikhilesh uint8_t edge_map[][nodes_per_stage][nodes_per_stage], 28761d77071SPavan Nikhilesh char *ename[], struct test_node_data *node_data, 28861d77071SPavan Nikhilesh rte_node_t **node_map) 28961d77071SPavan Nikhilesh { 29061d77071SPavan Nikhilesh uint8_t total_percent = 0; 29161d77071SPavan Nikhilesh uint16_t edges = 0; 29261d77071SPavan Nikhilesh int i; 29361d77071SPavan Nikhilesh 29461d77071SPavan Nikhilesh for (i = 0; i < nodes_per_stage && edges < MAX_EDGES_PER_NODE; i++) { 29561d77071SPavan Nikhilesh if (edge_map[stage + 1][i][node]) { 29661d77071SPavan Nikhilesh ename[edges] = malloc(sizeof(char) * RTE_NODE_NAMESIZE); 29761d77071SPavan Nikhilesh snprintf(ename[edges], RTE_NODE_NAMESIZE, "%s", 29861d77071SPavan Nikhilesh rte_node_id_to_name(node_map[stage + 1][i])); 29961d77071SPavan Nikhilesh node_data->next_nodes[edges] = node_map[stage + 1][i]; 30061d77071SPavan Nikhilesh node_data->next_percentage[edges] = 30161d77071SPavan Nikhilesh edge_map[stage + 1][i][node]; 30261d77071SPavan Nikhilesh edges++; 30361d77071SPavan Nikhilesh total_percent += edge_map[stage + 1][i][node]; 30461d77071SPavan Nikhilesh } 30561d77071SPavan Nikhilesh } 30661d77071SPavan Nikhilesh 30761d77071SPavan Nikhilesh if (edges >= MAX_EDGES_PER_NODE || (edges && total_percent != 100)) { 30861d77071SPavan Nikhilesh for (i = 0; i < edges; i++) 30961d77071SPavan Nikhilesh free(ename[i]); 31061d77071SPavan Nikhilesh return RTE_EDGE_ID_INVALID; 31161d77071SPavan Nikhilesh } 31261d77071SPavan Nikhilesh 31361d77071SPavan Nikhilesh return edges; 31461d77071SPavan Nikhilesh } 31561d77071SPavan Nikhilesh 31661d77071SPavan Nikhilesh static int 31761d77071SPavan Nikhilesh graph_init(const char *gname, uint8_t nb_srcs, uint8_t nb_sinks, 31861d77071SPavan Nikhilesh uint32_t stages, uint16_t nodes_per_stage, 31961d77071SPavan Nikhilesh uint8_t src_map[][nodes_per_stage], uint8_t snk_map[][nb_sinks], 32061d77071SPavan Nikhilesh uint8_t edge_map[][nodes_per_stage][nodes_per_stage], 32161d77071SPavan Nikhilesh uint8_t burst_one) 32261d77071SPavan Nikhilesh { 32361d77071SPavan Nikhilesh struct test_graph_perf *graph_data; 32461d77071SPavan Nikhilesh char nname[RTE_NODE_NAMESIZE / 2]; 32561d77071SPavan Nikhilesh struct test_node_data *node_data; 32661d77071SPavan Nikhilesh char *ename[nodes_per_stage]; 3279b72ea1fSAmit Prakash Shukla struct rte_graph_param gconf = {0}; 32861d77071SPavan Nikhilesh const struct rte_memzone *mz; 32961d77071SPavan Nikhilesh uint8_t total_percent = 0; 33061d77071SPavan Nikhilesh rte_node_t *src_nodes; 33161d77071SPavan Nikhilesh rte_node_t *snk_nodes; 33261d77071SPavan Nikhilesh rte_node_t **node_map; 33361d77071SPavan Nikhilesh char **node_patterns; 33461d77071SPavan Nikhilesh rte_graph_t graph_id; 33561d77071SPavan Nikhilesh rte_edge_t edges; 33661d77071SPavan Nikhilesh rte_edge_t count; 33761d77071SPavan Nikhilesh uint32_t i, j, k; 33861d77071SPavan Nikhilesh 33961d77071SPavan Nikhilesh mz = rte_memzone_reserve(TEST_GRAPH_PERF_MZ, 34061d77071SPavan Nikhilesh sizeof(struct test_graph_perf), 0, 0); 34161d77071SPavan Nikhilesh if (mz == NULL) { 34261d77071SPavan Nikhilesh printf("Failed to allocate graph common memory\n"); 34361d77071SPavan Nikhilesh return -ENOMEM; 34461d77071SPavan Nikhilesh } 34561d77071SPavan Nikhilesh 34661d77071SPavan Nikhilesh graph_data = mz->addr; 34761d77071SPavan Nikhilesh graph_data->nb_nodes = 0; 34861d77071SPavan Nikhilesh graph_data->node_data = 34961d77071SPavan Nikhilesh malloc(sizeof(struct test_node_data) * 35061d77071SPavan Nikhilesh (nb_srcs + nb_sinks + stages * nodes_per_stage)); 35161d77071SPavan Nikhilesh if (graph_data->node_data == NULL) { 35261d77071SPavan Nikhilesh printf("Failed to reserve memzone for graph data\n"); 35361d77071SPavan Nikhilesh goto memzone_free; 35461d77071SPavan Nikhilesh } 35561d77071SPavan Nikhilesh 35661d77071SPavan Nikhilesh node_patterns = malloc(sizeof(char *) * 35761d77071SPavan Nikhilesh (nb_srcs + nb_sinks + stages * nodes_per_stage)); 35861d77071SPavan Nikhilesh if (node_patterns == NULL) { 35961d77071SPavan Nikhilesh printf("Failed to reserve memory for node patterns\n"); 36061d77071SPavan Nikhilesh goto data_free; 36161d77071SPavan Nikhilesh } 36261d77071SPavan Nikhilesh 36361d77071SPavan Nikhilesh src_nodes = malloc(sizeof(rte_node_t) * nb_srcs); 36461d77071SPavan Nikhilesh if (src_nodes == NULL) { 36561d77071SPavan Nikhilesh printf("Failed to reserve memory for src nodes\n"); 36661d77071SPavan Nikhilesh goto pattern_free; 36761d77071SPavan Nikhilesh } 36861d77071SPavan Nikhilesh 36961d77071SPavan Nikhilesh snk_nodes = malloc(sizeof(rte_node_t) * nb_sinks); 37061d77071SPavan Nikhilesh if (snk_nodes == NULL) { 37161d77071SPavan Nikhilesh printf("Failed to reserve memory for snk nodes\n"); 37261d77071SPavan Nikhilesh goto src_free; 37361d77071SPavan Nikhilesh } 37461d77071SPavan Nikhilesh 37561d77071SPavan Nikhilesh node_map = malloc(sizeof(rte_node_t *) * stages + 37661d77071SPavan Nikhilesh sizeof(rte_node_t) * nodes_per_stage * stages); 37761d77071SPavan Nikhilesh if (node_map == NULL) { 37861d77071SPavan Nikhilesh printf("Failed to reserve memory for node map\n"); 37961d77071SPavan Nikhilesh goto snk_free; 38061d77071SPavan Nikhilesh } 38161d77071SPavan Nikhilesh 38261d77071SPavan Nikhilesh /* Setup the Graph */ 38361d77071SPavan Nikhilesh for (i = 0; i < stages; i++) { 38461d77071SPavan Nikhilesh node_map[i] = 38561d77071SPavan Nikhilesh (rte_node_t *)(node_map + stages) + nodes_per_stage * i; 38661d77071SPavan Nikhilesh for (j = 0; j < nodes_per_stage; j++) { 38761d77071SPavan Nikhilesh total_percent = 0; 38861d77071SPavan Nikhilesh for (k = 0; k < nodes_per_stage; k++) 38961d77071SPavan Nikhilesh total_percent += edge_map[i][j][k]; 39061d77071SPavan Nikhilesh if (!total_percent) 39161d77071SPavan Nikhilesh continue; 39261d77071SPavan Nikhilesh node_patterns[graph_data->nb_nodes] = 39361d77071SPavan Nikhilesh malloc(RTE_NODE_NAMESIZE); 39461d77071SPavan Nikhilesh if (node_patterns[graph_data->nb_nodes] == NULL) { 39561d77071SPavan Nikhilesh printf("Failed to create memory for pattern\n"); 39661d77071SPavan Nikhilesh goto pattern_name_free; 39761d77071SPavan Nikhilesh } 39861d77071SPavan Nikhilesh 39961d77071SPavan Nikhilesh /* Clone a worker node */ 40061d77071SPavan Nikhilesh snprintf(nname, sizeof(nname), "%d-%d", i, j); 40161d77071SPavan Nikhilesh node_map[i][j] = 40261d77071SPavan Nikhilesh graph_node_get(TEST_GRAPH_WRK_NAME, nname); 40361d77071SPavan Nikhilesh if (node_map[i][j] == RTE_NODE_ID_INVALID) { 40461d77071SPavan Nikhilesh printf("Failed to create node[%s]\n", nname); 40561d77071SPavan Nikhilesh graph_data->nb_nodes++; 40661d77071SPavan Nikhilesh goto pattern_name_free; 40761d77071SPavan Nikhilesh } 40861d77071SPavan Nikhilesh snprintf(node_patterns[graph_data->nb_nodes], 40961d77071SPavan Nikhilesh RTE_NODE_NAMESIZE, "%s", 41061d77071SPavan Nikhilesh rte_node_id_to_name(node_map[i][j])); 41161d77071SPavan Nikhilesh node_data = 41261d77071SPavan Nikhilesh &graph_data->node_data[graph_data->nb_nodes]; 41361d77071SPavan Nikhilesh node_data->node_id = node_map[i][j]; 41461d77071SPavan Nikhilesh node_data->is_sink = false; 41561d77071SPavan Nikhilesh graph_data->nb_nodes++; 41661d77071SPavan Nikhilesh } 41761d77071SPavan Nikhilesh } 41861d77071SPavan Nikhilesh 41961d77071SPavan Nikhilesh for (i = 0; i < stages - 1; i++) { 42061d77071SPavan Nikhilesh for (j = 0; j < nodes_per_stage; j++) { 42161d77071SPavan Nikhilesh /* Count edges i.e connections of worker node to next */ 42261d77071SPavan Nikhilesh node_data = 42361d77071SPavan Nikhilesh graph_get_node_data(graph_data, node_map[i][j]); 42461d77071SPavan Nikhilesh edges = graph_node_count_edges(i, j, nodes_per_stage, 42561d77071SPavan Nikhilesh edge_map, ename, 42661d77071SPavan Nikhilesh node_data, node_map); 42761d77071SPavan Nikhilesh if (edges == RTE_EDGE_ID_INVALID) { 42861d77071SPavan Nikhilesh printf("Invalid edge configuration\n"); 42961d77071SPavan Nikhilesh goto pattern_name_free; 43061d77071SPavan Nikhilesh } 43161d77071SPavan Nikhilesh if (!edges) 43261d77071SPavan Nikhilesh continue; 43361d77071SPavan Nikhilesh 43461d77071SPavan Nikhilesh /* Connect a node in stage 'i' to nodes 43561d77071SPavan Nikhilesh * in stage 'i + 1' with edges. 43661d77071SPavan Nikhilesh */ 43761d77071SPavan Nikhilesh count = rte_node_edge_update( 43861d77071SPavan Nikhilesh node_map[i][j], 0, 43961d77071SPavan Nikhilesh (const char **)(uintptr_t)ename, edges); 44061d77071SPavan Nikhilesh for (k = 0; k < edges; k++) 44161d77071SPavan Nikhilesh free(ename[k]); 44261d77071SPavan Nikhilesh if (count != edges) { 44361d77071SPavan Nikhilesh printf("Couldn't add edges %d %d\n", edges, 44461d77071SPavan Nikhilesh count); 44561d77071SPavan Nikhilesh goto pattern_name_free; 44661d77071SPavan Nikhilesh } 44761d77071SPavan Nikhilesh } 44861d77071SPavan Nikhilesh } 44961d77071SPavan Nikhilesh 45061d77071SPavan Nikhilesh /* Setup Source nodes */ 45161d77071SPavan Nikhilesh for (i = 0; i < nb_srcs; i++) { 45261d77071SPavan Nikhilesh edges = 0; 45361d77071SPavan Nikhilesh total_percent = 0; 45461d77071SPavan Nikhilesh node_patterns[graph_data->nb_nodes] = malloc(RTE_NODE_NAMESIZE); 45561d77071SPavan Nikhilesh if (node_patterns[graph_data->nb_nodes] == NULL) { 45661d77071SPavan Nikhilesh printf("Failed to create memory for pattern\n"); 45761d77071SPavan Nikhilesh goto pattern_name_free; 45861d77071SPavan Nikhilesh } 45961d77071SPavan Nikhilesh /* Clone a source node */ 46061d77071SPavan Nikhilesh snprintf(nname, sizeof(nname), "%d", i); 46161d77071SPavan Nikhilesh src_nodes[i] = 46261d77071SPavan Nikhilesh graph_node_get(burst_one ? TEST_GRAPH_SRC_BRST_ONE_NAME 46361d77071SPavan Nikhilesh : TEST_GRAPH_SRC_NAME, 46461d77071SPavan Nikhilesh nname); 46561d77071SPavan Nikhilesh if (src_nodes[i] == RTE_NODE_ID_INVALID) { 46661d77071SPavan Nikhilesh printf("Failed to create node[%s]\n", nname); 46761d77071SPavan Nikhilesh graph_data->nb_nodes++; 46861d77071SPavan Nikhilesh goto pattern_name_free; 46961d77071SPavan Nikhilesh } 47061d77071SPavan Nikhilesh snprintf(node_patterns[graph_data->nb_nodes], RTE_NODE_NAMESIZE, 47161d77071SPavan Nikhilesh "%s", rte_node_id_to_name(src_nodes[i])); 47261d77071SPavan Nikhilesh node_data = &graph_data->node_data[graph_data->nb_nodes]; 47361d77071SPavan Nikhilesh node_data->node_id = src_nodes[i]; 47461d77071SPavan Nikhilesh node_data->is_sink = false; 47561d77071SPavan Nikhilesh graph_data->nb_nodes++; 47661d77071SPavan Nikhilesh 47761d77071SPavan Nikhilesh /* Prepare next node list to connect to */ 47861d77071SPavan Nikhilesh for (j = 0; j < nodes_per_stage; j++) { 47961d77071SPavan Nikhilesh if (!src_map[i][j]) 48061d77071SPavan Nikhilesh continue; 48161d77071SPavan Nikhilesh ename[edges] = malloc(sizeof(char) * RTE_NODE_NAMESIZE); 48261d77071SPavan Nikhilesh snprintf(ename[edges], RTE_NODE_NAMESIZE, "%s", 48361d77071SPavan Nikhilesh rte_node_id_to_name(node_map[0][j])); 48461d77071SPavan Nikhilesh node_data->next_nodes[edges] = node_map[0][j]; 48561d77071SPavan Nikhilesh node_data->next_percentage[edges] = src_map[i][j]; 48661d77071SPavan Nikhilesh edges++; 48761d77071SPavan Nikhilesh total_percent += src_map[i][j]; 48861d77071SPavan Nikhilesh } 48961d77071SPavan Nikhilesh 49061d77071SPavan Nikhilesh if (!edges) 49161d77071SPavan Nikhilesh continue; 49261d77071SPavan Nikhilesh if (edges >= MAX_EDGES_PER_NODE || total_percent != 100) { 49361d77071SPavan Nikhilesh printf("Invalid edge configuration\n"); 49461d77071SPavan Nikhilesh for (j = 0; j < edges; j++) 49561d77071SPavan Nikhilesh free(ename[j]); 49661d77071SPavan Nikhilesh goto pattern_name_free; 49761d77071SPavan Nikhilesh } 49861d77071SPavan Nikhilesh 49961d77071SPavan Nikhilesh /* Connect to list of next nodes using edges */ 50061d77071SPavan Nikhilesh count = rte_node_edge_update(src_nodes[i], 0, 50161d77071SPavan Nikhilesh (const char **)(uintptr_t)ename, 50261d77071SPavan Nikhilesh edges); 50361d77071SPavan Nikhilesh for (k = 0; k < edges; k++) 50461d77071SPavan Nikhilesh free(ename[k]); 50561d77071SPavan Nikhilesh if (count != edges) { 50661d77071SPavan Nikhilesh printf("Couldn't add edges %d %d\n", edges, count); 50761d77071SPavan Nikhilesh goto pattern_name_free; 50861d77071SPavan Nikhilesh } 50961d77071SPavan Nikhilesh } 51061d77071SPavan Nikhilesh 51161d77071SPavan Nikhilesh /* Setup Sink nodes */ 51261d77071SPavan Nikhilesh for (i = 0; i < nb_sinks; i++) { 51361d77071SPavan Nikhilesh node_patterns[graph_data->nb_nodes] = malloc(RTE_NODE_NAMESIZE); 51461d77071SPavan Nikhilesh if (node_patterns[graph_data->nb_nodes] == NULL) { 51561d77071SPavan Nikhilesh printf("Failed to create memory for pattern\n"); 51661d77071SPavan Nikhilesh goto pattern_name_free; 51761d77071SPavan Nikhilesh } 51861d77071SPavan Nikhilesh 51961d77071SPavan Nikhilesh /* Clone a sink node */ 52061d77071SPavan Nikhilesh snprintf(nname, sizeof(nname), "%d", i); 52161d77071SPavan Nikhilesh snk_nodes[i] = graph_node_get(TEST_GRAPH_SNK_NAME, nname); 52261d77071SPavan Nikhilesh if (snk_nodes[i] == RTE_NODE_ID_INVALID) { 52361d77071SPavan Nikhilesh printf("Failed to create node[%s]\n", nname); 52461d77071SPavan Nikhilesh graph_data->nb_nodes++; 52561d77071SPavan Nikhilesh goto pattern_name_free; 52661d77071SPavan Nikhilesh } 52761d77071SPavan Nikhilesh snprintf(node_patterns[graph_data->nb_nodes], RTE_NODE_NAMESIZE, 52861d77071SPavan Nikhilesh "%s", rte_node_id_to_name(snk_nodes[i])); 52961d77071SPavan Nikhilesh node_data = &graph_data->node_data[graph_data->nb_nodes]; 53061d77071SPavan Nikhilesh node_data->node_id = snk_nodes[i]; 53161d77071SPavan Nikhilesh node_data->is_sink = true; 53261d77071SPavan Nikhilesh graph_data->nb_nodes++; 53361d77071SPavan Nikhilesh } 53461d77071SPavan Nikhilesh 53561d77071SPavan Nikhilesh /* Connect last stage worker nodes to sink nodes */ 53661d77071SPavan Nikhilesh for (i = 0; i < nodes_per_stage; i++) { 53761d77071SPavan Nikhilesh edges = 0; 53861d77071SPavan Nikhilesh total_percent = 0; 53961d77071SPavan Nikhilesh node_data = graph_get_node_data(graph_data, 54061d77071SPavan Nikhilesh node_map[stages - 1][i]); 54161d77071SPavan Nikhilesh /* Prepare list of sink nodes to connect to */ 54261d77071SPavan Nikhilesh for (j = 0; j < nb_sinks; j++) { 54361d77071SPavan Nikhilesh if (!snk_map[i][j]) 54461d77071SPavan Nikhilesh continue; 54561d77071SPavan Nikhilesh ename[edges] = malloc(sizeof(char) * RTE_NODE_NAMESIZE); 54661d77071SPavan Nikhilesh snprintf(ename[edges], RTE_NODE_NAMESIZE, "%s", 54761d77071SPavan Nikhilesh rte_node_id_to_name(snk_nodes[j])); 54861d77071SPavan Nikhilesh node_data->next_nodes[edges] = snk_nodes[j]; 54961d77071SPavan Nikhilesh node_data->next_percentage[edges] = snk_map[i][j]; 55061d77071SPavan Nikhilesh edges++; 55161d77071SPavan Nikhilesh total_percent += snk_map[i][j]; 55261d77071SPavan Nikhilesh } 55361d77071SPavan Nikhilesh if (!edges) 55461d77071SPavan Nikhilesh continue; 55561d77071SPavan Nikhilesh if (edges >= MAX_EDGES_PER_NODE || total_percent != 100) { 55661d77071SPavan Nikhilesh printf("Invalid edge configuration\n"); 55761d77071SPavan Nikhilesh for (j = 0; j < edges; j++) 55861d77071SPavan Nikhilesh free(ename[i]); 55961d77071SPavan Nikhilesh goto pattern_name_free; 56061d77071SPavan Nikhilesh } 56161d77071SPavan Nikhilesh 56261d77071SPavan Nikhilesh /* Connect a worker node to a list of sink nodes */ 56361d77071SPavan Nikhilesh count = rte_node_edge_update(node_map[stages - 1][i], 0, 56461d77071SPavan Nikhilesh (const char **)(uintptr_t)ename, 56561d77071SPavan Nikhilesh edges); 56661d77071SPavan Nikhilesh for (k = 0; k < edges; k++) 56761d77071SPavan Nikhilesh free(ename[k]); 56861d77071SPavan Nikhilesh if (count != edges) { 56961d77071SPavan Nikhilesh printf("Couldn't add edges %d %d\n", edges, count); 57061d77071SPavan Nikhilesh goto pattern_name_free; 57161d77071SPavan Nikhilesh } 57261d77071SPavan Nikhilesh } 57361d77071SPavan Nikhilesh 57461d77071SPavan Nikhilesh /* Create a Graph */ 57561d77071SPavan Nikhilesh gconf.socket_id = SOCKET_ID_ANY; 57661d77071SPavan Nikhilesh gconf.nb_node_patterns = graph_data->nb_nodes; 57761d77071SPavan Nikhilesh gconf.node_patterns = (const char **)(uintptr_t)node_patterns; 57861d77071SPavan Nikhilesh 57961d77071SPavan Nikhilesh graph_id = rte_graph_create(gname, &gconf); 58061d77071SPavan Nikhilesh if (graph_id == RTE_GRAPH_ID_INVALID) { 58161d77071SPavan Nikhilesh printf("Graph creation failed with error = %d\n", rte_errno); 58261d77071SPavan Nikhilesh goto pattern_name_free; 58361d77071SPavan Nikhilesh } 58461d77071SPavan Nikhilesh graph_data->graph_id = graph_id; 58561d77071SPavan Nikhilesh 5862e908855SPavan Nikhilesh free(node_map); 58761d77071SPavan Nikhilesh for (i = 0; i < graph_data->nb_nodes; i++) 58861d77071SPavan Nikhilesh free(node_patterns[i]); 58961d77071SPavan Nikhilesh free(snk_nodes); 59061d77071SPavan Nikhilesh free(src_nodes); 59161d77071SPavan Nikhilesh free(node_patterns); 59261d77071SPavan Nikhilesh return 0; 59361d77071SPavan Nikhilesh 59461d77071SPavan Nikhilesh pattern_name_free: 5952e908855SPavan Nikhilesh free(node_map); 59661d77071SPavan Nikhilesh for (i = 0; i < graph_data->nb_nodes; i++) 59761d77071SPavan Nikhilesh free(node_patterns[i]); 59861d77071SPavan Nikhilesh snk_free: 59961d77071SPavan Nikhilesh free(snk_nodes); 60061d77071SPavan Nikhilesh src_free: 60161d77071SPavan Nikhilesh free(src_nodes); 60261d77071SPavan Nikhilesh pattern_free: 60361d77071SPavan Nikhilesh free(node_patterns); 60461d77071SPavan Nikhilesh data_free: 60561d77071SPavan Nikhilesh free(graph_data->node_data); 60661d77071SPavan Nikhilesh memzone_free: 60761d77071SPavan Nikhilesh rte_memzone_free(mz); 60861d77071SPavan Nikhilesh return -ENOMEM; 60961d77071SPavan Nikhilesh } 61061d77071SPavan Nikhilesh 61161d77071SPavan Nikhilesh /* Worker thread function */ 61261d77071SPavan Nikhilesh static int 61361d77071SPavan Nikhilesh _graph_perf_wrapper(void *args) 61461d77071SPavan Nikhilesh { 61561d77071SPavan Nikhilesh struct graph_lcore_data *data = args; 61661d77071SPavan Nikhilesh struct rte_graph *graph; 61761d77071SPavan Nikhilesh 61861d77071SPavan Nikhilesh /* Lookup graph */ 61961d77071SPavan Nikhilesh graph = rte_graph_lookup(rte_graph_id_to_name(data->graph_id)); 62061d77071SPavan Nikhilesh 62161d77071SPavan Nikhilesh /* Graph walk until done */ 62261d77071SPavan Nikhilesh while (!data->done) 62361d77071SPavan Nikhilesh rte_graph_walk(graph); 62461d77071SPavan Nikhilesh 62561d77071SPavan Nikhilesh return 0; 62661d77071SPavan Nikhilesh } 62761d77071SPavan Nikhilesh 62861d77071SPavan Nikhilesh static int 62961d77071SPavan Nikhilesh measure_perf_get(rte_graph_t graph_id) 63061d77071SPavan Nikhilesh { 63161d77071SPavan Nikhilesh const char *pattern = rte_graph_id_to_name(graph_id); 63261d77071SPavan Nikhilesh uint32_t lcore_id = rte_get_next_lcore(-1, 1, 0); 63361d77071SPavan Nikhilesh struct rte_graph_cluster_stats_param param; 63461d77071SPavan Nikhilesh struct rte_graph_cluster_stats *stats; 63561d77071SPavan Nikhilesh struct graph_lcore_data *data; 63661d77071SPavan Nikhilesh 63761d77071SPavan Nikhilesh data = rte_zmalloc("Graph_perf", sizeof(struct graph_lcore_data), 63861d77071SPavan Nikhilesh RTE_CACHE_LINE_SIZE); 63961d77071SPavan Nikhilesh data->graph_id = graph_id; 64061d77071SPavan Nikhilesh data->done = 0; 64161d77071SPavan Nikhilesh 64261d77071SPavan Nikhilesh /* Run graph worker thread function */ 64361d77071SPavan Nikhilesh rte_eal_remote_launch(_graph_perf_wrapper, data, lcore_id); 64461d77071SPavan Nikhilesh 64561d77071SPavan Nikhilesh /* Collect stats for few msecs */ 64661d77071SPavan Nikhilesh if (rte_graph_has_stats_feature()) { 64761d77071SPavan Nikhilesh memset(¶m, 0, sizeof(param)); 64861d77071SPavan Nikhilesh param.f = stdout; 64961d77071SPavan Nikhilesh param.socket_id = SOCKET_ID_ANY; 65061d77071SPavan Nikhilesh param.graph_patterns = &pattern; 65161d77071SPavan Nikhilesh param.nb_graph_patterns = 1; 65261d77071SPavan Nikhilesh 65361d77071SPavan Nikhilesh stats = rte_graph_cluster_stats_create(¶m); 65461d77071SPavan Nikhilesh if (stats == NULL) { 65561d77071SPavan Nikhilesh printf("Failed to create stats\n"); 65661d77071SPavan Nikhilesh return -ENOMEM; 65761d77071SPavan Nikhilesh } 65861d77071SPavan Nikhilesh 65961d77071SPavan Nikhilesh rte_delay_ms(3E2); 66061d77071SPavan Nikhilesh rte_graph_cluster_stats_get(stats, true); 66161d77071SPavan Nikhilesh rte_delay_ms(1E3); 66261d77071SPavan Nikhilesh rte_graph_cluster_stats_get(stats, false); 66361d77071SPavan Nikhilesh rte_graph_cluster_stats_destroy(stats); 66461d77071SPavan Nikhilesh } else 66561d77071SPavan Nikhilesh rte_delay_ms(1E3); 66661d77071SPavan Nikhilesh 66761d77071SPavan Nikhilesh data->done = 1; 66861d77071SPavan Nikhilesh rte_eal_wait_lcore(lcore_id); 66961d77071SPavan Nikhilesh 67061d77071SPavan Nikhilesh return 0; 67161d77071SPavan Nikhilesh } 67261d77071SPavan Nikhilesh 67361d77071SPavan Nikhilesh static inline void 67461d77071SPavan Nikhilesh graph_fini(void) 67561d77071SPavan Nikhilesh { 67661d77071SPavan Nikhilesh const struct rte_memzone *mz = rte_memzone_lookup(TEST_GRAPH_PERF_MZ); 67761d77071SPavan Nikhilesh struct test_graph_perf *graph_data; 67861d77071SPavan Nikhilesh 67961d77071SPavan Nikhilesh if (mz == NULL) 68061d77071SPavan Nikhilesh return; 68161d77071SPavan Nikhilesh graph_data = mz->addr; 68261d77071SPavan Nikhilesh 68361d77071SPavan Nikhilesh rte_graph_destroy(graph_data->graph_id); 68461d77071SPavan Nikhilesh free(graph_data->node_data); 68561d77071SPavan Nikhilesh rte_memzone_free(rte_memzone_lookup(TEST_GRAPH_PERF_MZ)); 68661d77071SPavan Nikhilesh } 68761d77071SPavan Nikhilesh 68861d77071SPavan Nikhilesh static int 68961d77071SPavan Nikhilesh measure_perf(void) 69061d77071SPavan Nikhilesh { 69161d77071SPavan Nikhilesh const struct rte_memzone *mz; 69261d77071SPavan Nikhilesh struct test_graph_perf *graph_data; 69361d77071SPavan Nikhilesh 69461d77071SPavan Nikhilesh mz = rte_memzone_lookup(TEST_GRAPH_PERF_MZ); 6952e908855SPavan Nikhilesh if (mz == NULL) 6962e908855SPavan Nikhilesh return -ENOMEM; 69761d77071SPavan Nikhilesh graph_data = mz->addr; 69861d77071SPavan Nikhilesh 69961d77071SPavan Nikhilesh return measure_perf_get(graph_data->graph_id); 70061d77071SPavan Nikhilesh } 70161d77071SPavan Nikhilesh 70261d77071SPavan Nikhilesh static inline int 70361d77071SPavan Nikhilesh graph_hr_4s_1n_1src_1snk(void) 70461d77071SPavan Nikhilesh { 70561d77071SPavan Nikhilesh return measure_perf(); 70661d77071SPavan Nikhilesh } 70761d77071SPavan Nikhilesh 70861d77071SPavan Nikhilesh static inline int 70961d77071SPavan Nikhilesh graph_hr_4s_1n_1src_1snk_brst_one(void) 71061d77071SPavan Nikhilesh { 71161d77071SPavan Nikhilesh return measure_perf(); 71261d77071SPavan Nikhilesh } 71361d77071SPavan Nikhilesh 71461d77071SPavan Nikhilesh static inline int 71561d77071SPavan Nikhilesh graph_hr_4s_1n_2src_1snk(void) 71661d77071SPavan Nikhilesh { 71761d77071SPavan Nikhilesh return measure_perf(); 71861d77071SPavan Nikhilesh } 71961d77071SPavan Nikhilesh 72061d77071SPavan Nikhilesh static inline int 72161d77071SPavan Nikhilesh graph_hr_4s_1n_1src_2snk(void) 72261d77071SPavan Nikhilesh { 72361d77071SPavan Nikhilesh return measure_perf(); 72461d77071SPavan Nikhilesh } 72561d77071SPavan Nikhilesh 72661d77071SPavan Nikhilesh static inline int 72761d77071SPavan Nikhilesh graph_tree_4s_4n_1src_4snk(void) 72861d77071SPavan Nikhilesh { 72961d77071SPavan Nikhilesh return measure_perf(); 73061d77071SPavan Nikhilesh } 73161d77071SPavan Nikhilesh 73261d77071SPavan Nikhilesh static inline int 73361d77071SPavan Nikhilesh graph_reverse_tree_3s_4n_1src_1snk(void) 73461d77071SPavan Nikhilesh { 73561d77071SPavan Nikhilesh return measure_perf(); 73661d77071SPavan Nikhilesh } 73761d77071SPavan Nikhilesh 73861d77071SPavan Nikhilesh static inline int 73961d77071SPavan Nikhilesh graph_parallel_tree_5s_4n_4src_4snk(void) 74061d77071SPavan Nikhilesh { 74161d77071SPavan Nikhilesh return measure_perf(); 74261d77071SPavan Nikhilesh } 74361d77071SPavan Nikhilesh 74461d77071SPavan Nikhilesh /* Graph Topology 74561d77071SPavan Nikhilesh * nodes per stage: 1 74661d77071SPavan Nikhilesh * stages: 4 74761d77071SPavan Nikhilesh * src: 1 74861d77071SPavan Nikhilesh * sink: 1 74961d77071SPavan Nikhilesh */ 75061d77071SPavan Nikhilesh static inline int 75161d77071SPavan Nikhilesh graph_init_hr(void) 75261d77071SPavan Nikhilesh { 75361d77071SPavan Nikhilesh uint8_t edge_map[][1][1] = { 75461d77071SPavan Nikhilesh { {100} }, 75561d77071SPavan Nikhilesh { {100} }, 75661d77071SPavan Nikhilesh { {100} }, 75761d77071SPavan Nikhilesh { {100} }, 75861d77071SPavan Nikhilesh }; 75961d77071SPavan Nikhilesh uint8_t src_map[][1] = { {100} }; 76061d77071SPavan Nikhilesh uint8_t snk_map[][1] = { {100} }; 76161d77071SPavan Nikhilesh 76261d77071SPavan Nikhilesh return graph_init("graph_hr", SOURCES(src_map), SINKS(snk_map), 76361d77071SPavan Nikhilesh STAGES(edge_map), NODES_PER_STAGE(edge_map), src_map, 76461d77071SPavan Nikhilesh snk_map, edge_map, 0); 76561d77071SPavan Nikhilesh } 76661d77071SPavan Nikhilesh 76761d77071SPavan Nikhilesh /* Graph Topology 76861d77071SPavan Nikhilesh * nodes per stage: 1 76961d77071SPavan Nikhilesh * stages: 4 77061d77071SPavan Nikhilesh * src: 1 77161d77071SPavan Nikhilesh * sink: 1 77261d77071SPavan Nikhilesh */ 77361d77071SPavan Nikhilesh static inline int 77461d77071SPavan Nikhilesh graph_init_hr_brst_one(void) 77561d77071SPavan Nikhilesh { 77661d77071SPavan Nikhilesh uint8_t edge_map[][1][1] = { 77761d77071SPavan Nikhilesh { {100} }, 77861d77071SPavan Nikhilesh { {100} }, 77961d77071SPavan Nikhilesh { {100} }, 78061d77071SPavan Nikhilesh { {100} }, 78161d77071SPavan Nikhilesh }; 78261d77071SPavan Nikhilesh uint8_t src_map[][1] = { {100} }; 78361d77071SPavan Nikhilesh uint8_t snk_map[][1] = { {100} }; 78461d77071SPavan Nikhilesh 78561d77071SPavan Nikhilesh return graph_init("graph_hr", SOURCES(src_map), SINKS(snk_map), 78661d77071SPavan Nikhilesh STAGES(edge_map), NODES_PER_STAGE(edge_map), src_map, 78761d77071SPavan Nikhilesh snk_map, edge_map, 1); 78861d77071SPavan Nikhilesh } 78961d77071SPavan Nikhilesh 79061d77071SPavan Nikhilesh /* Graph Topology 79161d77071SPavan Nikhilesh * nodes per stage: 1 79261d77071SPavan Nikhilesh * stages: 4 79361d77071SPavan Nikhilesh * src: 2 79461d77071SPavan Nikhilesh * sink: 1 79561d77071SPavan Nikhilesh */ 79661d77071SPavan Nikhilesh static inline int 79761d77071SPavan Nikhilesh graph_init_hr_multi_src(void) 79861d77071SPavan Nikhilesh { 79961d77071SPavan Nikhilesh uint8_t edge_map[][1][1] = { 80061d77071SPavan Nikhilesh { {100} }, 80161d77071SPavan Nikhilesh { {100} }, 80261d77071SPavan Nikhilesh { {100} }, 80361d77071SPavan Nikhilesh { {100} }, 80461d77071SPavan Nikhilesh }; 80561d77071SPavan Nikhilesh uint8_t src_map[][1] = { 80661d77071SPavan Nikhilesh {100}, {100} 80761d77071SPavan Nikhilesh }; 80861d77071SPavan Nikhilesh uint8_t snk_map[][1] = { {100} }; 80961d77071SPavan Nikhilesh 81061d77071SPavan Nikhilesh return graph_init("graph_hr", SOURCES(src_map), SINKS(snk_map), 81161d77071SPavan Nikhilesh STAGES(edge_map), NODES_PER_STAGE(edge_map), src_map, 81261d77071SPavan Nikhilesh snk_map, edge_map, 0); 81361d77071SPavan Nikhilesh } 81461d77071SPavan Nikhilesh 81561d77071SPavan Nikhilesh /* Graph Topology 81661d77071SPavan Nikhilesh * nodes per stage: 1 81761d77071SPavan Nikhilesh * stages: 4 81861d77071SPavan Nikhilesh * src: 1 81961d77071SPavan Nikhilesh * sink: 2 82061d77071SPavan Nikhilesh */ 82161d77071SPavan Nikhilesh static inline int 82261d77071SPavan Nikhilesh graph_init_hr_multi_snk(void) 82361d77071SPavan Nikhilesh { 82461d77071SPavan Nikhilesh uint8_t edge_map[][1][1] = { 82561d77071SPavan Nikhilesh { {100} }, 82661d77071SPavan Nikhilesh { {100} }, 82761d77071SPavan Nikhilesh { {100} }, 82861d77071SPavan Nikhilesh { {100} }, 82961d77071SPavan Nikhilesh }; 83061d77071SPavan Nikhilesh uint8_t src_map[][1] = { {100} }; 83161d77071SPavan Nikhilesh uint8_t snk_map[][2] = { {50, 50} }; 83261d77071SPavan Nikhilesh 83361d77071SPavan Nikhilesh return graph_init("graph_hr", SOURCES(src_map), SINKS(snk_map), 83461d77071SPavan Nikhilesh STAGES(edge_map), NODES_PER_STAGE(edge_map), src_map, 83561d77071SPavan Nikhilesh snk_map, edge_map, 0); 83661d77071SPavan Nikhilesh } 83761d77071SPavan Nikhilesh 83861d77071SPavan Nikhilesh /* Graph Topology 83961d77071SPavan Nikhilesh * nodes per stage: 4 84061d77071SPavan Nikhilesh * stages: 4 84161d77071SPavan Nikhilesh * src: 1 84261d77071SPavan Nikhilesh * sink: 4 84361d77071SPavan Nikhilesh */ 84461d77071SPavan Nikhilesh static inline int 84561d77071SPavan Nikhilesh graph_init_tree(void) 84661d77071SPavan Nikhilesh { 84761d77071SPavan Nikhilesh uint8_t edge_map[][4][4] = { 84861d77071SPavan Nikhilesh { 84961d77071SPavan Nikhilesh {100, 0, 0, 0}, 85061d77071SPavan Nikhilesh {0, 0, 0, 0}, 85161d77071SPavan Nikhilesh {0, 0, 0, 0}, 85261d77071SPavan Nikhilesh {0, 0, 0, 0} 85361d77071SPavan Nikhilesh }, 85461d77071SPavan Nikhilesh { 85561d77071SPavan Nikhilesh {50, 0, 0, 0}, 85661d77071SPavan Nikhilesh {50, 0, 0, 0}, 85761d77071SPavan Nikhilesh {0, 0, 0, 0}, 85861d77071SPavan Nikhilesh {0, 0, 0, 0} 85961d77071SPavan Nikhilesh }, 86061d77071SPavan Nikhilesh { 86161d77071SPavan Nikhilesh {33, 33, 0, 0}, 86261d77071SPavan Nikhilesh {34, 34, 0, 0}, 86361d77071SPavan Nikhilesh {33, 33, 0, 0}, 86461d77071SPavan Nikhilesh {0, 0, 0, 0} 86561d77071SPavan Nikhilesh }, 86661d77071SPavan Nikhilesh { 86761d77071SPavan Nikhilesh {25, 25, 25, 0}, 86861d77071SPavan Nikhilesh {25, 25, 25, 0}, 86961d77071SPavan Nikhilesh {25, 25, 25, 0}, 87061d77071SPavan Nikhilesh {25, 25, 25, 0} 87161d77071SPavan Nikhilesh } 87261d77071SPavan Nikhilesh }; 87361d77071SPavan Nikhilesh uint8_t src_map[][4] = { {100, 0, 0, 0} }; 87461d77071SPavan Nikhilesh uint8_t snk_map[][4] = { 87561d77071SPavan Nikhilesh {100, 0, 0, 0}, 87661d77071SPavan Nikhilesh {0, 100, 0, 0}, 87761d77071SPavan Nikhilesh {0, 0, 100, 0}, 87861d77071SPavan Nikhilesh {0, 0, 0, 100} 87961d77071SPavan Nikhilesh }; 88061d77071SPavan Nikhilesh 88161d77071SPavan Nikhilesh return graph_init("graph_full_split", SOURCES(src_map), SINKS(snk_map), 88261d77071SPavan Nikhilesh STAGES(edge_map), NODES_PER_STAGE(edge_map), src_map, 88361d77071SPavan Nikhilesh snk_map, edge_map, 0); 88461d77071SPavan Nikhilesh } 88561d77071SPavan Nikhilesh 88661d77071SPavan Nikhilesh /* Graph Topology 88761d77071SPavan Nikhilesh * nodes per stage: 4 88861d77071SPavan Nikhilesh * stages: 3 88961d77071SPavan Nikhilesh * src: 1 89061d77071SPavan Nikhilesh * sink: 1 89161d77071SPavan Nikhilesh */ 89261d77071SPavan Nikhilesh static inline int 89361d77071SPavan Nikhilesh graph_init_reverse_tree(void) 89461d77071SPavan Nikhilesh { 89561d77071SPavan Nikhilesh uint8_t edge_map[][4][4] = { 89661d77071SPavan Nikhilesh { 89761d77071SPavan Nikhilesh {25, 25, 25, 25}, 89861d77071SPavan Nikhilesh {25, 25, 25, 25}, 89961d77071SPavan Nikhilesh {25, 25, 25, 25}, 90061d77071SPavan Nikhilesh {25, 25, 25, 25} 90161d77071SPavan Nikhilesh }, 90261d77071SPavan Nikhilesh { 90361d77071SPavan Nikhilesh {33, 33, 33, 33}, 90461d77071SPavan Nikhilesh {33, 33, 33, 33}, 90561d77071SPavan Nikhilesh {34, 34, 34, 34}, 90661d77071SPavan Nikhilesh {0, 0, 0, 0} 90761d77071SPavan Nikhilesh }, 90861d77071SPavan Nikhilesh { 90961d77071SPavan Nikhilesh {50, 50, 50, 0}, 91061d77071SPavan Nikhilesh {50, 50, 50, 0}, 91161d77071SPavan Nikhilesh {0, 0, 0, 0}, 91261d77071SPavan Nikhilesh {0, 0, 0, 0} 91361d77071SPavan Nikhilesh }, 91461d77071SPavan Nikhilesh }; 91561d77071SPavan Nikhilesh uint8_t src_map[][4] = { {25, 25, 25, 25} }; 91661d77071SPavan Nikhilesh uint8_t snk_map[][1] = { {100}, {100}, {0}, {0} }; 91761d77071SPavan Nikhilesh 91861d77071SPavan Nikhilesh return graph_init("graph_full_split", SOURCES(src_map), SINKS(snk_map), 91961d77071SPavan Nikhilesh STAGES(edge_map), NODES_PER_STAGE(edge_map), src_map, 92061d77071SPavan Nikhilesh snk_map, edge_map, 0); 92161d77071SPavan Nikhilesh } 92261d77071SPavan Nikhilesh 92361d77071SPavan Nikhilesh /* Graph Topology 92461d77071SPavan Nikhilesh * nodes per stage: 4 92561d77071SPavan Nikhilesh * stages: 5 92661d77071SPavan Nikhilesh * src: 4 92761d77071SPavan Nikhilesh * sink: 4 92861d77071SPavan Nikhilesh */ 92961d77071SPavan Nikhilesh static inline int 93061d77071SPavan Nikhilesh graph_init_parallel_tree(void) 93161d77071SPavan Nikhilesh { 93261d77071SPavan Nikhilesh uint8_t edge_map[][4][4] = { 93361d77071SPavan Nikhilesh { 93461d77071SPavan Nikhilesh {100, 0, 0, 0}, 93561d77071SPavan Nikhilesh {0, 100, 0, 0}, 93661d77071SPavan Nikhilesh {0, 0, 100, 0}, 93761d77071SPavan Nikhilesh {0, 0, 0, 100} 93861d77071SPavan Nikhilesh }, 93961d77071SPavan Nikhilesh { 94061d77071SPavan Nikhilesh {100, 0, 0, 0}, 94161d77071SPavan Nikhilesh {0, 100, 0, 0}, 94261d77071SPavan Nikhilesh {0, 0, 100, 0}, 94361d77071SPavan Nikhilesh {0, 0, 0, 100} 94461d77071SPavan Nikhilesh }, 94561d77071SPavan Nikhilesh { 94661d77071SPavan Nikhilesh {100, 0, 0, 0}, 94761d77071SPavan Nikhilesh {0, 100, 0, 0}, 94861d77071SPavan Nikhilesh {0, 0, 100, 0}, 94961d77071SPavan Nikhilesh {0, 0, 0, 100} 95061d77071SPavan Nikhilesh }, 95161d77071SPavan Nikhilesh { 95261d77071SPavan Nikhilesh {100, 0, 0, 0}, 95361d77071SPavan Nikhilesh {0, 100, 0, 0}, 95461d77071SPavan Nikhilesh {0, 0, 100, 0}, 95561d77071SPavan Nikhilesh {0, 0, 0, 100} 95661d77071SPavan Nikhilesh }, 95761d77071SPavan Nikhilesh { 95861d77071SPavan Nikhilesh {100, 0, 0, 0}, 95961d77071SPavan Nikhilesh {0, 100, 0, 0}, 96061d77071SPavan Nikhilesh {0, 0, 100, 0}, 96161d77071SPavan Nikhilesh {0, 0, 0, 100} 96261d77071SPavan Nikhilesh }, 96361d77071SPavan Nikhilesh }; 96461d77071SPavan Nikhilesh uint8_t src_map[][4] = { 96561d77071SPavan Nikhilesh {100, 0, 0, 0}, 96661d77071SPavan Nikhilesh {0, 100, 0, 0}, 96761d77071SPavan Nikhilesh {0, 0, 100, 0}, 96861d77071SPavan Nikhilesh {0, 0, 0, 100} 96961d77071SPavan Nikhilesh }; 97061d77071SPavan Nikhilesh uint8_t snk_map[][4] = { 97161d77071SPavan Nikhilesh {100, 0, 0, 0}, 97261d77071SPavan Nikhilesh {0, 100, 0, 0}, 97361d77071SPavan Nikhilesh {0, 0, 100, 0}, 97461d77071SPavan Nikhilesh {0, 0, 0, 100} 97561d77071SPavan Nikhilesh }; 97661d77071SPavan Nikhilesh 97761d77071SPavan Nikhilesh return graph_init("graph_parallel", SOURCES(src_map), SINKS(snk_map), 97861d77071SPavan Nikhilesh STAGES(edge_map), NODES_PER_STAGE(edge_map), src_map, 97961d77071SPavan Nikhilesh snk_map, edge_map, 0); 98061d77071SPavan Nikhilesh } 98161d77071SPavan Nikhilesh 98261d77071SPavan Nikhilesh /** Graph Creation cheat sheet 98361d77071SPavan Nikhilesh * edge_map -> dictates graph flow from worker stage 0 to worker stage n-1. 98461d77071SPavan Nikhilesh * src_map -> dictates source nodes enqueue percentage to worker stage 0. 98561d77071SPavan Nikhilesh * snk_map -> dictates stage n-1 enqueue percentage to sink. 98661d77071SPavan Nikhilesh * 98761d77071SPavan Nikhilesh * Layout: 98861d77071SPavan Nikhilesh * edge_map[<nb_stages>][<nodes_per_stg>][<nodes_in_nxt_stg = nodes_per_stg>] 98961d77071SPavan Nikhilesh * src_map[<nb_sources>][<nodes_in_stage0 = nodes_per_stage>] 99061d77071SPavan Nikhilesh * snk_map[<nodes_in_stage(n-1) = nodes_per_stage>][<nb_sinks>] 99161d77071SPavan Nikhilesh * 99261d77071SPavan Nikhilesh * The last array dictates the percentage of received objs to enqueue to next 99361d77071SPavan Nikhilesh * stage. 99461d77071SPavan Nikhilesh * 99561d77071SPavan Nikhilesh * Note: edge_map[][0][] will always be unused as it will receive from source 99661d77071SPavan Nikhilesh * 99761d77071SPavan Nikhilesh * Example: 99861d77071SPavan Nikhilesh * Graph: 99961d77071SPavan Nikhilesh * http://bit.ly/2PqbqOy 100061d77071SPavan Nikhilesh * Each stage(n) connects to all nodes in the next stage in decreasing 100161d77071SPavan Nikhilesh * order. 100261d77071SPavan Nikhilesh * Since we can't resize the edge_map dynamically we get away by creating 100361d77071SPavan Nikhilesh * dummy nodes and assigning 0 percentages. 100461d77071SPavan Nikhilesh * Max nodes across all stages = 4 100561d77071SPavan Nikhilesh * stages = 3 100661d77071SPavan Nikhilesh * nb_src = 1 100761d77071SPavan Nikhilesh * nb_snk = 1 100861d77071SPavan Nikhilesh * // Stages 100961d77071SPavan Nikhilesh * edge_map[][4][4] = { 101061d77071SPavan Nikhilesh * // Nodes per stage 101161d77071SPavan Nikhilesh * { 101261d77071SPavan Nikhilesh * {25, 25, 25, 25}, 101361d77071SPavan Nikhilesh * {25, 25, 25, 25}, 101461d77071SPavan Nikhilesh * {25, 25, 25, 25}, 101561d77071SPavan Nikhilesh * {25, 25, 25, 25} 101661d77071SPavan Nikhilesh * }, // This will be unused. 101761d77071SPavan Nikhilesh * { 101861d77071SPavan Nikhilesh * // Nodes enabled in current stage + prev stage enq % 101961d77071SPavan Nikhilesh * {33, 33, 33, 33}, 102061d77071SPavan Nikhilesh * {33, 33, 33, 33}, 102161d77071SPavan Nikhilesh * {34, 34, 34, 34}, 102261d77071SPavan Nikhilesh * {0, 0, 0, 0} 102361d77071SPavan Nikhilesh * }, 102461d77071SPavan Nikhilesh * { 102561d77071SPavan Nikhilesh * {50, 50, 50, 0}, 102661d77071SPavan Nikhilesh * {50, 50, 50, 0}, 102761d77071SPavan Nikhilesh * {0, 0, 0, 0}, 102861d77071SPavan Nikhilesh * {0, 0, 0, 0} 102961d77071SPavan Nikhilesh * }, 103061d77071SPavan Nikhilesh * }; 103161d77071SPavan Nikhilesh * Above, each stage tells how much it should receive from previous except 103261d77071SPavan Nikhilesh * from stage_0. 103361d77071SPavan Nikhilesh * 103461d77071SPavan Nikhilesh * src_map[][4] = { {25, 25, 25, 25} }; 103561d77071SPavan Nikhilesh * Here, we tell each source the % it has to send to stage_0 nodes. In 103661d77071SPavan Nikhilesh * case we want 2 source node we can declare as 103761d77071SPavan Nikhilesh * src_map[][4] = { {25, 25, 25, 25}, {25, 25, 25, 25} }; 103861d77071SPavan Nikhilesh * 103961d77071SPavan Nikhilesh * snk_map[][1] = { {100}, {100}, {0}, {0} } 104061d77071SPavan Nikhilesh * Here, we tell stage - 1 nodes how much to enqueue to sink_0. 104161d77071SPavan Nikhilesh * If we have 2 sinks we can do as follows 104261d77071SPavan Nikhilesh * snk_map[][2] = { {50, 50}, {50, 50}, {0, 0}, {0, 0} } 104361d77071SPavan Nikhilesh */ 104461d77071SPavan Nikhilesh 104561d77071SPavan Nikhilesh static struct unit_test_suite graph_perf_testsuite = { 104661d77071SPavan Nikhilesh .suite_name = "Graph library performance test suite", 104761d77071SPavan Nikhilesh .setup = graph_perf_setup, 104861d77071SPavan Nikhilesh .teardown = graph_perf_teardown, 104961d77071SPavan Nikhilesh .unit_test_cases = { 105061d77071SPavan Nikhilesh TEST_CASE_ST(graph_init_hr, graph_fini, 105161d77071SPavan Nikhilesh graph_hr_4s_1n_1src_1snk), 105261d77071SPavan Nikhilesh TEST_CASE_ST(graph_init_hr_brst_one, graph_fini, 105361d77071SPavan Nikhilesh graph_hr_4s_1n_1src_1snk_brst_one), 105461d77071SPavan Nikhilesh TEST_CASE_ST(graph_init_hr_multi_src, graph_fini, 105561d77071SPavan Nikhilesh graph_hr_4s_1n_2src_1snk), 105661d77071SPavan Nikhilesh TEST_CASE_ST(graph_init_hr_multi_snk, graph_fini, 105761d77071SPavan Nikhilesh graph_hr_4s_1n_1src_2snk), 105861d77071SPavan Nikhilesh TEST_CASE_ST(graph_init_tree, graph_fini, 105961d77071SPavan Nikhilesh graph_tree_4s_4n_1src_4snk), 106061d77071SPavan Nikhilesh TEST_CASE_ST(graph_init_reverse_tree, graph_fini, 106161d77071SPavan Nikhilesh graph_reverse_tree_3s_4n_1src_1snk), 106261d77071SPavan Nikhilesh TEST_CASE_ST(graph_init_parallel_tree, graph_fini, 106361d77071SPavan Nikhilesh graph_parallel_tree_5s_4n_4src_4snk), 106461d77071SPavan Nikhilesh TEST_CASES_END(), /**< NULL terminate unit test array */ 106561d77071SPavan Nikhilesh }, 106661d77071SPavan Nikhilesh }; 106761d77071SPavan Nikhilesh 106861d77071SPavan Nikhilesh static int 106961d77071SPavan Nikhilesh test_graph_perf_func(void) 107061d77071SPavan Nikhilesh { 107161d77071SPavan Nikhilesh return unit_test_suite_runner(&graph_perf_testsuite); 107261d77071SPavan Nikhilesh } 107361d77071SPavan Nikhilesh 10743c60274cSJie Zhou #endif /* !RTE_EXEC_ENV_WINDOWS */ 10753c60274cSJie Zhou 107661d77071SPavan Nikhilesh REGISTER_TEST_COMMAND(graph_perf_autotest, test_graph_perf_func); 1077